From bf4444aa1a3655b5bcecc701be9617c31bebbf9f Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 21:32:14 -0400 Subject: [PATCH 0001/1123] ci: Add dev build ci on macOS --- .github/workflows/build-dev.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/build-dev.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml new file mode 100644 index 00000000..99167537 --- /dev/null +++ b/.github/workflows/build-dev.yml @@ -0,0 +1,31 @@ +name: Build dev version artifacts +on: [pull_request, push] + +jobs: + + macos-build: + runs-on: macos-latest + steps: + - name: Install GCC compiler + run: brew install gcc + - name: Install Ninja build system + run: brew install ninja + - name: Install CMake + run: brew install cmake + - name: Install dependencies + run: brew install qt@6 zlib libpng libzip + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" + - name: Build + run: cmake --build ./build --parallel + - name: Install + run: cmake --install ./build + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-macos + path: build/install From 565fe537e9d9a0a9c6f49157becbee89917d3da3 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 21:56:08 -0400 Subject: [PATCH 0002/1123] ci: Set `CMAKE_PREFIX_PATH` for macOS --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 99167537..4c757d0f 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -17,7 +17,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_PREFIX_PATH="/usr/local/Cellar/zlib/*/lib;/usr/local/Cellar/libpng/*/lib;/usr/local/Cellar/libzip/*/lib" - name: Build run: cmake --build ./build --parallel - name: Install From a62ce7b6ec12639235c949b2446c62fd33486e06 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:04:25 -0400 Subject: [PATCH 0003/1123] ci: (Temporary) Check lib directory for test --- .github/workflows/build-dev.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4c757d0f..b4f4129c 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -14,10 +14,12 @@ jobs: run: brew install cmake - name: Install dependencies run: brew install qt@6 zlib libpng libzip + - name: (Temporary) Check lib directory + run: ls -al /usr/local/lib - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_PREFIX_PATH="/usr/local/Cellar/zlib/*/lib;/usr/local/Cellar/libpng/*/lib;/usr/local/Cellar/libzip/*/lib" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" - name: Build run: cmake --build ./build --parallel - name: Install From 73a01afd00c39b9deb55d138cfdc7fa8ef0bbac4 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:14:44 -0400 Subject: [PATCH 0004/1123] ci: Reinstall zlib & libpng & libzip --- .github/workflows/build-dev.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b4f4129c..e632dbc6 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -13,7 +13,13 @@ jobs: - name: Install CMake run: brew install cmake - name: Install dependencies - run: brew install qt@6 zlib libpng libzip + run: brew install qt@6 + - name: Reinstall zlib + run: brew reinstall zlib + - name: Reinstall libpng + run: brew reinstall libpng + - name: Reinstall libzip + run: brew reinstall libzip - name: (Temporary) Check lib directory run: ls -al /usr/local/lib - name: Checkout repository From 69168fee420d18191efe92761a145a8cf0be6f94 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:20:56 -0400 Subject: [PATCH 0005/1123] ci: Set `CMAKE_PREFIX_PATH` for macOS --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e632dbc6..434c4c7d 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -25,7 +25,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_PREFIX_PATH="/usr/local/lib" - name: Build run: cmake --build ./build --parallel - name: Install From 3d01c292f7c2025b653a3775d0426bf7f958e46f Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:37:24 -0400 Subject: [PATCH 0006/1123] ci: Try to fix PNG_LIBRARY --- .github/workflows/build-dev.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 434c4c7d..4f96ab46 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -20,12 +20,10 @@ jobs: run: brew reinstall libpng - name: Reinstall libzip run: brew reinstall libzip - - name: (Temporary) Check lib directory - run: ls -al /usr/local/lib - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_PREFIX_PATH="/usr/local/lib" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DPNG_LIBRARY=/usr/local/lib - name: Build run: cmake --build ./build --parallel - name: Install From a40f13f6fdc2b3b1cc770d417d9bb2a3c16f6b6d Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:41:42 -0400 Subject: [PATCH 0007/1123] ci: Remove extra brew install --- .github/workflows/build-dev.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4f96ab46..855462d0 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -6,24 +6,14 @@ jobs: macos-build: runs-on: macos-latest steps: - - name: Install GCC compiler - run: brew install gcc - name: Install Ninja build system run: brew install ninja - - name: Install CMake - run: brew install cmake - name: Install dependencies run: brew install qt@6 - - name: Reinstall zlib - run: brew reinstall zlib - - name: Reinstall libpng - run: brew reinstall libpng - - name: Reinstall libzip - run: brew reinstall libzip - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DPNG_LIBRARY=/usr/local/lib + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" - name: Build run: cmake --build ./build --parallel - name: Install From 23eaf91cd22409bb0d345cd0351d3a119bb5cbf9 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:47:19 -0400 Subject: [PATCH 0008/1123] ci: (Temporary) Check PATH --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 855462d0..69267c0e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -10,6 +10,8 @@ jobs: run: brew install ninja - name: Install dependencies run: brew install qt@6 + - name: (Temporary) Check PATH + run: echo $PATH - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake From b132f4fdbc425a8da094f124b3c847be9da38f39 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:52:58 -0400 Subject: [PATCH 0009/1123] ci: Add `/usr/local/lib` to PATH --- .github/workflows/build-dev.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 69267c0e..37b17ecf 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -10,7 +10,9 @@ jobs: run: brew install ninja - name: Install dependencies run: brew install qt@6 - - name: (Temporary) Check PATH + - name: Add /usr/local/lib to PATH + run: export PATH="/usr/local/lib:$PATH" + - name: Check PATH run: echo $PATH - name: Checkout repository uses: actions/checkout@v2 From 4a6b6d0e6e80caaf17458d6d6ab40e1a87aa66c9 Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 22:56:41 -0400 Subject: [PATCH 0010/1123] ci: Fix `$PATH` --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 37b17ecf..f7e0c436 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -11,7 +11,7 @@ jobs: - name: Install dependencies run: brew install qt@6 - name: Add /usr/local/lib to PATH - run: export PATH="/usr/local/lib:$PATH" + run: export $PATH="/usr/local/lib:$PATH" - name: Check PATH run: echo $PATH - name: Checkout repository From bb4a0e711a80174a2733072a054c31e20623032b Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 23:00:11 -0400 Subject: [PATCH 0011/1123] ci: Fix `export PATH` --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f7e0c436..adf5a781 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -11,7 +11,7 @@ jobs: - name: Install dependencies run: brew install qt@6 - name: Add /usr/local/lib to PATH - run: export $PATH="/usr/local/lib:$PATH" + run: export PATH=/usr/local/lib:$PATH - name: Check PATH run: echo $PATH - name: Checkout repository From 06cc8a10aa3a9e4ca656675c38867e230e23f6fa Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 23:04:47 -0400 Subject: [PATCH 0012/1123] ci: Fix `PATH` update --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index adf5a781..2d6767f9 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -11,7 +11,7 @@ jobs: - name: Install dependencies run: brew install qt@6 - name: Add /usr/local/lib to PATH - run: export PATH=/usr/local/lib:$PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - name: Checkout repository From 8398ff894f89206ca5e07a20b9f27cc657b6afda Mon Sep 17 00:00:00 2001 From: Cubik Date: Fri, 7 Apr 2023 23:44:42 -0400 Subject: [PATCH 0013/1123] build(VisualCraftL): Set libpng requirement to `1.4.12` --- VisualCraftL/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 58426f5e..ea564f11 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -77,7 +77,7 @@ add_library(VisualCraftL_static STATIC ${VCL_source_files}) find_package(ZLIB 1.2.11 REQUIRED) -find_package(PNG 1.6.37 REQUIRED) +find_package(PNG 1.4.12 REQUIRED) find_package(libzip 1.9.2 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) From d7e57d1f61b1b45d738b7a8746f1e228e5c41aaa Mon Sep 17 00:00:00 2001 From: Cubik Date: Sat, 8 Apr 2023 00:04:14 -0400 Subject: [PATCH 0014/1123] ci: Configure `macdeployqt` --- .github/workflows/build-dev.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 2d6767f9..37ff4697 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -19,9 +19,15 @@ jobs: - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" - name: Build - run: cmake --build ./build --parallel + run: cd build && cmake --build . --parallel - name: Install - run: cmake --install ./build + run: cmake --install . && cd install + - name: deployqt for SlopeCraft + run: macdeployqt SlopeCraft.app + - name: deployqt for MapViewer + run: macdeployqt MapViewer.app + - name: deployqt for imageCutter + run: macdeployqt imageCutter.app - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts From 1447949e6583b13c93d197214686828f824d484f Mon Sep 17 00:00:00 2001 From: Cubik Date: Sat, 8 Apr 2023 00:15:30 -0400 Subject: [PATCH 0015/1123] ci: Fix `cd` --- .github/workflows/build-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 37ff4697..3521dac9 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -21,13 +21,13 @@ jobs: - name: Build run: cd build && cmake --build . --parallel - name: Install - run: cmake --install . && cd install + run: cd build && cmake --install . - name: deployqt for SlopeCraft - run: macdeployqt SlopeCraft.app + run: cd build/install && macdeployqt SlopeCraft.app - name: deployqt for MapViewer - run: macdeployqt MapViewer.app + run: cd build/install && macdeployqt MapViewer.app - name: deployqt for imageCutter - run: macdeployqt imageCutter.app + run: cd build/install && macdeployqt imageCutter.app - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts From 3c49507207355cd83b1c903f4b144d3808fb962f Mon Sep 17 00:00:00 2001 From: Cubik Date: Sat, 8 Apr 2023 00:32:17 -0400 Subject: [PATCH 0016/1123] ci: Group commands --- .github/workflows/build-dev.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3521dac9..5cdfcd58 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -18,16 +18,20 @@ jobs: uses: actions/checkout@v2 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" - - name: Build - run: cd build && cmake --build . --parallel - - name: Install - run: cd build && cmake --install . - - name: deployqt for SlopeCraft - run: cd build/install && macdeployqt SlopeCraft.app - - name: deployqt for MapViewer - run: cd build/install && macdeployqt MapViewer.app - - name: deployqt for imageCutter - run: cd build/install && macdeployqt imageCutter.app + - name: Build and Install + run: | + cd build + cmake --build . --parallel + cmake --install . + cd install + macdeployqt SlopeCraft.app + chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + macdeployqt MapViewer.app + chmod +x MapViewer.app/Contents/MacOS/MapViewer + macdeployqt imageCutter.app + chmod +x imageCutter.app/Contents/MacOS/imageCutter + chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + chmod +x vccl.app/Contents/MacOS/vccl - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts From 7286f5d6201ae583e28af5aec54387f83673ee6d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:03:07 +0800 Subject: [PATCH 0017/1123] add linux action --- .github/workflows/build-dev.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f7e0c436..f318c36b 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -29,3 +29,15 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-macos path: build/install + + linux-build: + runs-on: ubuntu-latest + steps: + - name: List installed + run: apt list --installed > $HOME/installed-packages.txt + - name: Upload package list txt + uses: actions/upload-artifact@v2 + with: + name: ubuntu-installed-packages.txt + path: $HOME/installed-packages.txt + \ No newline at end of file From e029fde8df25366b6c361564d55222a07169fd58 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:11:27 +0800 Subject: [PATCH 0018/1123] fix ubuntu action --- .github/workflows/build-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 8d38aca8..ae501a8a 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,10 +44,10 @@ jobs: runs-on: ubuntu-latest steps: - name: List installed - run: apt list --installed > $HOME/installed-packages.txt + run: apt list --installed > ./installed-packages.txt - name: Upload package list txt - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ubuntu-installed-packages.txt - path: $HOME/installed-packages.txt + path: ./installed-packages.txt \ No newline at end of file From ab025bbc3c82db240059008aa4512e2e56724f81 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:39:17 +0800 Subject: [PATCH 0019/1123] add install and config for linux-build --- .github/workflows/build-dev.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index ae501a8a..0fb4970b 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,10 +44,17 @@ jobs: runs-on: ubuntu-latest steps: - name: List installed - run: apt list --installed > ./installed-packages.txt - - name: Upload package list txt - uses: actions/upload-artifact@v3 - with: - name: ubuntu-installed-packages.txt - path: ./installed-packages.txt + run: apt list --installed + - name: Install cmake, ninja + run: sudo apt install cmake ninja + - name: Install qt6 + run: sudo apt install libqt6widgets6 qt6-base-dev-tools linguist-qt6 + - name: Install cuda tookit (for opencl sdk) + run: sudo apt install nvidia-cuda-toolkit + - name: List installed packages + run: apt list --installed + - name: Checkout repository + uses: actions/checkout@v2 + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=OpenCL -DCMAKE_BUILD_TYPE:STRING=Debug \ No newline at end of file From df1425c4579a497f3f5a4cb06b014b7240bd816b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:41:54 +0800 Subject: [PATCH 0020/1123] Fix ninja installation for linux-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 0fb4970b..18eb6667 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -46,7 +46,7 @@ jobs: - name: List installed run: apt list --installed - name: Install cmake, ninja - run: sudo apt install cmake ninja + run: sudo apt install cmake ninja-build - name: Install qt6 run: sudo apt install libqt6widgets6 qt6-base-dev-tools linguist-qt6 - name: Install cuda tookit (for opencl sdk) From 2ea2d3151741c06fa988ee5d29e19aec011fede8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:50:15 +0800 Subject: [PATCH 0021/1123] disable mac build temporarly --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 18eb6667..bef900c4 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -6,6 +6,8 @@ jobs: macos-build: runs-on: macos-latest steps: + # Disable this action temporarily to save time. I will recover them. + steps_disable_temporarily: - name: Install Ninja build system run: brew install ninja - name: Install dependencies From a65e6a42a7ffe5a163fdf0ed82374e624a98aced Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:51:00 +0800 Subject: [PATCH 0022/1123] add cmake --build for linux-build --- .github/workflows/build-dev.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index bef900c4..73573b9f 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -59,4 +59,5 @@ jobs: uses: actions/checkout@v2 - name: CMake configure run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=OpenCL -DCMAKE_BUILD_TYPE:STRING=Debug - \ No newline at end of file + - name: CMake build + run: cmake --build ./build --parallel \ No newline at end of file From 46495a955ec18a1b2f0c0ac4d652599d52858079 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:52:30 +0800 Subject: [PATCH 0023/1123] hide mac os build temporarily --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 73573b9f..16bfa7fa 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -6,6 +6,8 @@ jobs: macos-build: runs-on: macos-latest steps: + - name: no work to do + run: echo MacOS build is shadowed now. # Disable this action temporarily to save time. I will recover them. steps_disable_temporarily: - name: Install Ninja build system From 2cf24e182d80809c70075bcc679cd0447eb92257 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 13:56:02 +0800 Subject: [PATCH 0024/1123] Restore macos action (failed to shadow it) --- .github/workflows/build-dev.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 16bfa7fa..f102328d 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -6,10 +6,6 @@ jobs: macos-build: runs-on: macos-latest steps: - - name: no work to do - run: echo MacOS build is shadowed now. - # Disable this action temporarily to save time. I will recover them. - steps_disable_temporarily: - name: Install Ninja build system run: brew install ninja - name: Install dependencies From 72dc4226a70983cb8575a86fab19b1ad9befcb67 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 14:11:25 +0800 Subject: [PATCH 0025/1123] fix qt major version to 6 (no longer find Qt5) --- MapViewer/CMakeLists.txt | 4 ++-- SlopeCraftMain/CMakeLists.txt | 9 ++++----- VisualCraft/CMakeLists.txt | 6 +++--- imageCutter/CMakeLists.txt | 4 ++-- vccl/CMakeLists.txt | 4 ++-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index f01401ca..d7c18f51 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_AUTORCC ON) find_package(ZLIB 1.2.11 REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) set(MapViewer_header_files @@ -65,7 +65,7 @@ find_package(OpenMP REQUIRED) target_link_libraries(MapViewer PRIVATE ZLIB::ZLIB - Qt${QT_VERSION_MAJOR}::Widgets + Qt6::Widgets OpenMP::OpenMP_CXX) set_target_properties(MapViewer PROPERTIES diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index 9097e73c..32765265 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -12,8 +12,7 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) set(SlopeCraftMain_windows_rc_file) @@ -103,9 +102,9 @@ target_link_libraries(SlopeCraft PRIVATE BlockListManager SlopeCraftL - Qt${QT_VERSION_MAJOR}::Widgets - Qt${QT_VERSION_MAJOR}::Network - Qt${QT_VERSION_MAJOR}::Concurrent + Qt6::Widgets + Qt6::Network + Qt6::Concurrent VersionDialog ) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index 9175553d..3f41f886 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -90,9 +90,9 @@ target_compile_features(VisualCraft PRIVATE cxx_std_20) target_link_libraries(VisualCraft PRIVATE VisualCraftL - Qt${QT_VERSION_MAJOR}::Widgets - Qt${QT_VERSION_MAJOR}::Network - Qt${QT_VERSION_MAJOR}::Concurrent + Qt6::Widgets + Qt6::Network + Qt6::Concurrent magic_enum::magic_enum OpenMP::OpenMP_CXX VersionDialog diff --git a/imageCutter/CMakeLists.txt b/imageCutter/CMakeLists.txt index ab8c7eab..9901be0f 100644 --- a/imageCutter/CMakeLists.txt +++ b/imageCutter/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) set(imageCutter_header_files CutterWind.h @@ -60,7 +60,7 @@ qt_add_resources(imageCutter "translations" target_link_libraries(imageCutter PRIVATE - Qt${QT_VERSION_MAJOR}::Widgets) + Qt6::Widgets) set_target_properties(imageCutter PROPERTIES VERSION ${PROJECT_VERSION} diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index 4101cd4f..de80b88f 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -18,8 +18,8 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) +#find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) From e82a01518c66c5cfe31f7459a4edd0850687d019 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 14:45:10 +0800 Subject: [PATCH 0026/1123] Fix installation on Qt 6.2.4 --- VisualCraft/VCWind.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index ebada0fe..4fb307d9 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -28,7 +28,7 @@ This file is part of SlopeCraft. #include #include #include - +#include #include "VC_block_class.h" #include "ui_VCWind.h" @@ -90,7 +90,8 @@ void VCWind::callback_progress_range_add(void *__w, int delta) noexcept { // utilitiy functions void VCWind::append_default_to_rp_or_bsl(QListWidget *qlw, bool is_rp) noexcept { - const QString txt = is_rp ? VCWind::tr("原版资源包") : VCWind::tr("原版json"); + const QString txt = + is_rp ? VCWind::tr("原版资源包") : VCWind::tr("原版 json"); QListWidgetItem *qlwi = new QListWidgetItem(txt); qlwi->setData(Qt::UserRole, true); @@ -209,12 +210,21 @@ QByteArray VCWind::checksum_basic_colorset_option( hash.addData(json.toUtf8()); } - hash.addData(QByteArrayView((const char *)&opt.face, sizeof(opt.face))); - hash.addData(QByteArrayView((const char *)&opt.version, sizeof(opt.version))); - hash.addData(QByteArrayView((const char *)&opt.layers, sizeof(opt.layers))); - hash.addData(QByteArrayView((const char *)&opt.biome, sizeof(opt.biome))); - hash.addData(QByteArrayView((const char *)&opt.is_leaves_transparent, - sizeof(opt.is_leaves_transparent))); +#if QT_VERSION > 0x060300 +#define VC_PMACRO_QBAV_CLASS QByteArrayView +#else +#define VC_PMACRO_QBAV_CLASS QByteArray +#endif + + hash.addData(VC_PMACRO_QBAV_CLASS{(const char *)&opt.face, sizeof(opt.face)}); + hash.addData( + VC_PMACRO_QBAV_CLASS{(const char *)&opt.version, sizeof(opt.version)}); + hash.addData( + VC_PMACRO_QBAV_CLASS{(const char *)&opt.layers, sizeof(opt.layers)}); + hash.addData( + VC_PMACRO_QBAV_CLASS{(const char *)&opt.biome, sizeof(opt.biome)}); + hash.addData(VC_PMACRO_QBAV_CLASS{(const char *)&opt.is_leaves_transparent, + sizeof(opt.is_leaves_transparent)}); return hash.result(); } @@ -286,7 +296,7 @@ void VCWind::on_pb_remove_rp_clicked() noexcept { void VCWind::on_pb_add_bsl_clicked() noexcept { static QString prev_dir{""}; QStringList jsons = QFileDialog::getOpenFileNames( - this, VCWind::tr("选择方块id json文件"), prev_dir, "*.json"); + this, VCWind::tr("选择方块 id json 文件"), prev_dir, "*.json"); if (jsons.size() <= 0) { return; } @@ -467,7 +477,7 @@ void VCWind::setup_basical_colorset() noexcept { VCL_block_state_list *bsl = VCWind::create_block_state_list(current_option); if (bsl == nullptr) { QMessageBox::critical( - this, VCWind::tr("方块状态列表json解析失败"), + this, VCWind::tr("方块状态列表 json 解析失败"), VCWind::tr("在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。"), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close}); VCL_destroy_resource_pack(rp); @@ -487,7 +497,7 @@ void VCWind::setup_basical_colorset() noexcept { if (!success) { const auto ret = QMessageBox::critical( - this, VCWind::tr("资源包/方块状态列表json解析失败"), + this, VCWind::tr("资源包/方块状态列表 json 解析失败"), VCWind::tr("部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)" "。尝试移除解析失败的资源包/方块列表,或者减小最大层数。"), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close}); From 1813042d22e70ef4bddab2b12f02414398c0fb0b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 14:48:11 +0800 Subject: [PATCH 0027/1123] fix find_package(Qt for linux-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f102328d..fe5bb878 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -48,7 +48,7 @@ jobs: - name: Install cmake, ninja run: sudo apt install cmake ninja-build - name: Install qt6 - run: sudo apt install libqt6widgets6 qt6-base-dev-tools linguist-qt6 + run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install cuda tookit (for opencl sdk) run: sudo apt install nvidia-cuda-toolkit - name: List installed packages From 6e7133a2930ed234e760129d223ef6d615c5c204 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 14:56:47 +0800 Subject: [PATCH 0028/1123] add libpng libzip and eigen for linux-build --- .github/workflows/build-dev.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index fe5bb878..d1981aa7 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -47,6 +47,8 @@ jobs: run: apt list --installed - name: Install cmake, ninja run: sudo apt install cmake ninja-build + - name: Install libzip, libpng, eigen3 + run: sudo apt install libzip-dev libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install cuda tookit (for opencl sdk) @@ -58,4 +60,6 @@ jobs: - name: CMake configure run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=OpenCL -DCMAKE_BUILD_TYPE:STRING=Debug - name: CMake build - run: cmake --build ./build --parallel \ No newline at end of file + run: cmake --build ./build --parallel + - name: CMake install + run: cmake --install ./build \ No newline at end of file From 61adc8c97dd991caacdc8db472865c99a1e54b21 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:01:58 +0800 Subject: [PATCH 0029/1123] reduce libzip version requirements --- VisualCraftL/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index ea564f11..20eb4676 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -78,7 +78,7 @@ add_library(VisualCraftL_static STATIC find_package(ZLIB 1.2.11 REQUIRED) find_package(PNG 1.4.12 REQUIRED) -find_package(libzip 1.9.2 REQUIRED) +find_package(libzip 1.7.0 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt 9.1.0 REQUIRED) From 1d19cbab88bda3e19bd388ee49af75a737b6f3fd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:12:28 +0800 Subject: [PATCH 0030/1123] Fix find_package(zip for linux-build --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index d1981aa7..4498f421 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -47,8 +47,8 @@ jobs: run: apt list --installed - name: Install cmake, ninja run: sudo apt install cmake ninja-build - - name: Install libzip, libpng, eigen3 - run: sudo apt install libzip-dev libpng-dev libeigen3-dev + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install cuda tookit (for opencl sdk) From 101ea2bfedf9ef2661deee2848aae2324fcec13d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:20:39 +0800 Subject: [PATCH 0031/1123] fix opencl --- .github/workflows/build-dev.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4498f421..c1775f2e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -51,8 +51,9 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - name: Install cuda tookit (for opencl sdk) - run: sudo apt install nvidia-cuda-toolkit + - name: Install nvidia-opencl-dev + run: sudo apt install nvidia-opencl-dev + #run: sudo apt install nvidia-cuda-toolkit - name: List installed packages run: apt list --installed - name: Checkout repository From df7c2a0a05132f81ba4f81ff6a27b9b750c7b01e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:24:05 +0800 Subject: [PATCH 0032/1123] fix opencl --- .github/workflows/build-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index c1775f2e..f8deaa4a 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -51,9 +51,9 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - name: Install nvidia-opencl-dev - run: sudo apt install nvidia-opencl-dev - #run: sudo apt install nvidia-cuda-toolkit + - name: Install OpenCL + run: sudo apt install nvidia-cuda-toolkit opencl-c-headers opencl-clhpp-headers + #run: sudo apt install nvidia-opencl-dev - name: List installed packages run: apt list --installed - name: Checkout repository From 8a827e4c94f27440c59db1491ac1f92c3e714555 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:30:46 +0800 Subject: [PATCH 0033/1123] fix opencl --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f8deaa4a..12409c8e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -52,7 +52,7 @@ jobs: - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit opencl-c-headers opencl-clhpp-headers + run: sudo apt install nvidia-cuda-toolkit cuda-repo-ubuntu2204-11-8-local ocl-icd-libopencl1 #run: sudo apt install nvidia-opencl-dev - name: List installed packages run: apt list --installed From 999ba1991d7d1437541c5752e74916be7ea2dd71 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:35:08 +0800 Subject: [PATCH 0034/1123] fix opencl --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 12409c8e..618bc762 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -52,7 +52,7 @@ jobs: - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit cuda-repo-ubuntu2204-11-8-local ocl-icd-libopencl1 + run: sudo apt install nvidia-cuda-toolkit ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers #run: sudo apt install nvidia-opencl-dev - name: List installed packages run: apt list --installed From df6bf1048a205211e66506b6d1efae0e38cc8813 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:46:37 +0800 Subject: [PATCH 0035/1123] fix opencl --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 618bc762..d1ead56c 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -52,7 +52,7 @@ jobs: - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + run: sudo apt install nvidia-cuda-toolkit nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers #run: sudo apt install nvidia-opencl-dev - name: List installed packages run: apt list --installed From f628b7628fe796283a3658c51fb3802f1b42fb8f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 15:55:03 +0800 Subject: [PATCH 0036/1123] add upload for linux build, and skip opencl --- .github/workflows/build-dev.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index d1ead56c..1a43b2d2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -40,7 +40,7 @@ jobs: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-macos path: build/install - linux-build: + linux-build-none: runs-on: ubuntu-latest steps: - name: List installed @@ -51,16 +51,20 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - #run: sudo apt install nvidia-opencl-dev - - name: List installed packages - run: apt list --installed + #- name: Install OpenCL + # run: sudo apt install nvidia-cuda-toolkit nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: Checkout repository uses: actions/checkout@v2 - - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=OpenCL -DCMAKE_BUILD_TYPE:STRING=Debug - - name: CMake build + - name: CMake configure - debug + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + - name: CMake build - debug run: cmake --build ./build --parallel - - name: CMake install - run: cmake --install ./build \ No newline at end of file + - name: CMake install - debug + run: cmake --install ./build + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload artifacts - debug + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-debug + path: build/install \ No newline at end of file From 1038923dd101a87d21366a31e8e4f8845e3c2c5b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:00:34 +0800 Subject: [PATCH 0037/1123] add qt6 widgets, gui, network and concurrent for linux-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 1a43b2d2..0369cfea 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -50,7 +50,7 @@ jobs: - name: Install libzip, libpng, Eigen3 run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 - run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: Checkout repository From ddfaa1934e46362097ce9fdad55e16b16fcf62de Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:10:34 +0800 Subject: [PATCH 0038/1123] try to fix find_package(qt6 --- .github/workflows/build-dev.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 0369cfea..3e8f0bd9 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -52,7 +52,10 @@ jobs: - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 #- name: Install OpenCL - # run: sudo apt install nvidia-cuda-toolkit nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + # run: sudo apt install nvidia-cuda-toolkit + #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + - name: List qt-related packages + run: apt list --installed | grep qt - name: Checkout repository uses: actions/checkout@v2 - name: CMake configure - debug From a0996a8bb2d17870187f3165008296b41fca8f20 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:12:59 +0800 Subject: [PATCH 0039/1123] try to fix find_package(qt6 for linux-build --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3e8f0bd9..ca041683 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -51,8 +51,8 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 - #- name: Install OpenCL - # run: sudo apt install nvidia-cuda-toolkit + - name: Install OpenCL + run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: List qt-related packages run: apt list --installed | grep qt From e8d2b4139b36d53a92267e7545ae521df806c3a2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:30:59 +0800 Subject: [PATCH 0040/1123] add tar.xz compress to linux-build --- .github/workflows/build-dev.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index ca041683..b7e57017 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -66,8 +66,13 @@ jobs: run: cmake --install ./build - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Compress + run: | + cd build/install + tar -cf compress.tar ./* + xz -9 ./compress.tar - name: Upload artifacts - debug - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-debug - path: build/install \ No newline at end of file + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-debug.tar.xz + path: build/install/compress.tar.xz \ No newline at end of file From 2b71244da5364ecc74ed93dae2d0cc5ce349eb16 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:50:04 +0800 Subject: [PATCH 0041/1123] skip opencl installation for linux-build --- .github/workflows/build-dev.yml | 29 ++++++++++++++++------------- CMakeLists.txt | 13 ++++++------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b7e57017..b18370d8 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -43,6 +43,8 @@ jobs: linux-build-none: runs-on: ubuntu-latest steps: + - name: Make directories + run: mkdir build install upload - name: List installed run: apt list --installed - name: Install cmake, ninja @@ -51,28 +53,29 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 - - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit + - name: Install additional qt packages # I don't know why they are required + run: sudo apt isntall libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n + #- name: Install OpenCL + # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: List qt-related packages run: apt list --installed | grep qt - name: Checkout repository uses: actions/checkout@v2 - - name: CMake configure - debug - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./build/install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug - - name: CMake build - debug + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + - name: CMake build run: cmake --build ./build --parallel - - name: CMake install - debug + - name: CMake install run: cmake --install ./build - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Compress + - name: Compress as tar.xz run: | - cd build/install - tar -cf compress.tar ./* - xz -9 ./compress.tar - - name: Upload artifacts - debug + tar -cf ./upload/compress.tar ./install/* + xz -9 ./upload/compress.tar + - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-debug.tar.xz - path: build/install/compress.tar.xz \ No newline at end of file + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + path: ./upload/compress.tar.xz \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c4226ee9..861f23f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,12 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) +if(NOT DEFINED CMAKE_INSTALL_PREFIX) +# manage the install prefix +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install + CACHE PATH "Where to install SlopeCraft.") +endif() + if(${MSVC}) add_compile_options("/Zc:__cplusplus") add_compile_options("/wd4819") @@ -35,12 +41,7 @@ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") Please use gcc.") endif() -# manage the install prefix -set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install - CACHE PATH "Where to install SlopeCraft.") -# set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}) -# set(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_PREFIX}) if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) # delete files here file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) @@ -133,8 +134,6 @@ if(EXISTS ${CMAKE_BINARY_DIR}/utilities/ColorManip/__rsc_ColorManip_cl_rc.c) endif() endif() -set(CMAKE_INCLUDE_CURRENT_DIR ON) - set(SlopeCraft_readme_and_license_files LICENSE From 22daaa338808f5fd4842b327cd8b257ec1ee425a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 16:52:05 +0800 Subject: [PATCH 0042/1123] fix spelling mistake --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b18370d8..34aed618 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -54,7 +54,7 @@ jobs: - name: Install qt6 run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 - name: Install additional qt packages # I don't know why they are required - run: sudo apt isntall libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n + run: sudo apt install libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers From f60c76e06cd105f07bb7c4ca30799570ac3b6ec8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 17:10:18 +0800 Subject: [PATCH 0043/1123] try to fix find_package(Qt6 for linux-build --- .github/workflows/build-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 34aed618..b85d590b 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -52,9 +52,9 @@ jobs: - name: Install libzip, libpng, Eigen3 run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 - run: sudo apt install qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 - - name: Install additional qt packages # I don't know why they are required - run: sudo apt install libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + #- name: Install additional qt packages # I don't understand why they are required + # run: sudo apt install libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers From f643489ecd90bb4108ceba4f731fcad1e7417be9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 17:11:48 +0800 Subject: [PATCH 0044/1123] try to fix find_package(Qt6 for linux-build --- .github/workflows/build-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b85d590b..6dc89c94 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -55,11 +55,11 @@ jobs: run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools #- name: Install additional qt packages # I don't understand why they are required # run: sudo apt install libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n - #- name: Install OpenCL - # run: sudo apt install nvidia-cuda-toolkit + - name: Install OpenCL + run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - - name: List qt-related packages - run: apt list --installed | grep qt + - name: List all packages + run: apt list --installed - name: Checkout repository uses: actions/checkout@v2 - name: CMake configure From eaf8f36914d02281cd6bfe62eaf048a2c6789bc3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 17:34:31 +0800 Subject: [PATCH 0045/1123] try to fix find_package(Qt6 for linux-build --- .github/workflows/build-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 6dc89c94..b513621d 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -53,10 +53,10 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - #- name: Install additional qt packages # I don't understand why they are required - # run: sudo apt install libqt5core5a libqt5dbus5 libqt5network5 qttranslations5-l10n - - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit + - name: Install additional qt packages # I don't understand why they are required + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + #- name: Install OpenCL + # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: List all packages run: apt list --installed From c2d2b7b127be0133695be88417fe9be9bf267ad4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 17:48:54 +0800 Subject: [PATCH 0046/1123] fix compress for linux-build --- .github/workflows/build-dev.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b513621d..0c837ded 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Make directories - run: mkdir build install upload + run: mkdir build install - name: List installed run: apt list --installed - name: Install cmake, ninja @@ -53,8 +53,9 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - name: Install additional qt packages # I don't understand why they are required + - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers @@ -72,10 +73,12 @@ jobs: run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Compress as tar.xz run: | - tar -cf ./upload/compress.tar ./install/* - xz -9 ./upload/compress.tar + cd ./install + tar -cf compress.tar ./install/* + xz -9 ./compress.tar + cd .. - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz - path: ./upload/compress.tar.xz \ No newline at end of file + path: ./install/compress.tar.xz \ No newline at end of file From bf8dcdabe41e89980676ccfffa0bd60b6bf64d9d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:03:44 +0800 Subject: [PATCH 0047/1123] try to fix linux install --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 0c837ded..f1768265 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -69,6 +69,8 @@ jobs: run: cmake --build ./build --parallel - name: CMake install run: cmake --install ./build + - name: List all files: + run: ls -R - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Compress as tar.xz From b0cb0658bcb035e3889d5e20417ab12e08dec03f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:04:22 +0800 Subject: [PATCH 0048/1123] fix build script --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f1768265..71b6a3c7 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -69,7 +69,7 @@ jobs: run: cmake --build ./build --parallel - name: CMake install run: cmake --install ./build - - name: List all files: + - name: List all files run: ls -R - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV From ef120c4e360e283bb53020e4d944e3db0752dd1f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:17:32 +0800 Subject: [PATCH 0049/1123] try to find linux-build installation --- .github/workflows/build-dev.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 71b6a3c7..44e102d0 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -45,6 +45,11 @@ jobs: steps: - name: Make directories run: mkdir build install + - name: Make variables + run: | + export CWD=$(pwd) + export BUILD_DIR=$CWD/build + export INSTALL_DIR=#CWD/install - name: List installed run: apt list --installed - name: Install cmake, ninja @@ -64,23 +69,22 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + run: cmake -S . -B $BUILD_DIR -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug - name: CMake build - run: cmake --build ./build --parallel + run: cmake --build $BUILD_DIR --parallel - name: CMake install - run: cmake --install ./build + run: cmake --install $BUILD_DIR - name: List all files run: ls -R - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Compress as tar.xz run: | - cd ./install - tar -cf compress.tar ./install/* + cd $INSTALL_DIR + tar -cf compress.tar ./* xz -9 ./compress.tar - cd .. - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz - path: ./install/compress.tar.xz \ No newline at end of file + path: $INSTALL_DIR/compress.tar.xz \ No newline at end of file From 67c318c6d08fc4d21f153cdc418700361317df04 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:21:43 +0800 Subject: [PATCH 0050/1123] try to find linux-build installation --- .github/workflows/build-dev.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 44e102d0..00309415 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -48,8 +48,9 @@ jobs: - name: Make variables run: | export CWD=$(pwd) - export BUILD_DIR=$CWD/build export INSTALL_DIR=#CWD/install + echo $CWD + echo $INSTALL_DIR - name: List installed run: apt list --installed - name: Install cmake, ninja @@ -69,13 +70,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: CMake configure - run: cmake -S . -B $BUILD_DIR -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug - name: CMake build - run: cmake --build $BUILD_DIR --parallel + run: cmake --build ./build --parallel - name: CMake install - run: cmake --install $BUILD_DIR - - name: List all files - run: ls -R + run: cmake --install ./build + #- name: List all files + # run: ls -R - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Compress as tar.xz From 2a9b4b9d51e86dcf6be8af1c5631f95ff297b965 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:25:11 +0800 Subject: [PATCH 0051/1123] try to find linux-build installation --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 00309415..198bfa01 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -48,7 +48,7 @@ jobs: - name: Make variables run: | export CWD=$(pwd) - export INSTALL_DIR=#CWD/install + export INSTALL_DIR=$CWD/install echo $CWD echo $INSTALL_DIR - name: List installed From 4785e73f9bf49bf11c5f280548a298de967c5f4f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 18:35:22 +0800 Subject: [PATCH 0052/1123] convert CMAKE_INSTALL_PREFIX to absolute path --- .github/workflows/build-dev.yml | 2 +- CMakeLists.txt | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 198bfa01..d7e38d6f 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -70,7 +70,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug - name: CMake build run: cmake --build ./build --parallel - name: CMake install diff --git a/CMakeLists.txt b/CMakeLists.txt index 861f23f2..332734b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,12 +17,15 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) -if(NOT DEFINED CMAKE_INSTALL_PREFIX) # manage the install prefix -set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install - CACHE PATH "Where to install SlopeCraft.") +if(NOT DEFINED CMAKE_INSTALL_PREFIX) +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) endif() +# convert relative path to absolute +cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX OUTPUT_VARIABLE CMAKE_INSTALL_PREFIX) +message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") + if(${MSVC}) add_compile_options("/Zc:__cplusplus") add_compile_options("/wd4819") From 4763802d172c0c2bd9317eca6b722b38e6bae326 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 19:17:52 +0800 Subject: [PATCH 0053/1123] try to find linux-build installation --- .github/workflows/build-dev.yml | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index d7e38d6f..4d2ebfa3 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -45,47 +45,53 @@ jobs: steps: - name: Make directories run: mkdir build install - - name: Make variables - run: | - export CWD=$(pwd) - export INSTALL_DIR=$CWD/install - echo $CWD - echo $INSTALL_DIR - - name: List installed - run: apt list --installed + + #- name: List installed + # run: apt list --installed + - name: Install cmake, ninja run: sudo apt install cmake ninja-build + - name: Install libzip, libpng, Eigen3 run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - - name: List all packages - run: apt list --installed + #- name: List all packages + # run: apt list --installed + - name: Checkout repository uses: actions/checkout@v2 + - name: CMake configure run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + - name: CMake build run: cmake --build ./build --parallel + - name: CMake install run: cmake --install ./build #- name: List all files # run: ls -R - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Compress as tar.xz run: | - cd $INSTALL_DIR + cd install tar -cf compress.tar ./* xz -9 ./compress.tar + cd .. + - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz - path: $INSTALL_DIR/compress.tar.xz \ No newline at end of file + path: install/compress.tar.xz \ No newline at end of file From a8c30f81aae9f92e8b304865f007ebf6b416dafb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 19:18:50 +0800 Subject: [PATCH 0054/1123] try to find linux-build installation --- .github/workflows/build-dev.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4d2ebfa3..2656813d 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -83,15 +83,14 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Compress as tar.xz + - name: Compress as tar run: | cd install tar -cf compress.tar ./* - xz -9 ./compress.tar cd .. - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz - path: install/compress.tar.xz \ No newline at end of file + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar + path: install/compress.tar \ No newline at end of file From 3eeb2ca8ac3eff2ffa2e2786c4ec3ec6bdf4e2e1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 19:37:02 +0800 Subject: [PATCH 0055/1123] fix linux installation --- .github/workflows/build-dev.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 2656813d..48970e3e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -67,6 +67,9 @@ jobs: #- name: List all packages # run: apt list --installed + - name: Install xz (Release as tar.xz) + run: sudo apt install xz-utils + - name: Checkout repository uses: actions/checkout@v2 @@ -76,7 +79,7 @@ jobs: - name: CMake build run: cmake --build ./build --parallel - - name: CMake install + - name: CMake install # Uptil now, we have not get a prefect way to deploy qt shared libs. This may be finished in cmake script run: cmake --install ./build #- name: List all files # run: ls -R @@ -87,10 +90,11 @@ jobs: run: | cd install tar -cf compress.tar ./* + xz -9 ./compress.tar cd .. - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar - path: install/compress.tar \ No newline at end of file + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + path: install/compress.tar.xz \ No newline at end of file From 606c5bcee4e5787604a68480359796749f7df7b8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 20:17:53 +0800 Subject: [PATCH 0056/1123] small changes to linux-build --- .github/workflows/build-dev.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 48970e3e..bd2570fa 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -40,7 +40,7 @@ jobs: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-macos path: build/install - linux-build-none: + linux-build: runs-on: ubuntu-latest steps: - name: Make directories @@ -86,15 +86,17 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Compress as tar + - name: Compress run: | cd install tar -cf compress.tar ./* xz -9 ./compress.tar + mv ./compress.tar.xz SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz cd .. - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz - path: install/compress.tar.xz \ No newline at end of file + #name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + path: install/SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + if-no-files-found: error \ No newline at end of file From a1d7fafd690d3183149ed34986e656ed5fc798db Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 20:23:31 +0800 Subject: [PATCH 0057/1123] remove fixed override list in vcl --- VisualCraftL/CMakeLists.txt | 4 +- VisualCraftL/ParseResourcePack.h | 3 - VisualCraftL/ResourcePack.cpp | 152 +++++++-------------- VisualCraftL/textures_need_to_override.cpp | 60 -------- VisualCraftL/textures_need_to_override.h | 60 -------- 5 files changed, 50 insertions(+), 229 deletions(-) delete mode 100644 VisualCraftL/textures_need_to_override.cpp delete mode 100644 VisualCraftL/textures_need_to_override.h diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 58426f5e..5069fecb 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -42,8 +42,8 @@ set(VCL_source_files VisualCraftL.h VisualCraftL.cpp - textures_need_to_override.h - textures_need_to_override.cpp + #textures_need_to_override.h + #textures_need_to_override.cpp TokiVC.h TokiVC.cpp diff --git a/VisualCraftL/ParseResourcePack.h b/VisualCraftL/ParseResourcePack.h index 218c4192..fefe97df 100644 --- a/VisualCraftL/ParseResourcePack.h +++ b/VisualCraftL/ParseResourcePack.h @@ -623,9 +623,6 @@ class VCL_resource_pack { const Eigen::Array *find_texture(std::string_view path, bool override_only) const noexcept; - [[deprecated]] bool override_textures( - VCL_biome_t biome, bool replace_transparent_with_black) noexcept; - bool override_required_textures(VCL_biome_t biome, bool replace_transparent_with_black, const VCL_block *const *const blkpp, diff --git a/VisualCraftL/ResourcePack.cpp b/VisualCraftL/ResourcePack.cpp index ab67bae1..f34071a4 100644 --- a/VisualCraftL/ResourcePack.cpp +++ b/VisualCraftL/ResourcePack.cpp @@ -26,7 +26,6 @@ This file is part of SlopeCraft. #include bool VCL_resource_pack::copy(const VCL_resource_pack &src) noexcept { - this->textures_original = src.textures_original; this->textures_override = src.textures_override; this->block_states = src.block_states; @@ -67,7 +66,6 @@ bool VCL_resource_pack::filter_model_textures( const std::unordered_map &filter, bool is_missing_error) noexcept { - for (auto &pair : this->block_models) { for (auto &ele : pair.second.elements) { for (auto &face : ele.faces) { @@ -76,10 +74,10 @@ bool VCL_resource_pack::filter_model_textures( face.texture = it->second; } else { if (is_missing_error) { - std::string msg = - fmt::format("Failed to filter image pointer {}. Missing in the " - "filter and is_missing_error is set to true.", - (const void *)face.texture); + std::string msg = fmt::format( + "Failed to filter image pointer {}. Missing in the " + "filter and is_missing_error is set to true.", + (const void *)face.texture); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -140,8 +138,7 @@ bool process_block_state_list_in_id( cur_statement_beg = cur + 1; } - if (cur >= end) - break; + if (cur >= end) break; } return true; @@ -151,12 +148,9 @@ bool resource_json::process_full_id(std::string_view full_id, std::string *namespace_name, std::string *pure_id, state_list *states) noexcept { - if (namespace_name != nullptr) - *namespace_name = ""; - if (pure_id != nullptr) - pure_id->clear(); - if (states != nullptr) - states->clear(); + if (namespace_name != nullptr) *namespace_name = ""; + if (pure_id != nullptr) pure_id->clear(); + if (states != nullptr) states->clear(); if (full_id.find_first_of(':') != full_id.find_last_of(':')) { return false; @@ -177,11 +171,9 @@ bool resource_json::process_full_id(std::string_view full_id, const bool have_left_bracket = (idx_left_bracket != full_id.npos); const bool have_right_bracket = (idx_right_bracket != full_id.npos); - if (have_left_bracket != have_right_bracket) - return false; + if (have_left_bracket != have_right_bracket) return false; - if (idx_colon != full_id.npos && idx_colon > idx_left_bracket) - return false; + if (idx_colon != full_id.npos && idx_colon > idx_left_bracket) return false; if (have_left_bracket && (idx_left_bracket >= idx_right_bracket)) { return false; @@ -219,13 +211,12 @@ bool resource_json::process_full_id(std::string_view full_id, std::variant VCL_resource_pack::find_model(const std::string &block_state_str, buffer_t &buffer) const noexcept { - if (!resource_json::process_full_id(block_state_str, nullptr, &buffer.pure_id, &buffer.state_list)) { - std::string msg = - fmt::format("invalid full block id that can not be parsed to a list " - "of block states : \"{}\"", - block_state_str.c_str()); + std::string msg = fmt::format( + "invalid full block id that can not be parsed to a list " + "of block states : \"{}\"", + block_state_str.c_str()); VCL_report(VCL_report_type_t::error, msg.c_str()); return model_with_rotation{nullptr}; @@ -254,10 +245,10 @@ VCL_resource_pack::find_model(const std::string &block_state_str, if (buffer.pure_id == "air") { return block_model::model{}; } - std::string msg = - fmt::format("Undefined reference to block state whose pure block id " - "is : \"{}\" and full block id is : \"{}\"\n", - buffer.pure_id, block_state_str); + std::string msg = fmt::format( + "Undefined reference to block state whose pure block id " + "is : \"{}\" and full block id is : \"{}\"\n", + buffer.pure_id, block_state_str); VCL_report(VCL_report_type_t::error, msg.c_str()); return model_with_rotation{nullptr}; } @@ -270,10 +261,10 @@ VCL_resource_pack::find_model(const std::string &block_state_str, // face_exposed = block_model::invrotate(face_exposed, model.x, model.y); if (model.model_name == nullptr) { - std::string msg = - fmt::format("No block model for full id : \"{}\", this is usually " - "because block states mismatch.", - block_state_str); + std::string msg = fmt::format( + "No block model for full id : \"{}\", this is usually " + "because block states mismatch.", + block_state_str); VCL_report(VCL_report_type_t::error, msg.c_str()); return model_with_rotation{nullptr}; } @@ -309,7 +300,6 @@ VCL_resource_pack::find_model(const std::string &block_state_str, const auto models = multipart.block_model_names(buffer.state_list); for (const auto &md : models) { - if constexpr (false) { std::string msg = fmt::format("x_rot = {}, y_rot = {}", int(md.x), int(md.y)); @@ -371,17 +361,16 @@ VCL_resource_pack::find_model(const std::string &block_state_str, bool VCL_resource_pack::compute_projection( const std::string &block_state_str, VCL_face_t face_exposed, block_model::EImgRowMajor_t *const img, buffer_t &buffer) const noexcept { - std::variant ret = this->find_model(block_state_str, buffer); if (ret.index() == 0) { auto model = std::get<0>(ret); if (model.model_ptr == nullptr) { - std::string msg = - fmt::format("failed to find a block model for full id :\"{}\", " - "function find_model returned nullptr\n", - block_state_str.c_str()); + std::string msg = fmt::format( + "failed to find a block model for full id :\"{}\", " + "function find_model returned nullptr\n", + block_state_str.c_str()); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -417,12 +406,12 @@ bool VCL_resource_pack::override_texture( const auto &img_original = it->second; if (img_original.rows() != 16 || img_original.cols() != 16) { - std::string msg = - fmt::format("Failed to override texture \"{0}\" with given " - "color {1:#x}, the image size of " - "original texture \"{0}\" is {2} * {3} instead of 16 * 16", - path_in_original, standard_color, img_original.rows(), - img_original.cols()); + std::string msg = fmt::format( + "Failed to override texture \"{0}\" with given " + "color {1:#x}, the image size of " + "original texture \"{0}\" is {2} * {3} instead of 16 * 16", + path_in_original, standard_color, img_original.rows(), + img_original.cols()); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -475,8 +464,8 @@ bool VCL_resource_pack::override_texture( return true; } -std::array -VCL_resource_pack::locate_color_rc(VCL_biome_info info) const noexcept { +std::array VCL_resource_pack::locate_color_rc( + VCL_biome_info info) const noexcept { assert(info.downfall == info.downfall); assert(info.temperature == info.temperature); const float t_adj = std::clamp(info.temperature, 0.0f, 1.0f); @@ -496,7 +485,6 @@ VCL_resource_pack::locate_color_rc(VCL_biome_info info) const noexcept { uint32_t VCL_resource_pack::standard_color(VCL_biome_info info, bool is_foliage) const noexcept { - const auto rc = this->locate_color_rc(info); const int r = rc[0]; @@ -561,48 +549,6 @@ uint32_t VCL_resource_pack::standard_color( return default_result; } -#include "textures_need_to_override.h" - -bool VCL_resource_pack::override_textures( - VCL_biome_t biome, bool replace_transparent_with_black) noexcept { - const std::string_view *grass_ids = nullptr; - size_t grass_num = 0; - const std::string_view *foliage_ids = nullptr; - size_t foliage_num = 0; - if (this->is_MC12) { - grass_ids = VCL_12_grass_texture_names; - grass_num = VCL_12_grass_texture_name_size; - foliage_ids = VCL_12_foliage_texture_names; - foliage_num = VCL_12_foliage_texture_name_size; - } else { - grass_ids = VCL_latest_grass_texture_names; - grass_num = VCL_latest_grass_texture_name_size; - foliage_ids = VCL_latest_foliage_texture_names; - foliage_num = VCL_latest_foliage_texture_name_size; - } - - for (size_t gid = 0; gid < grass_num; gid++) { - const bool ok = this->override_texture( - grass_ids[gid], this->standard_color(biome, grass_ids[gid]), - replace_transparent_with_black); - if (!ok) { - return false; - } - } - - for (size_t fid = 0; fid < foliage_num; fid++) { - - const bool ok = this->override_texture( - foliage_ids[fid], this->standard_color(biome, foliage_ids[fid]), - replace_transparent_with_black); - if (!ok) { - return false; - } - } - - return this->update_block_model_textures(); -} - bool VCL_resource_pack::update_block_model_textures() noexcept { std::unordered_map @@ -612,12 +558,12 @@ bool VCL_resource_pack::update_block_model_textures() noexcept { for (auto &pair : this->textures_override) { auto it = this->textures_original.find(pair.first); if (it == this->textures_original.end()) { - std::string msg = - fmt::format("Internal logical error when invoking function " - "\"VCL_resource_pack::update_block_model_textures\" : " - "texture \"{}\" is overrided, but failed to find the " - "image with same id in this->texture_original.", - pair.first); + std::string msg = fmt::format( + "Internal logical error when invoking function " + "\"VCL_resource_pack::update_block_model_textures\" : " + "texture \"{}\" is overrided, but failed to find the " + "image with same id in this->texture_original.", + pair.first); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -655,10 +601,10 @@ bool VCL_resource_pack::override_required_textures( } if (is_grass == is_foliage) { - - std::string msg = fmt::format("Failed to override texture for block {} " - "because it is both grass and foliage.", - blk.full_id_ptr()->c_str()); + std::string msg = fmt::format( + "Failed to override texture for block {} " + "because it is both grass and foliage.", + blk.full_id_ptr()->c_str()); return false; } @@ -682,7 +628,6 @@ bool VCL_resource_pack::override_required_textures( for (const auto &element : md->elements) { for (size_t idx = 0; idx < 6; idx++) { - const auto &face = element.faces[idx]; if (is_grass && (idx != (size_t)VCL_face_t::face_up)) { @@ -702,7 +647,6 @@ bool VCL_resource_pack::override_required_textures( } for (auto &pair : textures_used) { - for (const auto &j : this->textures_original) { if (&j.second == pair.first) { pair.second.name = j.first.c_str(); @@ -710,10 +654,10 @@ bool VCL_resource_pack::override_required_textures( } if (pair.second.name == nullptr) { - std::string msg = - fmt::format("Failed to override texture at address {}, because this " - "image cannot be found in this->textures_original.", - (const void *)(pair.first)); + std::string msg = fmt::format( + "Failed to override texture at address {}, because this " + "image cannot be found in this->textures_original.", + (const void *)(pair.first)); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } diff --git a/VisualCraftL/textures_need_to_override.cpp b/VisualCraftL/textures_need_to_override.cpp deleted file mode 100644 index 8a11fb2e..00000000 --- a/VisualCraftL/textures_need_to_override.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "textures_need_to_override.h" - -const std::string_view VCL_12_grass_texture_names[] = { - "minecraft:blocks/double_plant_grass_bottom", - "minecraft:blocks/double_plant_grass_top", - "minecraft:blocks/grass_side_overlay", "minecraft:blocks/grass_top"}; - -const size_t VCL_12_grass_texture_name_size = - sizeof(VCL_12_grass_texture_names) / sizeof(std::string_view); - -const std::string_view VCL_12_foliage_texture_names[] = { - "minecraft:blocks/leaves_acacia", "minecraft:blocks/leaves_big_oak", - "minecraft:blocks/leaves_birch", "minecraft:blocks/leaves_jungle", - "minecraft:blocks/leaves_oak", "minecraft:blocks/leaves_spruce", - "minecraft:blocks/vine"}; - -const size_t VCL_12_foliage_texture_name_size = - sizeof(VCL_12_foliage_texture_names) / sizeof(std::string_view); - -const std::string_view VCL_latest_grass_texture_names[] = { - "minecraft:block/grass_block_top", - "minecraft:block/grass_block_side", - "minecraft:block/grass_block_side_overlay", - "minecraft:block/grass", - "minecraft:block/tall_grass_bottom", - "minecraft:block/tall_grass_top"}; - -const size_t VCL_latest_grass_texture_name_size = - sizeof(VCL_latest_grass_texture_names) / sizeof(std::string_view); - -const std::string_view VCL_latest_foliage_texture_names[] = { - "minecraft:block/acacia_leaves", "minecraft:block/birch_leaves", - "minecraft:block/dark_oak_leaves", "minecraft:block/jungle_leaves", - "minecraft:block/mangrove_leaves", "minecraft:block/oak_leaves", - "minecraft:block/spruce_leaves", "minecraft:block/vine"}; - -const size_t VCL_latest_foliage_texture_name_size = - sizeof(VCL_latest_foliage_texture_names) / sizeof(std::string_view); \ No newline at end of file diff --git a/VisualCraftL/textures_need_to_override.h b/VisualCraftL/textures_need_to_override.h deleted file mode 100644 index 4ec7ff35..00000000 --- a/VisualCraftL/textures_need_to_override.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef SLOPECRAFT_VISUALCRAFTL_TEXTURES_NEED_TO_OVERRIDE_H -#define SLOPECRAFT_VISUALCRAFTL_TEXTURES_NEED_TO_OVERRIDE_H - -#include - -extern const std::string_view VCL_12_grass_texture_names[]; -extern const size_t VCL_12_grass_texture_name_size; -extern const std::string_view VCL_12_foliage_texture_names[]; -extern const size_t VCL_12_foliage_texture_name_size; - -extern const std::string_view VCL_latest_grass_texture_names[]; -extern const size_t VCL_latest_grass_texture_name_size; -extern const std::string_view VCL_latest_foliage_texture_names[]; -extern const size_t VCL_latest_foliage_texture_name_size; - -struct VCL_texture_names_to_override { - VCL_texture_names_to_override() = delete; - VCL_texture_names_to_override(bool is_MC12) { - if (is_MC12) { - this->grass = VCL_12_grass_texture_names; - this->num_grass = VCL_12_grass_texture_name_size; - this->foliage = VCL_12_foliage_texture_names; - this->num_foliage = VCL_12_foliage_texture_name_size; - } else { - - this->grass = VCL_latest_grass_texture_names; - this->num_grass = VCL_latest_grass_texture_name_size; - this->foliage = VCL_latest_foliage_texture_names; - this->num_foliage = VCL_latest_foliage_texture_name_size; - } - } - const std::string_view *grass; - size_t num_grass; - const std::string_view *foliage; - size_t num_foliage; -}; - -#endif // SLOPECRAFT_VISUALCRAFTL_TEXTURES_NEED_TO_OVERRIDE_H \ No newline at end of file From da1151a8f9924d3d88ac1738c250183903b864fb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 8 Apr 2023 20:37:03 +0800 Subject: [PATCH 0058/1123] restore artifact name for linux-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index bd2570fa..4495526c 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -97,6 +97,6 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v3 with: - #name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux path: install/SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz if-no-files-found: error \ No newline at end of file From 0932ebb3427f1639a64aa2df3314fe556d1f4d04 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 9 Apr 2023 02:00:48 +0800 Subject: [PATCH 0059/1123] Add cpack for deb and tar.xz packs --- CMakeLists.txt | 11 ++--------- cpack/deb.cmake | 25 +++++++++++++++++++++++++ cpack/make-packs.cmake | 16 ++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 cpack/deb.cmake create mode 100644 cpack/make-packs.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 332734b1..272166b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,13 +137,6 @@ if(EXISTS ${CMAKE_BINARY_DIR}/utilities/ColorManip/__rsc_ColorManip_cl_rc.c) endif() endif() -set(SlopeCraft_readme_and_license_files +include(cmake/install.cmake) - LICENSE - README.md - README-en.md - license-translations/LICENSE-zh.md -) - -install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}) +include(cpack/make-packs.cmake) \ No newline at end of file diff --git a/cpack/deb.cmake b/cpack/deb.cmake new file mode 100644 index 00000000..a9f60f25 --- /dev/null +++ b/cpack/deb.cmake @@ -0,0 +1,25 @@ +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "SlopeCraft group") +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE x86_64) + +set(SlopeCraft_debian_opencl_deps) +if(${SlopeCraft_GPU_API}) + set(SlopeCraft_debian_opencl_deps + ocl-icd-libopencl1 + ) +endif() + +set(CPACK_DEBIAN_PACKAGE_DEPENDS + libzip4 + libpng16-16 + libqt6core6 + libqt6gui6 + libqt6widgets6 + libqt6network6 + libqt6concurrent6 + libopengl0 + libglx0 + ${SlopeCraft_debian_opencl_deps} + ) + +set(CPACK_DEBIAN_PACKAGE_DESCRIPTION + "Get your Minecraft pixel painting in multiple kinds of forms") \ No newline at end of file diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake new file mode 100644 index 00000000..07647214 --- /dev/null +++ b/cpack/make-packs.cmake @@ -0,0 +1,16 @@ +# Common attributes +set(CPACK_PACKAGE_NAME SlopeCraft) +set(CPACK_PACKAGE_VERSION ${SlopeCraft_version}) +set(CPACK_PACKAGE_VENDOR "SlopeCraft group") +set(CPACK_PACKAGE_CONTACT https://github.com/SlopeCraft) +set(CPACK_PACKAGE_HOMEPAGE_URL https://github.com/SlopeCraft) + +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) +endif() + + + +include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) + +include(CPack) \ No newline at end of file From b5424a8da352990208c28733d3a9ada07738140f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 9 Apr 2023 02:01:06 +0800 Subject: [PATCH 0060/1123] install plugins for linux --- MapViewer/install.cmake | 3 +++ SlopeCraftMain/install.cmake | 3 +++ VisualCraft/install.cmake | 4 ++++ cmake/deploy_qt.cmake.in | 4 ++++ cmake/find_qt6.cmake | 17 +++++++++++++++-- cmake/install.cmake | 29 +++++++++++++++++++++++++++++ cmake/install_plugins.cmake | 9 +++++++++ imageCutter/install.cmake | 2 ++ vccl/install.cmake | 4 ++++ 9 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 cmake/install.cmake create mode 100644 cmake/install_plugins.cmake diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 940e0b87..e9375c96 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -25,6 +25,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") RUNTIME DESTINATION bin BUNDLE DESTINATION lib ) + + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() endif() diff --git a/SlopeCraftMain/install.cmake b/SlopeCraftMain/install.cmake index 98b152c5..5522a74e 100644 --- a/SlopeCraftMain/install.cmake +++ b/SlopeCraftMain/install.cmake @@ -134,6 +134,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) + return() endif() diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index b11eef85..d75ccebf 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -28,6 +28,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") install(FILES vc-config.json DESTINATION bin) + + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) + return() endif() diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index 63c05e64..32ec249e 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -9,6 +9,10 @@ if(${WIN32}) return() endif() +if(${LINUX}) + return() +endif() + if(${APPLE}) message(STATUS "Running macdeployqt for @AppName@ ...") execute_process( diff --git a/cmake/find_qt6.cmake b/cmake/find_qt6.cmake index d0125e4d..f18d4561 100644 --- a/cmake/find_qt6.cmake +++ b/cmake/find_qt6.cmake @@ -14,12 +14,25 @@ # endif() message(STATUS "Searching for Qt6. CMAKE_PREFIX_PATH = " ${CMAKE_PREFIX_PATH}) -find_package(QT NAMES Qt6 COMPONENTS Widgets LinguistTools REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) if(${WIN32}) find_program(SlopeCraft_Qt_windeployqt_executable windeployqt PATHS ${CMAKE_PREFIX_PATH}) endif() +if(${LINUX}) + if(NOT EXISTS ${Qt6_DIR}) + message(WARNING "Qt6_DIR is not set. No way to find platform plugins") + endif() + + #message(STATUS "Qt6_DIR = ${Qt6_DIR}") + + file(GLOB_RECURSE SlopeCraft_Qt_plugin_platform_files "${Qt6_DIR}/../../../plugins/platforms/*") + file(GLOB_RECURSE SlopeCraft_Qt_plugin_imageformat_files "${Qt6_DIR}/../../../plugins/imageformats/*") + + #message(STATUS "Qt platform plugin files: ${SlopeCraft_Qt_plugin_platform_files}") +endif() + if(${APPLE}) find_program(SlopeCraft_Qt_macdeployqt_executable macdeployqt PATHS ${CMAKE_PREFIX_PATH}) -endif() +endif() \ No newline at end of file diff --git a/cmake/install.cmake b/cmake/install.cmake new file mode 100644 index 00000000..76fe9e1a --- /dev/null +++ b/cmake/install.cmake @@ -0,0 +1,29 @@ +set(SlopeCraft_readme_and_license_files + + LICENSE + README.md + README-en.md + license-translations/LICENSE-zh.md +) + +if(${WIN32}) + install(FILES ${SlopeCraft_readme_and_license_files} + DESTINATION ${CMAKE_INSTALL_PREFIX}) + return() +endif() + +if(${LINUX}) + + install(FILES ${SlopeCraft_readme_and_license_files} + DESTINATION .) + return() +endif() + +if(${APPLE}) + install(FILES ${SlopeCraft_readme_and_license_files} + DESTINATION ${CMAKE_INSTALL_PREFIX}) + return() +endif() + + +message(WARNING "No rule to install readme and license files. Unknown system name.") \ No newline at end of file diff --git a/cmake/install_plugins.cmake b/cmake/install_plugins.cmake new file mode 100644 index 00000000..b3f0cc16 --- /dev/null +++ b/cmake/install_plugins.cmake @@ -0,0 +1,9 @@ +if(NOT ${LINUX}) + message(WARNING "This script should be only called on Linux.") +endif() + + +install(FILES ${SlopeCraft_Qt_plugin_platform_files} + DESTINATION bin/platforms) +install(FILES ${SlopeCraft_Qt_plugin_imageformat_files} + DESTINATION bin/imageformats) \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 35217fb3..cc4e0909 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -26,6 +26,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") BUNDLE DESTINATION lib ) + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() endif() diff --git a/vccl/install.cmake b/vccl/install.cmake index dd921b0a..3e7ef64a 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -25,6 +25,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") LIBRARY DESTINATION lib) install(FILES vccl-config.json DESTINATION bin) + + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) + return() endif() From 562cb14e2e94fe9adb06cd34d7e735f0d387614e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 9 Apr 2023 02:02:47 +0800 Subject: [PATCH 0061/1123] add deb pack dependencies --- cpack/deb.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpack/deb.cmake b/cpack/deb.cmake index a9f60f25..db422cfe 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -17,7 +17,11 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS libqt6network6 libqt6concurrent6 libopengl0 + libqt6opengl6 + libqt6openglwidgets6 + libqt6dbus6 libglx0 + qt6-qpa-plugins ${SlopeCraft_debian_opencl_deps} ) From 2b875f0baebd2a42b80a86a47b491ceca97aa3e1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 9 Apr 2023 02:11:38 +0800 Subject: [PATCH 0062/1123] assign build type for macos-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4495526c..80dd8e1a 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -17,7 +17,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_BUILD_TYPE=Release - name: Build and Install run: | cd build From 8518c300532509fde1d13782fe77288f6a1cae47 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 9 Apr 2023 02:25:53 +0800 Subject: [PATCH 0063/1123] make packs and upload --- .github/workflows/build-dev.yml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 80dd8e1a..79399101 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Make directories - run: mkdir build install + run: mkdir build install pack #- name: List installed # run: apt list --installed @@ -86,17 +86,23 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Compress - run: | - cd install - tar -cf compress.tar ./* - xz -9 ./compress.tar - mv ./compress.tar.xz SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + - name: Make deb and tar.xz packs with cpack + run: | + cd build + cpack -G DEB -B ../pack + cpack -G TXZ -B ../pack cd .. - - name: Upload artifacts + - name: Upload deb pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-deb + path: pack/SlopeCraft*.deb + if-no-files-found: error + + - name: Upload tar.xz pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux - path: install/SlopeCraft-dev-${{ env.SHORT_SHA }}-linux.tar.xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-tar.xz + path: pack/SlopeCraft*.tar.xz if-no-files-found: error \ No newline at end of file From 301ee171558ccaca21a1799b6c6a610df9880afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 13:26:18 +0800 Subject: [PATCH 0064/1123] migrate find_lupdate to find_qt6.cmake --- CMakeLists.txt | 15 ++------------- cmake/find_qt6.cmake | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 272166b0..d42450f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ option(SlopeCraft_gprof "Profile with gprof" OFF) # manage the install prefix if(NOT DEFINED CMAKE_INSTALL_PREFIX) -set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) + set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) endif() # convert relative path to absolute @@ -44,7 +44,6 @@ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") Please use gcc.") endif() - if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) # delete files here file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) @@ -60,17 +59,7 @@ include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -# find lupdate executable -if(${SlopeCraft_update_ts_files} AND(NOT DEFINED SlopeCraft_Qt_lupdate_executable)) - find_program(SlopeCraft_Qt_lupdate_executable name lupdate PATHS ${CMAKE_PREFIX_PATH} REQUIRED) - message(STATUS "Found lupdate at : " ${SlopeCraft_Qt_lupdate_executable}) - - if(${SlopeCraft_update_ts_no_obsolete}) - set(SlopeCraft_ts_flags) - else() - set(SlopeCraft_ts_flags "-no-obsolete") - endif() -endif() +include(cmake/install_if_is_shared.cmake) add_definitions("-D_USE_MATH_DEFINES") add_definitions("-DSCL_FIND_GlobalEnums_BY_PATH") diff --git a/cmake/find_qt6.cmake b/cmake/find_qt6.cmake index f18d4561..9adfec63 100644 --- a/cmake/find_qt6.cmake +++ b/cmake/find_qt6.cmake @@ -16,6 +16,18 @@ message(STATUS "Searching for Qt6. CMAKE_PREFIX_PATH = " ${CMAKE_PREFIX_PATH}) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) +# find lupdate executable +if(${SlopeCraft_update_ts_files} AND(NOT DEFINED SlopeCraft_Qt_lupdate_executable)) + find_program(SlopeCraft_Qt_lupdate_executable name lupdate PATHS ${CMAKE_PREFIX_PATH} REQUIRED) + message(STATUS "Found lupdate at : " ${SlopeCraft_Qt_lupdate_executable}) + + if(${SlopeCraft_update_ts_no_obsolete}) + set(SlopeCraft_ts_flags) + else() + set(SlopeCraft_ts_flags "-no-obsolete") + endif() +endif() + if(${WIN32}) find_program(SlopeCraft_Qt_windeployqt_executable windeployqt PATHS ${CMAKE_PREFIX_PATH}) endif() @@ -25,12 +37,11 @@ if(${LINUX}) message(WARNING "Qt6_DIR is not set. No way to find platform plugins") endif() - #message(STATUS "Qt6_DIR = ${Qt6_DIR}") - + # message(STATUS "Qt6_DIR = ${Qt6_DIR}") file(GLOB_RECURSE SlopeCraft_Qt_plugin_platform_files "${Qt6_DIR}/../../../plugins/platforms/*") file(GLOB_RECURSE SlopeCraft_Qt_plugin_imageformat_files "${Qt6_DIR}/../../../plugins/imageformats/*") - #message(STATUS "Qt platform plugin files: ${SlopeCraft_Qt_plugin_platform_files}") + # message(STATUS "Qt platform plugin files: ${SlopeCraft_Qt_plugin_platform_files}") endif() if(${APPLE}) From 098178574389fb741fe3a2019a40068c1ea22510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 13:27:41 +0800 Subject: [PATCH 0065/1123] install libzip, libpng, zlib and gomp dll on win --- MapViewer/install.cmake | 4 +- SlopeCraftL/install.cmake | 2 + VisualCraftL/CMakeLists.txt | 5 +- VisualCraftL/install.cmake | 4 ++ cmake/install.cmake | 16 +++++- cmake/install_if_is_shared.cmake | 92 ++++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 cmake/install_if_is_shared.cmake diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index e9375c96..0e661f75 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -16,6 +16,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) + return() endif() @@ -25,7 +27,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") RUNTIME DESTINATION bin BUNDLE DESTINATION lib ) - + # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index a52016ba..e6fc3647 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -39,6 +39,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/include) + SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) + return() endif() diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index a5a91e15..9f6f19a9 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -42,9 +42,8 @@ set(VCL_source_files VisualCraftL.h VisualCraftL.cpp - #textures_need_to_override.h - #textures_need_to_override.cpp - + # textures_need_to_override.h + # textures_need_to_override.cpp TokiVC.h TokiVC.cpp TokiVC_flagdiagram.cpp diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index ea5b8dff..4792292e 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -40,6 +40,10 @@ if(${WIN32}) LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib) install(FILES ${VCL_include_headers} DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include) + + SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) + SlopeCraft_install_if_is_shared(libzip::zip ${CMAKE_INSTALL_PREFIX}) + SlopeCraft_install_if_is_shared(PNG::PNG ${CMAKE_INSTALL_PREFIX}) return() endif() diff --git a/cmake/install.cmake b/cmake/install.cmake index 76fe9e1a..f03a4ef4 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -9,11 +9,24 @@ set(SlopeCraft_readme_and_license_files if(${WIN32}) install(FILES ${SlopeCraft_readme_and_license_files} DESTINATION ${CMAKE_INSTALL_PREFIX}) + + set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") + + find_library(libgomp_dll + NAMES gomp-1 + PATHS ${CMAKE_PREFIX_PATH} + NO_CMAKE_INSTALL_PREFIX) + + if(NOT libgomp_dll) + message(WARNING "Failed to find libgomp dll.") + else() + install(FILES ${libgomp_dll} + DESTINATION ${CMAKE_INSTALL_PREFIX}) + endif() return() endif() if(${LINUX}) - install(FILES ${SlopeCraft_readme_and_license_files} DESTINATION .) return() @@ -25,5 +38,4 @@ if(${APPLE}) return() endif() - message(WARNING "No rule to install readme and license files. Unknown system name.") \ No newline at end of file diff --git a/cmake/install_if_is_shared.cmake b/cmake/install_if_is_shared.cmake new file mode 100644 index 00000000..d6740f18 --- /dev/null +++ b/cmake/install_if_is_shared.cmake @@ -0,0 +1,92 @@ +function(SlopeCraft_install_lib lib_location dest) + cmake_path(GET lib_location EXTENSION extension) + + # message(STATUS "extension of ${lib_location} is ${extension}") + if((extension MATCHES ".dll.a") OR(extension MATCHES ".dll.lib")) + cmake_path(GET lib_location STEM lib_stem) + + # message(STATUS "lib_stem = ${lib_stem}") + set(dll_name "${lib_stem}.dll") + + # message(STATUS "dll_name = ${dll_name}") + cmake_path(GET lib_location PARENT_PATH search_dir) + cmake_path(GET search_dir PARENT_PATH search_dir) + + # message("search_dir = ${search_dir}") + + # find_file(dll_location + # NAMES ${dll_name} + # HINTS ${search_dir}/bin/${dll_name} + # PATHS ${search_dir} + # PATH_SUFFIXES bin + # NO_CACHE) + find_library(dll_location + NAMES lib_stem + PATHS ${search_dir} + PATH_SUFFIXES bin + NO_CACHE) + + if(NOT dll_location) + # message(STATUS "find_library failed to find ${dll_name}, retry with file GLOB") + file(GLOB dll_location "${search_dir}/bin/${lib_stem}*.dll") + + list(LENGTH dll_location len) + + if(len LESS_EQUAL 0) + message(WARNING "Trying to install dll of ${lib_location}, but failed to find ${dll_name}. + The released package may failed to find this dll.") + return() + endif() + endif() + + SlopeCraft_install_lib(${dll_location} ${dest}) + + return() + endif() + + if(extension MATCHES ".dll") + message(STATUS "Install ${lib_location} to ${dest}") + install(FILES ${lib_location} + DESTINATION ${dest}) + return() + endif() + + if((extension MATCHES ".a") OR(extension MATCHES ".lib")) + return() + endif() +endfunction(SlopeCraft_install_lib) + +function(SlopeCraft_install_if_is_shared target dest) + get_target_property(target_type ${target} TYPE) + + # message(STATUS "Type of ${target} is : ${target_type}") + get_target_property(target_name ${target} NAME) + + # message(STATUS "Name of ${target} is : ${target_name}") + get_target_property(target_suffix ${target} SUFFIX) + + # message(STATUS "Suffix of ${target} is : ${target_suffix}") + get_target_property(target_location ${target} LOCATION) + + # message(STATUS "Location of ${target} is : ${target_location}") + set(skip_this false) + + if(${target_type} STREQUAL EXECUTABLE) + set(skip_this true) + endif() + + if(${target_type} STREQUAL STATIC_LIBRARY) + set(skip_this true) + endif() + + if(${target_type} STREQUAL OBJECT_LIBRARY) + set(skip_this true) + endif() + + if(${skip_this}) + message(STATUS "Skip installing ${target} because it is not a shared lib. TYPE = ${target_type}") + return() + endif() + + SlopeCraft_install_lib(${target_location} ${dest}) +endfunction(SlopeCraft_install_if_is_shared) \ No newline at end of file From 66e743aba65d23e1dd95b7ae5a9a798ff3c7ed81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 14:09:30 +0800 Subject: [PATCH 0066/1123] restrict build-dev trigger(temporarily) --- .github/workflows/build-dev.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 79399101..c3764380 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -1,5 +1,9 @@ name: Build dev version artifacts -on: [pull_request, push] +on: + pull_request: + push: + branches: + - feat-github-action jobs: From c8b67995dc821bc1da5940dc28db5b0f34be0f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 14:11:42 +0800 Subject: [PATCH 0067/1123] Add empty windows action --- .github/workflows/build-dev-win.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/build-dev-win.yml diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml new file mode 100644 index 00000000..4fda8a70 --- /dev/null +++ b/.github/workflows/build-dev-win.yml @@ -0,0 +1,13 @@ +name: Build dev version artifacts for window +on: + push: + branches: + - feat-github-action-wind + +jobs: + + win-build: + runs-on: windows-latest + steps: + - name: empty step + run: cd . \ No newline at end of file From 9779c8c1cb13be50b5866e587c553730d97b8eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 14:56:13 +0800 Subject: [PATCH 0068/1123] fix win action --- .github/workflows/build-dev-win.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 4fda8a70..74ee51ad 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -2,7 +2,7 @@ name: Build dev version artifacts for window on: push: branches: - - feat-github-action-wind + - feat-github-action-win jobs: @@ -10,4 +10,6 @@ jobs: runs-on: windows-latest steps: - name: empty step - run: cd . \ No newline at end of file + run: cd . + + #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 89bf573a82ba4b187dc514d3ca8e96961fcfc9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:00:49 +0800 Subject: [PATCH 0069/1123] see environment --- .github/workflows/build-dev-win.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 74ee51ad..028f4d6c 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -9,7 +9,17 @@ jobs: win-build: runs-on: windows-latest steps: - - name: empty step - run: cd . + - name: Checkout repository + uses: actions/checkout@v2 + - name: See environment + run: | + where cmake + where ninja + where 7z + where cl + where clang + where gcc + where vcpkg + #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 65f3854583f6174bded466fb2cc76ae402c5df04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:02:22 +0800 Subject: [PATCH 0070/1123] check win-build environment --- .github/workflows/build-dev-win.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 028f4d6c..27f50c6e 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -12,14 +12,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: See environment - run: | - where cmake - where ninja - where 7z - where cl - where clang - where gcc - where vcpkg + run: where cmake ninja 7z cl clang gcc vcpkg #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 934dce0259f8ba2450920a4c93587e31e1b2ff1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:04:43 +0800 Subject: [PATCH 0071/1123] check win-build environment --- .github/workflows/build-dev-win.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 27f50c6e..1a4d49b5 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -11,6 +11,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + - name: start cmd + run: cmd - name: See environment run: where cmake ninja 7z cl clang gcc vcpkg From 8473f907c07190515a092681c443f681131cf04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:16:00 +0800 Subject: [PATCH 0072/1123] check win-build environment --- .github/workflows/build-dev-win.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 1a4d49b5..209aeb28 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -11,10 +11,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 - - name: start cmd - run: cmd - name: See environment - run: where cmake ninja 7z cl clang gcc vcpkg + run: where.exe cmake ninja 7z cl clang gcc vcpkg #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From c25605cce88dfb0ef02c7fc67fe791bea5f9b01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:36:20 +0800 Subject: [PATCH 0073/1123] check win-build environment --- .github/workflows/build-dev-win.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 209aeb28..01f3bf4b 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -9,10 +9,18 @@ jobs: win-build: runs-on: windows-latest steps: - - name: Checkout repository - uses: actions/checkout@v2 + #- name: Checkout repository + # uses: actions/checkout@v2 - name: See environment - run: where.exe cmake ninja 7z cl clang gcc vcpkg + run: where.exe cmake ninja 7z clang gcc vcpkg + - name: See versions + run: | + cmake --version + ninja --version + clang --version + gcc --version + - name: See Path + run: $env:path -split ';' #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 30c9ab8c846932ce0125520d8f42583964e134fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 15:52:26 +0800 Subject: [PATCH 0074/1123] Download gcc12 for win-build --- .github/workflows/build-dev-win.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 01f3bf4b..1359917e 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -21,6 +21,17 @@ jobs: gcc --version - name: See Path run: $env:path -split ';' - + - name: Make dirs + run: | + mkdir bin + mkdir archives + mkdir bin/mingw64 + mkdir bin/Qt6.4.0-gcc12-shared + - name: Download and extract mingw64 + run: | + curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + 7z x archives/gcc12.7z -o./bin + - name: Tree + run: tree . #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 6f238c32055165499e0a659bf31cbf8e06103a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:03:08 +0800 Subject: [PATCH 0075/1123] Download gcc12 for win-build --- .github/workflows/build-dev-win.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 1359917e..86bacccf 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -27,10 +27,10 @@ jobs: mkdir archives mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared - - name: Download and extract mingw64 - run: | - curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - 7z x archives/gcc12.7z -o./bin + - name: Download mingw64 + run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + - name : Extract mingw + run: 7z x -o./bin archives/gcc12.7z - name: Tree run: tree . From 292bc0538cd1850d685983dafbe37174c401dd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:04:08 +0800 Subject: [PATCH 0076/1123] Download gcc12 for win-build --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 86bacccf..f2d42178 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -30,7 +30,7 @@ jobs: - name: Download mingw64 run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - name : Extract mingw - run: 7z x -o./bin archives/gcc12.7z + run: 7z x -obin ./archives/gcc12.7z - name: Tree run: tree . From a6b9d45ff6a7d6d6464bb3eeb3cfc1ea44b57808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:06:01 +0800 Subject: [PATCH 0077/1123] Download gcc12 for win-build --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index f2d42178..6c1ed7e6 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -30,7 +30,7 @@ jobs: - name: Download mingw64 run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - name : Extract mingw - run: 7z x -obin ./archives/gcc12.7z + run: 7z x -o.\bin ./archives/gcc12.7z - name: Tree run: tree . From 19c484e89f4691a164b29b203b25477e5e60bb78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:08:00 +0800 Subject: [PATCH 0078/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 6c1ed7e6..3ad8af75 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -24,13 +24,12 @@ jobs: - name: Make dirs run: | mkdir bin - mkdir archives mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared - name: Download mingw64 - run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + run: curl -o bin/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - name : Extract mingw - run: 7z x -o.\bin ./archives/gcc12.7z + run: 7z x ./bin/gcc12.7z - name: Tree run: tree . From 82f29d30e8666d270343f562efb63b1938bf76e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:14:39 +0800 Subject: [PATCH 0079/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 3ad8af75..04ac98a2 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -26,10 +26,12 @@ jobs: mkdir bin mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared + mkdir archives + mkdir build - name: Download mingw64 - run: curl -o bin/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - name : Extract mingw - run: 7z x ./bin/gcc12.7z + run: 7z x ./archives/gcc12.7z -obin - name: Tree run: tree . From 73860a77dfcece5fab4a31c09d20409399ddf7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:16:06 +0800 Subject: [PATCH 0080/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 04ac98a2..a8cb25ee 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -28,10 +28,11 @@ jobs: mkdir bin/Qt6.4.0-gcc12-shared mkdir archives mkdir build - - name: Download mingw64 - run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - - name : Extract mingw - run: 7z x ./archives/gcc12.7z -obin + - name: Download and extract mingw64 + run: | + curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + 7z x archives/gcc12.7z -obin + - name: Tree run: tree . From ef52a740a2cebf47fad321749e74875ab6d1d3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:18:23 +0800 Subject: [PATCH 0081/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index a8cb25ee..0c208bd2 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -28,11 +28,10 @@ jobs: mkdir bin/Qt6.4.0-gcc12-shared mkdir archives mkdir build - - name: Download and extract mingw64 - run: | - curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - 7z x archives/gcc12.7z -obin - + - name: Download mingw64 + run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + - name : Extract mingw + run: 7z x archives/gcc12.7z -obin - name: Tree run: tree . From 1fd34780f5f5fdedfdf46d3529dfe6310a25e325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:21:03 +0800 Subject: [PATCH 0082/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 0c208bd2..cbb598c9 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -26,12 +26,14 @@ jobs: mkdir bin mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared - mkdir archives mkdir build - name: Download mingw64 - run: curl -o archives/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + run: curl -o bin/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z - name : Extract mingw - run: 7z x archives/gcc12.7z -obin + run: | + cd bin + 7z x gcc12.7z + cd .. - name: Tree run: tree . From e59739bc33260de8f84abd834af3bc14f86879ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 16:25:25 +0800 Subject: [PATCH 0083/1123] fix gcc12 extraction for win-build --- .github/workflows/build-dev-win.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index cbb598c9..426f2874 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -29,12 +29,13 @@ jobs: mkdir build - name: Download mingw64 run: curl -o bin/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + - name: Tree + run: tree . - name : Extract mingw run: | cd bin + dir gcc12.7z 7z x gcc12.7z cd .. - - name: Tree - run: tree . #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From cb136cf1e5a8460c4c94a583c9dd41e64633b869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 17:56:35 +0800 Subject: [PATCH 0084/1123] download qt6.4.0 for win-build --- .github/workflows/build-dev-win.yml | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 426f2874..f155c1f8 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -28,14 +28,24 @@ jobs: mkdir bin/Qt6.4.0-gcc12-shared mkdir build - name: Download mingw64 - run: curl -o bin/gcc12.7z https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z + run: | + cmd + curl -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" + dir bin/gcc12.7z + exit + - name: Download Qt6.4.0-gcc12-shared + run: | + cmd + curl -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + dir bin/Qt6.4.0-gcc12-shared.7z + exit - name: Tree run: tree . - - name : Extract mingw - run: | - cd bin - dir gcc12.7z - 7z x gcc12.7z - cd .. + #- name : Extract mingw + # run: | + # cd bin + # dir gcc12.7z + # 7z x gcc12.7z + # cd .. #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file From 091b91b80d49864e5146ae703632459998d77598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:03:18 +0800 Subject: [PATCH 0085/1123] try fixing download --- .github/workflows/build-dev-win.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index f155c1f8..03f69341 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -30,13 +30,13 @@ jobs: - name: Download mingw64 run: | cmd - curl -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" - dir bin/gcc12.7z + curl -JLO "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" + exit - name: Download Qt6.4.0-gcc12-shared run: | cmd - curl -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + curl -JLO "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" dir bin/Qt6.4.0-gcc12-shared.7z exit - name: Tree From acbddb933fb089b27bb72ef1bf00d6a8aa0e66c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:09:08 +0800 Subject: [PATCH 0086/1123] try fixing download --- .github/workflows/build-dev-win.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 03f69341..648c668d 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -37,7 +37,6 @@ jobs: run: | cmd curl -JLO "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" - dir bin/Qt6.4.0-gcc12-shared.7z exit - name: Tree run: tree . From bf5fbd6c1dbcb571159bf39ae173839171fba3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:11:15 +0800 Subject: [PATCH 0087/1123] try fixing download --- .github/workflows/build-dev-win.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 648c668d..0eefa565 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -38,8 +38,8 @@ jobs: cmd curl -JLO "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" exit - - name: Tree - run: tree . + - name: List all files + run: tree /f #- name : Extract mingw # run: | # cd bin From bd8dad012cd4b9333c7d844ea13d8145288723c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:13:23 +0800 Subject: [PATCH 0088/1123] try fixing download --- .github/workflows/build-dev-win.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 0eefa565..95068c0b 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -30,13 +30,13 @@ jobs: - name: Download mingw64 run: | cmd - curl -JLO "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" + curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" exit - name: Download Qt6.4.0-gcc12-shared run: | cmd - curl -JLO "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" exit - name: List all files run: tree /f From 7aceef453cbc3ef24c6089485af24fa402b439f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:15:11 +0800 Subject: [PATCH 0089/1123] extract files --- .github/workflows/build-dev-win.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 95068c0b..c7f139ff 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -27,16 +27,17 @@ jobs: mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared mkdir build - - name: Download mingw64 + - name: Download mingw64 and extract run: | cmd curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" - + 7z x -obin bin/gcc12.7z exit - - name: Download Qt6.4.0-gcc12-shared + - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + 7z x -obin bin/Qt6.4.0-gcc12-shared.7z exit - name: List all files run: tree /f From 61c2e2169381b64bf0034efb6fa4cc677b9ef853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:50:50 +0800 Subject: [PATCH 0090/1123] build and install zlib --- .github/workflows/build-dev-win.yml | 32 +++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index c7f139ff..c8b787e3 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -33,19 +33,35 @@ jobs: curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" 7z x -obin bin/gcc12.7z exit + # gcc installation dir: bin/mingw64 + # gcc.exe: bin/mingw64/bin/gcc.exe + # g++.exe: bin/mingw64/bin/g++.exe - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" 7z x -obin bin/Qt6.4.0-gcc12-shared.7z exit - - name: List all files - run: tree /f - #- name : Extract mingw - # run: | - # cd bin - # dir gcc12.7z - # 7z x gcc12.7z + # Qt installation dir: bin/Qt6.4.0-gcc12-shared + - name: Build and install zlib + run: | + $basedir=(pwd).path + cd 3rdParty + git clone https://github.com/madler/zlib.git + cd zlib + git checkout v1.2.13 + cd $basedir + mkdir bin/build-zlib + cmake -S bin/zlib -B bin/build.zlib -DCMAKE_C_COMPILER=$basedir/bin/mingw64/bin/gcc.exe -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 + cmake --build bin/build.zlib --parallel + cmake --install bin/build.zlib + #- name: Build and install libzip + # run: | + # cmd + # cd 3rdParty + # git clone https://github.com/nih-at/libzip.git + # cd libzip + # git checkout v1.9.2 # cd .. - #https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z \ No newline at end of file + # cd .. \ No newline at end of file From dea8c2320b54b3ea529c150fd3d5d85d93890ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 18:55:42 +0800 Subject: [PATCH 0091/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index c8b787e3..48dd4fff 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -27,6 +27,7 @@ jobs: mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared mkdir build + mkdir 3rdParty - name: Download mingw64 and extract run: | cmd @@ -36,13 +37,6 @@ jobs: # gcc installation dir: bin/mingw64 # gcc.exe: bin/mingw64/bin/gcc.exe # g++.exe: bin/mingw64/bin/g++.exe - - name: Download Qt6.4.0-gcc12-shared and extract - run: | - cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" - 7z x -obin bin/Qt6.4.0-gcc12-shared.7z - exit - # Qt installation dir: bin/Qt6.4.0-gcc12-shared - name: Build and install zlib run: | $basedir=(pwd).path @@ -55,6 +49,14 @@ jobs: cmake -S bin/zlib -B bin/build.zlib -DCMAKE_C_COMPILER=$basedir/bin/mingw64/bin/gcc.exe -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 cmake --build bin/build.zlib --parallel cmake --install bin/build.zlib + + - name: Download Qt6.4.0-gcc12-shared and extract + run: | + cmd + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + 7z x -obin bin/Qt6.4.0-gcc12-shared.7z + exit + # Qt installation dir: bin/Qt6.4.0-gcc12-shared #- name: Build and install libzip # run: | # cmd From fb62d18f0778bf2baa9121460a82e104b7e1900e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:03:49 +0800 Subject: [PATCH 0092/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 48dd4fff..ff937b29 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -46,10 +46,17 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -S bin/zlib -B bin/build.zlib -DCMAKE_C_COMPILER=$basedir/bin/mingw64/bin/gcc.exe -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 + cmake -S 3rdParty/zlib -B bin/build.zlib -DCMAKE_C_COMPILER=$basedir/bin/mingw64/bin/gcc.exe -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 cmake --build bin/build.zlib --parallel cmake --install bin/build.zlib + - name: Upload gcc + uses: actions/upload-artifact@v3 + with: + name: gcc12-with-zlib + path: bin/mingw64 + if-no-files-found: error + - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd From 3649c95532972ab214647f40746fa902a334ba81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:05:40 +0800 Subject: [PATCH 0093/1123] fix workflow --- .github/workflows/build-dev-win.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index ff937b29..88456a1d 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -52,10 +52,10 @@ jobs: - name: Upload gcc uses: actions/upload-artifact@v3 - with: - name: gcc12-with-zlib - path: bin/mingw64 - if-no-files-found: error + with: + name: gcc12-with-zlib + path: bin/mingw64 + if-no-files-found: error - name: Download Qt6.4.0-gcc12-shared and extract run: | From 07d4f0291ec82344694e35dfc81d6443ef6a81b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:10:16 +0800 Subject: [PATCH 0094/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 88456a1d..e379aec7 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -13,12 +13,12 @@ jobs: # uses: actions/checkout@v2 - name: See environment run: where.exe cmake ninja 7z clang gcc vcpkg - - name: See versions - run: | - cmake --version - ninja --version - clang --version - gcc --version + #- name: See versions + # run: | + # cmake --version + # ninja --version + # clang --version + # gcc --version - name: See Path run: $env:path -split ';' - name: Make dirs @@ -46,9 +46,9 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build.zlib -DCMAKE_C_COMPILER=$basedir/bin/mingw64/bin/gcc.exe -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 - cmake --build bin/build.zlib --parallel - cmake --install bin/build.zlib + cmake -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 -G Ninja + cmake --build bin/build-zlib --parallel + cmake --install bin/build-zlib - name: Upload gcc uses: actions/upload-artifact@v3 From a2b621e79a64c8fdef7fbe644378aa7dab925f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:13:00 +0800 Subject: [PATCH 0095/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index e379aec7..d3fd7c8e 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -46,7 +46,7 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$basedir/bin/mingw64 -G Ninja + cmake -G Ninja -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib From 3c662411eb86e39bd08f235118387cfe949081c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:15:51 +0800 Subject: [PATCH 0096/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index d3fd7c8e..081cf736 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -40,6 +40,7 @@ jobs: - name: Build and install zlib run: | $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") cd 3rdParty git clone https://github.com/madler/zlib.git cd zlib From 3f92da7674cf5f519402cb197369803b36d49e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:16:20 +0800 Subject: [PATCH 0097/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 081cf736..86d9c2da 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -47,7 +47,7 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -G Ninja -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake -G Ninja -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib From 59e136366b2bfc4bf83309bb4bc620cd6521aedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:19:11 +0800 Subject: [PATCH 0098/1123] fix build and install zlib --- .github/workflows/build-dev-win.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 86d9c2da..370cd6a1 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -41,13 +41,14 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + echo "basedir = $basedir" cd 3rdParty git clone https://github.com/madler/zlib.git cd zlib git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -G Ninja -S 3rdParty/zlib -B bin/build-zlib -DCMAKE_C_COMPILER="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib From 6685e6726c5deb56e9a22ad22edbee4b953198cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:27:21 +0800 Subject: [PATCH 0099/1123] build and install libzip --- .github/workflows/build-dev-win.yml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 370cd6a1..76b1d23c 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -51,7 +51,21 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib - + + - name: Build and install libzip + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + cd 3rdParty + git clone https://github.com/nih-at/libzip.git + cd libzip + git checkout v1.9.2 + cd $basedir + mkdir bin/build-libzip + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true + cmake --build bin/build-libzip --parallel + cmake --install bin/build-libzip + - name: Upload gcc uses: actions/upload-artifact@v3 with: @@ -66,13 +80,4 @@ jobs: 7z x -obin bin/Qt6.4.0-gcc12-shared.7z exit # Qt installation dir: bin/Qt6.4.0-gcc12-shared - #- name: Build and install libzip - # run: | - # cmd - # cd 3rdParty - # git clone https://github.com/nih-at/libzip.git - # cd libzip - # git checkout v1.9.2 - # cd .. - - # cd .. \ No newline at end of file + \ No newline at end of file From 98abee9a3cd325081d7470ea6a6b55601d769624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:39:45 +0800 Subject: [PATCH 0100/1123] build and install libpng for win-build --- .github/workflows/build-dev-win.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 76b1d23c..ecec302f 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -66,10 +66,24 @@ jobs: cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip + - name: Build and install libpng + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + cd 3rdParty + git clone https://github.com/glennrp/libpng.git + cd libpng + git checkout v1.6.39 + cd $basedir + mkdir bin/build-libpng + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake --build bin/build-libpng --parallel + cmake --install bin/build-libpng + - name: Upload gcc uses: actions/upload-artifact@v3 with: - name: gcc12-with-zlib + name: gcc12-with-zlib,libzip,libpng path: bin/mingw64 if-no-files-found: error From d276beb2ea16f045d665f9fabaa65f6d4ad0c862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:46:39 +0800 Subject: [PATCH 0101/1123] search for project location --- .github/workflows/build-dev-win.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index ecec302f..1144fa37 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -28,6 +28,7 @@ jobs: mkdir bin/Qt6.4.0-gcc12-shared mkdir build mkdir 3rdParty + - name: Download mingw64 and extract run: | cmd @@ -79,13 +80,6 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng - - - name: Upload gcc - uses: actions/upload-artifact@v3 - with: - name: gcc12-with-zlib,libzip,libpng - path: bin/mingw64 - if-no-files-found: error - name: Download Qt6.4.0-gcc12-shared and extract run: | @@ -93,5 +87,21 @@ jobs: curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" 7z x -obin bin/Qt6.4.0-gcc12-shared.7z exit + + - name: Tree /f + run: tree /f D:/ > bin/all_files_on_D.txt + - name: Upload all_files_on_D.txt + uses: actions/upload-artifact@v3 + with: + name: all_files_on_D.txt + path: bin/all_files_on_D.txt + if-no-files-found: error # Qt installation dir: bin/Qt6.4.0-gcc12-shared - \ No newline at end of file + + + #- name: Upload gcc + # uses: actions/upload-artifact@v3 + # with: + # name: gcc12-with-zlib,libzip,libpng + # path: bin/mingw64 + # if-no-files-found: error \ No newline at end of file From d3a54bc4b0fabe0b672442eb670b2401e6ed5449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:54:55 +0800 Subject: [PATCH 0102/1123] search for project location --- .github/workflows/build-dev-win.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 1144fa37..5de3fbb0 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -9,18 +9,18 @@ jobs: win-build: runs-on: windows-latest steps: - #- name: Checkout repository - # uses: actions/checkout@v2 - - name: See environment - run: where.exe cmake ninja 7z clang gcc vcpkg + - name: Checkout repository + uses: actions/checkout@v2 + #- name: See environment + # run: where.exe cmake ninja 7z clang gcc vcpkg #- name: See versions # run: | # cmake --version # ninja --version # clang --version # gcc --version - - name: See Path - run: $env:path -split ';' + #- name: See Path + # run: $env:path -split ';' - name: Make dirs run: | mkdir bin @@ -52,6 +52,10 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib + cmd + rmdir /Q /S 3rdParty/zlib + rmdir /Q /S bin/build-zlib + exit - name: Build and install libzip run: | @@ -66,6 +70,10 @@ jobs: cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip + cmd + rmdir /Q /S 3rdParty/libzip + rmdir /Q /S bin/build-libzip + exit - name: Build and install libpng run: | @@ -80,6 +88,10 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng + cmd + rmdir /Q /S 3rdParty/libpng + rmdir /Q /S bin/build-libpng + exit - name: Download Qt6.4.0-gcc12-shared and extract run: | From 5e25ef3e8f61842197adf2db608c60f093e948b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 19:57:46 +0800 Subject: [PATCH 0103/1123] search for project location --- .github/workflows/build-dev-win.yml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 5de3fbb0..6595a0d7 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -52,10 +52,8 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib - cmd - rmdir /Q /S 3rdParty/zlib - rmdir /Q /S bin/build-zlib - exit + Remove-Item -Path "$basedir/3rdParty/zlib" -Recurse + Remove-Item -Path "$basedir/bin/build-zlib" -Recurse - name: Build and install libzip run: | @@ -70,10 +68,8 @@ jobs: cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip - cmd - rmdir /Q /S 3rdParty/libzip - rmdir /Q /S bin/build-libzip - exit + Remove-Item -Path "$basedir/3rdParty/libzip" -Recurse + Remove-Item -Path "$basedir/bin/build-libzip" -Recurse - name: Build and install libpng run: | @@ -88,10 +84,8 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng - cmd - rmdir /Q /S 3rdParty/libpng - rmdir /Q /S bin/build-libpng - exit + Remove-Item -Path "$basedir/3rdParty/libpng" -Recurse + Remove-Item -Path "$basedir/bin/build-libpng" -Recurse - name: Download Qt6.4.0-gcc12-shared and extract run: | From 45e5d58374cf28f854dbc18f216ed140f7f4d1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:00:26 +0800 Subject: [PATCH 0104/1123] search for project location --- .github/workflows/build-dev-win.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 6595a0d7..14606945 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -52,8 +52,6 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib - Remove-Item -Path "$basedir/3rdParty/zlib" -Recurse - Remove-Item -Path "$basedir/bin/build-zlib" -Recurse - name: Build and install libzip run: | @@ -68,8 +66,6 @@ jobs: cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip - Remove-Item -Path "$basedir/3rdParty/libzip" -Recurse - Remove-Item -Path "$basedir/bin/build-libzip" -Recurse - name: Build and install libpng run: | @@ -84,8 +80,6 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng - Remove-Item -Path "$basedir/3rdParty/libpng" -Recurse - Remove-Item -Path "$basedir/bin/build-libpng" -Recurse - name: Download Qt6.4.0-gcc12-shared and extract run: | From 2543540532859fff2d0f9d69407b280ce92afe43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:15:01 +0800 Subject: [PATCH 0105/1123] Add configure, build and install for windows build --- .github/workflows/build-dev-win.yml | 35 ++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 14606945..539e1389 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -87,16 +87,35 @@ jobs: curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" 7z x -obin bin/Qt6.4.0-gcc12-shared.7z exit - - - name: Tree /f - run: tree /f D:/ > bin/all_files_on_D.txt - - name: Upload all_files_on_D.txt + # Qt installation dir: bin/Qt6.4.0-gcc12-shared + - name: CMake configure + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + mkdir build + mkdir install + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX="$basedir/install" -DCMAKE_BUILD_TYPE=Release -DSlopeCraft_GPU_API=None + - name: CMake build + run: cmake --build ./build --parallel + - name: CMake install + run: cmake --install ./build + - name: Upload artifacts uses: actions/upload-artifact@v3 - with: - name: all_files_on_D.txt - path: bin/all_files_on_D.txt + with: + name: SlopeCraft-dev-windows.zip + path: install if-no-files-found: error - # Qt installation dir: bin/Qt6.4.0-gcc12-shared + + + #- name: Tree /f + # run: tree /f D:/ > bin/all_files_on_D.txt + #- name: Upload all_files_on_D.txt + # uses: actions/upload-artifact@v3 + # with: + # name: all_files_on_D.txt + # path: bin/all_files_on_D.txt + # if-no-files-found: error + #- name: Upload gcc From 77340d9403184f626200562537b12eb64b1fe66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:15:29 +0800 Subject: [PATCH 0106/1123] remove extra spaces --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 539e1389..ea23a896 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -94,7 +94,7 @@ jobs: $basedir=($basedir).replace("\\","/") mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX="$basedir/install" -DCMAKE_BUILD_TYPE=Release -DSlopeCraft_GPU_API=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX="$basedir/install" -DCMAKE_BUILD_TYPE=Release -DSlopeCraft_GPU_API=None - name: CMake build run: cmake --build ./build --parallel - name: CMake install From 032ecb4ea660c3cc1b12634c5083b3bc5c33c5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:21:02 +0800 Subject: [PATCH 0107/1123] fix configure for win-build --- .github/workflows/build-dev-win.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index ea23a896..906a7d8e 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -92,7 +92,6 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") - mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX="$basedir/install" -DCMAKE_BUILD_TYPE=Release -DSlopeCraft_GPU_API=None - name: CMake build From 2d77a3f265d947d4bd68885d57bf22038d2dd145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:38:44 +0800 Subject: [PATCH 0108/1123] fix find_qt6 --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 906a7d8e..0ee7b398 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -93,7 +93,7 @@ jobs: $basedir=(pwd).path $basedir=($basedir).replace("\\","/") mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX="$basedir/install" -DCMAKE_BUILD_TYPE=Release -DSlopeCraft_GPU_API=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build run: cmake --build ./build --parallel - name: CMake install From c6d7517b4da158298d7879938dccd2cec7d5d2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:49:25 +0800 Subject: [PATCH 0109/1123] fix qt extraction --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 0ee7b398..f18ee9ad 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -85,7 +85,7 @@ jobs: run: | cmd curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" - 7z x -obin bin/Qt6.4.0-gcc12-shared.7z + 7z x -obin/Qt6.4.0-gcc12-shared bin/Qt6.4.0-gcc12-shared.7z exit # Qt installation dir: bin/Qt6.4.0-gcc12-shared - name: CMake configure From 8c28096cf1e0ac9d4c2fed6b11f94811d85a6aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 20:50:06 +0800 Subject: [PATCH 0110/1123] remove QT6_DIR from config command --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index f18ee9ad..55ff944d 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -93,7 +93,7 @@ jobs: $basedir=(pwd).path $basedir=($basedir).replace("\\","/") mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build run: cmake --build ./build --parallel - name: CMake install From 709dc68d564eacc3c35cc69e807d7ab40b6da88a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 21:15:01 +0800 Subject: [PATCH 0111/1123] try to fix Qt extraction --- .github/workflows/build-dev-win.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 55ff944d..6c2ddda6 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -26,7 +26,6 @@ jobs: mkdir bin mkdir bin/mingw64 mkdir bin/Qt6.4.0-gcc12-shared - mkdir build mkdir 3rdParty - name: Download mingw64 and extract @@ -85,13 +84,15 @@ jobs: run: | cmd curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" - 7z x -obin/Qt6.4.0-gcc12-shared bin/Qt6.4.0-gcc12-shared.7z + 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z exit + tree /f bin/Qt6.4.0-gcc12-shared # Qt installation dir: bin/Qt6.4.0-gcc12-shared - name: CMake configure run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build From 7d6276c70d2ae99ae1566a28e1f4f3d7771b4b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 21:26:48 +0800 Subject: [PATCH 0112/1123] Change another qt bin source --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 6c2ddda6..392471fd 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -83,7 +83,7 @@ jobs: - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared.7z" + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z exit tree /f bin/Qt6.4.0-gcc12-shared From b3522c810ad63c06985e7d52ca78751a7ef09178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 21:37:52 +0800 Subject: [PATCH 0113/1123] add prefix of compiler to path for win build --- .github/workflows/build-dev-win.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 392471fd..ed622c54 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -83,7 +83,7 @@ jobs: - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-pure-build.7z" 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z exit tree /f bin/Qt6.4.0-gcc12-shared @@ -92,6 +92,7 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + $env:path="$env:path;$basedir/bin/mingw64/bin" mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None From 90c3b1c80cb4b8b966270d7aefbfd1817e5f423d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 21:56:01 +0800 Subject: [PATCH 0114/1123] try to fix qt moc testing error --- .github/workflows/build-dev-win.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index ed622c54..6c5dabf7 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -19,8 +19,8 @@ jobs: # ninja --version # clang --version # gcc --version - #- name: See Path - # run: $env:path -split ';' + - name: See Path + run: $env:path -split ';' - name: Make dirs run: | mkdir bin From 82a2d0843e405833455e6b312a38f57d180691f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 22:17:55 +0800 Subject: [PATCH 0115/1123] filter out perl pathes frron $env:path --- .github/workflows/build-dev-win.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 6c5dabf7..73ae8cfd 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -92,7 +92,12 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") - $env:path="$env:path;$basedir/bin/mingw64/bin" + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + echo $new_path.split(';') + $env:path="$new_path;$basedir/bin/mingw64/bin" + echo $env:path.split(';') mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None From 63915d225fae549284c0670727affd4c4c6a4265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 22:25:04 +0800 Subject: [PATCH 0116/1123] try to fix qm problems --- .github/workflows/build-dev-win.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 73ae8cfd..0eccb479 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -102,7 +102,11 @@ jobs: mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build - run: cmake --build ./build --parallel + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $env:path="$env:path;$basedir/bin/mingw64/bin" + cmake --build ./build --parallel - name: CMake install run: cmake --install ./build - name: Upload artifacts From 8ba351247ac0fb5a3c4348ed529000f5706da44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 22:35:00 +0800 Subject: [PATCH 0117/1123] try to fix qm problems --- .github/workflows/build-dev-win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 0eccb479..3547e145 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -83,7 +83,7 @@ jobs: - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-pure-build.7z" + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z exit tree /f bin/Qt6.4.0-gcc12-shared From 73694c2f06b44502552db56187c5373bb2c6753c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 22:41:19 +0800 Subject: [PATCH 0118/1123] try to fix qm problems --- .github/workflows/build-dev-win.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 3547e145..98fab42b 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -19,8 +19,8 @@ jobs: # ninja --version # clang --version # gcc --version - - name: See Path - run: $env:path -split ';' + #- name: See Path + # run: $env:path -split ';' - name: Make dirs run: | mkdir bin @@ -104,8 +104,10 @@ jobs: - name: CMake build run: | $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $env:path="$env:path;$basedir/bin/mingw64/bin" + $basedir=($basedir).replace("\\","/")$exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" cmake --build ./build --parallel - name: CMake install run: cmake --install ./build From 5628be934d4a0ff072a0436491cecc031edbbcdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 22:46:14 +0800 Subject: [PATCH 0119/1123] try to fix qm problems --- .github/workflows/build-dev-win.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 98fab42b..c19251c2 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -100,11 +100,12 @@ jobs: echo $env:path.split(';') mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DQT6_DIR="$basedir/bin/Qt6.4.0-gcc12-shared/lib/cmake" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build run: | $basedir=(pwd).path - $basedir=($basedir).replace("\\","/")$exclude_key_words="perl","Strawberry" + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} $env:path="$new_path;$basedir/bin/mingw64/bin" From 51d87d1f17739dbb3a7638c15b6a1e74027caacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 23:07:37 +0800 Subject: [PATCH 0120/1123] limit number of processors --- .github/workflows/build-dev-win.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index c19251c2..12a12e10 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -109,7 +109,8 @@ jobs: $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} $env:path="$new_path;$basedir/bin/mingw64/bin" - cmake --build ./build --parallel + echo "Number of processors = $env:NUMBER_OF_PROCESSORS" + cmake --build ./build --parallel 10 - name: CMake install run: cmake --install ./build - name: Upload artifacts From 58f77f166f0aa6125732c1b54593573f8f6108dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 23:19:08 +0800 Subject: [PATCH 0121/1123] Fix install --- .github/workflows/build-dev-win.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 12a12e10..cfa397a0 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -112,7 +112,14 @@ jobs: echo "Number of processors = $env:NUMBER_OF_PROCESSORS" cmake --build ./build --parallel 10 - name: CMake install - run: cmake --install ./build + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" + cmake --install ./build - name: Upload artifacts uses: actions/upload-artifact@v3 with: From 7fb23a951a836a8b5b165076fdfe45c25bc5f119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 23:35:40 +0800 Subject: [PATCH 0122/1123] fix upload artifacts in win-build --- .github/workflows/build-dev-win.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index cfa397a0..214c697f 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -6,7 +6,7 @@ on: jobs: - win-build: + windows-build: runs-on: windows-latest steps: - name: Checkout repository @@ -100,7 +100,7 @@ jobs: echo $env:path.split(';') mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - name: CMake build run: | $basedir=(pwd).path @@ -120,10 +120,12 @@ jobs: foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} $env:path="$new_path;$basedir/bin/mingw64/bin" cmake --install ./build + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-windows.zip + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows path: install if-no-files-found: error From 503634a096d16362d9eb1df4455d940b45935c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 9 Apr 2023 23:51:51 +0800 Subject: [PATCH 0123/1123] use relative install path for windows --- MapViewer/install.cmake | 6 +++--- SlopeCraftL/install.cmake | 22 +++++++++++----------- SlopeCraftMain/install.cmake | 10 +++++----- VisualCraft/install.cmake | 4 ++-- VisualCraftL/install.cmake | 26 +++++++++++++------------- imageCutter/install.cmake | 4 ++-- vccl/install.cmake | 10 +++++----- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 0e661f75..53636b7d 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -3,8 +3,8 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINA if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS MapViewer - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . + BUNDLE DESTINATION . ) # Run windeployqt at build time @@ -16,7 +16,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) + SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) return() endif() diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index e6fc3647..b9bbcb62 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -17,29 +17,29 @@ set(SlopeCraft_SCL_Cpp_include_files if(CMAKE_SYSTEM_NAME MATCHES "Windows") # install for applications install(TARGETS SlopeCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION . + LIBRARY DESTINATION .) # install to lib dirs install(TARGETS SlopeCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib + RUNTIME DESTINATION ./../install_SlopeCraftL/Cpp/bin + LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib + # LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib ) # install(TARGETS SlopeCraftL_C - # RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/bin - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/lib + # RUNTIME DESTINATION ./../install_SlopeCraftL/C/bin + # LIBRARY DESTINATION ./../install_SlopeCraftL/C/lib - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/lib + # LIBRARY DESTINATION ./../install_SlopeCraftL/C/lib # ) install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include) + DESTINATION ./../install_SlopeCraftL/Cpp/include) # install(FILES ${SlopeCraft_SCL_C_include_files} - # DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/include) - SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) + # DESTINATION ./../install_SlopeCraftL/C/include) + SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) return() endif() diff --git a/SlopeCraftMain/install.cmake b/SlopeCraftMain/install.cmake index 5522a74e..e2b99667 100644 --- a/SlopeCraftMain/install.cmake +++ b/SlopeCraftMain/install.cmake @@ -58,7 +58,7 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Install app install(TARGETS SlopeCraft - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . ) # Run windeployqt at build time @@ -72,25 +72,25 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks) + DESTINATION Blocks) file(COPY ${SlopeCraft_install_jsons} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) # Install all png files of fixedblocks install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks/FixedBlocks) + DESTINATION Blocks/FixedBlocks) file(COPY ${SlopeCraft_install_png_fixedblocks} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) # Install all png files of customblocks install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks/CustomBlocks) + DESTINATION Blocks/CustomBlocks) file(COPY ${SlopeCraft_install_png_customblocks} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) # Install presets install(FILES ${SlopeCraft_install_presets} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks/Presets) + DESTINATION Blocks/Presets) file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index d75ccebf..c77cf230 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -4,11 +4,11 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINA if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . ) install(FILES vc-config.json - DESTINATION ${CMAKE_INSTALL_PREFIX}) + DESTINATION .) # Run windeployqt at build time add_custom_target(Windeployqt-VisualCraft ALL diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index 4792292e..c7f2e19a 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -24,26 +24,26 @@ set(VCL_include_headers if(${WIN32}) # install for app install(TARGETS VisualCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX} + # LIBRARY DESTINATION . ) install(FILES ${VCL_app_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks_VCL) + DESTINATION Blocks_VCL) # install for lib install(TARGETS VisualCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib) - install(TARGETS VisualCraftL_static - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib) - install(FILES ${VCL_include_headers} - DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include) + RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) - SlopeCraft_install_if_is_shared(ZLIB::ZLIB ${CMAKE_INSTALL_PREFIX}) - SlopeCraft_install_if_is_shared(libzip::zip ${CMAKE_INSTALL_PREFIX}) - SlopeCraft_install_if_is_shared(PNG::PNG ${CMAKE_INSTALL_PREFIX}) + # install(TARGETS VisualCraftL_static + # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) + install(FILES ${VCL_include_headers} + DESTINATION ../install_SlopeCraftL/Cpp/include) + SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) + SlopeCraft_install_if_is_shared(libzip::zip .) + SlopeCraft_install_if_is_shared(PNG::PNG .) return() endif() diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index cc4e0909..68abe2f6 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -3,8 +3,8 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINA if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS imageCutter - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . + BUNDLE DESTINATION . ) # Run windeployqt at build time diff --git a/vccl/install.cmake b/vccl/install.cmake index 3e7ef64a..eb62ff63 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -4,9 +4,9 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINA if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS vccl - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION .) install(FILES vccl-config.json - DESTINATION ${CMAKE_INSTALL_PREFIX}) + DESTINATION .) # Run windeployqt at build time add_custom_target(Windeployqt-vccl ALL @@ -25,10 +25,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") LIBRARY DESTINATION lib) install(FILES vccl-config.json DESTINATION bin) - + # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) - + return() endif() @@ -39,7 +39,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install config json file, vccl will try to find it by ./vccl-config.json install(FILES vccl-config.json - DESTINATION ${CMAKE_INSTALL_PREFIX}/vccl.app/Contents/MacOS) + DESTINATION ${CMAKE_INSTALL_PREFIX}/vccl.app/Contents/MacOS) # Run macdeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) From c8dc8a4e05207fa5785a54b3fc34485cc3ebe68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 00:53:42 +0800 Subject: [PATCH 0124/1123] copy deployed qt files when packing --- cpack/make-packs.cmake | 9 +++++++++ cpack/pack_deployed_files.cmake.in | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 cpack/pack_deployed_files.cmake.in diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 07647214..020386f8 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.16) + # Common attributes set(CPACK_PACKAGE_NAME SlopeCraft) set(CPACK_PACKAGE_VERSION ${SlopeCraft_version}) @@ -9,7 +11,14 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) endif() +if(${WIN32}) + configure_file(${CMAKE_SOURCE_DIR}/cpack/pack_deployed_files.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake + @ONLY) + list(APPEND CPACK_PRE_BUILD_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake) + # set(CPACK_PACKAGE_FILES) +endif() include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) diff --git a/cpack/pack_deployed_files.cmake.in b/cpack/pack_deployed_files.cmake.in new file mode 100644 index 00000000..bd99e0d4 --- /dev/null +++ b/cpack/pack_deployed_files.cmake.in @@ -0,0 +1,26 @@ +# message(STATUS "Copying qt deployed files") + +set(SlopeCraft_pack_dest ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/${CPACK_SYSTEM_NAME}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}) + +message(STATUS "Copying deployed files to ${SlopeCraft_pack_dest}") + +file(GLOB deployed_dlls "@CMAKE_INSTALL_PREFIX@/*.dll") +file(COPY ${deployed_dlls} DESTINATION ${SlopeCraft_pack_dest}) + +function(SlopeCraft_glob_and_copy sub_dir_name pack_dest) + message(STATUS "Copying @CMAKE_INSTALL_PREFIX@/${sub_dir_name} to ${pack_dest}/${sub_dir_name}") + file(GLOB temp "@CMAKE_INSTALL_PREFIX@/${sub_dir_name}/*") + file(COPY ${temp} DESTINATION ${pack_dest}/${sub_dir_name}) +endfunction(SlopeCraft_glob_and_copy) + +SlopeCraft_glob_and_copy(platforms ${SlopeCraft_pack_dest}) +SlopeCraft_glob_and_copy(imageformats ${SlopeCraft_pack_dest}) +SlopeCraft_glob_and_copy(styles ${SlopeCraft_pack_dest}) +SlopeCraft_glob_and_copy(tls ${SlopeCraft_pack_dest}) +SlopeCraft_glob_and_copy(translations ${SlopeCraft_pack_dest}) + +# message(STATUS "CPACK_PACKAGE_DIRECTORY = ${CPACK_PACKAGE_DIRECTORY}") + +# message(STATUS "CPACK_PACKAGE_INSTALL_DIRECTORY = ${CPACK_PACKAGE_INSTALL_DIRECTORY}") +# message(STATUS "CPACK_INSTALLED_DIRECTORIES = ${CPACK_INSTALLED_DIRECTORIES}") +# message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}") \ No newline at end of file From dd178a6c5f68a65f83496e9eedd6df14748b0870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 00:56:42 +0800 Subject: [PATCH 0125/1123] run cpack in win-build --- .github/workflows/build-dev-win.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 214c697f..a97f925e 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -122,11 +122,22 @@ jobs: cmake --install ./build - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload artifacts + - name: Make zip and 7z packs with CPack + run: | + mkdir pack + cpack ./build -G ZIP -B pack + cpack ./build -G 7Z -B pack + - name: Upload zip pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.zip + path: pack/SlopeCraft*.zip + if-no-files-found: error + - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows - path: install + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.7z + path: pack/SlopeCraft*.7z if-no-files-found: error From 33c0f8263825dff8a31c8b0150c6674a97ec855e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 01:11:03 +0800 Subject: [PATCH 0126/1123] fix cpack running --- .github/workflows/build-dev-win.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index a97f925e..798f0d58 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -121,12 +121,12 @@ jobs: $env:path="$new_path;$basedir/bin/mingw64/bin" cmake --install ./build - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV - name: Make zip and 7z packs with CPack run: | mkdir pack - cpack ./build -G ZIP -B pack - cpack ./build -G 7Z -B pack + cpack --config ./build/CPackConfig.cmake -G ZIP -B ./pack + cpack --config ./build/CPackConfig.cmake -G 7Z -B ./pack - name: Upload zip pack uses: actions/upload-artifact@v3 with: From 1fed34384a94a44eab3f05e9d9d57e8de4253743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 01:23:12 +0800 Subject: [PATCH 0127/1123] fix cpack running --- .github/workflows/build-dev-win.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 798f0d58..3026f976 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -124,9 +124,12 @@ jobs: run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV - name: Make zip and 7z packs with CPack run: | - mkdir pack - cpack --config ./build/CPackConfig.cmake -G ZIP -B ./pack - cpack --config ./build/CPackConfig.cmake -G 7Z -B ./pack + mkdir pack + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + cd ./build + cpack -G ZIP -B "$basedir/pack" + cpack -G 7Z -B "$basedir/pack" - name: Upload zip pack uses: actions/upload-artifact@v3 with: From a27af8e15c4a2d36cbfca150207a06b337dd43ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 01:41:59 +0800 Subject: [PATCH 0128/1123] see cpack log --- .github/workflows/build-dev-win.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index 3026f976..ef688ca7 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -129,7 +129,9 @@ jobs: $basedir=($basedir).replace("\\","/") cd ./build cpack -G ZIP -B "$basedir/pack" + type "D:/a/SlopeCraft/SlopeCraft/pack/_CPack_Packages/win64/ZIP/PreinstallOutput.log" cpack -G 7Z -B "$basedir/pack" + type "D:/a/SlopeCraft/SlopeCraft/pack/_CPack_Packages/win64/7Z/PreinstallOutput.log" - name: Upload zip pack uses: actions/upload-artifact@v3 with: From 5755be632247e0861b7c2e12488429c62a8bfa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 01:52:46 +0800 Subject: [PATCH 0129/1123] fix cpack running --- .github/workflows/build-dev-win.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml index ef688ca7..0b30afdf 100644 --- a/.github/workflows/build-dev-win.yml +++ b/.github/workflows/build-dev-win.yml @@ -124,14 +124,15 @@ jobs: run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV - name: Make zip and 7z packs with CPack run: | - mkdir pack $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" cd ./build cpack -G ZIP -B "$basedir/pack" - type "D:/a/SlopeCraft/SlopeCraft/pack/_CPack_Packages/win64/ZIP/PreinstallOutput.log" cpack -G 7Z -B "$basedir/pack" - type "D:/a/SlopeCraft/SlopeCraft/pack/_CPack_Packages/win64/7Z/PreinstallOutput.log" - name: Upload zip pack uses: actions/upload-artifact@v3 with: From 0eaea34c3d30ca7d635e2d92e561f0ca96d2f01a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 11:22:15 +0800 Subject: [PATCH 0130/1123] move windows-build scripts to build-dev.yml --- .github/workflows/build-dev-win.yml | 166 ---------------------------- .github/workflows/build-dev.yml | 163 ++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 167 deletions(-) delete mode 100644 .github/workflows/build-dev-win.yml diff --git a/.github/workflows/build-dev-win.yml b/.github/workflows/build-dev-win.yml deleted file mode 100644 index 0b30afdf..00000000 --- a/.github/workflows/build-dev-win.yml +++ /dev/null @@ -1,166 +0,0 @@ -name: Build dev version artifacts for window -on: - push: - branches: - - feat-github-action-win - -jobs: - - windows-build: - runs-on: windows-latest - steps: - - name: Checkout repository - uses: actions/checkout@v2 - #- name: See environment - # run: where.exe cmake ninja 7z clang gcc vcpkg - #- name: See versions - # run: | - # cmake --version - # ninja --version - # clang --version - # gcc --version - #- name: See Path - # run: $env:path -split ';' - - name: Make dirs - run: | - mkdir bin - mkdir bin/mingw64 - mkdir bin/Qt6.4.0-gcc12-shared - mkdir 3rdParty - - - name: Download mingw64 and extract - run: | - cmd - curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" - 7z x -obin bin/gcc12.7z - exit - # gcc installation dir: bin/mingw64 - # gcc.exe: bin/mingw64/bin/gcc.exe - # g++.exe: bin/mingw64/bin/g++.exe - - name: Build and install zlib - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - echo "basedir = $basedir" - cd 3rdParty - git clone https://github.com/madler/zlib.git - cd zlib - git checkout v1.2.13 - cd $basedir - mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" - cmake --build bin/build-zlib --parallel - cmake --install bin/build-zlib - - - name: Build and install libzip - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - cd 3rdParty - git clone https://github.com/nih-at/libzip.git - cd libzip - git checkout v1.9.2 - cd $basedir - mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true - cmake --build bin/build-libzip --parallel - cmake --install bin/build-libzip - - - name: Build and install libpng - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - cd 3rdParty - git clone https://github.com/glennrp/libpng.git - cd libpng - git checkout v1.6.39 - cd $basedir - mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" - cmake --build bin/build-libpng --parallel - cmake --install bin/build-libpng - - - name: Download Qt6.4.0-gcc12-shared and extract - run: | - cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" - 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z - exit - tree /f bin/Qt6.4.0-gcc12-shared - # Qt installation dir: bin/Qt6.4.0-gcc12-shared - - name: CMake configure - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - echo $new_path.split(';') - $env:path="$new_path;$basedir/bin/mingw64/bin" - echo $env:path.split(';') - mkdir build - mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None - - name: CMake build - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" - echo "Number of processors = $env:NUMBER_OF_PROCESSORS" - cmake --build ./build --parallel 10 - - name: CMake install - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" - cmake --install ./build - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV - - name: Make zip and 7z packs with CPack - run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" - cd ./build - cpack -G ZIP -B "$basedir/pack" - cpack -G 7Z -B "$basedir/pack" - - name: Upload zip pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.zip - path: pack/SlopeCraft*.zip - if-no-files-found: error - - name: Upload 7z pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.7z - path: pack/SlopeCraft*.7z - if-no-files-found: error - - - #- name: Tree /f - # run: tree /f D:/ > bin/all_files_on_D.txt - #- name: Upload all_files_on_D.txt - # uses: actions/upload-artifact@v3 - # with: - # name: all_files_on_D.txt - # path: bin/all_files_on_D.txt - # if-no-files-found: error - - - - #- name: Upload gcc - # uses: actions/upload-artifact@v3 - # with: - # name: gcc12-with-zlib,libzip,libpng - # path: bin/mingw64 - # if-no-files-found: error \ No newline at end of file diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index c3764380..c7628bae 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -4,6 +4,8 @@ on: push: branches: - feat-github-action + - main + - dev jobs: @@ -109,4 +111,163 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-tar.xz path: pack/SlopeCraft*.tar.xz - if-no-files-found: error \ No newline at end of file + if-no-files-found: error + + windows-build: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + #- name: See environment + # run: where.exe cmake ninja 7z clang gcc vcpkg + #- name: See versions + # run: | + # cmake --version + # ninja --version + # clang --version + # gcc --version + #- name: See Path + # run: $env:path -split ';' + - name: Make dirs + run: | + mkdir bin + mkdir bin/mingw64 + mkdir bin/Qt6.4.0-gcc12-shared + mkdir 3rdParty + + - name: Download mingw64 and extract + run: | + cmd + curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" + 7z x -obin bin/gcc12.7z + exit + # gcc installation dir: bin/mingw64 + # gcc.exe: bin/mingw64/bin/gcc.exe + # g++.exe: bin/mingw64/bin/g++.exe + - name: Build and install zlib + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + echo "basedir = $basedir" + cd 3rdParty + git clone https://github.com/madler/zlib.git + cd zlib + git checkout v1.2.13 + cd $basedir + mkdir bin/build-zlib + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake --build bin/build-zlib --parallel + cmake --install bin/build-zlib + + - name: Build and install libzip + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + cd 3rdParty + git clone https://github.com/nih-at/libzip.git + cd libzip + git checkout v1.9.2 + cd $basedir + mkdir bin/build-libzip + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true + cmake --build bin/build-libzip --parallel + cmake --install bin/build-libzip + + - name: Build and install libpng + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + cd 3rdParty + git clone https://github.com/glennrp/libpng.git + cd libpng + git checkout v1.6.39 + cd $basedir + mkdir bin/build-libpng + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake --build bin/build-libpng --parallel + cmake --install bin/build-libpng + + - name: Download Qt6.4.0-gcc12-shared and extract + run: | + cmd + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" + 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z + exit + tree /f bin/Qt6.4.0-gcc12-shared + # Qt installation dir: bin/Qt6.4.0-gcc12-shared + - name: CMake configure + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + echo $new_path.split(';') + $env:path="$new_path;$basedir/bin/mingw64/bin" + echo $env:path.split(';') + mkdir build + mkdir install + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None + - name: CMake build + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" + echo "Number of processors = $env:NUMBER_OF_PROCESSORS" + cmake --build ./build --parallel 10 + - name: CMake install + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" + cmake --install ./build + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV + - name: Make zip and 7z packs with CPack + run: | + $basedir=(pwd).path + $basedir=($basedir).replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" + cd ./build + cpack -G ZIP -B "$basedir/pack" + cpack -G 7Z -B "$basedir/pack" + - name: Upload zip pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.zip + path: pack/SlopeCraft*.zip + if-no-files-found: error + - name: Upload 7z pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.7z + path: pack/SlopeCraft*.7z + if-no-files-found: error + + + #- name: Tree /f + # run: tree /f D:/ > bin/all_files_on_D.txt + #- name: Upload all_files_on_D.txt + # uses: actions/upload-artifact@v3 + # with: + # name: all_files_on_D.txt + # path: bin/all_files_on_D.txt + # if-no-files-found: error + + + + #- name: Upload gcc + # uses: actions/upload-artifact@v3 + # with: + # name: gcc12-with-zlib,libzip,libpng + # path: bin/mingw64 + # if-no-files-found: error \ No newline at end of file From e059993e78b3defd9b8311374588660067e32b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 14:35:23 +0800 Subject: [PATCH 0131/1123] try to fix short sha in win-build --- .github/workflows/build-dev.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index c7628bae..0082b2a4 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -118,6 +118,12 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + - name: Get short SHA + run: | + echo "GITHUB_SHA = $GITHUB_SHA" + $short_sha=$GITHUB_SHA.substring(0,7) + echo "short_sha = $short_sha" + echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV #- name: See environment # run: where.exe cmake ninja 7z clang gcc vcpkg #- name: See versions @@ -227,8 +233,6 @@ jobs: foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} $env:path="$new_path;$basedir/bin/mingw64/bin" cmake --install ./build - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $env:GITHUB_ENV - name: Make zip and 7z packs with CPack run: | $basedir=(pwd).path @@ -240,16 +244,18 @@ jobs: cd ./build cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" + - name: Upload zip pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.zip + name: SlopeCraft-dev-${{env.SHORT_SHA}}-windows.zip path: pack/SlopeCraft*.zip if-no-files-found: error + - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-windows.7z + name: SlopeCraft-dev-${{env.SHORT_SHA}}-windows.7z path: pack/SlopeCraft*.7z if-no-files-found: error From 25cc0e9b5bd811ca82eddc43bf8cd7d30826ed04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 14:37:33 +0800 Subject: [PATCH 0132/1123] try to fix short sha in win-build --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 0082b2a4..e73ab2ad 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -120,8 +120,8 @@ jobs: uses: actions/checkout@v2 - name: Get short SHA run: | - echo "GITHUB_SHA = $GITHUB_SHA" - $short_sha=$GITHUB_SHA.substring(0,7) + echo "GITHUB_SHA = $env:GITHUB_SHA" + $short_sha=$env:GITHUB_SHA.substring(0,7) echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV #- name: See environment From dca2f720318f2e9a74ee674e0b94d6c012bb8906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:05:32 +0800 Subject: [PATCH 0133/1123] test build_type matrix --- .github/workflows/build-dev.yml | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e73ab2ad..ad3257e3 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -11,6 +11,19 @@ jobs: macos-build: runs-on: macos-latest + strategy: + matrix: + build_type: [Release, Debug] + env: + BUILD_TYPE: ${{ matrix.build_type }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo ${{ matrix.build_type }} + echo $matrix + echo $matrix.build_type + echo $build_type + echo $BUILD_TYPE steps: - name: Install Ninja build system run: brew install ninja @@ -48,7 +61,19 @@ jobs: linux-build: runs-on: ubuntu-latest + strategy: + matrix: + build_type: [Release, Debug] + env: + BUILD_TYPE: ${{ matrix.build_type }} steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo ${{ matrix.build_type }} + echo $matrix + echo $matrix.build_type + echo $build_type + echo $BUILD_TYPE - name: Make directories run: mkdir build install pack @@ -115,7 +140,19 @@ jobs: windows-build: runs-on: windows-latest + strategy: + matrix: + build_type: [Release, Debug] + env: + BUILD_TYPE: ${{ matrix.build_type }} steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo ${{ matrix.build_type }} + echo $matrix + echo $matrix.build_type + echo $BUILD_TYPE + echo $env:BUILD_TYPE - name: Checkout repository uses: actions/checkout@v2 - name: Get short SHA From ef726f0e57371edededca0c15dbe378844f972c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:06:23 +0800 Subject: [PATCH 0134/1123] fix github action yaml --- .github/workflows/build-dev.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index ad3257e3..a9305d1b 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -24,7 +24,6 @@ jobs: echo $matrix.build_type echo $build_type echo $BUILD_TYPE - steps: - name: Install Ninja build system run: brew install ninja - name: Install dependencies From a864e05a1d8b3913d30ea1b4659371654caac579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:08:54 +0800 Subject: [PATCH 0135/1123] test build_type matrix --- .github/workflows/build-dev.yml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index a9305d1b..4aec20fc 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -19,10 +19,6 @@ jobs: steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | - echo ${{ matrix.build_type }} - echo $matrix - echo $matrix.build_type - echo $build_type echo $BUILD_TYPE - name: Install Ninja build system run: brew install ninja @@ -68,10 +64,6 @@ jobs: steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | - echo ${{ matrix.build_type }} - echo $matrix - echo $matrix.build_type - echo $build_type echo $BUILD_TYPE - name: Make directories run: mkdir build install pack @@ -147,11 +139,8 @@ jobs: steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | - echo ${{ matrix.build_type }} - echo $matrix - echo $matrix.build_type - echo $BUILD_TYPE - echo $env:BUILD_TYPE + echo "BUILD_TYPE = $BUILD_TYPE" + echo "env:BUILD_TYPE = $env:BUILD_TYPE" - name: Checkout repository uses: actions/checkout@v2 - name: Get short SHA From d23584f427f75856575971e4905dee590fdce82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:14:03 +0800 Subject: [PATCH 0136/1123] change CMAKE_BUILD_TYPE by matrix.build_type --- .github/workflows/build-dev.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4aec20fc..9857855e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -31,7 +31,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_BUILD_TYPE=Release + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build @@ -51,7 +51,7 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v2 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-macos + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-macos path: build/install linux-build: @@ -96,7 +96,7 @@ jobs: uses: actions/checkout@v2 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=Debug + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - name: CMake build run: cmake --build ./build --parallel @@ -118,14 +118,14 @@ jobs: - name: Upload deb pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-deb + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-linux-deb path: pack/SlopeCraft*.deb if-no-files-found: error - name: Upload tar.xz pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-linux-tar.xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-linux-tar-xz path: pack/SlopeCraft*.tar.xz if-no-files-found: error @@ -139,7 +139,6 @@ jobs: steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | - echo "BUILD_TYPE = $BUILD_TYPE" echo "env:BUILD_TYPE = $env:BUILD_TYPE" - name: Checkout repository uses: actions/checkout@v2 @@ -186,7 +185,7 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -200,7 +199,7 @@ jobs: git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -214,7 +213,7 @@ jobs: git checkout v1.6.39 cd $basedir mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -238,7 +237,7 @@ jobs: echo $env:path.split(';') mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=Release -DSlopeCraft_GPU_API:STRING=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=$env:BUILD_TYPE -DSlopeCraft_GPU_API:STRING=None - name: CMake build run: | $basedir=(pwd).path @@ -273,14 +272,14 @@ jobs: - name: Upload zip pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{env.SHORT_SHA}}-windows.zip + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-windows-zip path: pack/SlopeCraft*.zip if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{env.SHORT_SHA}}-windows.7z + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-windows-7z path: pack/SlopeCraft*.7z if-no-files-found: error From 8ac965bf3a78243c1f236634aa8dfd837c3128bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:18:11 +0800 Subject: [PATCH 0137/1123] assign gpu_api by matrix --- .github/workflows/build-dev.yml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 9857855e..23f393f4 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -13,13 +13,16 @@ jobs: runs-on: macos-latest strategy: matrix: - build_type: [Release, Debug] + build_type: [Debug, Release] + gpu_api: [None] env: BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE + echo $GPU_API - name: Install Ninja build system run: brew install ninja - name: Install dependencies @@ -31,7 +34,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API="None" -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build @@ -58,13 +61,16 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - build_type: [Release, Debug] + build_type: [Debug, Release] + gpu_api: [None] env: BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE + echo $GPU_API - name: Make directories run: mkdir build install pack @@ -96,7 +102,7 @@ jobs: uses: actions/checkout@v2 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=None -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - name: CMake build run: cmake --build ./build --parallel @@ -133,13 +139,16 @@ jobs: runs-on: windows-latest strategy: matrix: - build_type: [Release, Debug] + build_type: [Debug, Release] + gpu_api: [None] env: BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" + echo "env:GPU_API = $env:GPU_API" - name: Checkout repository uses: actions/checkout@v2 - name: Get short SHA @@ -237,7 +246,7 @@ jobs: echo $env:path.split(';') mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=$env:BUILD_TYPE -DSlopeCraft_GPU_API:STRING=None + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=$env:BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$env:GPU_API - name: CMake build run: | $basedir=(pwd).path From 96ba107fd0d3c8e6d3fc6f957300615132b21954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 15:25:01 +0800 Subject: [PATCH 0138/1123] try to fix build_type on win-build --- .github/workflows/build-dev.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 23f393f4..fb374d63 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -188,13 +188,14 @@ jobs: $basedir=(pwd).path $basedir=($basedir).replace("\\","/") echo "basedir = $basedir" + $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty git clone https://github.com/madler/zlib.git cd zlib git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -202,13 +203,14 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty git clone https://github.com/nih-at/libzip.git cd libzip git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -216,13 +218,14 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty git clone https://github.com/glennrp/libpng.git cd libpng git checkout v1.6.39 cd $basedir mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -238,6 +241,8 @@ jobs: run: | $basedir=(pwd).path $basedir=($basedir).replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + $GPU_API=$env:GPU_API $exclude_key_words="perl","Strawberry" $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} @@ -246,7 +251,7 @@ jobs: echo $env:path.split(';') mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE:STRING=$env:BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$env:GPU_API + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" - name: CMake build run: | $basedir=(pwd).path From 3c609deceb55b7e90f39830cc69161e21d6e1896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 16:05:53 +0800 Subject: [PATCH 0139/1123] Remove empty OpenCL rc file at build time --- CMakeLists.txt | 16 ++----------- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 23 +++++++++++++++---- .../OpenCL/remove_empty_rc_file.cmake.in | 15 ++++++++++++ 3 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index d42450f4..68e87385 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,13 +85,13 @@ if(${SlopeCraft_vectorize}) # list(APPEND SlopeCraft_vectorize_flags "-O3") endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if(${LINUX}) message(STATUS "setting runpath for linux") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if(${WIN32}) add_compile_definitions("_CRT_SECURE_NO_WARNINGS") endif() @@ -105,9 +105,6 @@ add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) include_directories(${CMAKE_BINARY_DIR}/utilities) -set(SlopeCraft_resource_file_to_touch_and_remove) -mark_as_advanced(SlopeCraft_resource_file_to_touch_and_remove) - add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) @@ -118,14 +115,5 @@ add_subdirectory(VisualCraftL) add_subdirectory(VisualCraft) add_subdirectory(vccl) -if(EXISTS ${CMAKE_BINARY_DIR}/utilities/ColorManip/__rsc_ColorManip_cl_rc.c) - file(SIZE ${CMAKE_BINARY_DIR}/utilities/ColorManip/__rsc_ColorManip_cl_rc.c size_of_file) - - if(${size_of_file} LESS_EQUAL 0) - # file(REMOVE ${CMAKE_BINARY_DIR}/utilities/ColorManip/__rsc_ColorManip_cl_rc.c) - endif() -endif() - include(cmake/install.cmake) - include(cpack/make-packs.cmake) \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index e47b4301..65f94b14 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -15,11 +15,26 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(OCLWrapper PROPERTIES POSITION_INDEPENDENT_CODE TRUE) endif() +# convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) add_resource(ColorManip_cl_rc ColorDiff.cl) -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/__rsc_ColorManip_cl_rc.c) -mark_as_advanced(SlopeCraft_resource_file_to_touch_and_remove) -list(APPEND SlopeCraft_resource_file_to_touch_and_remove ${CMAKE_CURRENT_BINARY_DIR}/__rsc_ColorManip_cl_rc.c) +# create an empty .c file to pass qt's checking during configuration +set(file_to_check ${CMAKE_CURRENT_BINARY_DIR}/__rsc_ColorManip_cl_rc.c) +file(TOUCH ${file_to_check}) + +# This script is expceted to delete the touched empty .c file, +# because ResourceCreator.cmake thinks the resource is generated, even if the .c file is empty. +# So we need to delete .c manually to force ResourceCreator.cmake to generate it. +configure_file(remove_empty_rc_file.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/remove_empty_rc_file.cmake + @ONLY) + +# Add a custom target to execute the cmake script +add_custom_target(RemoveEmptyRCFile ALL + COMMAND cmake -P ${CMAKE_CURRENT_BINARY_DIR}/remove_empty_rc_file.cmake) + +# The custom target must be executed before ColorManip_cl_rc +add_dependencies(ColorManip_cl_rc RemoveEmptyRCFile) target_include_directories(OCLWrapper PRIVATE ${SlopeCraft_Eigen3_include_dir}) target_include_directories(OCLWrapper PUBLIC ${CMAKE_SOURCE_DIR}) @@ -31,5 +46,5 @@ target_link_libraries(GPUInterface PUBLIC OCLWrapper) target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) if(${LINUX}) - set_target_properties(GPUInterface PROPERTIES TARGET_INDENPENDENT_CODE TRUE) + set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) endif() \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in b/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in new file mode 100644 index 00000000..54ff74a0 --- /dev/null +++ b/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in @@ -0,0 +1,15 @@ +set(file_to_check @file_to_check@) + +if(NOT EXISTS ${file_to_check}) + return() +endif() + +file(SIZE ${file_to_check} file_size) + +if(${file_to_check} GREATER 0) + return() +endif() + +message(STATUS "${file_to_check} is found, but it is empty. Remove it so that it will be generated correctly.") + +file(REMOVE ${file_to_check}) \ No newline at end of file From 03cdf9e61b828802cad9cca0d948ac1e1d7b1517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 16:06:31 +0800 Subject: [PATCH 0140/1123] update translations --- VisualCraft/others/VisualCraft_en_US.ts | 60 ++++++++++++------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 1004a1c6..b81f487d 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -314,7 +314,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 全部方块 All blocks @@ -691,88 +691,88 @@ If you select a block in "Avaliable blocks" page, the other page will %1 - + 原版资源包 Vanilla - - 原版json - Default - - - + 选择资源包 Select resource pack - - 选择方块id json文件 - Select block state list json file - - - + 资源包解析失败 Failed to parse resource pack - + 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. - - 方块状态列表json解析失败 - Failed to parse block state list json + + 原版 json + - - 资源包/方块状态列表json解析失败 - Failed to parse resource packs or bsl jsons. + + 选择方块 id json 文件 + - + + 方块状态列表 json 解析失败 + + + + + 资源包/方块状态列表 json 解析失败 + + + + 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. - + 设置可用方块失败 Failed to set avaliable blocks - + 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. - + 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) - + 选择图片(可多选) Select images - + 读取图片失败 Failed to load image. - + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. - + 设置图片失败 Failed to set image - + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. From 1cf3b750a9fb483d5425a178eb5eb38694634ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 16:29:33 +0800 Subject: [PATCH 0141/1123] disable bzip2, lzma and zstd support for win-build --- .github/workflows/build-dev.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index fb374d63..d79f89b5 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -3,7 +3,6 @@ on: pull_request: push: branches: - - feat-github-action - main - dev @@ -210,7 +209,7 @@ jobs: git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip From 5c7cf7a14935e8876a820f58740dcdf59bce8850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 10 Apr 2023 16:38:51 +0800 Subject: [PATCH 0142/1123] simpilize window-build commands --- .github/workflows/build-dev.yml | 65 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index d79f89b5..3d5d6dad 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -53,7 +53,7 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v2 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-macos + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install linux-build: @@ -123,14 +123,14 @@ jobs: - name: Upload deb pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-linux-deb + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb path: pack/SlopeCraft*.deb if-no-files-found: error - name: Upload tar.xz pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-linux-tar-xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz path: pack/SlopeCraft*.tar.xz if-no-files-found: error @@ -148,14 +148,26 @@ jobs: run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" + - name: Checkout repository uses: actions/checkout@v2 + - name: Get short SHA run: | echo "GITHUB_SHA = $env:GITHUB_SHA" $short_sha=$env:GITHUB_SHA.substring(0,7) echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV + + - name: Filter perl-related pathes from env:path, and append directory of gcc12 to path + run: | + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$new_path;$basedir/bin/mingw64/bin" + echo "New path : $env:path.split(';')" + echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV + #- name: See environment # run: where.exe cmake ninja 7z clang gcc vcpkg #- name: See versions @@ -184,8 +196,7 @@ jobs: # g++.exe: bin/mingw64/bin/g++.exe - name: Build and install zlib run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") + $basedir=(pwd).path.replace("\\","/") echo "basedir = $basedir" $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty @@ -200,8 +211,7 @@ jobs: - name: Build and install libzip run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") + $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty git clone https://github.com/nih-at/libzip.git @@ -215,8 +225,7 @@ jobs: - name: Build and install libpng run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") + $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE cd 3rdParty git clone https://github.com/glennrp/libpng.git @@ -238,46 +247,28 @@ jobs: # Qt installation dir: bin/Qt6.4.0-gcc12-shared - name: CMake configure run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") + $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - echo $new_path.split(';') - $env:path="$new_path;$basedir/bin/mingw64/bin" - echo $env:path.split(';') + $env:path=$env:NEW_PATH mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" - name: CMake build run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH echo "Number of processors = $env:NUMBER_OF_PROCESSORS" cmake --build ./build --parallel 10 - name: CMake install run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH cmake --install ./build - name: Make zip and 7z packs with CPack run: | - $basedir=(pwd).path - $basedir=($basedir).replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH cd ./build cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" @@ -285,14 +276,14 @@ jobs: - name: Upload zip pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-windows-zip + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-windows-zip path: pack/SlopeCraft*.zip if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-windows-7z + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-windows-7z path: pack/SlopeCraft*.7z if-no-files-found: error From 6958f9869d4f63b9b8ccbd8338de59aaeef33a79 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 17:58:28 +0800 Subject: [PATCH 0143/1123] fix windows build --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3d5d6dad..e51f2f5e 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -161,6 +161,7 @@ jobs: - name: Filter perl-related pathes from env:path, and append directory of gcc12 to path run: | + $basedir=(pwd).path.replace("\\","/") $exclude_key_words="perl","Strawberry" $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} @@ -251,6 +252,7 @@ jobs: $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API $env:path=$env:NEW_PATH + echo "env:path = $env:path" mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" From d7f3fd7ed052182e83ca28e26b7ec5ca497735a0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 21:11:03 +0800 Subject: [PATCH 0144/1123] Generate OpenCL resource file at config time --- CMakeLists.txt | 2 ++ cmake/find_ResourceCreator.cmake | 11 +++++++++- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 20 +------------------ .../OpenCL/remove_empty_rc_file.cmake.in | 15 -------------- vccl/add_test_vccl.cmake | 12 ++++++++++- 5 files changed, 24 insertions(+), 36 deletions(-) delete mode 100644 utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 68e87385..7300169a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) + # manage the install prefix if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) @@ -105,6 +106,7 @@ add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) include_directories(${CMAKE_BINARY_DIR}/utilities) + add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) diff --git a/cmake/find_ResourceCreator.cmake b/cmake/find_ResourceCreator.cmake index 76d70ce0..391fde21 100644 --- a/cmake/find_ResourceCreator.cmake +++ b/cmake/find_ResourceCreator.cmake @@ -7,8 +7,17 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/.git) endif() message(STATUS "Cloning ResourceCreator.cmake...") -execute_process(COMMAND git clone "https://github.com/isRyven/ResourceCreator.cmake.git" +execute_process( + COMMAND git clone "https://github.com/SlopeCraft/ResourceCreator.cmake.git" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty COMMAND_ERROR_IS_FATAL ANY ) + +execute_process( + COMMAND git checkout v0.0.0 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake + COMMAND_ERROR_IS_FATAL ANY +) + + set(SlopeCraft_rc_creator_found TRUE) \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 65f94b14..bedcc013 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -16,25 +16,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() # convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) -add_resource(ColorManip_cl_rc ColorDiff.cl) - -# create an empty .c file to pass qt's checking during configuration -set(file_to_check ${CMAKE_CURRENT_BINARY_DIR}/__rsc_ColorManip_cl_rc.c) -file(TOUCH ${file_to_check}) - -# This script is expceted to delete the touched empty .c file, -# because ResourceCreator.cmake thinks the resource is generated, even if the .c file is empty. -# So we need to delete .c manually to force ResourceCreator.cmake to generate it. -configure_file(remove_empty_rc_file.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/remove_empty_rc_file.cmake - @ONLY) - -# Add a custom target to execute the cmake script -add_custom_target(RemoveEmptyRCFile ALL - COMMAND cmake -P ${CMAKE_CURRENT_BINARY_DIR}/remove_empty_rc_file.cmake) - -# The custom target must be executed before ColorManip_cl_rc -add_dependencies(ColorManip_cl_rc RemoveEmptyRCFile) +add_resource_config_time(ColorManip_cl_rc ColorDiff.cl) target_include_directories(OCLWrapper PRIVATE ${SlopeCraft_Eigen3_include_dir}) target_include_directories(OCLWrapper PUBLIC ${CMAKE_SOURCE_DIR}) diff --git a/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in b/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in deleted file mode 100644 index 54ff74a0..00000000 --- a/utilities/GPUWrapper/OpenCL/remove_empty_rc_file.cmake.in +++ /dev/null @@ -1,15 +0,0 @@ -set(file_to_check @file_to_check@) - -if(NOT EXISTS ${file_to_check}) - return() -endif() - -file(SIZE ${file_to_check} file_size) - -if(${file_to_check} GREATER 0) - return() -endif() - -message(STATUS "${file_to_check} is found, but it is empty. Remove it so that it will be generated correctly.") - -file(REMOVE ${file_to_check}) \ No newline at end of file diff --git a/vccl/add_test_vccl.cmake b/vccl/add_test_vccl.cmake index 41c0f4bb..37a2e117 100644 --- a/vccl/add_test_vccl.cmake +++ b/vccl/add_test_vccl.cmake @@ -5,6 +5,16 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_vccl_images) set(temp_testname_prefix test_vccl_images/) +file(GLOB test_source_images "${CMAKE_SOURCE_DIR}/binaries/images/*") + +set(test_source_images_space_list) + +foreach(img ${test_source_images}) + set(test_source_images_space_list "${test_source_images_space_list} \"${img}\"") +endforeach(img ${test_source_images}) + +message(STATUS "test_source_images_space_list = ${test_source_images_space_list}") + set(list_faces "up" "down" "north" "south" "east" "west") set(algos "RGB") @@ -34,7 +44,7 @@ foreach(_layers RANGE 1 3 1) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # COMMAND vccl --bsl ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json --rp ${zip_file} --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${VCL_test_images} --dither=${_dither} -j1 --out-image --benchmark --prefix ${test_name} --gpu --disable-config - COMMAND vccl --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${CMAKE_SOURCE_DIR}/binaries/images/* --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --gpu --lite --nbt ${generate_schem} + COMMAND vccl --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${test_source_images_space_list} --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --lite --nbt ${generate_schem} ) # From 9e80ecfdbd9c1b036a1acc318b65c84aecc6cca8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:40:47 +0800 Subject: [PATCH 0145/1123] fix testing --- tests/CMakeLists.txt | 2 +- tests/test_libSchem/CMakeLists.txt | 5 ++++- tests/test_libSchem/test_libSchem.cpp | 6 +++++- vccl/add_test_vccl.cmake | 25 +++++++++++++++++++++---- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5ad08920..e981ff58 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(test_libSchem) -add_subdirectory(test_SlopeCraftL) \ No newline at end of file +#add_subdirectory(test_SlopeCraftL) \ No newline at end of file diff --git a/tests/test_libSchem/CMakeLists.txt b/tests/test_libSchem/CMakeLists.txt index e565ba64..c57fc79b 100644 --- a/tests/test_libSchem/CMakeLists.txt +++ b/tests/test_libSchem/CMakeLists.txt @@ -6,4 +6,7 @@ add_executable(test_libSchem test_libSchem.cpp) -target_link_libraries(test_libSchem PRIVATE Schem NBTWriter -lz) \ No newline at end of file +target_link_libraries(test_libSchem PRIVATE Schem NBTWriter -lz) + +add_test(NAME test_libSchem + COMMAND test_libSchem) \ No newline at end of file diff --git a/tests/test_libSchem/test_libSchem.cpp b/tests/test_libSchem/test_libSchem.cpp index 3f4a362e..aa26a5ff 100644 --- a/tests/test_libSchem/test_libSchem.cpp +++ b/tests/test_libSchem/test_libSchem.cpp @@ -43,7 +43,7 @@ int main() { schem.resize(12, 9, 12); - std::vector ids; //= {"minecraft:air", "minecraft:glass"}; + std::vector ids; //= {"minecraft:air", "minecraft:glass"}; ids.resize(1); for (auto &id : ids) { @@ -85,6 +85,7 @@ int main() { if (has_error) { cout << "error idx = " << err_idx << endl; + return 1; } libSchem::litematic_info info; @@ -98,18 +99,21 @@ int main() { cout << "Failed to export file " << "test12.litematic" << endl; cout << "Error info = " << error_str << endl; + return 1; } if (!schem.export_structure("test12.nbt", true, nullptr, &error_str)) { cout << "Failed to export file " << "test12.nbt" << endl; cout << "Error info = " << error_str << endl; + return 1; } if (!schem.export_WESchem("test12.schem", weinfo, nullptr, &error_str)) { cout << "Failed to export file " << "test12.schem" << endl; cout << "Error info = " << error_str << endl; + return 1; } return 0; diff --git a/vccl/add_test_vccl.cmake b/vccl/add_test_vccl.cmake index 37a2e117..e60654b7 100644 --- a/vccl/add_test_vccl.cmake +++ b/vccl/add_test_vccl.cmake @@ -10,8 +10,17 @@ file(GLOB test_source_images "${CMAKE_SOURCE_DIR}/binaries/images/*") set(test_source_images_space_list) foreach(img ${test_source_images}) - set(test_source_images_space_list "${test_source_images_space_list} \"${img}\"") + if(${img} MATCHES " ") + set(test_source_images_space_list "${test_source_images_space_list} \"${img}\"") + else() + set(test_source_images_space_list "${test_source_images_space_list} ${img}") + endif() endforeach(img ${test_source_images}) +string(LENGTH ${test_source_images_space_list} len) +math(EXPR len "${len}-1") +string(SUBSTRING ${test_source_images_space_list} 1 ${len} test_source_images_space_list) +unset(len) + message(STATUS "test_source_images_space_list = ${test_source_images_space_list}") @@ -21,6 +30,10 @@ set(algos "RGB") set(dither "false") +cmake_policy(PUSH) + +cmake_policy(SET CMP0110 OLD) + # set(dither "true" "false") foreach(_layers RANGE 1 3 1) foreach(_ver RANGE 12 19) @@ -44,12 +57,16 @@ foreach(_layers RANGE 1 3 1) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # COMMAND vccl --bsl ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json --rp ${zip_file} --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${VCL_test_images} --dither=${_dither} -j1 --out-image --benchmark --prefix ${test_name} --gpu --disable-config - COMMAND vccl --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${test_source_images_space_list} --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --lite --nbt ${generate_schem} - ) + COMMAND vccl --img ${test_source_images} --mcver ${_ver} --face ${_face} --layers ${_layers} --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --lite --nbt ${generate_schem} + COMMAND_EXPAND_LISTS + ) # endforeach(_dither ${dither}) endforeach(_algo ${algos}) endforeach(_face ${list_faces}) endforeach(_ver RANGE 12 19) -endforeach(_layers RANGE 1 3 1) \ No newline at end of file +endforeach(_layers RANGE 1 3 1) + + +cmake_policy(POP) \ No newline at end of file From 84cf03b1a639926fe1c3d6499ff2d1f4cdbe22a0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:40:57 +0800 Subject: [PATCH 0146/1123] Add ctest to win-build and linux-build --- .github/workflows/build-dev.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e51f2f5e..daf112ac 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -110,6 +110,13 @@ jobs: run: cmake --install ./build #- name: List all files # run: ls -R + + - name: Run CTest + if: matrix.build_type == Debug + run: ctest -j20 --output-on-failure --stop-on-failure + + - name: Make zip and 7z packs with CPack + - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -256,17 +263,27 @@ jobs: mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" + - name: CMake build run: | $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH echo "Number of processors = $env:NUMBER_OF_PROCESSORS" cmake --build ./build --parallel 10 + - name: CMake install run: | $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cmake --install ./build + + - name: Run CTest + if: matrix.build_type == Debug + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + ctest -j10 --output-on-failure --stop-on-failure + - name: Make zip and 7z packs with CPack run: | $basedir=(pwd).path.replace("\\","/") From 1bdac3e9b58b4213880fbb155bd199706e62cb32 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:42:43 +0800 Subject: [PATCH 0147/1123] fix github action --- .github/workflows/build-dev.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index daf112ac..6989010b 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -106,16 +106,12 @@ jobs: - name: CMake build run: cmake --build ./build --parallel - - name: CMake install # Uptil now, we have not get a prefect way to deploy qt shared libs. This may be finished in cmake script + - name: CMake install run: cmake --install ./build - #- name: List all files - # run: ls -R - name: Run CTest if: matrix.build_type == Debug run: ctest -j20 --output-on-failure --stop-on-failure - - - name: Make zip and 7z packs with CPack - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV From ce7e76806ef7ed7accd945a5d34fea35ff0a1e3c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:44:08 +0800 Subject: [PATCH 0148/1123] fix github action --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 6989010b..73af7aa5 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -110,7 +110,7 @@ jobs: run: cmake --install ./build - name: Run CTest - if: matrix.build_type == Debug + if: matrix.build_type == "Debug" run: ctest -j20 --output-on-failure --stop-on-failure - name: Get short SHA @@ -274,7 +274,7 @@ jobs: cmake --install ./build - name: Run CTest - if: matrix.build_type == Debug + if: matrix.build_type == "Debug" run: | $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH From 0263ee5540aa094dfe12ad0cb9276d44f1cf3caf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:45:49 +0800 Subject: [PATCH 0149/1123] fix github action --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 73af7aa5..f44634de 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -110,7 +110,7 @@ jobs: run: cmake --install ./build - name: Run CTest - if: matrix.build_type == "Debug" + if: matrix.build_type == 'Debug' run: ctest -j20 --output-on-failure --stop-on-failure - name: Get short SHA @@ -274,7 +274,7 @@ jobs: cmake --install ./build - name: Run CTest - if: matrix.build_type == "Debug" + if: matrix.build_type == 'Debug' run: | $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH From 27ffb05a8b97d20edad91bd79dc2da622c74fa09 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 10 Apr 2023 23:50:32 +0800 Subject: [PATCH 0150/1123] fix github action --- .github/workflows/build-dev.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f44634de..81477bf2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -111,7 +111,9 @@ jobs: - name: Run CTest if: matrix.build_type == 'Debug' - run: ctest -j20 --output-on-failure --stop-on-failure + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -278,6 +280,7 @@ jobs: run: | $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH + cd ./build ctest -j10 --output-on-failure --stop-on-failure - name: Make zip and 7z packs with CPack From a5afe75b975185eb50ab291ccb455d4782cbe931 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 11 Apr 2023 00:06:37 +0800 Subject: [PATCH 0151/1123] disable win-build ctest, and test only on Release --- .github/workflows/build-dev.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 81477bf2..e7f5574a 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -110,7 +110,7 @@ jobs: run: cmake --install ./build - name: Run CTest - if: matrix.build_type == 'Debug' + if: matrix.build_type == 'Release' run: | cd ./build ctest -j20 --output-on-failure --stop-on-failure @@ -275,13 +275,13 @@ jobs: $env:path=$env:NEW_PATH cmake --install ./build - - name: Run CTest - if: matrix.build_type == 'Debug' - run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - cd ./build - ctest -j10 --output-on-failure --stop-on-failure + #- name: Run CTest + # if: matrix.build_type == 'Release' + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $env:path=$env:NEW_PATH + # cd ./build + # ctest -j10 --output-on-failure --stop-on-failure - name: Make zip and 7z packs with CPack run: | From 454f045527c26e8be1d5aaba56f7c7945d40e54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 11 Apr 2023 13:39:34 +0800 Subject: [PATCH 0152/1123] configure qt deploy code with @ONLY --- MapViewer/install.cmake | 4 +++- SlopeCraftMain/install.cmake | 4 +++- VisualCraft/install.cmake | 4 +++- cmake/deploy_qt.cmake.in | 4 ++++ cmake/install.cmake | 36 +++++++++++++++++++++++++++--------- imageCutter/install.cmake | 4 +++- vccl/install.cmake | 4 +++- 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 53636b7d..5835c7a9 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -1,5 +1,7 @@ set(AppName MapViewer) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS MapViewer diff --git a/SlopeCraftMain/install.cmake b/SlopeCraftMain/install.cmake index e2b99667..392d4c0c 100644 --- a/SlopeCraftMain/install.cmake +++ b/SlopeCraftMain/install.cmake @@ -13,7 +13,9 @@ file(GLOB SlopeCraft_install_presets "${CMAKE_CURRENT_SOURCE_DIR}/others/*.sc_preset_json") set(AppName SlopeCraft) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index c77cf230..faddbf21 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -1,6 +1,8 @@ set(AppName VisualCraft) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index 32ec249e..2b8e22dd 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -1,3 +1,5 @@ +# This file is expected to be run during installation + if(${WIN32}) message(STATUS "Running windeployqt for @AppName@ ...") execute_process( @@ -6,6 +8,8 @@ if(${WIN32}) OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) + message(STATUS "Current directory: ${CMAKE_CURRENT_SOURCE_DIR}") + return() endif() diff --git a/cmake/install.cmake b/cmake/install.cmake index f03a4ef4..51f75eea 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -6,23 +6,41 @@ set(SlopeCraft_readme_and_license_files license-translations/LICENSE-zh.md ) +function(SlopeCraft_install_dll dllname dest is_required) + find_library(dll_file + NAMES ${dllname} + PATHS ${CMAKE_PREFIX_PATH} + NO_CMAKE_INSTALL_PREFIX + NO_CACHE) + + if(NOT dll_file) + if(${is_required}) + message(WARNING "Failed to find ${dllname} dll.") + else() + message(STATUS "Failed to find ${dllname} dll.") + endif() + return() + endif() + + message(STATUS "Install ${dll_file} to ${dest}") + install(FILES ${dll_file} + DESTINATION ${dest}) +endfunction(SlopeCraft_install_dll) + if(${WIN32}) install(FILES ${SlopeCraft_readme_and_license_files} DESTINATION ${CMAKE_INSTALL_PREFIX}) set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - find_library(libgomp_dll - NAMES gomp-1 - PATHS ${CMAKE_PREFIX_PATH} - NO_CMAKE_INSTALL_PREFIX) - - if(NOT libgomp_dll) - message(WARNING "Failed to find libgomp dll.") + if(${MSVC}) else() - install(FILES ${libgomp_dll} - DESTINATION ${CMAKE_INSTALL_PREFIX}) + SlopeCraft_install_dll(gomp-1 . true) + SlopeCraft_install_dll(stdc++-6 . true) + SlopeCraft_install_dll(gcc_s_seh-1 . true) + SlopeCraft_install_dll(winpthread-1 . true) endif() + return() endif() diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 68abe2f6..ba4b1369 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -1,5 +1,7 @@ set(AppName imageCutter) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS imageCutter diff --git a/vccl/install.cmake b/vccl/install.cmake index eb62ff63..a8a1c7ea 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -1,6 +1,8 @@ set(AppName vccl) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) if(CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS vccl From f16be17b1c64c7ad25eef97b811a5bdf499b732c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 11 Apr 2023 14:21:44 +0800 Subject: [PATCH 0153/1123] try to fix ctest in windows build --- .github/workflows/build-dev.yml | 16 ++++++++-------- cpack/pack_deployed_files.cmake.in | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e7f5574a..3f9ef560 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -170,7 +170,7 @@ jobs: $exclude_key_words="perl","Strawberry" $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$new_path;$basedir/bin/mingw64/bin" + $env:path="$basedir/bin/mingw64/bin;$new_path" echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV @@ -275,13 +275,13 @@ jobs: $env:path=$env:NEW_PATH cmake --install ./build - #- name: Run CTest - # if: matrix.build_type == 'Release' - # run: | - # $basedir=(pwd).path.replace("\\","/") - # $env:path=$env:NEW_PATH - # cd ./build - # ctest -j10 --output-on-failure --stop-on-failure + - name: Run CTest + if: matrix.build_type == 'Release' + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + cd ./build + ctest -j10 --output-on-failure --stop-on-failure - name: Make zip and 7z packs with CPack run: | diff --git a/cpack/pack_deployed_files.cmake.in b/cpack/pack_deployed_files.cmake.in index bd99e0d4..4ef13ea7 100644 --- a/cpack/pack_deployed_files.cmake.in +++ b/cpack/pack_deployed_files.cmake.in @@ -1,3 +1,5 @@ +# This file is expected to be run during cpack + # message(STATUS "Copying qt deployed files") set(SlopeCraft_pack_dest ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/${CPACK_SYSTEM_NAME}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}) @@ -10,6 +12,7 @@ file(COPY ${deployed_dlls} DESTINATION ${SlopeCraft_pack_dest}) function(SlopeCraft_glob_and_copy sub_dir_name pack_dest) message(STATUS "Copying @CMAKE_INSTALL_PREFIX@/${sub_dir_name} to ${pack_dest}/${sub_dir_name}") file(GLOB temp "@CMAKE_INSTALL_PREFIX@/${sub_dir_name}/*") + file(COPY ${temp} DESTINATION ${pack_dest}/${sub_dir_name}) endfunction(SlopeCraft_glob_and_copy) From e0ca8246ed924ce4804a2af232465c84ae14de14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 11 Apr 2023 14:49:47 +0800 Subject: [PATCH 0154/1123] Disable ctest for win-build because .net error --- .github/workflows/build-dev.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3f9ef560..9c488c1c 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -275,13 +275,13 @@ jobs: $env:path=$env:NEW_PATH cmake --install ./build - - name: Run CTest - if: matrix.build_type == 'Release' - run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - cd ./build - ctest -j10 --output-on-failure --stop-on-failure + #- name: Run CTest + # if: matrix.build_type == 'Release' + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $env:path=$env:NEW_PATH + # cd ./build + # ctest -j10 --output-on-failure --stop-on-failure - name: Make zip and 7z packs with CPack run: | From 70a20d4e80d66b033ab9be8987c187adf011b2ca Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 11 Apr 2023 15:51:46 +0800 Subject: [PATCH 0155/1123] fork heuristic flow to SlopeCraft org --- cmake/find_HeuristicFlow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/find_HeuristicFlow.cmake b/cmake/find_HeuristicFlow.cmake index b5903e06..3cfad27c 100644 --- a/cmake/find_HeuristicFlow.cmake +++ b/cmake/find_HeuristicFlow.cmake @@ -30,7 +30,7 @@ if(${SlopeCraft_download_HeuristicFlow}) #if() message(STATUS "Cloning HeuristicFlow...") execute_process( - COMMAND git clone https://github.com/ToKiNoBug/HeuristicFlow.git + COMMAND git clone https://github.com/SlopeCraft/HeuristicFlow.git WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty COMMAND_ERROR_IS_FATAL ANY ECHO_ERROR_VARIABLE From 5d966c0b4a630f840bd316dae4375a0318fb2181 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 11 Apr 2023 15:53:06 +0800 Subject: [PATCH 0156/1123] Remove dependency to Qt6Concurrent --- SlopeCraftMain/CMakeLists.txt | 3 +-- VisualCraft/CMakeLists.txt | 3 +-- cpack/deb.cmake | 1 - vccl/CMakeLists.txt | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index 32765265..c5eb0e62 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(Qt6 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) set(SlopeCraftMain_windows_rc_file) @@ -104,7 +104,6 @@ target_link_libraries(SlopeCraft SlopeCraftL Qt6::Widgets Qt6::Network - Qt6::Concurrent VersionDialog ) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index 3f41f886..ef3c710b 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -find_package(Qt6 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) +find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) find_package(magic_enum REQUIRED) @@ -92,7 +92,6 @@ target_link_libraries(VisualCraft PRIVATE VisualCraftL Qt6::Widgets Qt6::Network - Qt6::Concurrent magic_enum::magic_enum OpenMP::OpenMP_CXX VersionDialog diff --git a/cpack/deb.cmake b/cpack/deb.cmake index db422cfe..c55cc417 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -15,7 +15,6 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS libqt6gui6 libqt6widgets6 libqt6network6 - libqt6concurrent6 libopengl0 libqt6opengl6 libqt6openglwidgets6 diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index de80b88f..e76c2a45 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -18,7 +18,6 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -#find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools Network Concurrent REQUIRED) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) From fc7bd6c9d99189110a72a266acfbf918c59f2a09 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 11 Apr 2023 20:54:00 +0800 Subject: [PATCH 0157/1123] Remove redundant output of SlopeCraft --- SlopeCraftMain/MainWindow.cpp | 37 +++++++++++------------ SlopeCraftMain/others/SlopeCraft_en_US.ts | 16 ++++++++-- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/SlopeCraftMain/MainWindow.cpp b/SlopeCraftMain/MainWindow.cpp index 35a9066b..c78f9bba 100644 --- a/SlopeCraftMain/MainWindow.cpp +++ b/SlopeCraftMain/MainWindow.cpp @@ -137,7 +137,7 @@ MainWindow::MainWindow(QWidget *parent) connect(ui->action_export_avaliable_color_list, &QAction::triggered, this, &MainWindow::exportAvailableColors); - qDebug("成功 connect 所有的菜单"); + // qDebug("成功 connect 所有的菜单"); connect(ui->NextPage, &QPushButton::clicked, this, &MainWindow::turnToPage2); connect(ui->NextPage2, &QPushButton::clicked, this, &MainWindow::turnToPage3); @@ -155,7 +155,7 @@ MainWindow::MainWindow(QWidget *parent) connect(ui->FinshExData, &QPushButton::clicked, this, &MainWindow::turnToPage8); connect(ui->Exit, &QPushButton::clicked, this, &MainWindow::close); - qDebug("成功 connect 所有的翻页按钮"); + // qDebug("成功 connect 所有的翻页按钮"); connect(ui->isGame12, &QRadioButton::toggled, this, &MainWindow::onGameVerClicked); @@ -259,7 +259,7 @@ void MainWindow::showPreview() { int totalNum = 0; kernel->getBlockCounts(&totalNum, preWind->BlockCount.data()); - qDebug() << "去重前有:" << preWind->Src.size() << "个元素"; + // qDebug() << "去重前有:" << preWind->Src.size() << "个元素"; auto iS = preWind->Src.begin(); for (auto ib = preWind->BlockCount.begin(); ib != preWind->BlockCount.end();) { @@ -278,8 +278,8 @@ void MainWindow::showPreview() { kernel->get3DSize(&preWind->size[0], &preWind->size[1], &preWind->size[2]); - qDebug() << "去重后有:" << preWind->Src.size() << "个元素"; - // preWind->Water=Blocks[12][0]; + // qDebug() << "去重后有:" << preWind->Src.size() << "个元素"; + // preWind->Water=Blocks[12][0]; preWind->Water = Manager->getQRadioButtonList()[12]; // preWind->Src[1]=Blocks[1][0];preWind->BlockCount[1]=1919810; EImage tempE; @@ -661,8 +661,8 @@ void MainWindow::on_ImportSettings_clicked() { void MainWindow::ReceiveTPS(tpS t) { this->Strategy = t; - qDebug("接收成功"); - qDebug() << "pTpS=" << t.pTpS << ". hTpS=" << t.hTpS; + // qDebug("接收成功"); + // qDebug() << "pTpS=" << t.pTpS << ". hTpS=" << t.hTpS; } QRgb ComposeColor(const QRgb front, const QRgb back) { @@ -679,10 +679,10 @@ QRgb ComposeColor(const QRgb front, const QRgb back) { inline void MainWindow::preProcess(char pureTpStrategy, char halfTpStrategy, QRgb BGC) { - qDebug("调用了 preProcess"); - // 透明像素处理策略:B->替换为背景色;A->空气;W->暂缓,等待处理 - // 半透明像素处理策略:B->替换为背景色;C->与背景色叠加;R->保留颜色;W->暂缓,等待处理 - qDebug("Cpoied"); + // qDebug("调用了 preProcess"); + // 透明像素处理策略:B->替换为背景色;A->空气;W->暂缓,等待处理 + // 半透明像素处理策略:B->替换为背景色;C->与背景色叠加;R->保留颜色;W->暂缓,等待处理 + // qDebug("Cpoied"); bool hasTotalTrans = false; if (pureTpStrategy != 'W' && halfTpStrategy != 'W') { QRgb *CL = nullptr; @@ -696,7 +696,7 @@ inline void MainWindow::preProcess(char pureTpStrategy, char halfTpStrategy, continue; case 'A': if (!hasTotalTrans) { - qDebug() << "发现纯透明像素"; + // qDebug() << "发现纯透明像素"; hasTotalTrans = true; } CL[c] = qRgba(0, 0, 0, 0); @@ -950,13 +950,13 @@ void MainWindow::algoProgressAdd(void *p, int deltaVal) { void MainWindow::on_Convert_clicked() { if (kernel->queryStep() < SlopeCraft::step::wait4Image) { - qDebug("setType again"); + // qDebug("setType again"); onBlockListChanged(); if (kernel->queryStep() < SlopeCraft::step::wait4Image) return; } if (kernel->queryStep() < SlopeCraft::step::convertionReady) { - qDebug("setImage again"); + // qDebug("setImage again"); kernelSetImg(); if (kernel->queryStep() < SlopeCraft::step::convertionReady) return; } @@ -1903,8 +1903,6 @@ void MainWindow::testBlockList() { // cerr<<"Success"<> map(reinterpret_cast(img.scanLine(0)), row_pixels, diff --git a/SlopeCraftMain/others/SlopeCraft_en_US.ts b/SlopeCraftMain/others/SlopeCraft_en_US.ts index 6b9c79f2..06e67cd7 100644 --- a/SlopeCraftMain/others/SlopeCraft_en_US.ts +++ b/SlopeCraftMain/others/SlopeCraft_en_US.ts @@ -1216,20 +1216,30 @@ Check your map type, remember that file-only map can't be exported as litem Svae structure file for blocklist testing - + 测试方块列表失败 Failed to test the block list. - + 具体信息: Detailed information: - + 保存颜色表 Save palette + + + 保存颜色表失败 + Failed to save colormap image + + + + 分配内存失败 + Failed to allocate memory for image + PreviewWind From d1bb20b034f78bf88dd74c32590a4a2f78bda810 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 11 Apr 2023 21:36:45 +0800 Subject: [PATCH 0158/1123] Add button to tutorial --- SlopeCraftMain/MainWindow.cpp | 4 + SlopeCraftMain/MainWindow.h | 2 + SlopeCraftMain/mainwindow.ui | 6 + SlopeCraftMain/others/SlopeCraft_en_US.ts | 261 +++++++++++----------- VisualCraft/VCWind.h | 1 + VisualCraft/VCWind.ui | 6 + VisualCraft/VCWind_subwindows.cpp | 4 + VisualCraft/others/VisualCraft_en_US.ts | 53 +++-- 8 files changed, 185 insertions(+), 152 deletions(-) diff --git a/SlopeCraftMain/MainWindow.cpp b/SlopeCraftMain/MainWindow.cpp index c78f9bba..56bdbf38 100644 --- a/SlopeCraftMain/MainWindow.cpp +++ b/SlopeCraftMain/MainWindow.cpp @@ -360,6 +360,10 @@ void MainWindow::InitializeAll() { } } +void MainWindow::on_actionTutorial_triggered() { + QDesktopServices::openUrl(QUrl{"https://slopecraft.readthedocs.io/"}); +} + void MainWindow::contactG() { QDesktopServices::openUrl(QUrl("https://github.com/SlopeCraft/SlopeCraft")); } diff --git a/SlopeCraftMain/MainWindow.h b/SlopeCraftMain/MainWindow.h index 8718740b..5d72b688 100644 --- a/SlopeCraftMain/MainWindow.h +++ b/SlopeCraftMain/MainWindow.h @@ -149,6 +149,8 @@ class MainWindow : public QMainWindow { // void when_network_finished(QNetworkReply *reply, bool is_manually); + void on_actionTutorial_triggered(); + void contactG(); void contactB(); // 翻页的自定义槽 diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index f9e3115c..59358795 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -3746,6 +3746,7 @@ li.checked::marker { content: "\2612"; } + @@ -4020,6 +4021,11 @@ li.checked::marker { content: "\2612"; } WE原理图 + + + 使用教程 + + isMapSurvival diff --git a/SlopeCraftMain/others/SlopeCraft_en_US.ts b/SlopeCraftMain/others/SlopeCraft_en_US.ts index 06e67cd7..81df661d 100644 --- a/SlopeCraftMain/others/SlopeCraft_en_US.ts +++ b/SlopeCraftMain/others/SlopeCraft_en_US.ts @@ -149,67 +149,67 @@ p, li { white-space: pre-wrap; } - - + + 开始 Start - - + + 导入图片 Import image - + 地图画类型 Type of map - + 方块列表 Block List - - + + 调整颜色 Convert to Map - + 导出为 Export - + 投影文件 Litematic - + 地图文件 Map data files - + 结构文件 Structure - + 完成 Finish @@ -220,7 +220,7 @@ p, li { white-space: pre-wrap; } - + 反馈Bug Report bugs @@ -455,13 +455,13 @@ map files - + 结束 Finish - + 导出 Export @@ -611,9 +611,9 @@ map files Export 3D - - - + + + GACvter参数 GACvter parameters @@ -624,7 +624,7 @@ map files - + WE原理图 WE Schem @@ -713,112 +713,117 @@ sequence number About - + 地图画 Map - + 高级 Advanced - + 批量操作 Batch operation - + 方块列表预设 Blocklist preset - - - - - - - + + + + + + + 转到页面 Goto this page - - - - + + + + 导出为投影文件 Export as litematic - - + + 导出为mcfunction Export as mcfunction - - + + 导出为地图文件 Export as map files - + 关于SlopeCraft About SlopeCraft - + 测试方块列表 Test block list - + 设置导出参数 Set exporting parameters - - + + 保存预设 Save preset - + 加载预设 Load preset - + 输出当前颜色表 Export current colorset + + + 使用教程 + Tutorial + - - - + + + 检查更新 Check updates - + 设置地图画类型 Set map type - + 设置方块列表 Set BlockList - + 选择图片 Select Image - + 打开图片失败 Failed to read image @@ -857,386 +862,386 @@ Detail information: %1 - + 要不试试换一张图片吧! Why not try another one? - + 图片尺寸: Image size: - + 像素 Pixels - + 图片中存在透明/半透明像素,已处理,您可以点击“设置”重新选择处理透明/半透明像素的方式。 重新设置处理方式后,需要重新导入一次。 There's transparent pixels in your image, SlopeCraft has processed it. You can click "Settings" to reset the strategy of processing transparent pixels. After you reset the strategy, load the image again. - + 导出为投影/结构方块文件 Export as litematic or structure - + 投影文件导出失败 Failed to export as litematic. - + 这可能是汉字编码错误造成的。请检查路径中是否有汉字 There might be sth wrong with characters' encoding, check if the filepath includes non-English characters. - + 错误信息: Error details : - + 你输入的起始序号不可用 Invalid sequence number. - + 请选择导出的文件夹 Please select a folder for exporting. - + 你选择的文件夹不存在! Folder dosen't exist! - + 请稍等 Please wait - + 具体信息: Detail: - + 未知游戏版本 Unknown game version - + 导出原理图失败 Failed to export. - + 方块种类超出上限。 The types of blocks overflow. - + 错误的文件扩展名 Invalid file extension name - + 三维结构中存在错误的方块 Wrong block in 3D structure. - + 无法创建/打开文件 Failed to create/open file - + 导出原版结构方块文件失败 Failed to export vanilla structure file. - + 导出时指定不使用结构空位表示空气,但方块列表中不包含空气。 When exporting as structure, you assigned not to replace air with structure void, but there is no air in the block palette. - + 转化原图为地图画时出错 Error occurred when converting image to map - + 原图为空!你可能没有导入原图! Your source image is empty! You might have forgot to import source image! - + 构建高度矩阵时出现错误 Error occurred when making height martix - + 原版地图画不允许出现第三个阴影(不存在的几何关系不可能生存实装!) 请检查你的地图画类型,纯文件地图画不可以导出为投影! The third shadow shouldn't apper in vanilla map! Check your map type, remember that file-only map can't be exported as litematic! - + 跳步操作 You skipped a step - + 有损压缩失败 Inteligent lossy compression failed - + 最大允许高度太小了 The maxmium allowed height is too low - + 允许使用的颜色过少 Too few colors allowed! - + 你应该勾选启用尽可能多的基色,颜色太少是不行的! You should enable as much base colors as possible. - + 这可能是因为路径中含有中文字符! This might because of non-English characters in filename of path. - + 删除临时文件失败 Failed to remove temporary file - + 在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 这可能是因为地图画行数过大。 尝试启用无损压缩,或者提高最大允许高度 Lossy compression failed to compress the maximun height down to max allowed hehight when computing height map. This may be caused by a too large image. Try enabling lossless compression, or enlarge max allowed height. - + 导出为 mcfunction Export as mcfunction - + 图片 (*.png *.bmp *.jpg *.tif *.GIF ) Image (*.png *.bmp *.jpg *.tif *.GIF ) - + 投影文件 (*.litematic) Litematic file (*.litematic) - + 结构方块文件 (*.nbt) Structure file(*.nbt) - + WorldEdit 原理图 (*.schem) WorldEdit schematic (*.schem) - + (xz 坐标=-65±128×整数) (xz coordinate = -65±128×<any integer>) - + 你输入的起始序号不可用,请输入大于等于 0 的整数! The initial sequence number is invalid, expected non-negative number! - + 请输入大于等于 0 的整数! Please input a non negative number! - + 你可以选择存档中的 data 文件夹 You can select the "data" dir in the saves of MC. - + 导出 WorldEdit 原理图失败 Failed to export WorldEdit schem - + 不支持导出 1.12 WorldEdit 原理图(.schematic 格式),仅支持.schem 格式 Exporting as WE schematic is not supported in MC 12(*.schematic), only *.schem is supported - + SlopeCraft 不允许你跳步操作,请按照左侧竖边栏的顺序操作! Skipping any step is not allowed by SlopeCraft - + 有损压缩的最大允许不要低于 14,否则很容易压缩失败 The maximum height of lossy compression should not be less than 14 - + 导出时 Gzip 压缩文件失败 Failed to compress a exported file - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 可用 - + 种颜色 colors available. - + 保存截屏 Save screenshot - + 图片 (*.jpg *.jpeg *.tif *.bmp *.png) Image (*.jpg *.jpeg *.tif *.bmp *.png) - + 保存当前显示图片 Save current image - + 图片 (*.png) Image (*.png) - + 保存预设文件失败 Failed to save preset file - + 无法创建文件"%1" Failed to create file "%1" - + 选择预设文件 Select a preset file - + 加载预设失败 Failed to load preset - + 测试方块列表的结构文件 Svae structure file for blocklist testing - + 测试方块列表失败 Failed to test the block list. - + 具体信息: Detailed information: - + 保存颜色表 Save palette - + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index f88b1951..74c0d5bc 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -217,6 +217,7 @@ class VCWind : public QMainWindow { void on_tabWidget_main_currentChanged(int page) noexcept; // auto connected + void on_ac_tutorial_triggered() noexcept; void on_ac_about_VisualCraft_triggered() noexcept; void on_ac_contact_bilibili_triggered() noexcept; void on_ac_contact_github_repo_triggered() noexcept; diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 85481bf8..85b1d0c3 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -1205,6 +1205,7 @@ + @@ -1322,6 +1323,11 @@ 刷新警告信息 + + + 使用教程 + + diff --git a/VisualCraft/VCWind_subwindows.cpp b/VisualCraft/VCWind_subwindows.cpp index fa813561..978daeec 100644 --- a/VisualCraft/VCWind_subwindows.cpp +++ b/VisualCraft/VCWind_subwindows.cpp @@ -47,6 +47,10 @@ void VCWind::on_ac_browse_block_triggered() noexcept { bb->show(); } +void VCWind::on_ac_tutorial_triggered() noexcept { + QDesktopServices::openUrl(QUrl{"https://slopecraft.readthedocs.io/"}); +} + void VCWind::on_ac_about_VisualCraft_triggered() noexcept { QMessageBox::information( this, VCWind::tr("关于 VisualCraft"), diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index b81f487d..a7269473 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -517,52 +517,57 @@ If you select a block in "Avaliable blocks" page, the other page will Contact developer - + 关于VisualCraft About VisualCraft - + 反馈bug Report bugs - - + + Github仓库 Github repository - + bilibili ? bilibili - + 生成测试投影 Generate testing litematic - + 查看所有颜色 Browse all colors - + 查看可用颜色 Browse avaliable colors - + 检查更新 Check updates - + 刷新警告信息 Flush warnings + + + 使用教程 + Tutorial + 原版结构方块文件(*.nbt) @@ -649,22 +654,22 @@ If you select a block in "Avaliable blocks" page, the other page will About - + 方块 Blocks - + 加载资源 Load resources - + 设置可用的方块 Set avaliable blocks - + 生物群系 Biomes @@ -714,22 +719,22 @@ If you select a block in "Avaliable blocks" page, the other page will 原版 json - + Vanilla 选择方块 id json 文件 - + Select block id json file 方块状态列表 json 解析失败 - + Failed to parse block state json list 资源包/方块状态列表 json 解析失败 - + The resource pack or block list json failed to be parsed @@ -777,12 +782,12 @@ If you select a block in "Avaliable blocks" page, the other page will This error is considered to be impossible. - + 关于 VisualCraft About VisualCraft - + VisualCraft 是一款全新的 Minecraft 像素画生成器,由 MC 玩家 TokiNoBug 开发,是 SlopeCraft 的子项目。与其他类似的软件不同,VisualCraft 旨在跟进最新的 MC 版本 (1.12~最新版)、支持最多的 MC 特性,提供最强大的功能。 @@ -791,7 +796,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 目前 VisualCraft 能够解析许多第三方资源包,也允许自定义增加加新方块。与传统的思路不同,VisualCraft 以方块模型的方式来解析资源包,尽量贴近 Minecraft 的方式,因此支持各种自定义的方块模型。 @@ -800,7 +805,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 在导出方面,VisualCraft 支持 Litematica mod 的投影 (*.litematic)、WorldEdit 原理图 (*.shem)(仅 1.13+可用)、原版结构方块文件 (*.nbt)、平面示意图 (*.png) 等方式。 @@ -809,7 +814,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + VisualCraft 支持用各种透明方块互相叠加,产生更多的颜色。软件最多支持不超过 65534 种颜色,受此限制,像素画的层数不超过3 层。 @@ -818,7 +823,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 由于颜色数量很多,VisualCraft 使用了显卡加速。目前支持的 API 有 OpenCL。现在正在使用的 API 是%1 The great amount of colors makes GPU accleration necessary. Now OpenCL is supported, and %1 is what currently being used. From e0cacd646802c9900b557e683f84c7332795ad4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Apr 2023 22:04:25 +0800 Subject: [PATCH 0159/1123] fix VC and vccl installation on macos --- VisualCraft/install.cmake | 11 +++++++--- VisualCraftL/install.cmake | 33 ++++++++---------------------- VisualCraftL/setup_zip_names.cmake | 16 +++++++++++++++ vccl/install.cmake | 11 +++++++--- 4 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 VisualCraftL/setup_zip_names.cmake diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index faddbf21..17a1b31b 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -38,13 +38,18 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS VisualCraft - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION . + BUNDLE DESTINATION .) # Install config json file, VisualCraft will try to find it by ./vc-config.json install(FILES vc-config.json - DESTINATION ${CMAKE_INSTALL_PREFIX}/VisualCraft.app/Contents/MacOS) + DESTINATION VisualCraft.app/Contents/MacOS) + + # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip + install(FILES ${VCL_app_files} + DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL) # Run macdeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index c7f2e19a..1f319fc9 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -1,21 +1,4 @@ - - -set(VCL_app_files - ${CMAKE_CURRENT_SOURCE_DIR}/VCL_blocks_fixed.json) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) - -foreach(mcver RANGE 12 19) - set(VCL_current_var_name VCL_resource_${mcver}) - - if(NOT DEFINED ${VCL_current_var_name}) - message(WARNING "${VCL_current_var_name} is not defined") - endif() - - list(APPEND VCL_app_files ${${VCL_current_var_name}}) -endforeach(mcver RANGE 12 19) - -unset(mcver) +include(setup_zip_names.cmake) set(VCL_include_headers VisualCraftL.h @@ -69,16 +52,16 @@ endif() if(${APPLE}) install(TARGETS VisualCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION . + LIBRARY DESTINATION .) + # zips and blocklist jsons are installed inside each macos bundle # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip - install(FILES ${VCL_app_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks_VCL) - + # install(FILES ${VCL_app_files} + # DESTINATION Blocks_VCL) install(TARGETS VisualCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib) + RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) return() endif() diff --git a/VisualCraftL/setup_zip_names.cmake b/VisualCraftL/setup_zip_names.cmake new file mode 100644 index 00000000..1de32e37 --- /dev/null +++ b/VisualCraftL/setup_zip_names.cmake @@ -0,0 +1,16 @@ +set(VCL_app_files + ${CMAKE_CURRENT_SOURCE_DIR}/VCL_blocks_fixed.json) + +include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) + +foreach(mcver RANGE 12 19) + set(VCL_current_var_name VCL_resource_${mcver}) + + if(NOT DEFINED ${VCL_current_var_name}) + message(WARNING "${VCL_current_var_name} is not defined") + endif() + + list(APPEND VCL_app_files ${${VCL_current_var_name}}) +endforeach(mcver RANGE 12 19) + +unset(mcver) \ No newline at end of file diff --git a/vccl/install.cmake b/vccl/install.cmake index a8a1c7ea..720a0c52 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -35,13 +35,18 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS vccl - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION . + BUNDLE DESTINATION .) # Install config json file, vccl will try to find it by ./vccl-config.json install(FILES vccl-config.json - DESTINATION ${CMAKE_INSTALL_PREFIX}/vccl.app/Contents/MacOS) + DESTINATION vccl.app/Contents/MacOS) + + # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip + install(FILES ${VCL_app_files} + DESTINATION vccl.app/Contents/MacOS/Blocks_VCL) # Run macdeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) From 46d8ece4efc1193538d71fe8fbfa97cc93076f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Apr 2023 22:04:39 +0800 Subject: [PATCH 0160/1123] use relative install prefix for macos --- MapViewer/install.cmake | 6 +++--- SlopeCraftL/install.cmake | 20 ++++++++++---------- SlopeCraftMain/install.cmake | 14 +++++++------- imageCutter/install.cmake | 6 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 5835c7a9..59453549 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -37,15 +37,15 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS MapViewer - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . + BUNDLE DESTINATION . ) # Install icon for macOS # MapViewer.app file(GLOB MapViewer_Icon ${CMAKE_SOURCE_DIR}/MapViewer/others/MapViewer.icns) install(FILES ${MapViewer_Icon} - DESTINATION ${CMAKE_INSTALL_PREFIX}/MapViewer.app/Contents/Resources) + DESTINATION MapViewer.app/Contents/Resources) return() endif() diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index b9bbcb62..ffaac535 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -60,28 +60,28 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # install for applications install(TARGETS SlopeCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) + RUNTIME DESTINATION . + LIBRARY DESTINATION .) # install to lib dirs install(TARGETS SlopeCraftL - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib + RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/lib + # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib ) # install(TARGETS SlopeCraftL_C - # RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/bin - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/lib + # RUNTIME DESTINATION ../install_SlopeCraftL/C/bin + # LIBRARY DESTINATION ../install_SlopeCraftL/C/lib # - # LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/lib + # LIBRARY DESTINATION ../install_SlopeCraftL/C/lib # ) install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include) + DESTINATION ../install_SlopeCraftL/Cpp/include) # install(FILES ${SlopeCraft_SCL_C_include_files} - # DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/C/include) + # DESTINATION ../install_SlopeCraftL/C/include) return() endif() diff --git a/SlopeCraftMain/install.cmake b/SlopeCraftMain/install.cmake index 392d4c0c..5daa80a9 100644 --- a/SlopeCraftMain/install.cmake +++ b/SlopeCraftMain/install.cmake @@ -21,37 +21,37 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS # Install app install(TARGETS SlopeCraft - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . + BUNDLE DESTINATION . ) # Install icons file(GLOB SlopeCraft_Icon ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.icns) install(FILES ${SlopeCraft_Icon} - DESTINATION ${CMAKE_INSTALL_PREFIX}/SlopeCraft.app/Contents/Resources) + DESTINATION SlopeCraft.app/Contents/Resources) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_INSTALL_PREFIX}/SlopeCraft.app/Contents/MacOS/Blocks) + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks) file(COPY ${SlopeCraft_install_jsons} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks) # Install all png files of fixedblocks install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_INSTALL_PREFIX}/SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) file(COPY ${SlopeCraft_install_png_fixedblocks} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) # Install all png files of customblocks install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_INSTALL_PREFIX}/SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) file(COPY ${SlopeCraft_install_png_customblocks} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) # Install presets install(FILES ${SlopeCraft_install_presets} - DESTINATION ${CMAKE_INSTALL_PREFIX}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/Presets) file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) return() diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index ba4b1369..7317f153 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -35,15 +35,15 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS imageCutter - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} - BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX} + RUNTIME DESTINATION . + BUNDLE DESTINATION . ) # Install icon for macOS file(GLOB imageCutter_Icon ${CMAKE_SOURCE_DIR}/imageCutter/others/imageCutterIconNew.icns) install(FILES ${imageCutter_Icon} - DESTINATION ${CMAKE_INSTALL_PREFIX}/imageCutter.app/Contents/Resources) + DESTINATION imageCutter.app/Contents/Resources) return() endif() From 17ba48781804201fa31237a781ee3826720b7389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Apr 2023 22:54:40 +0800 Subject: [PATCH 0161/1123] fix VC and vccl installation on macos --- VisualCraftL/setup_zip_names.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualCraftL/setup_zip_names.cmake b/VisualCraftL/setup_zip_names.cmake index 1de32e37..427a1dc4 100644 --- a/VisualCraftL/setup_zip_names.cmake +++ b/VisualCraftL/setup_zip_names.cmake @@ -1,5 +1,5 @@ set(VCL_app_files - ${CMAKE_CURRENT_SOURCE_DIR}/VCL_blocks_fixed.json) + ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) From 8b99d7ce1798f9096bc94af4d3c79274b1a0cb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Apr 2023 23:46:23 +0800 Subject: [PATCH 0162/1123] upload compress files in macos-build --- .github/workflows/build-dev.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 9c488c1c..f0fa1dec 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -40,21 +40,23 @@ jobs: cmake --build . --parallel cmake --install . cd install - macdeployqt SlopeCraft.app chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - macdeployqt MapViewer.app chmod +x MapViewer.app/Contents/MacOS/MapViewer - macdeployqt imageCutter.app chmod +x imageCutter.app/Contents/MacOS/imageCutter chmod +x VisualCraft.app/Contents/MacOS/VisualCraft chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd ./build/install + zip -9 -r SlopeCraft-5.0.0-macos.zip ./* + - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos - path: build/install + path: build/install/SlopeCraft-5.0.0-macos.zip linux-build: runs-on: ubuntu-latest From f3bf62d821fe9f47b48dcc11ae5351ebae1169cb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 16 Apr 2023 19:28:01 +0800 Subject: [PATCH 0163/1123] Add adaptive label --- utilities/AdaptiveLabel/AdaptiveLabel.cpp | 41 +++++++++++++++++++++++ utilities/AdaptiveLabel/AdaptiveLabel.h | 35 +++++++++++++++++++ utilities/AdaptiveLabel/CMakeLists.txt | 9 +++++ utilities/CMakeLists.txt | 1 + 4 files changed, 86 insertions(+) create mode 100644 utilities/AdaptiveLabel/AdaptiveLabel.cpp create mode 100644 utilities/AdaptiveLabel/AdaptiveLabel.h create mode 100644 utilities/AdaptiveLabel/CMakeLists.txt diff --git a/utilities/AdaptiveLabel/AdaptiveLabel.cpp b/utilities/AdaptiveLabel/AdaptiveLabel.cpp new file mode 100644 index 00000000..58c9787c --- /dev/null +++ b/utilities/AdaptiveLabel/AdaptiveLabel.cpp @@ -0,0 +1,41 @@ +#include "AdaptiveLabel.h" +#include +#include +#include + +AdaptiveLabel::AdaptiveLabel(QWidget* parent) : QLabel(parent) {} + +// AdaptiveLabel::~AdaptiveLabel() {} + +QPixmap AdaptiveLabel::pixmap() const noexcept { return this->real_image; } + +void AdaptiveLabel::setPixmap(const QPixmap& img) noexcept { + this->real_image = img; + + this->refresh_image(); +} + +void AdaptiveLabel::refresh_image() noexcept { + const auto raw_image_size = this->real_image.size(); + + if (raw_image_size.height() <= 0 || raw_image_size.width() <= 0) { + static_cast(this)->setPixmap(QPixmap{}); + return; + } + auto label_size = this->size(); + + label_size.setHeight(std::max(label_size.height(), 1)); + label_size.setWidth(std::max(label_size.width(), 1)); + + QPixmap scaled = + this->real_image.scaled(label_size, Qt::AspectRatioMode::KeepAspectRatio, + Qt::TransformationMode::SmoothTransformation); + + static_cast(this)->setPixmap(scaled); +} + +void AdaptiveLabel::resizeEvent(QResizeEvent* event) noexcept { + QLabel::resizeEvent(event); + + this->refresh_image(); +} \ No newline at end of file diff --git a/utilities/AdaptiveLabel/AdaptiveLabel.h b/utilities/AdaptiveLabel/AdaptiveLabel.h new file mode 100644 index 00000000..7f808d8e --- /dev/null +++ b/utilities/AdaptiveLabel/AdaptiveLabel.h @@ -0,0 +1,35 @@ +#include +#include +#include + +class AdaptiveLabel : public QLabel { + // Q_OBJECT + private: + QPixmap real_image; + + void refresh_image() noexcept; + + public: + explicit AdaptiveLabel(QWidget* parent); + ~AdaptiveLabel() = default; + + void setPixmap(const QPixmap&) noexcept; + + QPixmap pixmap() const noexcept; + + QLabel& base() noexcept { return *this; } + const QLabel& base() const noexcept { return *this; } + + void resizeEvent(QResizeEvent* event) noexcept override; + + // using QLabel::; + using QLabel::setAlignment; + using QLabel::setFrameShape; + using QLabel::setMinimumSize; + using QLabel::setObjectName; + using QLabel::setScaledContents; + using QLabel::setSizePolicy; + using QLabel::setStyleSheet; + using QLabel::setText; + using QLabel::sizePolicy; +}; \ No newline at end of file diff --git a/utilities/AdaptiveLabel/CMakeLists.txt b/utilities/AdaptiveLabel/CMakeLists.txt new file mode 100644 index 00000000..402eb878 --- /dev/null +++ b/utilities/AdaptiveLabel/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.20) + +find_package(Qt6 COMPONENTS Widgets REQUIRED) +add_library(AdaptiveLabel STATIC + AdaptiveLabel.h + AdaptiveLabel.cpp) + +target_link_libraries(AdaptiveLabel PUBLIC Qt6::Widgets) +target_include_directories(AdaptiveLabel INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 1f3e57ff..9837d208 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(MCDataVersion) add_subdirectory(GPUWrapper) add_subdirectory(ColorManip) add_subdirectory(ProcessBlockId) +add_subdirectory(AdaptiveLabel) add_subdirectory(BlockListManager) add_subdirectory(ExternalConverters) add_subdirectory(Schem) From d1c76b6d0cc5418998b6337ad2c0fbc0facb732e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 16 Apr 2023 19:28:30 +0800 Subject: [PATCH 0164/1123] Use adaptive label in SlopeCraft --- SlopeCraftMain/CMakeLists.txt | 1 + SlopeCraftMain/mainwindow.ui | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index c5eb0e62..ee2c799c 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -100,6 +100,7 @@ qt_add_resources(SlopeCraft "translations" # ${CMAKE_SOURCE_DIR}/CMakeLists.txt) target_link_libraries(SlopeCraft PRIVATE + AdaptiveLabel BlockListManager SlopeCraftL Qt6::Widgets diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index 59358795..43cdaab1 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -1030,7 +1030,7 @@ font: 11pt "微软雅黑"; 9 - + 0 @@ -1039,8 +1039,8 @@ font: 11pt "微软雅黑"; - 440 - 440 + 0 + 0 @@ -1056,7 +1056,7 @@ font: 11pt "微软雅黑"; :/new/Pic/BG2.png - true + false Qt::AlignCenter @@ -1822,8 +1822,8 @@ font: 11pt "微软雅黑"; 0 0 - 78 - 22 + 554 + 372 @@ -2422,7 +2422,7 @@ Litematica投影 - + 0 @@ -2448,7 +2448,7 @@ Litematica投影 :/new/Pic/BG2.png - true + false @@ -4027,6 +4027,13 @@ li.checked::marker { content: "\2612"; } + + + AdaptiveLabel + QLabel +
AdaptiveLabel.h
+
+
isMapSurvival isMapFlat From 55cbbe15984e3c1c19bf99eeac97ff944fd8dbf6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 16 Apr 2023 19:53:44 +0800 Subject: [PATCH 0165/1123] change name or resources --- CMakeLists.txt | 5 +++-- SlopeCraftMain/CMakeLists.txt | 2 +- VisualCraft/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7300169a..f92a16c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ if(${SlopeCraft_vectorize}) message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) - # add_compile_options(${SlopeCraft_vectorize_flags}) + add_compile_options(${SlopeCraft_vectorize_flags}) # list(APPEND SlopeCraft_vectorize_flags "-O3") endif() @@ -89,7 +89,8 @@ endif() if(${LINUX}) message(STATUS "setting runpath for linux") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) + #set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + #set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) endif() if(${WIN32}) diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index ee2c799c..bd1c677d 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -88,7 +88,7 @@ qt_add_executable(SlopeCraft qt_add_lrelease(SlopeCraft TS_FILES ${SlopeCraftMain_ts_files} QM_FILES_OUTPUT_VARIABLE SC_qm_files) -qt_add_resources(SlopeCraft "translations" +qt_add_resources(SlopeCraft "SC_translations" PREFIX "/i18n" BASE ${CMAKE_CURRENT_BINARY_DIR} FILES ${SC_qm_files}) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index ef3c710b..f569297b 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -113,7 +113,7 @@ set_target_properties(VisualCraft PROPERTIES # translation qt_add_lrelease(VisualCraft TS_FILES ${VisualCraft_ts_files} QM_FILES_OUTPUT_VARIABLE VC_qm_files) -qt_add_resources(VisualCraft "translations" +qt_add_resources(VisualCraft "VC_translations" PREFIX "/i18n" BASE ${CMAKE_CURRENT_BINARY_DIR} FILES ${VC_qm_files} From b9f8e6c2bcbba4ffd5ce63b6d57c5501fda28b2f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 16 Apr 2023 19:56:09 +0800 Subject: [PATCH 0166/1123] run lldb after macos-build --- .github/workflows/build-dev.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f0fa1dec..f8cd6ab6 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -57,6 +57,12 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install/SlopeCraft-5.0.0-macos.zip + - name: Run VisualCraft in lldb + run: | + cd ./build/install + lldb ./VisualCraft.app + run + quit linux-build: runs-on: ubuntu-latest From 638fb517b13c4a8c9ac6c6e0cd34572d049a36ee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 16 Apr 2023 19:57:10 +0800 Subject: [PATCH 0167/1123] run lldb after macos-build only in debug --- .github/workflows/build-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f8cd6ab6..31ac6315 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -58,6 +58,7 @@ jobs: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install/SlopeCraft-5.0.0-macos.zip - name: Run VisualCraft in lldb + if: matrix.build_type == 'Debug' run: | cd ./build/install lldb ./VisualCraft.app From 4e14ea96a0df58259aab5add392cfd209b1c1b2d Mon Sep 17 00:00:00 2001 From: Cubik Date: Sun, 16 Apr 2023 15:20:19 -0400 Subject: [PATCH 0168/1123] chore(gitignore): Ignore CLion generated files --- .gitignore | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index bc5c6fe7..abe28211 100644 --- a/.gitignore +++ b/.gitignore @@ -66,9 +66,13 @@ install/ 3rdParty/* .vscode/settings.json -### build +### build ### build/* binaries/* .vscode/* .vs/* -.cache/* \ No newline at end of file +.cache/* + +### CLion ### +.idea/* +cmake-build-debug/* From ebfa2529a4488556e63ea0e904b0013f363b5ff5 Mon Sep 17 00:00:00 2001 From: Cubik Date: Sun, 16 Apr 2023 15:23:48 -0400 Subject: [PATCH 0169/1123] chore(VisualCraft): Add VIsualCraft macOS app icon --- VisualCraft/others/VisualCraft.icns | Bin 0 -> 21517 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 VisualCraft/others/VisualCraft.icns diff --git a/VisualCraft/others/VisualCraft.icns b/VisualCraft/others/VisualCraft.icns new file mode 100644 index 0000000000000000000000000000000000000000..f13b8a2fe7d2d62c9a2b42e582f3206d57c7c751 GIT binary patch literal 21517 zcmZs?V~{93&?Y*zJ!fp&wmoykwr$(CZQHhO+qP%!dAGiM>(=fj-PQecr8<@T$dl?y z%nfZE0RaBOnj6xy|FfU~001x+^7#0$P@z!&d=wKWcRLF^M*M$1!2ejef7a|DL^C%t zasU7T{OA5t5ODDS#sI(@+FCjM7Xtu5_@{)1M#d%pApZ*k0s#NNqXB^ab%1~PU;CHN z@K^3v0f6y8^grqTbN^TS-!KR`AmINezeWH=0DwXc#`;dS4xIRs`i}C(4)`j@4vyxw zHuwy*9Q5?G48Mv1F#j?E0)T>m0091K0U-19i;K(u|K(R300r>>8U^~lMuGp&XdJ+Q z+XbLF^lys9*`^~r_RC)clFJSWsfaWU21^J?p%f-fg3YgAHvHjz8D|sk&zHKz<}#>b zsv4$cR`pcYEHvb+aIn<-*`_7Tx~^bG^6r5;N(MKQZ}CIxhw&H+iTf#>9$aQFKbPs8 zm1W5tI!wX(&w$Kwc@3 z`_v!WesiOFMn2o!cI8tXxn}8KqUT>QCgSLP@dIpw7nGq(%HT^{x`d5{7`$L^X8zIV|EDThSs9dMJRQ zy$LL|h7;L1cMTQh{>O?xaRJmqu)GO23_wlhyMuH^)cg=Ef#$DM&$DE)GC~2&xNx`N zVBOuRz?pNI#Oh@=imByc-vTJ-_X6|WPHbbkMCSdCpLr5duRB}Vk#rKJX+UXAL$8Au z)S*l2@J(I1geEQ6$i~^#o1P&JX$!v;01&j)e%x5WG^@8ZP?j{Ghz^Rf+gV85SHf6hem3=(Z9c%M@@A=4^FPLKE>C4;TbRf1u<{`*u)=QWuyO0YVA5nqoZ%TFntdUIpXzkVgu* z{*|e?l33E##I3c?w#L&AAK8XadHM5{^&!Uz5%{7!05AbZTr8;XWznlY#YvLsB;3M7f2 z*3#I^SMOz}?x@Y@LdsFgvOhQXMo@)7=pW159l>*D!+c)s(wBiSpTK@L+A@hn#*6S{ zZmzo`f1IQBd3u@+uIwGCgU#?>`^fe}V=4|8auN?`>`q4dDYiS1)Dl5XqF>eBHm=P* z6pP&BFIE-5IrpU7l8szG>nRJ@8~Buhz6j}|FOHX(J}5PHg$Lj}c;OtnbP2vJ2oRq) znbPxy9Z)$#`W2{cBQ_EHqG1m#;;Bm$05iomi&t~9^XRDC4f1tU$=53~ zCnf&AFt4rpAz~}PByZHuzNQ#a%DUBEd{
R2geW83gkz5yFYQGU=gsh4dHuGT(NM&? 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⪚InLIeY{7X###>aIv+o5HrRl|2HFG*^H15h z7kbaYdZRbQk*}$|WkGjBR2^N>c9xB1mT$`}wHp{d?!ID^ny08bwA}rX^~ycSy{U8= z)h<%B+rM`tmODm%wDfq6iLCxqhU!{BVi5*-dQIo~)t}=JX&z+0sZKN&M+aJ;Q_MIT z^Zz7rg4WNj_}}K%ERtO6DAy4dn?sj|iGVwMz+_(>%r@U2p-ju#omn8s3mLRsP~4J& zPPWc1O~>$ErcpSe)hRTa?W`?qbWodMsCBLHHG~?RG_KCES6%vZr0feI!O>Lsc*e_k zR$4RgC;57|ONtdN!Os|1qnrE%w>ZMC+r8wjCl@phMaI=d+bGzy0{2|EpdzLN`8n%R zASR$F++b>u!A@ngMnQv6hH~criCJTH#3VzTWIvoIr$zXjUaW7hQGS(~3=jdwVq=E$ ztf3Iqd#WIqy8FzP(P~s-sW`dCT#cf(oHBpZnqI|A?)8R};@`324Z2_v?~xn!=f>0w zcDkh!vE~|yKTXcV>@4^J^!S2Fl}la z--#qWh8z3}6+0j?TKt*xqQ4;~pb*;(&mjz#o9&F?xbg%IP+u-)$8xfa9R!Y_Tz=Xn zvn~&}&~fk-x&pB19Sw9Pt8?BS+J^+P&*&8jJB>fXAGhjapMTZNm<> z8<)g8z(Xux;hJj+v(Ix%fiJvkSH2IT2|+m>wbW(B!rb%CI?vCyn&M*^GXmp^R78e6~B(*o(7#4zkst**@C_O}0qa1&#u9y`o0VD0m z%Y73i=jM4w_GGTEjgK(wBoU`*6X$8?75#fWJm56!zPFr#`SL9*5GA|(t1LpEb4LNu z%teqDO_fTz?m56GT+(Qk_oVAco47s$Xayh2IG#4R3K*>hp!{JFcn2W@Fo}mqnH@)q zKbw8hLZ5CWP~rxs-t`M1HP1LFVo(m8xXOU6WH8Gt>*yB)!=r{N^~Fq?r+<60UjKQs zZiaAyi$IrLD>2A&w7^zsfD75?FFilzld)_-06x+Z>YBkVxgUoR;%Y zU9KawaZ(dU2A^lM0Xk|Et-x77?sPduR+O=P)iYEVD1HG44_JOAOnf5;xRAd=vH1?b z5n;MD?#u$MEQoJz==r0KYwJ-Um8z*myIL6=voG9=DQ`OkLJAIipZ5CFx2m)AS3>nH zGPKEtoE6&>rt9%xyg*5`++IAQCiT9Ty?t$^)&V%qvdjBE`QIz-M0u=-x@e`_kE$iU z#G8YIQg`F{?`yOr9a~p5!a|kJ5?a~FzE>rREaJn3N{RzZ_CsG37c*NlnupHa6L}c` zUM_gx=oo-C#i|m7DuDP!LAJF_%1`k#Jbn+J77@F{PHp zlu7R?Z~qepJtZYLALYl>t|Ee1*(@Vuyj=rcy@S{BavDB^kjUpIy8=btSkiJOEP(`~ za7AOs5xwfs%+=xi{g#5Yx;0X_Y1}Q}zo@i72_cg$mz#Q{xzmI!x+An6cc7&A0_L+O zU|=1$%-VU`*N{RN5V~0tGxkMFVq1qWJbtyy|*&C;DipczjLFf){LlV{u_oPKv5qL z1{waF&c_*nD-*sZPGXx7k8*2aIEg__9TB`io~WSR*mmU%prq~8*Yx0XTL?}rWAATc=KGPul7~wPjX`SgV7hzn+GilFB&K=FK^?Op|(ea zqEP=FXmkrY2Tr6tv)%Y|*~{et!~tmDt}EZ}+YWlfvrh~muiRpipHgS&N;87c!i zdM*Ov6-CUGaot~qwfqndA+sZ$eh&C=BncbJpJR?pJghfpT0NPmAuURThEXT?$cd_cReSS)lv zC2mUEsdN=YJmwp!NeCbFXFYmUw$YVmDFb@%s@G{UL-G_72V(9UkM+OeejR@2jKkT?~qUDEBVRbFN9CX z68J^@fj|z(EB}1Q&VQ`&06+YDo#Hw!`~YDg9~2ur|7b$Stw#YrtvEsJTcywdFp!KC z=)vVcwfpRZAb+igcW}4^_85-%P%Od)uc)xY>`RX1!LDm=0|^O#_?Zjwt9TP4<5V*G ehyVZp!a_3=&^Pm~hj~BvP(sW<_?ZnN&;QxGiIsE! literal 0 HcmV?d00001 From 26184b98d5796961d63745a8cf4e6ebaa786c23d Mon Sep 17 00:00:00 2001 From: Cubik Date: Sun, 16 Apr 2023 15:24:14 -0400 Subject: [PATCH 0170/1123] build(VisualCraft): Install & Enable macOS app icon --- VisualCraft/CMakeLists.txt | 2 +- VisualCraft/install.cmake | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index ef3c710b..fbe4d701 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -102,7 +102,7 @@ target_include_directories(VisualCraft PRIVATE ${SlopeCraft_Nlohmann_json_includ set_target_properties(VisualCraft PROPERTIES VERSION ${PROJECT_VERSION} - # MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns + MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns MACOSX_BUNDLE_GUI_IDENTIFIER "com.github.ToKiNoBug.SlopeCraft" MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index faddbf21..1a1e7369 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -42,6 +42,12 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX} BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}) + # Install icons + file(GLOB SlopeCraft_Icon + ${CMAKE_SOURCE_DIR}/VisualCraft/others/VisualCraft.icns) + install(FILES ${SlopeCraft_Icon} + DESTINATION ${CMAKE_INSTALL_PREFIX}/VisualCraft.app/Contents/Resources) + # Install config json file, VisualCraft will try to find it by ./vc-config.json install(FILES vc-config.json DESTINATION ${CMAKE_INSTALL_PREFIX}/VisualCraft.app/Contents/MacOS) From 94b3ccc803ba1f03e5f6db493e561b0df282d767 Mon Sep 17 00:00:00 2001 From: Cubik Date: Sun, 16 Apr 2023 15:26:10 -0400 Subject: [PATCH 0171/1123] build(VisualCraftL): Properly install `Blocks_VCL` in darwin --- VisualCraftL/install.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index c7f2e19a..2553a188 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -74,7 +74,9 @@ if(${APPLE}) # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}/Blocks_VCL) + DESTINATION ${CMAKE_INSTALL_PREFIX}/VisualCraft.app/Contents/MacOS/Blocks_VCL) + install(FILES ${VCL_app_files} + DESTINATION ${CMAKE_INSTALL_PREFIX}/vccl.app/Contents/MacOS/Blocks_VCL) install(TARGETS VisualCraftL RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/bin From f1621c5b28a9e5012220507107d166f450358386 Mon Sep 17 00:00:00 2001 From: Cubik Date: Sun, 16 Apr 2023 15:30:30 -0400 Subject: [PATCH 0172/1123] build(VisualCraft): Fix macOS app icon file name --- VisualCraft/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index fbe4d701..caebf11d 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -102,7 +102,7 @@ target_include_directories(VisualCraft PRIVATE ${SlopeCraft_Nlohmann_json_includ set_target_properties(VisualCraft PROPERTIES VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns + MACOSX_BUNDLE_ICON_FILE VisualCraft.icns MACOSX_BUNDLE_GUI_IDENTIFIER "com.github.ToKiNoBug.SlopeCraft" MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} From 1b439743e15134f1e780a88d71a4dcbe06ccbe93 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 11:41:42 +0800 Subject: [PATCH 0173/1123] add .idea/* to git ignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bc5c6fe7..84af618a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,9 @@ install/ ### build build/* binaries/* + +### ide .vscode/* .vs/* -.cache/* \ No newline at end of file +.cache/* +.idea/* \ No newline at end of file From 6490721cc0d5ac707b753465fef75590aa6178c8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 11:42:33 +0800 Subject: [PATCH 0174/1123] remove redundant empty lines --- CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f92a16c4..f1bf1b6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,9 +57,7 @@ list(LENGTH CMAKE_PREFIX_PATH temp_L) include(cmake/find_nlohmann_json.cmake) include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) - include(cmake/find_qt6.cmake) - include(cmake/install_if_is_shared.cmake) add_definitions("-D_USE_MATH_DEFINES") @@ -67,10 +65,8 @@ add_definitions("-DSCL_FIND_GlobalEnums_BY_PATH") # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) - if(${SlopeCraft_vectorize}) include(CheckCXXCompilerFlag) - add_definitions("-DSC_VECTORIZE_AVX2") if(${MSVC}) @@ -80,9 +76,7 @@ if(${SlopeCraft_vectorize}) endif() message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) - add_compile_options(${SlopeCraft_vectorize_flags}) - # list(APPEND SlopeCraft_vectorize_flags "-O3") endif() From 859390f73c43c1fad61f92a9562da0b5fc4d5b5f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 13:22:26 +0800 Subject: [PATCH 0175/1123] replace CMAKE_INSTALL_PREFIX with relative pathes --- VisualCraft/install.cmake | 4 ++-- vccl/install.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index dd68d13f..6846de94 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -47,13 +47,13 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") file(GLOB SlopeCraft_Icon ${CMAKE_SOURCE_DIR}/VisualCraft/others/VisualCraft.icns) install(FILES ${SlopeCraft_Icon} - DESTINATION ${CMAKE_INSTALL_PREFIX}/VisualCraft.app/Contents/Resources) + DESTINATION VisualCraft.app/Contents/Resources) # Install config json file, VisualCraft will try to find it by ./vc-config.json install(FILES vc-config.json DESTINATION VisualCraft.app/Contents/MacOS) - # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip + # Install zips. In vccl-config.json or vc-config.json, they are Ereferred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL) diff --git a/vccl/install.cmake b/vccl/install.cmake index 720a0c52..d9221278 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -44,7 +44,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES vccl-config.json DESTINATION vccl.app/Contents/MacOS) - # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip + # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} DESTINATION vccl.app/Contents/MacOS/Blocks_VCL) From 04027c70f6f7394a0b33d07eb98590aedf492df9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 13:50:47 +0800 Subject: [PATCH 0176/1123] hide debugging in macos-build action --- .github/workflows/build-dev.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 31ac6315..10461807 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -57,13 +57,13 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install/SlopeCraft-5.0.0-macos.zip - - name: Run VisualCraft in lldb - if: matrix.build_type == 'Debug' - run: | - cd ./build/install - lldb ./VisualCraft.app - run - quit + #- name: Run VisualCraft in lldb + # if: matrix.build_type == 'Debug' + # run: | + # cd ./build/install + # lldb ./VisualCraft.app + # run + # quit linux-build: runs-on: ubuntu-latest From 3c06c099a47d353f5a0dc0d399561c5a028de8c7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 13:51:38 +0800 Subject: [PATCH 0177/1123] update license installation --- VisualCraft/install.cmake | 2 +- cmake/install.cmake | 46 +++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 6846de94..dbf68f65 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -53,7 +53,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES vc-config.json DESTINATION VisualCraft.app/Contents/MacOS) - # Install zips. In vccl-config.json or vc-config.json, they are Ereferred like ./Blocks_VCL/Vanilla_1_19_3.zip + # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL) diff --git a/cmake/install.cmake b/cmake/install.cmake index 51f75eea..72c2266d 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -6,33 +6,33 @@ set(SlopeCraft_readme_and_license_files license-translations/LICENSE-zh.md ) -function(SlopeCraft_install_dll dllname dest is_required) - find_library(dll_file - NAMES ${dllname} - PATHS ${CMAKE_PREFIX_PATH} - NO_CMAKE_INSTALL_PREFIX - NO_CACHE) - - if(NOT dll_file) - if(${is_required}) - message(WARNING "Failed to find ${dllname} dll.") - else() - message(STATUS "Failed to find ${dllname} dll.") - endif() - return() - endif() - - message(STATUS "Install ${dll_file} to ${dest}") - install(FILES ${dll_file} - DESTINATION ${dest}) -endfunction(SlopeCraft_install_dll) - if(${WIN32}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}) + DESTINATION .) set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") + function(SlopeCraft_install_dll dllname dest is_required) + find_library(dll_file + NAMES ${dllname} + PATHS ${CMAKE_PREFIX_PATH} + NO_CMAKE_INSTALL_PREFIX + NO_CACHE) + + if(NOT dll_file) + if(${is_required}) + message(WARNING "Failed to find ${dllname} dll.") + else() + message(STATUS "Failed to find ${dllname} dll.") + endif() + return() + endif() + + message(STATUS "Install ${dll_file} to ${dest}") + install(FILES ${dll_file} + DESTINATION ${dest}) + endfunction(SlopeCraft_install_dll) + if(${MSVC}) else() SlopeCraft_install_dll(gomp-1 . true) @@ -52,7 +52,7 @@ endif() if(${APPLE}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION ${CMAKE_INSTALL_PREFIX}) + DESTINATION .) return() endif() From 5122cfade692ef4b60f0d4af1950f99da5300561 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 13:52:01 +0800 Subject: [PATCH 0178/1123] Fix table in english --- Blocks/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Blocks/README.md b/Blocks/README.md index 56a6f527..59130c68 100644 --- a/Blocks/README.md +++ b/Blocks/README.md @@ -34,8 +34,9 @@ Everything about blocklist is in this directory. **CustomBlocks.json** stores all user custom blocks, enabling users to use their favorite blocks in map art. Some slab blocks have been already written in this file as examples. Each block should have a corresponding image in **CustomBlocks** directory. Different blocks can share single image file. Each block has following attributes: + | Name | Type | Is Compulsory Item | Default Value | Description | -| :--------------: | :----: | :----------------: | :-----------: | ---------------------------------------------------------------------------------------------------------- | +| :--------------: | :----: | :----------------: | :-----------: |:-----------------------------------------------------------------------------------------------------------| | baseColor | byte | Yes | | The base color of this block | | id | string | Yes | | Block id in minecraft with full blockstates, like *minecraft:target[power=0]* | | version | byte | Yes | | The earlist version when block is added. 0 means earlier than 1.12, 12 means 1.12, 17 means 1.17 and so on | From b19f010834fb595c5da59e6d33e1b569d5954525 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 15:27:18 +0800 Subject: [PATCH 0179/1123] update version number --- CMakeLists.txt | 2 +- SlopeCraftMain/mainwindow.ui | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1bf1b6f..f1a09617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -set(SlopeCraft_version 5.0.0) +set(SlopeCraft_version 5.0.1) project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index 43cdaab1..c809eef8 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -33,7 +33,7 @@ - SlopeCraft v3.10.1 Copyright © 2021-2022 TokiNoBug + SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug @@ -674,7 +674,7 @@ font: 11pt "微软雅黑"; - <html><head/><body><p><span style=" font-size:16pt; font-weight:700; color:#ffff7f;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> + <html><head/><body><p><span style=" font-size:16pt; font-weight:700; color:#ffff7f;">Copyright © 2021-2023 TokiNoBug</span></p></body></html> Qt::AlignHCenter|Qt::AlignTop @@ -1822,8 +1822,8 @@ font: 11pt "微软雅黑"; 0 0 - 554 - 372 + 78 + 22 @@ -2450,6 +2450,9 @@ Litematica投影 false + + Qt::AlignCenter + From 87c8bb87ef409dea6b5b5804e47cf389afb1301d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 15:27:43 +0800 Subject: [PATCH 0180/1123] Show warnings when map data files will be recovered --- SlopeCraftMain/MainWindow.cpp | 90 ++++++++++++++++++++++++++++------- SlopeCraftMain/MainWindow.h | 6 +++ 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/SlopeCraftMain/MainWindow.cpp b/SlopeCraftMain/MainWindow.cpp index 56bdbf38..46fb6a91 100644 --- a/SlopeCraftMain/MainWindow.cpp +++ b/SlopeCraftMain/MainWindow.cpp @@ -1441,23 +1441,38 @@ void MainWindow::onExportLiteclicked(QString path) { return; } +constexpr inline int ceil_to_128(int x) noexcept { + const bool add_1 = (x % 128) > 0; + x = x / 128; + if (add_1) { + x += 1; + } + return std::max(1, x); +} + +int MainWindow::mapRows() const noexcept { + return ceil_to_128(this->kernel->getImageRows()); +} +int MainWindow::mapCols() const noexcept { + return ceil_to_128(this->kernel->getImageCols()); +} +int MainWindow::mapCount() const noexcept { + return this->mapRows() * this->mapCols(); +} + void MainWindow::on_InputDataIndex_textChanged() { bool isIndexValid = false; const int indexStart = ui->InputDataIndex->toPlainText().toInt(&isIndexValid); isIndexValid = isIndexValid && (indexStart >= 0); if (isIndexValid) { - if (ceil(kernel->getImageRows() / 128.0f) == 1 && - ceil(kernel->getImageCols() / 128.0f) == 1) - ui->ShowDataFileName->setText("map_" + QString::number(indexStart) + - ".dat"); + if (this->mapCount() == 1) + ui->ShowDataFileName->setText( + QStringLiteral("map_%1.dat").arg(indexStart)); else ui->ShowDataFileName->setText( - "map_" + QString::number(indexStart) + ".dat" + "~" + "map_" + - QString::number(indexStart + - ceil(kernel->getImageRows() / 128.0f) * - ceil(kernel->getImageRows() / 128.0f) - - 1) + - ".dat"); + QStringLiteral("map_%1.dat ~ map_%2.dat") + .arg(indexStart) + .arg(indexStart + this->mapCount() - 1)); ui->ExportData->setEnabled(true); return; } @@ -1470,6 +1485,28 @@ void MainWindow::on_InputDataIndex_textChanged() { void MainWindow::on_ExportData_clicked() { onExportDataclicked(""); } +std::vector MainWindow::existingMapDataFiles( + QString prefix) const noexcept { + std::vector ret; + ret.reserve(this->mapCount()); + const int start_number = this->ui->InputDataIndex->toPlainText().toInt(); + if (prefix.back() == '/' || prefix.back() == '\\') { + } else { + prefix += '/'; + } + + for (int idx = start_number; idx < this->mapCount() + start_number; idx++) { + QString filename = QStringLiteral("map_%1.dat").arg(idx); + QString abs_filename = prefix + filename; + if (!QFile(abs_filename).exists()) { + continue; + } + ret.emplace_back(filename); + } + + return ret; +} + void MainWindow::onExportDataclicked(QString path) { bool isIndexValid = false; const int indexStart = ui->InputDataIndex->toPlainText().toInt(&isIndexValid); @@ -1492,9 +1529,32 @@ void MainWindow::onExportDataclicked(QString path) { tr("你可以选择存档中的 data 文件夹")); return; } - this->prevOpenedDir = FolderPath; + { + auto files_to_be_covered = this->existingMapDataFiles(FolderPath); + if (files_to_be_covered.size() > 0) { + QString files{files_to_be_covered.front()}; + for (size_t idx = 1; idx < files_to_be_covered.size(); idx++) { + files += ';' + files_to_be_covered[idx]; + } + + auto ret=QMessageBox::warning( + this, tr("导出时将会覆盖部分地图文件"), + tr("%1 " + "个文件将被覆盖:\n%" + "2\n\n点击\"Yes\"将继续并覆盖这些文件,点击\"No\"将撤销本次操作。") + .arg(files_to_be_covered.size()) + .arg(files), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No}); + if(ret==QMessageBox::StandardButton::No) { + return; + } + } + } + + ui->InputDataIndex->setEnabled(false); ui->ExportData->setEnabled(false); ui->FinshExData->setEnabled(false); @@ -1504,13 +1564,7 @@ void MainWindow::onExportDataclicked(QString path) { FolderPath = FolderPath.replace('\\', '/'); ProductDir = FolderPath; - const uint32_t fileNum = ceil(kernel->getImageRows() / 128.0f) * - ceil(kernel->getImageRows() / 128.0f); - std::vector unCompressedBuffers(fileNum); - for (auto &i : unCompressedBuffers) { - i = new char[512]; - } - // int fileCount=0; + kernel->exportAsData(FolderPath.toLocal8Bit().data(), indexStart, //&fileCount,unCompressedBuffers.data() nullptr, nullptr); diff --git a/SlopeCraftMain/MainWindow.h b/SlopeCraftMain/MainWindow.h index 5d72b688..f7e39816 100644 --- a/SlopeCraftMain/MainWindow.h +++ b/SlopeCraftMain/MainWindow.h @@ -283,6 +283,12 @@ class MainWindow : public QMainWindow { static void algoProgressRangeSet(void *, int min, int max, int val); static void algoProgressAdd(void *, int deltaVal); + + int mapRows() const noexcept; + int mapCols() const noexcept; + int mapCount() const noexcept; + + std::vector existingMapDataFiles(QString prefix) const noexcept; }; using EImage = Eigen::ArrayXX; From dec0ed931aae00dcada6af096dc70822e0a7cd15 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 17 Apr 2023 19:59:29 +0800 Subject: [PATCH 0181/1123] Fix resizing in SlopeCraft --- SlopeCraftMain/mainwindow.ui | 144 ++++++++++++++++------------------- 1 file changed, 66 insertions(+), 78 deletions(-) diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index c809eef8..2274c618 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -1016,7 +1016,7 @@ font: 11pt "微软雅黑"; - + 9 @@ -1064,9 +1064,12 @@ font: 11pt "微软雅黑"; - - - + + + 0 + + + 0 @@ -1079,21 +1082,32 @@ font: 11pt "微软雅黑"; 30 + + + 5 + 2 + + - + + 9 + - - 透明度相关设置 + + Qt::LeftToRight + + + false - 设置 + 导入图片 - - + + - + 0 0 @@ -1102,78 +1116,67 @@ font: 11pt "微软雅黑"; - + <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> + + + Qt::AutoText true - - - - true - + + - + 0 0 - - - 100 - 30 - - - - - 100 - 30 - - - - - 5 - 2 - - - - 10 - + - 下一步 + + + + true - - + + - + 0 0 + + + 100 + 30 + + - - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - - - Qt::AutoText + + 透明度相关设置 - - true + + 设置 - - + + + + true + - + 0 0 @@ -1184,6 +1187,12 @@ font: 11pt "微软雅黑"; 30 + + + 100 + 30 + + 5 @@ -1192,33 +1201,14 @@ font: 11pt "微软雅黑"; - 9 + 10 - - Qt::LeftToRight - - - false - - 导入图片 + 下一步 - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -1822,8 +1812,8 @@ font: 11pt "微软雅黑"; 0 0 - 78 - 22 + 16 + 16 @@ -4042,7 +4032,6 @@ li.checked::marker { content: "\2612"; } isMapFlat isGame16 isBLSurvivalCheaper - ImportPic isBLSurvivalBetter isBLGlowing isBLCustom @@ -4063,7 +4052,6 @@ li.checked::marker { content: "\2612"; } FinishMcF _ExportMcF isBLCreative - NextPage NextPage2 From 6a370be50f7c88aa2d90d0bad7231b7c9d358799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 22:59:21 +0800 Subject: [PATCH 0182/1123] try to fix msvc and clang-msvc compilation --- CMakeLists.txt | 15 +- MapViewer/MapViewerWind.cpp | 136 +++-- SlopeCraftL/SlopeCraftL.cpp | 20 +- SlopeCraftL/TokiSlopeCraft.cpp | 4 + VisualCraftL/TokiVC_flagdiagram.cpp | 4 + VisualCraftL/VisualCraftL.cpp | 873 ++++++++++++++-------------- VisualCraftL/VisualCraftL_global.h | 8 +- utilities/Schem/Schem.cpp | 7 + utilities/Schem/Schem.h | 33 +- 9 files changed, 547 insertions(+), 553 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1a09617..7af6efa7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,6 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) - # manage the install prefix if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) @@ -30,8 +29,10 @@ message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") if(${MSVC}) add_compile_options("/Zc:__cplusplus") add_compile_options("/wd4819") - add_compile_definitions("ZLIB_WINAPI") - add_compile_definitions("Z_HAVE_UNISTD_H") + add_compile_options("/utf-8") + +# add_compile_definitions("ZLIB_WINAPI") +# 1add_compile_definitions("Z_HAVE_UNISTD_H") else() add_compile_options(-Wall -Wreturn-type -Wsign-compare -Wextra) add_link_options(-flto) @@ -65,6 +66,7 @@ add_definitions("-DSCL_FIND_GlobalEnums_BY_PATH") # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) + if(${SlopeCraft_vectorize}) include(CheckCXXCompilerFlag) add_definitions("-DSC_VECTORIZE_AVX2") @@ -77,14 +79,16 @@ if(${SlopeCraft_vectorize}) message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) add_compile_options(${SlopeCraft_vectorize_flags}) + # list(APPEND SlopeCraft_vectorize_flags "-O3") endif() if(${LINUX}) message(STATUS "setting runpath for linux") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") - #set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - #set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) + + # set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + # set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) endif() if(${WIN32}) @@ -101,7 +105,6 @@ add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) include_directories(${CMAKE_BINARY_DIR}/utilities) - add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) diff --git a/MapViewer/MapViewerWind.cpp b/MapViewer/MapViewerWind.cpp index dfed0772..372c4d79 100644 --- a/MapViewer/MapViewerWind.cpp +++ b/MapViewer/MapViewerWind.cpp @@ -186,8 +186,7 @@ MapViewerWind::MapViewerWind(QWidget *parent) MapViewerWind::~MapViewerWind() { for (QLabel *label : this->labels) { - if (label != nullptr) - delete label; + if (label != nullptr) delete label; } delete ui; } @@ -219,15 +218,14 @@ void MapViewerWind::reshape_tables() { for (int idx = 0; idx < int(this->maps.size()); idx++) { const int r = (is_col_major) ? (idx % rows) : (idx / cols); const int c = (is_col_major) ? (idx / rows) : (idx % cols); - if (r >= rows || c >= cols) - continue; + if (r >= rows || c >= cols) continue; QTableWidgetItem *item = new QTableWidgetItem(this->maps[idx].filename); ui->table_display_filename->setItem(r, c, item); } - for (QLabel *label : this->labels) { // detach label and layout + for (QLabel *label : this->labels) { // detach label and layout if (ui->grid_layout_compose_maps->indexOf(label) >= 0) { ui->grid_layout_compose_maps->removeWidget(label); } @@ -243,8 +241,7 @@ void MapViewerWind::reshape_tables() { for (int idx = 0; idx < int(this->maps.size()); idx++) { const int r = (is_col_major) ? (idx % rows) : (idx / cols); const int c = (is_col_major) ? (idx / rows) : (idx % cols); - if (r >= rows || c >= cols) - continue; + if (r >= rows || c >= cols) continue; ui->grid_layout_compose_maps->addWidget(this->labels[idx], r, c); } } @@ -312,8 +309,8 @@ void MapViewerWind::render_single_image() { std::list> error_list; - if (is_color_only_image_changed) { // if color only image is changed, repaint - // it + if (is_color_only_image_changed) { // if color only image is changed, repaint + // it new_image = QImage(cols, rows, QImage::Format_ARGB32); new_image.fill(QColor(255, 255, 255, 255)); @@ -333,7 +330,7 @@ void MapViewerWind::render_single_image() { .fill(image_map(r, c)); const int basecolor = this->maps[current_idx].content()(r, c) / 4; - if (basecolor > ::current_max_base_color) { // unlikely + if (basecolor > ::current_max_base_color) { // unlikely map_new_image.block(pixel_size * r, pixel_size * c, pixel_size, pixel_size) = map_unknown; error_list.emplace_back(std::make_pair(r, c)); @@ -385,12 +382,9 @@ void MapViewerWind::render_single_image() { // determine the value of draw_type single_map_draw_type draw_type = color_only; { - if (ui->radio_show_base_color->isChecked()) - (draw_type) = base_color; - if (ui->radio_show_map_color->isChecked()) - (draw_type) = map_color; - if (ui->radio_show_shade->isChecked()) - (draw_type) = shade; + if (ui->radio_show_base_color->isChecked()) (draw_type) = base_color; + if (ui->radio_show_map_color->isChecked()) (draw_type) = map_color; + if (ui->radio_show_shade->isChecked()) (draw_type) = shade; } // cout<<"draw type = "< displayed_numbers(new u8Array128RowMajor); switch (draw_type) { - case color_only: - abort(); - break; - case map_color: - //*displayed_numbers=this->maps[current_idx].content(); - memcpy(displayed_numbers->data(), this->maps[current_idx].content().data(), - this->maps[current_idx].content().size()); - break; - case base_color: - *displayed_numbers = (this->maps[current_idx].content()) / 4; - break; - case shade: - memcpy(displayed_numbers->data(), this->maps[current_idx].content().data(), - this->maps[current_idx].content().size()); - - constexpr uint64_t mask = - 0b0000001100000011000000110000001100000011000000110000001100000011; - - for (uint32_t idx = 0; - idx < displayed_numbers->size() * sizeof(uint8_t) / sizeof(uint64_t); - idx++) { - uint64_t &val = - *(idx + reinterpret_cast(displayed_numbers->data())); - val = val & mask; - } - /* - for(int64_t idx=0;idxsize();idx++) { - displayed_numbers->operator()(idx) - =displayed_numbers->operator()(idx)%4; - } - */ - break; + case color_only: + abort(); + break; + case map_color: + //*displayed_numbers=this->maps[current_idx].content(); + memcpy(displayed_numbers->data(), + this->maps[current_idx].content().data(), + this->maps[current_idx].content().size()); + break; + case base_color: + *displayed_numbers = (this->maps[current_idx].content()) / 4; + break; + case shade: + memcpy(displayed_numbers->data(), + this->maps[current_idx].content().data(), + this->maps[current_idx].content().size()); + + constexpr uint64_t mask = + 0b0000001100000011000000110000001100000011000000110000001100000011; + + for (uint32_t idx = 0; + idx < displayed_numbers->size() * sizeof(uint8_t) / sizeof(uint64_t); + idx++) { + uint64_t &val = + *(idx + reinterpret_cast(displayed_numbers->data())); + val = val & mask; + } + /* + for(int64_t idx=0;idxsize();idx++) { + displayed_numbers->operator()(idx) + =displayed_numbers->operator()(idx)%4; + } + */ + break; } QPixmap temp_image = QPixmap::fromImage(new_image); @@ -480,19 +476,19 @@ void MapViewerWind::render_single_image() { uint8_t cur_number = (*displayed_numbers)(r, c); switch (draw_type) { - case map_color: - text[0] = char((cur_number / 100) + '0'); - cur_number -= (cur_number / 100) * 100; - text[1] = char((cur_number / 10) + '0'); - text[2] = char((cur_number % 10) + '0'); - break; - case base_color: - text[0] = char(cur_number / 10 + '0'); - text[1] = char(cur_number % 10 + '0'); - break; - default: - text[0] = char((cur_number & 0b11) + '0'); - break; + case map_color: + text[0] = char((cur_number / 100) + '0'); + cur_number -= (cur_number / 100) * 100; + text[1] = char((cur_number / 10) + '0'); + text[2] = char((cur_number % 10) + '0'); + break; + case base_color: + text[0] = char(cur_number / 10 + '0'); + text[1] = char(cur_number % 10 + '0'); + break; + default: + text[0] = char((cur_number & 0b11) + '0'); + break; } painter.drawText(rect, Qt::AlignVCenter | Qt::AlignHCenter, text); @@ -543,7 +539,7 @@ void MapViewerWind::on_button_load_maps_clicked() { std::list> error_list; std::mutex lock; -#pragma omp parallel for +#pragma omp parallel for schedule(static) for (int idx = 0; idx < filenames.size(); idx++) { std::string error_info; if (!process_map_file(filenames[idx].toLocal8Bit().data(), @@ -591,8 +587,9 @@ void MapViewerWind::on_button_load_maps_clicked() { } } -#pragma omp parallel for - for (map &map : this->maps) { +#pragma omp parallel for schedule(static) + for (int idx = 0; idx < this->maps.size(); idx++) { + auto &map = this->maps[idx]; map.image = QImage(128, 128, QImage::Format::Format_ARGB32); Eigen::Map> image_map( reinterpret_cast(map.image.scanLine(0))); @@ -601,7 +598,7 @@ void MapViewerWind::on_button_load_maps_clicked() { } } - update_contents(); + this->update_contents(); } void MapViewerWind::on_checkbox_composed_show_spacing_toggled(bool is_checked) { @@ -611,8 +608,7 @@ void MapViewerWind::on_checkbox_composed_show_spacing_toggled(bool is_checked) { } void MapViewerWind::on_button_save_single_clicked() { - if (this->maps.size() <= 0) - return; + if (this->maps.size() <= 0) return; if (ui->label_show_single_map->pixmap().isNull()) { return; @@ -631,13 +627,11 @@ void MapViewerWind::on_button_save_single_clicked() { } void MapViewerWind::on_button_save_composed_clicked() { - if (this->maps.size() <= 0) - return; + if (this->maps.size() <= 0) return; const QString dest = QFileDialog::getSaveFileName(this, tr("保存为图片"), "", "*.png;;*.jpg;;*.gif"); - if (dest.isEmpty()) - return; + if (dest.isEmpty()) return; const int map_rows = ui->spinbox_rows->value(); const int map_cols = ui->spinbox_cols->value(); diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index cc0e1527..cb297992 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -47,16 +47,6 @@ Kernel::Kernel() {} using namespace SlopeCraft; -extern "C" { - -SCL_EXPORT Kernel *SCL_createKernel() { return new TokiSlopeCraft; } -SCL_EXPORT void SCL_destroyKernel(Kernel *k) { - delete static_cast(k); -} - -SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } -SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } - std::pair parse_block( const nlohmann::json &jo, std::string_view image_dir) noexcept(false) { simpleBlock ret; @@ -151,6 +141,16 @@ BlockListInterface *impl_createBlockList(const char *filename, return bl; } +extern "C" { + +SCL_EXPORT Kernel *SCL_createKernel() { return new TokiSlopeCraft; } +SCL_EXPORT void SCL_destroyKernel(Kernel *k) { + delete static_cast(k); +} + +SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } +SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } + SCL_EXPORT BlockListInterface *SCL_createBlockList( const char *filename, const blockListOption &option) { const bool can_write_err = diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 8e9a2f5c..66470b03 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -23,6 +23,10 @@ This file is part of SlopeCraft. #include "TokiSlopeCraft.h" #include +#ifdef RGB +#undef RGB +#endif + const Eigen::Array TokiSlopeCraft::DitherMapLR = { {0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, {3.0 / 16.0, 5.0 / 16.0, 1.0 / 16.0}}; const Eigen::Array TokiSlopeCraft::DitherMapRL = { diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index da02557d..7debbc05 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -26,6 +26,10 @@ This file is part of SlopeCraft. #include #include +#ifdef min +#undef min +#endif + constexpr uint32_t reverse_color(uint32_t ARGB_src) noexcept { return ARGB32(255 - getR(ARGB_src), 255 - getG(ARGB_src), 255 - getB(ARGB_src), getA(ARGB_src)); diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 922326cd..52f76cee 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -43,9 +43,8 @@ VCL_EXPORT_FUN void VCL_destroy_kernel(VCL_Kernel *const ptr) { } } -VCL_EXPORT_FUN VCL_resource_pack * -VCL_create_resource_pack(const int zip_file_count, - const char *const *const zip_file_names) { +VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( + const int zip_file_count, const char *const *const zip_file_names) { if (zip_file_count <= 0) { return nullptr; } @@ -123,9 +122,8 @@ VCL_EXPORT_FUN void VCL_destroy_resource_pack(VCL_resource_pack *const ptr) { } } -[[nodiscard]] VCL_EXPORT_FUN VCL_block_state_list * -VCL_create_block_state_list(const int file_count, - const char *const *const json_file_names) { +[[nodiscard]] VCL_EXPORT_FUN VCL_block_state_list *VCL_create_block_state_list( + const int file_count, const char *const *const json_file_names) { if (file_count <= 0 || json_file_names == nullptr) { return nullptr; } @@ -139,8 +137,8 @@ VCL_create_block_state_list(const int file_count, return bsl; } -VCL_EXPORT_FUN void -VCL_destroy_block_state_list(VCL_block_state_list *const ptr) { +VCL_EXPORT_FUN void VCL_destroy_block_state_list( + VCL_block_state_list *const ptr) { delete ptr; } @@ -267,7 +265,6 @@ VCL_EXPORT_FUN void VCL_display_resource_pack(const VCL_resource_pack *rp, VCL_EXPORT_FUN const uint32_t *VCL_get_colormap(const VCL_resource_pack *rp, bool is_foliage, int *rows, int *cols) { - if (rows != nullptr) { *rows = 256; } @@ -312,36 +309,34 @@ void VCL_display_block_state_list(const VCL_block_state_list *bsl) { VCL_report(VCL_report_type_t::information, msg.c_str(), true); } -VCL_EXPORT_FUN double -VCL_estimate_color_num(size_t num_layers, size_t num_foreground, - size_t num_background, - size_t num_nontransparent_non_background) { +VCL_EXPORT_FUN double VCL_estimate_color_num( + size_t num_layers, size_t num_foreground, size_t num_background, + size_t num_nontransparent_non_background) { double a = num_background; double b = num_foreground; double num_stacked = 0; switch (num_foreground) { - case 0: - num_stacked = a; - break; - case 1: - num_stacked = a + a * b; - break; - case 2: - num_stacked = a + (num_layers + 1) * b * a; - break; - default: - num_stacked = a + a * b * (std::pow(b - 1, num_layers + 1) - 1) / (b - 2); - break; + case 0: + num_stacked = a; + break; + case 1: + num_stacked = a + a * b; + break; + case 2: + num_stacked = a + (num_layers + 1) * b * a; + break; + default: + num_stacked = a + a * b * (std::pow(b - 1, num_layers + 1) - 1) / (b - 2); + break; } return num_stacked + num_nontransparent_non_background; } -VCL_EXPORT_FUN bool -VCL_set_resource_copy(const VCL_resource_pack *const rp, - const VCL_block_state_list *const bsl, - const VCL_set_resource_option &option) { +VCL_EXPORT_FUN bool VCL_set_resource_copy( + const VCL_resource_pack *const rp, const VCL_block_state_list *const bsl, + const VCL_set_resource_option &option) { if (rp == nullptr || bsl == nullptr) { return false; } @@ -368,10 +363,9 @@ VCL_set_resource_copy(const VCL_resource_pack *const rp, return ret; } -VCL_EXPORT_FUN bool -VCL_set_resource_move(VCL_resource_pack **rp_ptr, - VCL_block_state_list **bsl_ptr, - const VCL_set_resource_option &option) { +VCL_EXPORT_FUN bool VCL_set_resource_move( + VCL_resource_pack **rp_ptr, VCL_block_state_list **bsl_ptr, + const VCL_set_resource_option &option) { if (rp_ptr == nullptr || bsl_ptr == nullptr) { return false; } @@ -472,10 +466,9 @@ VCL_EXPORT_FUN size_t VCL_num_basic_colors() { return TokiVC::LUT_bcitb().size(); } -VCL_EXPORT_FUN int -VCL_get_basic_color_composition(size_t color_idx, - const VCL_block **const blocks_dest, - uint32_t *const color) { +VCL_EXPORT_FUN int VCL_get_basic_color_composition( + size_t color_idx, const VCL_block **const blocks_dest, + uint32_t *const color) { std::shared_lock lkgd(TokiVC_internal::global_lock); if (!TokiVC_internal::is_basic_color_set_ready) { @@ -514,9 +507,8 @@ VCL_get_basic_color_composition(size_t color_idx, return num_blocks; } -VCL_EXPORT_FUN bool -VCL_set_allowed_blocks(const VCL_block *const *const blocks_allowed, - size_t num_block_allowed) { +VCL_EXPORT_FUN bool VCL_set_allowed_blocks( + const VCL_block *const *const blocks_allowed, size_t num_block_allowed) { std::unique_lock lkgd(TokiVC_internal::global_lock); return TokiVC::set_allowed_no_lock(blocks_allowed, num_block_allowed); @@ -527,7 +519,6 @@ VCL_EXPORT_FUN void VCL_discard_allowed_blocks() { } VCL_EXPORT_FUN bool VCL_is_allowed_colorset_ok() { - std::shared_lock lkgd(TokiVC_internal::global_lock); if (!TokiVC_internal::is_basic_color_set_ready) { @@ -710,8 +701,7 @@ VCL_EXPORT_FUN bool VCL_is_block_enabled(const VCL_block *b) { } VCL_EXPORT_FUN void VCL_set_block_enabled(VCL_block *b, bool val) { - if (b == nullptr) - return; + if (b == nullptr) return; b->set_disabled(!val); } @@ -803,9 +793,8 @@ VCL_EXPORT_FUN VCL_block_class_t VCL_string_to_block_class(const char *str, return string_to_block_class(str, ok); } -[[nodiscard]] VCL_EXPORT_FUN VCL_model * -VCL_get_block_model(const VCL_block *block, - const VCL_resource_pack *resource_pack) { +[[nodiscard]] VCL_EXPORT_FUN VCL_model *VCL_get_block_model( + const VCL_block *block, const VCL_resource_pack *resource_pack) { if (block->full_id_ptr() == nullptr) { return nullptr; } @@ -824,9 +813,8 @@ VCL_get_block_model(const VCL_block *block, return ret; } -[[nodiscard]] VCL_EXPORT_FUN VCL_model * -VCL_get_block_model_by_name(const VCL_resource_pack *rp, const char *name) { - +[[nodiscard]] VCL_EXPORT_FUN VCL_model *VCL_get_block_model_by_name( + const VCL_resource_pack *rp, const char *name) { auto result = rp->find_model(name); if (result.index() == 0) { @@ -930,15 +918,15 @@ void default_report_callback(VCL_report_type_t type, const char *msg, bool) { const char *type_msg = nullptr; switch (type) { - case VCL_report_type_t::information: - type_msg = "Information : "; - break; - case VCL_report_type_t::warning: - type_msg = "Warning : "; - break; - case VCL_report_type_t::error: - type_msg = "Error : "; - break; + case VCL_report_type_t::information: + type_msg = "Information : "; + break; + case VCL_report_type_t::warning: + type_msg = "Warning : "; + break; + case VCL_report_type_t::error: + type_msg = "Error : "; + break; } printf("\n%s%s\n", type_msg, msg); @@ -1008,134 +996,134 @@ static_assert(std::is_trivially_copyable_v && VCL_EXPORT_FUN VCL_biome_info VCL_get_biome_info(VCL_biome_t biome) { switch (biome) { - case VCL_biome_t::the_void: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::plains: - return VCL_biome_info{0.8, 0.4}; - case VCL_biome_t::sunflower_plains: - return VCL_biome_info{0.8, 0.4}; - case VCL_biome_t::snowy_plains: - return VCL_biome_info{0, 0.5}; - case VCL_biome_t::ice_spikes: - return VCL_biome_info{0, 0.5}; - case VCL_biome_t::desert: - return VCL_biome_info{2, 0}; - case VCL_biome_t::swamp: - return VCL_biome_info{0.8, 0.9}; - case VCL_biome_t::mangrove_swamp: - return VCL_biome_info{0.8, 0.9}; - case VCL_biome_t::forest: - return VCL_biome_info{0.7, 0.4}; - case VCL_biome_t::flower_forest: - return VCL_biome_info{0.7, 0.8}; - case VCL_biome_t::birch_forest: - return VCL_biome_info{0.6, 0.6}; - case VCL_biome_t::dark_forest: - return VCL_biome_info{0.7, 0.8}; - case VCL_biome_t::old_growth_birch_forest: - return VCL_biome_info{0.6, 0.6}; - case VCL_biome_t::old_growth_pine_taiga: - return VCL_biome_info{0.3, 0.8}; - case VCL_biome_t::old_growth_spruce_taiga: - return VCL_biome_info{0.25, 0.8}; - case VCL_biome_t::taiga: - return VCL_biome_info{0.25, 0.8}; - case VCL_biome_t::snowy_taiga: - return VCL_biome_info{-0.5, 0.4}; - case VCL_biome_t::savanna: - return VCL_biome_info{2, 0}; - case VCL_biome_t::savanna_plateau: - return VCL_biome_info{2, 0}; - case VCL_biome_t::windswept_hills: - return VCL_biome_info{0.2, 0.3}; - case VCL_biome_t::windswept_gravelly_hills: - return VCL_biome_info{0.2, 0.3}; - case VCL_biome_t::windswept_forest: - return VCL_biome_info{0.2, 0.3}; - case VCL_biome_t::windswept_savanna: - return VCL_biome_info{2, 0}; - case VCL_biome_t::jungle: - return VCL_biome_info{0.95, 0.9}; - case VCL_biome_t::sparse_jungle: - return VCL_biome_info{0.95, 0.8}; - case VCL_biome_t::bamboo_jungle: - return VCL_biome_info{0.95, 0.9}; - case VCL_biome_t::badlands: - return VCL_biome_info{2, 0}; - case VCL_biome_t::eroded_badlands: - return VCL_biome_info{2, 0}; - case VCL_biome_t::wooded_badlands: - return VCL_biome_info{2, 0}; - case VCL_biome_t::meadow: - return VCL_biome_info{0.5, 0.8}; - case VCL_biome_t::grove: - return VCL_biome_info{-0.2, 0.8}; - case VCL_biome_t::snowy_slopes: - return VCL_biome_info{-0.3, 0.9}; - case VCL_biome_t::frozen_peaks: - return VCL_biome_info{-0.7, 0.9}; - case VCL_biome_t::jagged_peaks: - return VCL_biome_info{-0.7, 0.9}; - case VCL_biome_t::stony_peaks: - return VCL_biome_info{1, 0.3}; - case VCL_biome_t::river: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::frozen_river: - return VCL_biome_info{0, 0.5}; - case VCL_biome_t::beach: - return VCL_biome_info{0.8, 0.4}; - case VCL_biome_t::snowy_beach: - return VCL_biome_info{0.05, 0.3}; - case VCL_biome_t::stony_shore: - return VCL_biome_info{0.2, 0.3}; - case VCL_biome_t::warm_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::lukewarm_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::deep_lukewarm_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::deep_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::cold_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::deep_cold_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::frozen_ocean: - return VCL_biome_info{0, 0.5}; - case VCL_biome_t::deep_frozen_ocean: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::mushroom_fields: - return VCL_biome_info{0.9, 1}; - case VCL_biome_t::dripstone_caves: - return VCL_biome_info{0.8, 0.4}; - case VCL_biome_t::lush_caves: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::deep_dark: - return VCL_biome_info{0.8, 0.4}; - case VCL_biome_t::nether_wastes: - return VCL_biome_info{2, 0}; - case VCL_biome_t::warped_forest: - return VCL_biome_info{2, 0}; - case VCL_biome_t::crimson_forest: - return VCL_biome_info{2, 0}; - case VCL_biome_t::soul_sand_valley: - return VCL_biome_info{2, 0}; - case VCL_biome_t::basalt_deltas: - return VCL_biome_info{2, 0}; - case VCL_biome_t::the_end: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::end_highlands: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::end_midlands: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::small_end_islands: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::end_barrens: - return VCL_biome_info{0.5, 0.5}; - case VCL_biome_t::cherry_grove: - return VCL_biome_info{0.5, 0.8}; + case VCL_biome_t::the_void: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::plains: + return VCL_biome_info{0.8, 0.4}; + case VCL_biome_t::sunflower_plains: + return VCL_biome_info{0.8, 0.4}; + case VCL_biome_t::snowy_plains: + return VCL_biome_info{0, 0.5}; + case VCL_biome_t::ice_spikes: + return VCL_biome_info{0, 0.5}; + case VCL_biome_t::desert: + return VCL_biome_info{2, 0}; + case VCL_biome_t::swamp: + return VCL_biome_info{0.8, 0.9}; + case VCL_biome_t::mangrove_swamp: + return VCL_biome_info{0.8, 0.9}; + case VCL_biome_t::forest: + return VCL_biome_info{0.7, 0.4}; + case VCL_biome_t::flower_forest: + return VCL_biome_info{0.7, 0.8}; + case VCL_biome_t::birch_forest: + return VCL_biome_info{0.6, 0.6}; + case VCL_biome_t::dark_forest: + return VCL_biome_info{0.7, 0.8}; + case VCL_biome_t::old_growth_birch_forest: + return VCL_biome_info{0.6, 0.6}; + case VCL_biome_t::old_growth_pine_taiga: + return VCL_biome_info{0.3, 0.8}; + case VCL_biome_t::old_growth_spruce_taiga: + return VCL_biome_info{0.25, 0.8}; + case VCL_biome_t::taiga: + return VCL_biome_info{0.25, 0.8}; + case VCL_biome_t::snowy_taiga: + return VCL_biome_info{-0.5, 0.4}; + case VCL_biome_t::savanna: + return VCL_biome_info{2, 0}; + case VCL_biome_t::savanna_plateau: + return VCL_biome_info{2, 0}; + case VCL_biome_t::windswept_hills: + return VCL_biome_info{0.2, 0.3}; + case VCL_biome_t::windswept_gravelly_hills: + return VCL_biome_info{0.2, 0.3}; + case VCL_biome_t::windswept_forest: + return VCL_biome_info{0.2, 0.3}; + case VCL_biome_t::windswept_savanna: + return VCL_biome_info{2, 0}; + case VCL_biome_t::jungle: + return VCL_biome_info{0.95, 0.9}; + case VCL_biome_t::sparse_jungle: + return VCL_biome_info{0.95, 0.8}; + case VCL_biome_t::bamboo_jungle: + return VCL_biome_info{0.95, 0.9}; + case VCL_biome_t::badlands: + return VCL_biome_info{2, 0}; + case VCL_biome_t::eroded_badlands: + return VCL_biome_info{2, 0}; + case VCL_biome_t::wooded_badlands: + return VCL_biome_info{2, 0}; + case VCL_biome_t::meadow: + return VCL_biome_info{0.5, 0.8}; + case VCL_biome_t::grove: + return VCL_biome_info{-0.2, 0.8}; + case VCL_biome_t::snowy_slopes: + return VCL_biome_info{-0.3, 0.9}; + case VCL_biome_t::frozen_peaks: + return VCL_biome_info{-0.7, 0.9}; + case VCL_biome_t::jagged_peaks: + return VCL_biome_info{-0.7, 0.9}; + case VCL_biome_t::stony_peaks: + return VCL_biome_info{1, 0.3}; + case VCL_biome_t::river: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::frozen_river: + return VCL_biome_info{0, 0.5}; + case VCL_biome_t::beach: + return VCL_biome_info{0.8, 0.4}; + case VCL_biome_t::snowy_beach: + return VCL_biome_info{0.05, 0.3}; + case VCL_biome_t::stony_shore: + return VCL_biome_info{0.2, 0.3}; + case VCL_biome_t::warm_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::lukewarm_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::deep_lukewarm_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::deep_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::cold_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::deep_cold_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::frozen_ocean: + return VCL_biome_info{0, 0.5}; + case VCL_biome_t::deep_frozen_ocean: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::mushroom_fields: + return VCL_biome_info{0.9, 1}; + case VCL_biome_t::dripstone_caves: + return VCL_biome_info{0.8, 0.4}; + case VCL_biome_t::lush_caves: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::deep_dark: + return VCL_biome_info{0.8, 0.4}; + case VCL_biome_t::nether_wastes: + return VCL_biome_info{2, 0}; + case VCL_biome_t::warped_forest: + return VCL_biome_info{2, 0}; + case VCL_biome_t::crimson_forest: + return VCL_biome_info{2, 0}; + case VCL_biome_t::soul_sand_valley: + return VCL_biome_info{2, 0}; + case VCL_biome_t::basalt_deltas: + return VCL_biome_info{2, 0}; + case VCL_biome_t::the_end: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::end_highlands: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::end_midlands: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::small_end_islands: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::end_barrens: + return VCL_biome_info{0.5, 0.5}; + case VCL_biome_t::cherry_grove: + return VCL_biome_info{0.5, 0.8}; } return VCL_biome_info{NAN, NAN}; } @@ -1143,270 +1131,269 @@ VCL_EXPORT_FUN VCL_biome_info VCL_get_biome_info(VCL_biome_t biome) { #include const char *VCL_biome_name_ZH(VCL_biome_t b) noexcept { - switch (b) { - case VCL_biome_t::the_void: - return "虚空"; - case VCL_biome_t::plains: - return "平原"; - case VCL_biome_t::sunflower_plains: - return "向日葵平原"; - case VCL_biome_t::snowy_plains: - return "雪原"; - case VCL_biome_t::ice_spikes: - return "冰刺之地"; - case VCL_biome_t::desert: - return "沙漠"; - case VCL_biome_t::swamp: - return "湿地"; - case VCL_biome_t::mangrove_swamp: - return "红树林湿地"; - case VCL_biome_t::forest: - return "森林"; - case VCL_biome_t::flower_forest: - return "繁华森林"; - case VCL_biome_t::birch_forest: - return "白桦森林"; - case VCL_biome_t::dark_forest: - return "黑森林"; - case VCL_biome_t::old_growth_birch_forest: - return "原始桦木森林"; - case VCL_biome_t::old_growth_pine_taiga: - return "原始松木针叶林"; - case VCL_biome_t::old_growth_spruce_taiga: - return "原始云杉针叶林"; - case VCL_biome_t::taiga: - return "针叶林"; - case VCL_biome_t::snowy_taiga: - return "积雪针叶林"; - case VCL_biome_t::savanna: - return "热带草原"; - case VCL_biome_t::savanna_plateau: - return "热带高原"; - case VCL_biome_t::windswept_hills: - return "风袭丘陵"; - case VCL_biome_t::windswept_gravelly_hills: - return "风袭沙砾丘陵"; - case VCL_biome_t::windswept_forest: - return "风袭森林"; - case VCL_biome_t::windswept_savanna: - return "风袭热带草原"; - case VCL_biome_t::jungle: - return "丛林"; - case VCL_biome_t::sparse_jungle: - return "稀疏丛林"; - case VCL_biome_t::bamboo_jungle: - return "竹林"; - case VCL_biome_t::badlands: - return "恶地 (粘土山)"; - case VCL_biome_t::eroded_badlands: - return "风蚀恶地"; - case VCL_biome_t::wooded_badlands: - return "疏林恶地"; - case VCL_biome_t::meadow: - return "草甸"; - case VCL_biome_t::grove: - return "雪林"; - case VCL_biome_t::snowy_slopes: - return "积雪山坡"; - case VCL_biome_t::frozen_peaks: - return "冰封山峰"; - case VCL_biome_t::jagged_peaks: - return "尖峭山峰"; - case VCL_biome_t::stony_peaks: - return "裸岩山峰"; - case VCL_biome_t::river: - return "河流"; - case VCL_biome_t::frozen_river: - return "冻河"; - case VCL_biome_t::beach: - return "沙滩"; - case VCL_biome_t::snowy_beach: - return "积雪沙滩"; - case VCL_biome_t::stony_shore: - return "石岸"; - case VCL_biome_t::warm_ocean: - return "暖水海洋"; - case VCL_biome_t::lukewarm_ocean: - return "温水海洋"; - case VCL_biome_t::deep_lukewarm_ocean: - return "温水深海"; - case VCL_biome_t::ocean: - return "海洋"; - case VCL_biome_t::deep_ocean: - return "深海"; - case VCL_biome_t::cold_ocean: - return "冷水海洋"; - case VCL_biome_t::deep_cold_ocean: - return "冷水深海"; - case VCL_biome_t::frozen_ocean: - return "冻洋"; - case VCL_biome_t::deep_frozen_ocean: - return "冰冻深海"; - case VCL_biome_t::mushroom_fields: - return "蘑菇岛"; - case VCL_biome_t::dripstone_caves: - return "溶洞"; - case VCL_biome_t::lush_caves: - return "繁茂洞穴"; - case VCL_biome_t::deep_dark: - return "Deep ♂ Dark ♂"; - case VCL_biome_t::nether_wastes: - return "下界荒地"; - case VCL_biome_t::warped_forest: - return "扭曲森林"; - case VCL_biome_t::crimson_forest: - return "绯红森林"; - case VCL_biome_t::soul_sand_valley: - return "灵魂沙峡谷"; - case VCL_biome_t::basalt_deltas: - return "玄武岩三角洲"; - case VCL_biome_t::the_end: - return "末地"; - case VCL_biome_t::end_highlands: - return "末地高原"; - case VCL_biome_t::end_midlands: - return "末地内陆"; - case VCL_biome_t::small_end_islands: - return "末地小型岛屿"; - case VCL_biome_t::end_barrens: - return "末地荒地"; - case VCL_biome_t::cherry_grove: - return "樱花树林 (1.20)"; + case VCL_biome_t::the_void: + return "虚空"; + case VCL_biome_t::plains: + return "平原"; + case VCL_biome_t::sunflower_plains: + return "向日葵平原"; + case VCL_biome_t::snowy_plains: + return "雪原"; + case VCL_biome_t::ice_spikes: + return "冰刺之地"; + case VCL_biome_t::desert: + return "沙漠"; + case VCL_biome_t::swamp: + return "湿地"; + case VCL_biome_t::mangrove_swamp: + return "红树林湿地"; + case VCL_biome_t::forest: + return "森林"; + case VCL_biome_t::flower_forest: + return "繁华森林"; + case VCL_biome_t::birch_forest: + return "白桦森林"; + case VCL_biome_t::dark_forest: + return "黑森林"; + case VCL_biome_t::old_growth_birch_forest: + return "原始桦木森林"; + case VCL_biome_t::old_growth_pine_taiga: + return "原始松木针叶林"; + case VCL_biome_t::old_growth_spruce_taiga: + return "原始云杉针叶林"; + case VCL_biome_t::taiga: + return "针叶林"; + case VCL_biome_t::snowy_taiga: + return "积雪针叶林"; + case VCL_biome_t::savanna: + return "热带草原"; + case VCL_biome_t::savanna_plateau: + return "热带高原"; + case VCL_biome_t::windswept_hills: + return "风袭丘陵"; + case VCL_biome_t::windswept_gravelly_hills: + return "风袭沙砾丘陵"; + case VCL_biome_t::windswept_forest: + return "风袭森林"; + case VCL_biome_t::windswept_savanna: + return "风袭热带草原"; + case VCL_biome_t::jungle: + return "丛林"; + case VCL_biome_t::sparse_jungle: + return "稀疏丛林"; + case VCL_biome_t::bamboo_jungle: + return "竹林"; + case VCL_biome_t::badlands: + return "恶地 (粘土山)"; + case VCL_biome_t::eroded_badlands: + return "风蚀恶地"; + case VCL_biome_t::wooded_badlands: + return "疏林恶地"; + case VCL_biome_t::meadow: + return "草甸"; + case VCL_biome_t::grove: + return "雪林"; + case VCL_biome_t::snowy_slopes: + return "积雪山坡"; + case VCL_biome_t::frozen_peaks: + return "冰封山峰"; + case VCL_biome_t::jagged_peaks: + return "尖峭山峰"; + case VCL_biome_t::stony_peaks: + return "裸岩山峰"; + case VCL_biome_t::river: + return "河流"; + case VCL_biome_t::frozen_river: + return "冻河"; + case VCL_biome_t::beach: + return "沙滩"; + case VCL_biome_t::snowy_beach: + return "积雪沙滩"; + case VCL_biome_t::stony_shore: + return "石岸"; + case VCL_biome_t::warm_ocean: + return "暖水海洋"; + case VCL_biome_t::lukewarm_ocean: + return "温水海洋"; + case VCL_biome_t::deep_lukewarm_ocean: + return "温水深海"; + case VCL_biome_t::ocean: + return "海洋"; + case VCL_biome_t::deep_ocean: + return "深海"; + case VCL_biome_t::cold_ocean: + return "冷水海洋"; + case VCL_biome_t::deep_cold_ocean: + return "冷水深海"; + case VCL_biome_t::frozen_ocean: + return "冻洋"; + case VCL_biome_t::deep_frozen_ocean: + return "冰冻深海"; + case VCL_biome_t::mushroom_fields: + return "蘑菇岛"; + case VCL_biome_t::dripstone_caves: + return "溶洞"; + case VCL_biome_t::lush_caves: + return "繁茂洞穴"; + case VCL_biome_t::deep_dark: + return "Deep ♂ Dark ♂"; + case VCL_biome_t::nether_wastes: + return "下界荒地"; + case VCL_biome_t::warped_forest: + return "扭曲森林"; + case VCL_biome_t::crimson_forest: + return "绯红森林"; + case VCL_biome_t::soul_sand_valley: + return "灵魂沙峡谷"; + case VCL_biome_t::basalt_deltas: + return "玄武岩三角洲"; + case VCL_biome_t::the_end: + return "末地"; + case VCL_biome_t::end_highlands: + return "末地高原"; + case VCL_biome_t::end_midlands: + return "末地内陆"; + case VCL_biome_t::small_end_islands: + return "末地小型岛屿"; + case VCL_biome_t::end_barrens: + return "末地荒地"; + case VCL_biome_t::cherry_grove: + return "樱花树林 (1.20)"; } return "Unamed"; } const char *VCL_biome_name_EN(VCL_biome_t b) noexcept { switch (b) { - case VCL_biome_t::the_void: - return "The Void"; - case VCL_biome_t::plains: - return "Plains"; - case VCL_biome_t::sunflower_plains: - return "Sunflower Plains"; - case VCL_biome_t::snowy_plains: - return "Snowy Plains"; - case VCL_biome_t::ice_spikes: - return "Ice Spikes"; - case VCL_biome_t::desert: - return "Desert"; - case VCL_biome_t::swamp: - return "Swamp"; - case VCL_biome_t::mangrove_swamp: - return "Mangrove Swamp"; - case VCL_biome_t::forest: - return "Forest"; - case VCL_biome_t::flower_forest: - return "Flower Forest"; - case VCL_biome_t::birch_forest: - return "Birch Forest"; - case VCL_biome_t::dark_forest: - return "Dark Forest"; - case VCL_biome_t::old_growth_birch_forest: - return "Old Growth Birch Forest"; - case VCL_biome_t::old_growth_pine_taiga: - return "Old Growth Pine Taiga"; - case VCL_biome_t::old_growth_spruce_taiga: - return "Old Growth Spruce Taiga"; - case VCL_biome_t::taiga: - return "Taiga"; - case VCL_biome_t::snowy_taiga: - return "Snowy Taiga"; - case VCL_biome_t::savanna: - return "Savanna"; - case VCL_biome_t::savanna_plateau: - return "Savanna Plateau"; - case VCL_biome_t::windswept_hills: - return "Windswept Hills"; - case VCL_biome_t::windswept_gravelly_hills: - return "Windswept Gravelly Hills"; - case VCL_biome_t::windswept_forest: - return "Windswept Forest"; - case VCL_biome_t::windswept_savanna: - return "Windswept Savanna"; - case VCL_biome_t::jungle: - return "Jungle"; - case VCL_biome_t::sparse_jungle: - return "Sparse Jungle"; - case VCL_biome_t::bamboo_jungle: - return "Bamboo Jungle"; - case VCL_biome_t::badlands: - return "Badlands"; - case VCL_biome_t::eroded_badlands: - return "Eroded Badlands"; - case VCL_biome_t::wooded_badlands: - return "Wooded Badlands"; - case VCL_biome_t::meadow: - return "Meadow"; - case VCL_biome_t::grove: - return "Grove"; - case VCL_biome_t::snowy_slopes: - return "Snowy Slopes"; - case VCL_biome_t::frozen_peaks: - return "Frozen Peaks"; - case VCL_biome_t::jagged_peaks: - return "Jagged Peaks"; - case VCL_biome_t::stony_peaks: - return "Stony Peaks"; - case VCL_biome_t::river: - return "River"; - case VCL_biome_t::frozen_river: - return "Frozen River"; - case VCL_biome_t::beach: - return "Beach"; - case VCL_biome_t::snowy_beach: - return "Snowy Beach"; - case VCL_biome_t::stony_shore: - return "Stony Shore"; - case VCL_biome_t::warm_ocean: - return "Warm Ocean"; - case VCL_biome_t::lukewarm_ocean: - return "Lukewarm Ocean"; - case VCL_biome_t::deep_lukewarm_ocean: - return "Deep Lukewarm Ocean"; - case VCL_biome_t::ocean: - return "Ocean"; - case VCL_biome_t::deep_ocean: - return "Deep Ocean"; - case VCL_biome_t::cold_ocean: - return "Cold Ocean"; - case VCL_biome_t::deep_cold_ocean: - return "Deep Cold Ocean"; - case VCL_biome_t::frozen_ocean: - return "Frozen Ocean"; - case VCL_biome_t::deep_frozen_ocean: - return "Deep Frozen Ocean"; - case VCL_biome_t::mushroom_fields: - return "Mushroom Fields"; - case VCL_biome_t::dripstone_caves: - return "Dripstone Caves"; - case VCL_biome_t::lush_caves: - return "Lush Caves"; - case VCL_biome_t::deep_dark: - return "Deep Dark"; - case VCL_biome_t::nether_wastes: - return "Nether Wastes"; - case VCL_biome_t::warped_forest: - return "Warped Forest"; - case VCL_biome_t::crimson_forest: - return "Crimson Forest"; - case VCL_biome_t::soul_sand_valley: - return "Soul Sand Valley"; - case VCL_biome_t::basalt_deltas: - return "Basalt Deltas"; - case VCL_biome_t::the_end: - return "The End"; - case VCL_biome_t::end_highlands: - return "End Highlands"; - case VCL_biome_t::end_midlands: - return "End Midlands"; - case VCL_biome_t::small_end_islands: - return "Small End Islands"; - case VCL_biome_t::end_barrens: - return "End Barrens"; - case VCL_biome_t::cherry_grove: - return "Cherry Grove"; + case VCL_biome_t::the_void: + return "The Void"; + case VCL_biome_t::plains: + return "Plains"; + case VCL_biome_t::sunflower_plains: + return "Sunflower Plains"; + case VCL_biome_t::snowy_plains: + return "Snowy Plains"; + case VCL_biome_t::ice_spikes: + return "Ice Spikes"; + case VCL_biome_t::desert: + return "Desert"; + case VCL_biome_t::swamp: + return "Swamp"; + case VCL_biome_t::mangrove_swamp: + return "Mangrove Swamp"; + case VCL_biome_t::forest: + return "Forest"; + case VCL_biome_t::flower_forest: + return "Flower Forest"; + case VCL_biome_t::birch_forest: + return "Birch Forest"; + case VCL_biome_t::dark_forest: + return "Dark Forest"; + case VCL_biome_t::old_growth_birch_forest: + return "Old Growth Birch Forest"; + case VCL_biome_t::old_growth_pine_taiga: + return "Old Growth Pine Taiga"; + case VCL_biome_t::old_growth_spruce_taiga: + return "Old Growth Spruce Taiga"; + case VCL_biome_t::taiga: + return "Taiga"; + case VCL_biome_t::snowy_taiga: + return "Snowy Taiga"; + case VCL_biome_t::savanna: + return "Savanna"; + case VCL_biome_t::savanna_plateau: + return "Savanna Plateau"; + case VCL_biome_t::windswept_hills: + return "Windswept Hills"; + case VCL_biome_t::windswept_gravelly_hills: + return "Windswept Gravelly Hills"; + case VCL_biome_t::windswept_forest: + return "Windswept Forest"; + case VCL_biome_t::windswept_savanna: + return "Windswept Savanna"; + case VCL_biome_t::jungle: + return "Jungle"; + case VCL_biome_t::sparse_jungle: + return "Sparse Jungle"; + case VCL_biome_t::bamboo_jungle: + return "Bamboo Jungle"; + case VCL_biome_t::badlands: + return "Badlands"; + case VCL_biome_t::eroded_badlands: + return "Eroded Badlands"; + case VCL_biome_t::wooded_badlands: + return "Wooded Badlands"; + case VCL_biome_t::meadow: + return "Meadow"; + case VCL_biome_t::grove: + return "Grove"; + case VCL_biome_t::snowy_slopes: + return "Snowy Slopes"; + case VCL_biome_t::frozen_peaks: + return "Frozen Peaks"; + case VCL_biome_t::jagged_peaks: + return "Jagged Peaks"; + case VCL_biome_t::stony_peaks: + return "Stony Peaks"; + case VCL_biome_t::river: + return "River"; + case VCL_biome_t::frozen_river: + return "Frozen River"; + case VCL_biome_t::beach: + return "Beach"; + case VCL_biome_t::snowy_beach: + return "Snowy Beach"; + case VCL_biome_t::stony_shore: + return "Stony Shore"; + case VCL_biome_t::warm_ocean: + return "Warm Ocean"; + case VCL_biome_t::lukewarm_ocean: + return "Lukewarm Ocean"; + case VCL_biome_t::deep_lukewarm_ocean: + return "Deep Lukewarm Ocean"; + case VCL_biome_t::ocean: + return "Ocean"; + case VCL_biome_t::deep_ocean: + return "Deep Ocean"; + case VCL_biome_t::cold_ocean: + return "Cold Ocean"; + case VCL_biome_t::deep_cold_ocean: + return "Deep Cold Ocean"; + case VCL_biome_t::frozen_ocean: + return "Frozen Ocean"; + case VCL_biome_t::deep_frozen_ocean: + return "Deep Frozen Ocean"; + case VCL_biome_t::mushroom_fields: + return "Mushroom Fields"; + case VCL_biome_t::dripstone_caves: + return "Dripstone Caves"; + case VCL_biome_t::lush_caves: + return "Lush Caves"; + case VCL_biome_t::deep_dark: + return "Deep Dark"; + case VCL_biome_t::nether_wastes: + return "Nether Wastes"; + case VCL_biome_t::warped_forest: + return "Warped Forest"; + case VCL_biome_t::crimson_forest: + return "Crimson Forest"; + case VCL_biome_t::soul_sand_valley: + return "Soul Sand Valley"; + case VCL_biome_t::basalt_deltas: + return "Basalt Deltas"; + case VCL_biome_t::the_end: + return "The End"; + case VCL_biome_t::end_highlands: + return "End Highlands"; + case VCL_biome_t::end_midlands: + return "End Midlands"; + case VCL_biome_t::small_end_islands: + return "Small End Islands"; + case VCL_biome_t::end_barrens: + return "End Barrens"; + case VCL_biome_t::cherry_grove: + return "Cherry Grove"; } return "Unamed"; diff --git a/VisualCraftL/VisualCraftL_global.h b/VisualCraftL/VisualCraftL_global.h index 55a611fc..205d4936 100644 --- a/VisualCraftL/VisualCraftL_global.h +++ b/VisualCraftL/VisualCraftL_global.h @@ -25,8 +25,8 @@ This file is part of SlopeCraft. // #ifdef VISUALCRAFTL_BUILD -#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ - defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ +#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ + defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ defined(__WIN32__) || defined(__NT__) #define Q_DECL_EXPORT __declspec(dllexport) #define Q_DECL_IMPORT __declspec(dllimport) @@ -42,7 +42,7 @@ This file is part of SlopeCraft. #endif #ifdef _WIN32 -#define VCL_EXPORT_FUN __stdcall VCL_EXPORT +#define VCL_EXPORT_FUN VCL_EXPORT #else #define VCL_EXPORT_FUN VCL_EXPORT #endif @@ -53,4 +53,4 @@ This file is part of SlopeCraft. #include "SC_version_buildtime.h" #endif -#endif // SLOPECRAFT_VISUALCRAFT_VISUALCRAFTL_GLOBAL_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_VISUALCRAFTL_GLOBAL_H \ No newline at end of file diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 5c3a1f37..07d469d2 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -39,6 +39,13 @@ litematic_info::litematic_info() : time_created(std::time(nullptr) * 1000), time_modified(std::time(nullptr) * 1000) {} +void Schem::resize(int64_t x, int64_t y, int64_t z) noexcept { + if (x < 0 || y < 0 || z < 0) { + return; + } + this->xzy.resize(x, z, y); +} + void Schem::set_block_id(const char *const *const block_ids, const int num) noexcept { if (num < 0) { diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index a73bfb36..19d6807f 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -41,8 +41,8 @@ struct litematic_info { std::string regionname_utf8{"Software developer : TokiNoBug."}; std::string author_utf8{"SlopeCraft"}; std::string destricption_utf8{"This litematic is generated by SlopeCraft."}; - uint64_t time_created; //< Miliseconds since 1970 - uint64_t time_modified; //< Miliseconds since 1970 + uint64_t time_created; //< Miliseconds since 1970 + uint64_t time_modified; //< Miliseconds since 1970 }; struct WorldEditSchem_info { @@ -53,18 +53,18 @@ struct WorldEditSchem_info { "WorldEdit schem generated by SlopeCraft, deveploer TokiNoBug."}; std::string author_utf8{"SlopeCraft"}; std::vector required_mods_utf8{}; - uint64_t date; //< Miliseconds since 1970 + uint64_t date; //< Miliseconds since 1970 }; class Schem { -public: + public: // using ele_t = std::conditional_t<(max_block_count > 256), uint16_t, // uint8_t>; using ele_t = uint16_t; static constexpr ele_t invalid_ele_t = ~ele_t(0); -private: + private: /// The 3 indices are stored in [x][z][y] col-major, and in minecraft the /// best storage is [y][z][x] row-major Eigen::Tensor xzy; @@ -74,7 +74,7 @@ class Schem { ::SCL_gameVersion MC_major_ver; MCDataVersion::MCDataVersion_t MC_data_ver; -public: + public: Schem() { xzy.resize(0, 0, 0); } Schem(int64_t x, int64_t y, int64_t z) { xzy.resize(x, y, z); @@ -87,12 +87,7 @@ class Schem { inline const ele_t *data() const noexcept { return xzy.data(); } - inline void resize(int64_t x, int64_t y, int64_t z) noexcept { - if (x < 0 || y < 0 || z < 0) { - return; - } - xzy.resize(x, z, y); - } + void resize(int64_t x, int64_t y, int64_t z) noexcept; inline bool check_version_id() const noexcept { return MCDataVersion::is_data_version_suitable(this->MC_major_ver, @@ -170,8 +165,8 @@ class Schem { return this->MC_data_ver; } - inline void - set_MC_version_number(const MCDataVersion::MCDataVersion_t _) noexcept { + inline void set_MC_version_number( + const MCDataVersion::MCDataVersion_t _) noexcept { this->MC_data_ver = _; } @@ -194,8 +189,8 @@ class Schem { * \return true The schem contains invalid block(s) * \return false The schem don't contain any invalid block. */ - bool - have_invalid_block(int64_t *first_invalid_block_idx = nullptr) const noexcept; + bool have_invalid_block( + int64_t *first_invalid_block_idx = nullptr) const noexcept; /** * \brief Search for invalid block. @@ -212,7 +207,7 @@ class Schem { void process_mushroom_states() noexcept; -public: + public: bool export_litematic(std::string_view filename, const litematic_info &info = litematic_info(), SCL_errorFlag *const error_flag = nullptr, @@ -229,6 +224,6 @@ class Schem { std::string *const error_str = nullptr) const noexcept; }; -} // namespace libSchem +} // namespace libSchem -#endif // SCHEM_SCHEM_H \ No newline at end of file +#endif // SCHEM_SCHEM_H \ No newline at end of file From 95560fbcd549faa6a59fb8d810f4bab0584869ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 22:59:50 +0800 Subject: [PATCH 0183/1123] keep symlinks in macos-build zipping --- .github/workflows/build-dev.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 10461807..4ec071fc 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -48,7 +48,7 @@ jobs: - name: Compress as zip run: | cd ./build/install - zip -9 -r SlopeCraft-5.0.0-macos.zip ./* + zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -57,6 +57,10 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install/SlopeCraft-5.0.0-macos.zip + - name: test vccl + run: | + cd ./build/install + ./vccl.app --version #- name: Run VisualCraft in lldb # if: matrix.build_type == 'Debug' # run: | From 99fae71d49d0eb3e1d6c23b84e4d45236c5ab7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 23:00:54 +0800 Subject: [PATCH 0184/1123] fix github action --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4ec071fc..4cde507a 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -59,8 +59,8 @@ jobs: path: build/install/SlopeCraft-5.0.0-macos.zip - name: test vccl run: | - cd ./build/install - ./vccl.app --version + cd ./build/install + ./vccl.app --version #- name: Run VisualCraft in lldb # if: matrix.build_type == 'Debug' # run: | From 13dd06d26e6746ed1eea3cc17f0ea345f38cee6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 23:26:13 +0800 Subject: [PATCH 0185/1123] change the installation prefix of vccl-macos --- vccl/install.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vccl/install.cmake b/vccl/install.cmake index d9221278..811e91a7 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -37,16 +37,16 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS vccl - RUNTIME DESTINATION . - BUNDLE DESTINATION .) + RUNTIME DESTINATION vccl-contents + BUNDLE DESTINATION vccl-contents) # Install config json file, vccl will try to find it by ./vccl-config.json install(FILES vccl-config.json - DESTINATION vccl.app/Contents/MacOS) + DESTINATION vccl-contents/vccl.app/Contents/MacOS) # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} - DESTINATION vccl.app/Contents/MacOS/Blocks_VCL) + DESTINATION vccl-contents/vccl.app/Contents/MacOS/Blocks_VCL) # Run macdeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) From 71e3bd795a547713e656ec2552e0fe98a3ec9cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 23:38:18 +0800 Subject: [PATCH 0186/1123] specialize vccl installation on mac --- vccl/deploy_qt_for_vccl_macos.cmake.in | 13 +++++++++++++ vccl/install.cmake | 17 ++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 vccl/deploy_qt_for_vccl_macos.cmake.in diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in new file mode 100644 index 00000000..359f73df --- /dev/null +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -0,0 +1,13 @@ +# This script should run during installtion + +message(STATUS "Running macdeployqt for @AppName@ ...") +execute_process( + COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" + WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/@vccl_prefix@" + OUTPUT_QUIET + COMMAND_ERROR_IS_FATAL ANY) + +file(CREATE_LINK + "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl" + "@CMAKE_INSTALL_PREFIX@/vccl" + SYMBOLIC) diff --git a/vccl/install.cmake b/vccl/install.cmake index 811e91a7..ce2c9643 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -35,21 +35,24 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") endif() if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + set(vccl_prefix vccl-contents) + + configure_file(deploy_qt_for_vccl_macos.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) + include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS vccl - RUNTIME DESTINATION vccl-contents - BUNDLE DESTINATION vccl-contents) + RUNTIME DESTINATION ${vccl_prefix} + BUNDLE DESTINATION ${vccl_prefix}) # Install config json file, vccl will try to find it by ./vccl-config.json install(FILES vccl-config.json - DESTINATION vccl-contents/vccl.app/Contents/MacOS) + DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS) # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} - DESTINATION vccl-contents/vccl.app/Contents/MacOS/Blocks_VCL) - - # Run macdeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) + # Do not run deploy_qt.cmake, but a specialied one + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) return() endif() \ No newline at end of file From 34e520cd01fd37ee950d0b20436873d0af5c62b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 17 Apr 2023 23:44:22 +0800 Subject: [PATCH 0187/1123] fix test vccl --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4cde507a..b20a6b83 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -60,7 +60,7 @@ jobs: - name: test vccl run: | cd ./build/install - ./vccl.app --version + ./vccl --version #- name: Run VisualCraft in lldb # if: matrix.build_type == 'Debug' # run: | From b7b26d3001ba4bbfe7b19a3fc45743e7b3dddb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 00:07:27 +0800 Subject: [PATCH 0188/1123] fix vccl chmod --- .github/workflows/build-dev.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b20a6b83..4a68d2d2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,7 +44,8 @@ jobs: chmod +x MapViewer.app/Contents/MacOS/MapViewer chmod +x imageCutter.app/Contents/MacOS/imageCutter chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - chmod +x vccl.app/Contents/MacOS/vccl + chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # chmod +x vccl.app/Contents/MacOS/vccl - name: Compress as zip run: | cd ./build/install From 5b75094df5d533bf3a165160822044d2ec93f356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 00:10:18 +0800 Subject: [PATCH 0189/1123] run macos-build seperately --- .github/workflows/macos-build.yml | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/macos-build.yml diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml new file mode 100644 index 00000000..12b51d1b --- /dev/null +++ b/.github/workflows/macos-build.yml @@ -0,0 +1,71 @@ +name: Build dev version artifacts +on: + pull_request: + push: + branches: + - change-vccl-macos + + +jobs: + + macos-build: + runs-on: macos-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: brew install qt@6 + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - name: Build and Install + run: | + cd build + cmake --build . --parallel + cmake --install . + cd install + chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + chmod +x MapViewer.app/Contents/MacOS/MapViewer + chmod +x imageCutter.app/Contents/MacOS/imageCutter + chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd ./build/install + zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos + path: build/install/SlopeCraft-5.0.0-macos.zip + - name: test vccl + run: | + cd ./build/install + ./vccl --version + #- name: Run VisualCraft in lldb + # if: matrix.build_type == 'Debug' + # run: | + # cd ./build/install + # lldb ./VisualCraft.app + # run + # quit \ No newline at end of file From 36ad7cd9eb634daf8d75b361a4bb7204eb4f8a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 00:33:19 +0800 Subject: [PATCH 0190/1123] change vccl on mac --- .github/workflows/macos-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index 12b51d1b..c05eeac4 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -61,7 +61,7 @@ jobs: - name: test vccl run: | cd ./build/install - ./vccl --version + otool -L ./vccl #- name: Run VisualCraft in lldb # if: matrix.build_type == 'Debug' # run: | From 35b3de06e38279d3018c43173efb9426ac43ca54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 00:51:22 +0800 Subject: [PATCH 0191/1123] add -d to otool --- .github/workflows/macos-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml index c05eeac4..abe23be4 100644 --- a/.github/workflows/macos-build.yml +++ b/.github/workflows/macos-build.yml @@ -61,7 +61,7 @@ jobs: - name: test vccl run: | cd ./build/install - otool -L ./vccl + otool -L -d ./vccl #- name: Run VisualCraft in lldb # if: matrix.build_type == 'Debug' # run: | From 363659a312fb7a0ed7e947fe113d43201a8128e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 01:09:17 +0800 Subject: [PATCH 0192/1123] finish editing macos-build --- .github/workflows/build-dev.yml | 11 ----- .github/workflows/macos-build.yml | 71 ------------------------------- 2 files changed, 82 deletions(-) delete mode 100644 .github/workflows/macos-build.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4a68d2d2..4c488bbf 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -58,17 +58,6 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos path: build/install/SlopeCraft-5.0.0-macos.zip - - name: test vccl - run: | - cd ./build/install - ./vccl --version - #- name: Run VisualCraft in lldb - # if: matrix.build_type == 'Debug' - # run: | - # cd ./build/install - # lldb ./VisualCraft.app - # run - # quit linux-build: runs-on: ubuntu-latest diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml deleted file mode 100644 index abe23be4..00000000 --- a/.github/workflows/macos-build.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Build dev version artifacts -on: - pull_request: - push: - branches: - - change-vccl-macos - - -jobs: - - macos-build: - runs-on: macos-latest - strategy: - matrix: - build_type: [Debug, Release] - gpu_api: [None] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: brew install qt@6 - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - - name: Build and Install - run: | - cd build - cmake --build . --parallel - cmake --install . - cd install - chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - chmod +x MapViewer.app/Contents/MacOS/MapViewer - chmod +x imageCutter.app/Contents/MacOS/imageCutter - chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl - # chmod +x vccl.app/Contents/MacOS/vccl - - name: Compress as zip - run: | - cd ./build/install - zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos - path: build/install/SlopeCraft-5.0.0-macos.zip - - name: test vccl - run: | - cd ./build/install - otool -L -d ./vccl - #- name: Run VisualCraft in lldb - # if: matrix.build_type == 'Debug' - # run: | - # cd ./build/install - # lldb ./VisualCraft.app - # run - # quit \ No newline at end of file From 73be4518480b7a4bddd96fe78e12cebc205952f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 13:12:36 +0800 Subject: [PATCH 0193/1123] optionally create symlinks on win (for developers) --- CMakeLists.txt | 5 +++++ SlopeCraftMain/CMakeLists.txt | 9 +++++++++ VisualCraft/CMakeLists.txt | 9 +++++++++ vccl/CMakeLists.txt | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7af6efa7..dcd1c584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,11 @@ add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) include_directories(${CMAKE_BINARY_DIR}/utilities) +if(${WIN32}) + add_custom_target(SC_create_all_symlinks + COMMENT "A interface target to create all symlinks on windows") +endif() + add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index bd1c677d..00ba59d4 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -120,4 +120,13 @@ set_target_properties(SlopeCraft PROPERTIES qt_finalize_executable(SlopeCraft) +if(${WIN32}) + add_custom_target(SC_create_symlink_SC + COMMAND mklink SlopeCraftL.dll "..\\SlopeCraftL\\SlopeCraftL.dll" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS SlopeCraftL + COMMENT "Create symlink to SlopeCraftL.dll for SlopeCraft.exe") + add_dependencies(SC_create_all_symlinks SC_create_symlink_SC) +endif() + include(install.cmake) \ No newline at end of file diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index 37f0757b..bf04faf2 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -125,4 +125,13 @@ include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) configure_file(vc-config-to-bin-dir.json.in vc-config.json) +if(${WIN32}) + add_custom_target(SC_create_symlink_VC + COMMAND mklink VisualCraftL.dll "..\\VisualCraftL\\VisualCraftL.dll" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS VisualCraftL + COMMENT "Create symlink to VisualCraftL.dll for VisualCraft.exe") + add_dependencies(SC_create_all_symlinks SC_create_symlink_VC) +endif() + include(install.cmake) \ No newline at end of file diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index e76c2a45..f19d3b0c 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -55,6 +55,15 @@ set_target_properties(vccl PROPERTIES MACOSX_BUNDLE TRUE ) +if(${WIN32}) + add_custom_target(SC_create_symlink_VCCL + COMMAND mklink VisualCraftL.dll "..\\VisualCraftL\\VisualCraftL.dll" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS VisualCraftL + COMMENT "Create symlink to VisualCraftL.dll for vccl.exe") + add_dependencies(SC_create_all_symlinks SC_create_symlink_VCCL) +endif() + include(install.cmake) include(add_test_vccl.cmake) \ No newline at end of file From 6479c3e0e7e0b88d78ef0e4054fcd4e044970a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 13:12:46 +0800 Subject: [PATCH 0194/1123] fix a warnings in MapViewer --- MapViewer/MapViewerWind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MapViewer/MapViewerWind.cpp b/MapViewer/MapViewerWind.cpp index 372c4d79..bfde47e2 100644 --- a/MapViewer/MapViewerWind.cpp +++ b/MapViewer/MapViewerWind.cpp @@ -588,7 +588,7 @@ void MapViewerWind::on_button_load_maps_clicked() { } #pragma omp parallel for schedule(static) - for (int idx = 0; idx < this->maps.size(); idx++) { + for (int idx = 0; idx < (int)this->maps.size(); idx++) { auto &map = this->maps[idx]; map.image = QImage(128, 128, QImage::Format::Format_ARGB32); Eigen::Map> image_map( From 2adff84e77a91a76594430e8b86d2693815af172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 18 Apr 2023 22:24:50 +0800 Subject: [PATCH 0195/1123] update translations --- MapViewer/MapViewer_en_US.ts | 22 +- SlopeCraftMain/others/SlopeCraft_en_US.ts | 414 +++++++++++----------- 2 files changed, 226 insertions(+), 210 deletions(-) diff --git a/MapViewer/MapViewer_en_US.ts b/MapViewer/MapViewer_en_US.ts index e522e943..bfbee63a 100644 --- a/MapViewer/MapViewer_en_US.ts +++ b/MapViewer/MapViewer_en_US.ts @@ -41,7 +41,7 @@ - + 请选择地图文件 Please select files @@ -97,8 +97,8 @@ - - + + 保存为图片 Save @@ -108,43 +108,43 @@ Show grid - + 地图数: Map count: - + There is/are - + 个像素点出现未知的基色,它们使用了Mojang未定义的基色。这可能是因为软件版本较旧而游戏版本太新,或者地图文件损坏。 其行、列坐标分别为: pixel(s) which have unknown base color, they are using basecolors out of Mojang's defination. This may be caused by damaged map data file, or the software version is too old. - + 地图中有Mojang未定义基色 Undefined basecolor in map data files (undefined by Mojang) - + 选择地图数据文件 Select map data files - + 加载地图文件失败 Failed to load map data file(s) - + 出错的文件: Map data file: - + 错误信息: diff --git a/SlopeCraftMain/others/SlopeCraft_en_US.ts b/SlopeCraftMain/others/SlopeCraft_en_US.ts index 81df661d..074bb811 100644 --- a/SlopeCraftMain/others/SlopeCraft_en_US.ts +++ b/SlopeCraftMain/others/SlopeCraft_en_US.ts @@ -149,67 +149,67 @@ p, li { white-space: pre-wrap; } - + 开始 Start - - + + 导入图片 Import image - - + + 地图画类型 Type of map - + 方块列表 Block List - + 调整颜色 Convert to Map - + 导出为 Export - + 投影文件 Litematic - + 地图文件 Map data files - + 结构文件 Structure - - + + 完成 Finish @@ -220,7 +220,7 @@ p, li { white-space: pre-wrap; } - + 反馈Bug Report bugs @@ -255,84 +255,84 @@ p, li { white-space: pre-wrap; } <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Highest quality, but requires to edit saves.</span></p></body></html> - + 设置 Settings - - - + + + 下一步 Next - + <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> <html><head/><body><p>Step 1,click the load Image button, choose the image you want to make into map.</p><p>The size of image should be multiple of 128 pixels.</p><p></p><p></p><p>Provided that you want to build it, don't choose a large image. 128×128 is enough.</p></body></html> - + <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> <html><head/><body><p align="justify">Step 2</p><p align="justify">Set the type and gameversion of your map.</p><p align="justify">3D means 3D map paintings built in survival.</p><p align="justify">Flat is like a floor which is easiest to build.</p><p align="justify">File-only Maps has most colors but can't be built.</p></body></html> - + 游戏版本 Game Version - + 1.18 - + 1.19 - + 立体地图画 3D Map - + 平板地图画 Flat Map - + 纯文件地图画 File-only Map - + 预设方块列表 Presets - + <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> <html><head/><body><p align="justify">Step 3</p><p align="justify">Select a block for each colors. </p><p align="justify">Here we have 4 presets above, You can also set your custom block list in the scroll area.</p></body></html> - + 优先混凝土 Use Concrete - + 优先羊毛 Use Wool - + 优先染色玻璃 Use Glass - + 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 调整颜色可能会比较慢,下面的进度条指示了进度。 @@ -341,132 +341,132 @@ p, li { white-space: pre-wrap; } It might be laggy, the progressbar shows the progress. - + 导出为 地图文件 Export map files - + 显示原图 Show image - + 显示地图画 Show Map - + 转换为地图画 Convert to map - + 算法 Algothrims - + 抖动仿色 Dithering - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 智能有损压缩 Intelligent Lossy Compress - + 投影名称 Litematic name - + 总方块数 Total count - + 压缩高度 Compressing - + 防火 Fire Proof - + layers - + 搭桥间隔: Construct interval: - + 投影尺寸 Size - + 允许搭桥 Construct Glass Bridge - + 防末影人 Enderman Proof - + 投影区域名称 Region name - + 其他选项 Others - + 搭桥 Glass Bridge - + <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> <html><head/><body><p align="justify"> The last step is to make your map into a litematic file, to make it easier to be built.</p><p align="justify">3 blanks on the left side are some properties of your litematic file. </p><p align="justify">If you turn on "Compress height(lossless)", SlopeCraft will try to compress the height of 3d map according to rule of maps, in order to prevent it from surpassing 256(not always effective on all kinds of images).</p><p align="justify">Two bars below exhibit some information of your map. </p><p align="justify">This process might be quite slow, see the progress bar.</p></body></html> - + 结束 Finish - - + + 导出 Export - + 预览 Preview @@ -476,334 +476,334 @@ map files Flat diagram - + 透明度相关设置 About transparency - + 适合创造 Suitable for creative mod - + 适合生存早期 Suitable for survival mod(undeveloped) - + 适合生存后期 - + 适合光影 Suitable for shaders - + 自定义 Custom - + RGB欧式距离 RGB Euclidean Distance - + 更好的RGB色差公式 A better RGB color difference formula - + 不是简单的欧式距离 Not simple Euclidean distance - + Lab1994公式 The Lab1994 color difference formula - + Lab2000公式 The Lab2000 color difference formula - + XYZ欧式距离 XYZ Euclidean Distance - + 遗传算法 Genetic algorithm - + GACvter GACvter - + 用分辨率换颜色 Trade colors with resolution - + 方便建造,耗费玻璃 Easy to build but cost many glass blocks - + 降低总高度,破坏连续性 Lower the total height and break the continousness - + 用玻璃包围防火方块 Cover burnable blocks with glass - + 用玻璃包围可偷方块 Cover stealable blocks with glasses - + 降低总高度,微调颜色 Lower the total height and modify colors slightly - + 节省大量存储空间 Save disk space greatly - + 用结构空位代替 Replace with structure void - + 空气处理方式 Air processing method - + 原理图名称 Name of schematic - + 依赖mod名称 Dependent mods - + 导出平面示意图 Export flat diagram - + 导出三维结构 Export 3D - - - + + + GACvter参数 GACvter parameters - + 构建三维结构 Build 3D - + WE原理图 WE Schem - + 保存当前图片 Save current Image - + 导出为 原版结构文件 Export Vanilla structure - + 导出为 WorldEdit原理图 Export WE Schem - + 导出为 Litematica投影 Export Litematic - + <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> <html><head/><body><p align="justify">The last step is to generate map data files.</p><p align="justify">The name of map data files is like<span style=" font-weight:700;"> map_3.dat</span>, it's used to storage content of maps. In it's file name, 3 refers to the sequence number of map data files. Sequence number starts with 0.</p><p align="justify">Located in<span style=" font-weight:700;"> data</span> folder in your saves, map data files can only be manipulated with enough authority. If you are neither single-player nor op in a server, you should export it as litematic instead of map data files.</p><p align="justify">Each map can only show a 128×128 frame, a large image results to multiple map data files. Thus, a continuous series of sequence numbers will be occupied.</p><p align="justify">For ex, run <span style=" font-weight:700;">/give @s filled_map{map:3}</span> will give you the map of <span style=" font-weight:700;">map_3.dat </span><p align="justify">1.12Command: /give @p filled_map 1 3</p><span style=" font-style:italic;">.</span></p><p align="justify">This is suitable for large images, but not for servers.</p></body></html> - + 导出的文件名 Map data files - + 地图文件起始序号 Beginning sequence number - + 地图画行数 Map rows - + 地图画列数 Map cols - + 地图文件数量 Map counts - + 查看导出的文件 See exported file - - + + 联系作者 Contact with me - + 退出 Exit - + <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021 TokiNoBug</span></p></body></html> <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">Your map is finished!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">About SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">You are currently using the 3rd generation of SlopeCraft, based on Qt, Eigen and zlib. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono) made great effort to the designing and optimization, and also developed a brand-new interface based on SlopeCraft's kernel. Besides, Cubik65536 and 67au made contribution to the adaption on MacOS and Linux platforms respectively.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Contact with me:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft on github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">My homepage on GitHub</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">This program is released under license GPL-3.0 or later.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - + 关于 About - + 地图画 Map - + 高级 Advanced - + 批量操作 Batch operation - + 方块列表预设 Blocklist preset - - - - - - - + + + + + + + 转到页面 Goto this page - - - + + + 导出为投影文件 Export as litematic - - + + 导出为mcfunction Export as mcfunction - + 导出为地图文件 Export as map files - + 关于SlopeCraft About SlopeCraft - + 测试方块列表 Test block list - + 设置导出参数 Set exporting parameters - - + + 保存预设 Save preset - + 加载预设 Load preset - + 输出当前颜色表 Export current colorset - + 使用教程 Tutorial - - - + + + 检查更新 Check updates @@ -904,134 +904,134 @@ After you reset the strategy, load the image again. Error details : - + 你输入的起始序号不可用 Invalid sequence number. - + 请选择导出的文件夹 Please select a folder for exporting. - + 你选择的文件夹不存在! Folder dosen't exist! - + 请稍等 Please wait - + 具体信息: Detail: - + 未知游戏版本 Unknown game version - - - - + + + + 导出原理图失败 Failed to export. - + 方块种类超出上限。 The types of blocks overflow. - + 错误的文件扩展名 Invalid file extension name - + 三维结构中存在错误的方块 Wrong block in 3D structure. - + 无法创建/打开文件 Failed to create/open file - + 导出原版结构方块文件失败 Failed to export vanilla structure file. - + 导出时指定不使用结构空位表示空气,但方块列表中不包含空气。 When exporting as structure, you assigned not to replace air with structure void, but there is no air in the block palette. - + 转化原图为地图画时出错 Error occurred when converting image to map - + 原图为空!你可能没有导入原图! Your source image is empty! You might have forgot to import source image! - + 构建高度矩阵时出现错误 Error occurred when making height martix - + 原版地图画不允许出现第三个阴影(不存在的几何关系不可能生存实装!) 请检查你的地图画类型,纯文件地图画不可以导出为投影! The third shadow shouldn't apper in vanilla map! Check your map type, remember that file-only map can't be exported as litematic! - + 跳步操作 You skipped a step - + 有损压缩失败 Inteligent lossy compression failed - + 最大允许高度太小了 The maxmium allowed height is too low - + 允许使用的颜色过少 Too few colors allowed! - + 你应该勾选启用尽可能多的基色,颜色太少是不行的! You should enable as much base colors as possible. - - + + 这可能是因为路径中含有中文字符! This might because of non-English characters in filename of path. - + 删除临时文件失败 Failed to remove temporary file - + 在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 这可能是因为地图画行数过大。 尝试启用无损压缩,或者提高最大允许高度 Lossy compression failed to compress the maximun height down to max allowed hehight when computing height map. This may be caused by a too large image. Try enabling lossless compression, or enlarge max allowed height. @@ -1066,182 +1066,198 @@ Check your map type, remember that file-only map can't be exported as litem (xz coordinate = -65±128×<any integer>) - + 你输入的起始序号不可用,请输入大于等于 0 的整数! The initial sequence number is invalid, expected non-negative number! - + 请输入大于等于 0 的整数! Please input a non negative number! - + 你可以选择存档中的 data 文件夹 You can select the "data" dir in the saves of MC. - + + 导出时将会覆盖部分地图文件 + Some files will be replaced + + + + %1 个文件将被覆盖: +%2 + +点击"Yes"将继续并覆盖这些文件,点击"No"将撤销本次操作。 + %1 file(s) will be replaced: +%2 + +Click "Yes" to continue and replace these files, or click "No" to cancel this operation. + + + 导出 WorldEdit 原理图失败 Failed to export WorldEdit schem - + 不支持导出 1.12 WorldEdit 原理图(.schematic 格式),仅支持.schem 格式 Exporting as WE schematic is not supported in MC 12(*.schematic), only *.schem is supported - + SlopeCraft 不允许你跳步操作,请按照左侧竖边栏的顺序操作! Skipping any step is not allowed by SlopeCraft - + 有损压缩的最大允许不要低于 14,否则很容易压缩失败 The maximum height of lossy compression should not be less than 14 - + 导出时 Gzip 压缩文件失败 Failed to compress a exported file - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 可用 - + 种颜色 colors available. - + 保存截屏 Save screenshot - + 图片 (*.jpg *.jpeg *.tif *.bmp *.png) Image (*.jpg *.jpeg *.tif *.bmp *.png) - + 保存当前显示图片 Save current image - + 图片 (*.png) Image (*.png) - + 保存预设文件失败 Failed to save preset file - + 无法创建文件"%1" Failed to create file "%1" - + 选择预设文件 Select a preset file - + 加载预设失败 Failed to load preset - + 测试方块列表的结构文件 Svae structure file for blocklist testing - + 测试方块列表失败 Failed to test the block list. - + 具体信息: Detailed information: - + 保存颜色表 Save palette - + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image From ec639a12fd046ab6e8de024f77bf2b6d3a09aff4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 18 Apr 2023 23:48:00 +0800 Subject: [PATCH 0196/1123] try to install opencl in linux-build --- .github/workflows/opencl-linux.yml | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/opencl-linux.yml diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml new file mode 100644 index 00000000..d0de78e3 --- /dev/null +++ b/.github/workflows/opencl-linux.yml @@ -0,0 +1,33 @@ +name: Build dev version artifacts +on: + pull_request: + push: + branches: + - opencl-in-github-action + +jobs: + + linux: + runs-on: ubuntu-latest + env: + steps: + - name: Install cmake, ninja + run: sudo apt install cmake ninja-build + + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install qt6 + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + + - name: Install additional qt-related packages + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install OpenCL + run: sudo apt install nvidia-cuda-toolkit + #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + - name: List all packages + run: apt list --installed + - name: find cl.hpp + run: sudo find / -name cl.hpp + From 8c0d8843c0c5f0052d4e37ed752c6f994278d9de Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 00:09:47 +0800 Subject: [PATCH 0197/1123] fix github actions --- .github/workflows/opencl-linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index d0de78e3..2ed63ea9 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -9,7 +9,6 @@ jobs: linux: runs-on: ubuntu-latest - env: steps: - name: Install cmake, ninja run: sudo apt install cmake ninja-build From d38ff0f37bba1212a7fa20dd1a190b1b2974f36d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 00:36:49 +0800 Subject: [PATCH 0198/1123] try to install cl.hpp --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 2ed63ea9..2866fea5 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -23,7 +23,7 @@ jobs: run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit + run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: List all packages run: apt list --installed From 29e66482cd1dd478c22120dcbd3a285e95968b57 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 00:44:36 +0800 Subject: [PATCH 0199/1123] try to install cl.hpp --- .github/workflows/opencl-linux.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 2866fea5..cfc2f520 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -10,21 +10,9 @@ jobs: linux: runs-on: ubuntu-latest steps: - - name: Install cmake, ninja - run: sudo apt install cmake ninja-build - - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - - - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - - name: Install additional qt-related packages - run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev - # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 - #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 nvidia-utils-525 libnvidia-common-525 opencl-c-headers opencl-clhpp-headers + #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev - name: List all packages run: apt list --installed - name: find cl.hpp From 5637fe263c2b042774ff1c659bdcf8d8fca3d172 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 00:57:22 +0800 Subject: [PATCH 0200/1123] try to install cl.hpp --- .github/workflows/opencl-linux.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index cfc2f520..44d7395b 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -16,5 +16,7 @@ jobs: - name: List all packages run: apt list --installed - name: find cl.hpp - run: sudo find / -name cl.hpp + run: | + sudo find / -name cl.hpp > find_clhpp.txt + cat ./find_clhpp.txt | grep cl.hpp From fc739e9ed749e8298ef43bc0bdb5742fa0b540c3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 01:01:42 +0800 Subject: [PATCH 0201/1123] try to install cl.hpp --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 44d7395b..072a77a4 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 nvidia-utils-525 libnvidia-common-525 opencl-c-headers opencl-clhpp-headers + run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 nvidia-utils-525 libnvidia-common-525 opencl-c-headers opencl-clhpp-headers nvidia-compute-utils-525 #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev - name: List all packages run: apt list --installed From 594f0051932fdc243b4ea1c1b7b403912d5de99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 12:52:29 +0800 Subject: [PATCH 0202/1123] fix vccl installation on macos --- vccl/deploy_qt_for_vccl_macos.cmake.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 359f73df..f8ef54db 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -11,3 +11,11 @@ file(CREATE_LINK "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl" "@CMAKE_INSTALL_PREFIX@/vccl" SYMBOLIC) +file(CREATE_LINK + "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl-config.json" + "@CMAKE_INSTALL_PREFIX@/vccl-config.json" + SYMBOLIC) +file(CREATE_LINK + "./@vccl_prefix@/vccl.app/Contents/MacOS/Blocks_VCL" + "@CMAKE_INSTALL_PREFIX@/Blocks_VCL" + SYMBOLIC) From 07398bfe303c876d7db58363c0014bbc60e1c4db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 12:56:05 +0800 Subject: [PATCH 0203/1123] install opencl headers for linux-build --- .github/workflows/opencl-linux.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 072a77a4..f8415527 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -16,7 +16,7 @@ jobs: - name: List all packages run: apt list --installed - name: find cl.hpp - run: | - sudo find / -name cl.hpp > find_clhpp.txt - cat ./find_clhpp.txt | grep cl.hpp + run: sudo find / -name cl.hpp > ./find_clhpp.txt + - name: list cl.hpp + run: cat ./find_clhpp.txt From 666eb42feb68c6dc3992e7edf844b895eae765a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 14:46:25 +0800 Subject: [PATCH 0204/1123] install opencl headers for linux-build --- .github/workflows/opencl-linux.yml | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index f8415527..7ed2eb84 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -10,13 +10,20 @@ jobs: linux: runs-on: ubuntu-latest steps: - - name: Install OpenCL - run: sudo apt install nvidia-cuda-toolkit libnvidia-compute-525 libnvidia-extra-525 nvidia-utils-525 libnvidia-common-525 opencl-c-headers opencl-clhpp-headers nvidia-compute-utils-525 - #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev - - name: List all packages - run: apt list --installed - - name: find cl.hpp - run: sudo find / -name cl.hpp > ./find_clhpp.txt - - name: list cl.hpp - run: cat ./find_clhpp.txt + - name: make dir + run: mkdir neo + - name: download + run: | + cd neo + wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-core_1.0.13230.7_amd64.deb + wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-opencl_1.0.13230.7_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu-dbgsym_1.3.25593.11_amd64.ddeb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu_1.3.25593.11_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb + - name: install + run: sudo dpkg -i ./neo/*.deb + - name: find cl.hpp + run: sudo find / -name cl.hpp \ No newline at end of file From 4037738cbee6658a1ee7e818a5d27d7719717ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 14:48:11 +0800 Subject: [PATCH 0205/1123] install opencl headers for linux-build --- .github/workflows/opencl-linux.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 7ed2eb84..2c81c366 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -23,7 +23,9 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb - name: install - run: sudo dpkg -i ./neo/*.deb + run: | + sudo apt install ocl-icd-libopencl1 + sudo dpkg -i ./neo/*.deb - name: find cl.hpp run: sudo find / -name cl.hpp \ No newline at end of file From 38d5dd34daa4aa14d9ffd0ebfee862819c96f9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 14:56:40 +0800 Subject: [PATCH 0206/1123] try to add opencl for linux-build --- .github/workflows/build-dev.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4c488bbf..a5b5d113 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -64,7 +64,7 @@ jobs: strategy: matrix: build_type: [Debug, Release] - gpu_api: [None] + gpu_api: [None, OpenCL] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -91,6 +91,21 @@ jobs: - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install intel OpenCL sdk + if: matrix.gpu_api == 'OpenCL' + run: | + mkdir neo + cd neo + wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-core_1.0.13230.7_amd64.deb + wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-opencl_1.0.13230.7_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu-dbgsym_1.3.25593.11_amd64.ddeb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu_1.3.25593.11_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb + wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb + sudo apt install ocl-icd-libopencl1 + sudo dpkg -i ./neo/*.deb + #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers From ef10327468ca059a056c3f9c01854e73bfdf6c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 14:57:17 +0800 Subject: [PATCH 0207/1123] try to add opencl for linux-build --- .github/workflows/opencl-linux.yml | 91 +++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 2c81c366..2055c6d1 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -7,13 +7,42 @@ on: jobs: - linux: + linux-build: runs-on: ubuntu-latest + strategy: + matrix: + build_type: [Debug] + gpu_api: [OpenCL] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} steps: - - name: make dir - run: mkdir neo - - name: download + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Make directories + run: mkdir build install pack + + #- name: List installed + # run: apt list --installed + + - name: Install cmake, ninja + run: sudo apt install cmake ninja-build + + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install qt6 + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + + - name: Install additional qt-related packages + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install intel OpenCL sdk + if: matrix.gpu_api == 'OpenCL' run: | + mkdir neo cd neo wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-core_1.0.13230.7_amd64.deb wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-opencl_1.0.13230.7_amd64.deb @@ -22,10 +51,56 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb - - name: install - run: | sudo apt install ocl-icd-libopencl1 sudo dpkg -i ./neo/*.deb - - name: find cl.hpp - run: sudo find / -name cl.hpp \ No newline at end of file + #- name: Install OpenCL + # run: sudo apt install nvidia-cuda-toolkit + #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + #- name: List all packages + # run: apt list --installed + + - name: Install xz (Release as tar.xz) + run: sudo apt install xz-utils + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + + - name: CMake build + run: cmake --build ./build --parallel + + - name: CMake install + run: cmake --install ./build + + - name: Run CTest + if: matrix.build_type == 'Release' + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + + - name: Make deb and tar.xz packs with cpack + run: | + cd build + cpack -G DEB -B ../pack + cpack -G TXZ -B ../pack + cd .. + + - name: Upload deb pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + path: pack/SlopeCraft*.deb + if-no-files-found: error + + - name: Upload tar.xz pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz + path: pack/SlopeCraft*.tar.xz + if-no-files-found: error \ No newline at end of file From fe9bd24ecb2a601a7ccaa5d49cbb684b367cd3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 15:21:31 +0800 Subject: [PATCH 0208/1123] fix opencl installation --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 2055c6d1..d5642aa2 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -52,7 +52,7 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb sudo apt install ocl-icd-libopencl1 - sudo dpkg -i ./neo/*.deb + sudo dpkg -i 。/*.deb #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit From 5e77300e13eba15ba119941e3fd168e896d720aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 15:22:04 +0800 Subject: [PATCH 0209/1123] fix opencl installation --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index d5642aa2..8051c72a 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -52,7 +52,7 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb sudo apt install ocl-icd-libopencl1 - sudo dpkg -i 。/*.deb + sudo dpkg -i ./*.deb #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit From 8e91646357f10e6995e1a499b4e560804ef00280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 15:25:54 +0800 Subject: [PATCH 0210/1123] fix opencl installation --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 8051c72a..65e0a05b 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -51,7 +51,7 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb - sudo apt install ocl-icd-libopencl1 + sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers sudo dpkg -i ./*.deb #- name: Install OpenCL From ada7efea76f0a162f36ba39d433f9da923b30d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 15:46:28 +0800 Subject: [PATCH 0211/1123] show opencl include dirs --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index bedcc013..044e7cdb 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -24,6 +24,9 @@ target_include_directories(OCLWrapper INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_features(OCLWrapper PUBLIC cxx_std_20) target_link_libraries(OCLWrapper PUBLIC OpenCL::OpenCL ColorManip_cl_rc) +message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") +message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") + target_link_libraries(GPUInterface PUBLIC OCLWrapper) target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) From 7d91106c5364f56084bd921f36188f0deb91a507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:02:17 +0800 Subject: [PATCH 0212/1123] show opencl include dirs --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 044e7cdb..9f1f0a26 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -27,6 +27,11 @@ target_link_libraries(OCLWrapper PUBLIC OpenCL::OpenCL ColorManip_cl_rc) message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") +if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) + file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") + message(WARNING "CL/cl.hpp will not be found correctly. \n Manually found opencl_hpp_file = ${opencl_hpp_file}") +endif() + target_link_libraries(GPUInterface PUBLIC OCLWrapper) target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) From 7c6f0a4da915323c5ebee1e482ca53e49f0e89fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:08:47 +0800 Subject: [PATCH 0213/1123] show opencl include dirs --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 9f1f0a26..4a6f2111 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -28,8 +28,13 @@ message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) - file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") - message(WARNING "CL/cl.hpp will not be found correctly. \n Manually found opencl_hpp_file = ${opencl_hpp_file}") + file(GLOB_RECURSE cl_h_file "${OpenCL_INCLUDE_DIR}/*/cl.h") + file(GLOB_RECURSE cl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") + file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/opencl.hpp") + message(WARNING "CL/cl.hpp will not be found correctly.") + message(STATUS "Manually found cl_h_file = ${cl_h_file}") + message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") + message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") endif() target_link_libraries(GPUInterface PUBLIC OCLWrapper) From a812d9eaffd0b4d54f7a4c90b3700803637d5e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:16:49 +0800 Subject: [PATCH 0214/1123] show opencl include dirs --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 2 + utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 61 ++++++++++------------ utilities/GPUWrapper/OpenCL/OCLWrapper.h | 28 +++++----- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 4a6f2111..87377b18 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -35,6 +35,8 @@ if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) message(STATUS "Manually found cl_h_file = ${cl_h_file}") message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") + + target_compile_definitions(OCLWrapper PRIVATE SLOPECRAFT_NO_CL_HPP) endif() target_link_libraries(GPUInterface PUBLIC OCLWrapper) diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 3cad951e..35519a6a 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -23,7 +23,6 @@ This file is part of SlopeCraft. #include "OCLWrapper.h" #include "../GPU_interface.h" -#include #include #include #include @@ -45,7 +44,6 @@ size_t ocl_warpper::platform_num() noexcept { cl::Platform private_fun_get_platform(size_t platform_idx, cl_int &err) noexcept { - constexpr size_t buffersize = 128; cl_platform_id plats[buffersize]; @@ -67,12 +65,10 @@ cl::Platform private_fun_get_platform(size_t platform_idx, ocl_warpper::ocl_platform::ocl_platform(size_t idx) { this->platform = private_fun_get_platform(idx, this->err); - if (this->err != CL_SUCCESS) - return; + if (this->err != CL_SUCCESS) return; this->name = this->platform.getInfo(&this->err); - if (this->err != CL_SUCCESS) - return; + if (this->err != CL_SUCCESS) return; this->err = this->platform.getDevices(CL_DEVICE_TYPE_ALL, &this->devices); } @@ -226,8 +222,9 @@ void ocl_warpper::ocl_resource::resize_task(size_t task_num) noexcept { this->context, this->task.rawcolor_f32_3_device, task_f32_3_required_bytes, CL_MEM_READ_ONLY, false); if (!this->ok()) { - this->err_msg = "Failed to allocate device memory for " - "this->task.rawcolor_f32_3_device."; + this->err_msg = + "Failed to allocate device memory for " + "this->task.rawcolor_f32_3_device."; return; } @@ -235,8 +232,9 @@ void ocl_warpper::ocl_resource::resize_task(size_t task_num) noexcept { this->context, this->task.result_idx_u16_device, result_idx_required_bytes, CL_MEM_WRITE_ONLY, false); if (!this->ok()) { - this->err_msg = "Failed to allocate device memory for " - "this->task.result_idx_u16_device."; + this->err_msg = + "Failed to allocate device memory for " + "this->task.result_idx_u16_device."; return; } @@ -244,8 +242,9 @@ void ocl_warpper::ocl_resource::resize_task(size_t task_num) noexcept { this->context, this->task.result_diff_f32_device, result_diff_required_bytes, CL_MEM_WRITE_ONLY, false); if (!this->ok()) { - this->err_msg = "Failed to allocate device memory for " - "this->task.result_diff_f32_device."; + this->err_msg = + "Failed to allocate device memory for " + "this->task.result_diff_f32_device."; return; } return; @@ -255,8 +254,7 @@ void ocl_warpper::ocl_resource::resize_colorset(size_t color_num) noexcept { this->error = private_fun_change_buf_size( this->context, this->colorset.colorset_float3, color_num * 3 * sizeof(float), CL_MEM_READ_ONLY, false); - if (!this->ok()) - return; + if (!this->ok()) return; this->colorset.colorset_color_num = color_num; } @@ -294,24 +292,23 @@ void ocl_warpper::ocl_resource::set_colorset( } } -cl::Kernel * -ocl_warpper::ocl_resource::kernel_by_algo(::SCL_convertAlgo algo) noexcept { - +cl::Kernel *ocl_warpper::ocl_resource::kernel_by_algo( + ::SCL_convertAlgo algo) noexcept { switch (algo) { - case SCL_convertAlgo::RGB: - return &this->k_RGB; - case SCL_convertAlgo::RGB_Better: - return &this->k_RGB_Better; - case SCL_convertAlgo::HSV: - return &this->k_HSV; - case SCL_convertAlgo::Lab94: - return &this->k_Lab94; - case SCL_convertAlgo::Lab00: - return &this->k_Lab00; - case SCL_convertAlgo::XYZ: - return &this->k_XYZ; - default: - return nullptr; + case SCL_convertAlgo::RGB: + return &this->k_RGB; + case SCL_convertAlgo::RGB_Better: + return &this->k_RGB_Better; + case SCL_convertAlgo::HSV: + return &this->k_HSV; + case SCL_convertAlgo::Lab94: + return &this->k_Lab94; + case SCL_convertAlgo::Lab00: + return &this->k_Lab00; + case SCL_convertAlgo::XYZ: + return &this->k_XYZ; + default: + return nullptr; } return nullptr; } @@ -403,7 +400,6 @@ void ocl_warpper::ocl_resource::set_task(const std::array *src, */ void ocl_warpper::ocl_resource::set_args(::SCL_convertAlgo algo) noexcept { - this->wait(); if (!this->ok()) { this->err_msg = "Failed to wait."; @@ -472,7 +468,6 @@ cl_int private_fun_change_buf_size(cl::Context &context, cl::Buffer &buf, void ocl_warpper::ocl_resource::execute(::SCL_convertAlgo algo, bool wait) noexcept { - this->set_args(algo); if (!this->ok()) { this->err_msg = "Failed to set args."; diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.h b/utilities/GPUWrapper/OpenCL/OCLWrapper.h index 2021c1ec..acbf5694 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.h +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.h @@ -22,9 +22,13 @@ This file is part of SlopeCraft. #ifndef SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H #define SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H +#ifdef SLOPECRAFT_NO_CL_HPP +#include +#else +#include +#endif #include "../GPU_interface.h" -#include #include #include #include @@ -35,7 +39,7 @@ namespace ocl_warpper { size_t platform_num() noexcept; class ocl_resource : public ::gpu_wrapper::gpu_interface { -public: + public: struct task_rcs { // std::vector buf_unconverted_ARGB_host; cl::Buffer rawcolor_f32_3_device; @@ -50,7 +54,7 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { uint16_t colorset_color_num{0}; }; -private: + private: cl_int error{CL_SUCCESS}; std::string err_msg{""}; cl::Platform platform; @@ -71,10 +75,10 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { // buffers to for colorset -private: + private: void init_resource() noexcept; -public: + public: inline int error_code() const noexcept { return this->error; } inline bool ok() const noexcept { return (this->error == CL_SUCCESS); } @@ -82,7 +86,7 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { return this->err_msg; } -public: + public: ocl_resource(); ocl_resource(cl::Platform plat, cl::Device dev); @@ -120,7 +124,7 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { return this->local_work_group_size(); } -private: + private: void resize_task(size_t task_num) noexcept; void resize_colorset(size_t color_num) noexcept; @@ -128,7 +132,7 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { void set_args(::SCL_convertAlgo algo) noexcept; -public: + public: // overrided functions const char *api_v() const noexcept override { return "OpenCL"; } @@ -173,7 +177,7 @@ class ocl_resource : public ::gpu_wrapper::gpu_interface { }; class ocl_platform : public ::gpu_wrapper::platform_wrapper { -public: + public: ocl_platform() = delete; ocl_platform(size_t idx); cl::Platform platform; @@ -190,7 +194,7 @@ class ocl_platform : public ::gpu_wrapper::platform_wrapper { }; class ocl_device : public ::gpu_wrapper::device_wrapper { -public: + public: ocl_device() = delete; ocl_device(cl::Device); @@ -201,6 +205,6 @@ class ocl_device : public ::gpu_wrapper::device_wrapper { const char *name_v() const noexcept override { return this->name.c_str(); } }; -} // namespace ocl_warpper +} // namespace ocl_warpper -#endif // SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H \ No newline at end of file +#endif // SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H \ No newline at end of file From 9df26be977a35280eb11e8609b7c113946c1f6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:33:03 +0800 Subject: [PATCH 0215/1123] show opencl include dirs --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 87377b18..79777898 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -28,6 +28,8 @@ message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) + target_compile_definitions(OCLWrapper PRIVATE SLOPECRAFT_NO_CL_HPP) + file(GLOB_RECURSE cl_h_file "${OpenCL_INCLUDE_DIR}/*/cl.h") file(GLOB_RECURSE cl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/opencl.hpp") @@ -36,7 +38,8 @@ if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") - target_compile_definitions(OCLWrapper PRIVATE SLOPECRAFT_NO_CL_HPP) + file(GLOB_RECURSE all_cl_files "${OpenCL_INCLUDE_DIR}/CL*") + message(STATUS "All opencl headers: ${all_cl_files}") endif() target_link_libraries(GPUInterface PUBLIC OCLWrapper) From 8f0e98e38c1aefb153bed853d8ba9a199da77ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:44:08 +0800 Subject: [PATCH 0216/1123] try to fix opencl in linux-build --- utilities/GPUWrapper/OpenCL/OCLWrapper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.h b/utilities/GPUWrapper/OpenCL/OCLWrapper.h index acbf5694..cedc5295 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.h +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.h @@ -24,6 +24,7 @@ This file is part of SlopeCraft. #define SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H #ifdef SLOPECRAFT_NO_CL_HPP #include +#include #else #include #endif From 2868943056b286bf710206b588a763b6b2b25b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:49:48 +0800 Subject: [PATCH 0217/1123] try to fix opencl in linux-build --- .github/workflows/opencl-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 65e0a05b..019afecd 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -52,6 +52,7 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + wget https://old-releases.ubuntu.com/ubuntu/pool/main/k/khronos-opencl-clhpp/opencl-clhpp-headers_2.2.0~~2.0.11+git9-g0192662-1_all.deb sudo dpkg -i ./*.deb #- name: Install OpenCL From 5aee03eaa3047e5f36b5c654aad8443f8af082f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 16:54:22 +0800 Subject: [PATCH 0218/1123] try to fix opencl in linux-build --- cmake/configure_vanilla_zips.cmake | 2 +- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/configure_vanilla_zips.cmake b/cmake/configure_vanilla_zips.cmake index c193cde5..086fbc3c 100644 --- a/cmake/configure_vanilla_zips.cmake +++ b/cmake/configure_vanilla_zips.cmake @@ -27,7 +27,7 @@ foreach(mcver RANGE 12 19) file(DOWNLOAD ${VCL_url_prefix}${VCL_current_zip_name} - ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name} SHOW_PROGRESS) + ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) if(EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) message(STATUS "Downloaded resoruce pack for MC${mcver}.") diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 79777898..b202dab0 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -38,7 +38,7 @@ if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") - file(GLOB_RECURSE all_cl_files "${OpenCL_INCLUDE_DIR}/CL*") + file(GLOB_RECURSE all_cl_files "${OpenCL_INCLUDE_DIR}/CL/*") message(STATUS "All opencl headers: ${all_cl_files}") endif() From ac5f277c263d51ea5a4c5053f3ffe36bdb2cb02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 17:49:16 +0800 Subject: [PATCH 0219/1123] try to fix opencl in linux-build --- .github/workflows/opencl-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index 019afecd..aaa10904 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -51,7 +51,7 @@ jobs: wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb - sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev wget https://old-releases.ubuntu.com/ubuntu/pool/main/k/khronos-opencl-clhpp/opencl-clhpp-headers_2.2.0~~2.0.11+git9-g0192662-1_all.deb sudo dpkg -i ./*.deb From 4159103956e2864c6789ea624e19258c498a0cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 18:03:14 +0800 Subject: [PATCH 0220/1123] try to fix opencl in linux-build --- .github/workflows/opencl-linux.yml | 13 +++---------- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 12 +++++++++++- utilities/GPUWrapper/OpenCL/OCLWrapper.h | 1 - 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml index aaa10904..47de347c 100644 --- a/.github/workflows/opencl-linux.yml +++ b/.github/workflows/opencl-linux.yml @@ -44,20 +44,13 @@ jobs: run: | mkdir neo cd neo - wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-core_1.0.13230.7_amd64.deb - wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.13230.7/intel-igc-opencl_1.0.13230.7_amd64.deb - wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu-dbgsym_1.3.25593.11_amd64.ddeb - wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-level-zero-gpu_1.3.25593.11_amd64.deb - wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd-dbgsym_23.05.25593.11_amd64.ddeb - wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/intel-opencl-icd_23.05.25593.11_amd64.deb - wget https://github.com/intel/compute-runtime/releases/download/23.05.25593.11/libigdgmm12_22.3.0_amd64.deb - sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev - wget https://old-releases.ubuntu.com/ubuntu/pool/main/k/khronos-opencl-clhpp/opencl-clhpp-headers_2.2.0~~2.0.11+git9-g0192662-1_all.deb - sudo dpkg -i ./*.deb + sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers #- name: Install OpenCL # run: sudo apt install nvidia-cuda-toolkit #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + + # wget https://old-releases.ubuntu.com/ubuntu/pool/main/k/khronos-opencl-clhpp/opencl-clhpp-headers_2.2.0~~2.0.11+git9-g0192662-1_all.deb #- name: List all packages # run: apt list --installed diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 35519a6a..7763dc59 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -116,10 +116,20 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { return; } +#ifndef SLOPECRAFT_NO_CL_HPP + std::pair src; src.first = (const char *)ColorManip_cl_rc; src.second = ColorManip_cl_rc_length; - this->program = cl::Program(this->context, {src}, &this->error); + this->program = cl::Program{this->context, {src}, &this->error}; +#else + this->program = cl::Program{ + this->context, + {this->device}, + std::string{(const char *)ColorManip_cl_rc, ColorManip_cl_rc_length}, + &this->error}; +#endif + if (!this->ok()) { this->err_msg = "Failed to create program with source files."; return; diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.h b/utilities/GPUWrapper/OpenCL/OCLWrapper.h index cedc5295..acbf5694 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.h +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.h @@ -24,7 +24,6 @@ This file is part of SlopeCraft. #define SLOPECRAFT_UTILITIES_COLORDIRR_OPENCL_H #ifdef SLOPECRAFT_NO_CL_HPP #include -#include #else #include #endif From 2b588faea3d405b22d8112c9d3318b7f6eced024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 18:15:38 +0800 Subject: [PATCH 0221/1123] fix opencl on linux-build --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 21 ++++++++++++--------- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 6 +++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index b202dab0..88fbd647 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -29,17 +29,20 @@ message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) target_compile_definitions(OCLWrapper PRIVATE SLOPECRAFT_NO_CL_HPP) - - file(GLOB_RECURSE cl_h_file "${OpenCL_INCLUDE_DIR}/*/cl.h") - file(GLOB_RECURSE cl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") - file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/opencl.hpp") - message(WARNING "CL/cl.hpp will not be found correctly.") - message(STATUS "Manually found cl_h_file = ${cl_h_file}") - message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") - message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") - + message(STATUS "Failed to find cl.hpp. This file doesn't exists in opencl include dir. + SlopeCraft assumes that opencl.hpp exists, and will try to include it.") + + # file(GLOB_RECURSE cl_h_file "${OpenCL_INCLUDE_DIR}/*/cl.h") + # file(GLOB_RECURSE cl_hpp_file "${OpenCL_INCLUDE_DIR}/*/cl.hpp") + # file(GLOB_RECURSE opencl_hpp_file "${OpenCL_INCLUDE_DIR}/*/opencl.hpp") + # message(WARNING "CL/cl.hpp will not be found correctly.") + # message(STATUS "Manually found cl_h_file = ${cl_h_file}") + # message(STATUS "Manually found cl_hpp_file = ${cl_hpp_file}") + # message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") file(GLOB_RECURSE all_cl_files "${OpenCL_INCLUDE_DIR}/CL/*") message(STATUS "All opencl headers: ${all_cl_files}") +else() + message(STATUS "Found opencl C++ header: ${OpenCL_INCLUDE_DIR}/CL/cl.hpp") endif() target_link_libraries(GPUInterface PUBLIC OCLWrapper) diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 7763dc59..7746cebc 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -116,13 +116,17 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { return; } +// Here the code differs according to if there is cl.hpp. API to create +// cl::Program is different in cl.hpp and opencl.hpp. I don't know why there are +// 2 differernt opencl C++ bindings. #ifndef SLOPECRAFT_NO_CL_HPP - + // This works with cl.hpp std::pair src; src.first = (const char *)ColorManip_cl_rc; src.second = ColorManip_cl_rc_length; this->program = cl::Program{this->context, {src}, &this->error}; #else + // this works with opencl.hpp this->program = cl::Program{ this->context, {this->device}, From 52b468997c101b81cdb16f92850c9071e8908256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 18:17:34 +0800 Subject: [PATCH 0222/1123] add opencl to linux-build --- .github/workflows/build-dev.yml | 22 +++---- .github/workflows/opencl-linux.yml | 100 ----------------------------- 2 files changed, 10 insertions(+), 112 deletions(-) delete mode 100644 .github/workflows/opencl-linux.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4c488bbf..cd8bf912 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -64,7 +64,7 @@ jobs: strategy: matrix: build_type: [Debug, Release] - gpu_api: [None] + gpu_api: [None, OpenCL] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -91,11 +91,9 @@ jobs: - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - #- name: Install OpenCL - # run: sudo apt install nvidia-cuda-toolkit - #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - #- name: List all packages - # run: apt list --installed + - name: Install intel OpenCL sdk + if: matrix.gpu_api == 'OpenCL' + run: sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: Install xz (Release as tar.xz) run: sudo apt install xz-utils @@ -111,12 +109,6 @@ jobs: - name: CMake install run: cmake --install ./build - - - name: Run CTest - if: matrix.build_type == 'Release' - run: | - cd ./build - ctest -j20 --output-on-failure --stop-on-failure - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -142,6 +134,12 @@ jobs: path: pack/SlopeCraft*.tar.xz if-no-files-found: error + - name: Run CTest + if: matrix.build_type == 'Release' + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure + windows-build: runs-on: windows-latest strategy: diff --git a/.github/workflows/opencl-linux.yml b/.github/workflows/opencl-linux.yml deleted file mode 100644 index 47de347c..00000000 --- a/.github/workflows/opencl-linux.yml +++ /dev/null @@ -1,100 +0,0 @@ -name: Build dev version artifacts -on: - pull_request: - push: - branches: - - opencl-in-github-action - -jobs: - - linux-build: - runs-on: ubuntu-latest - strategy: - matrix: - build_type: [Debug] - gpu_api: [OpenCL] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Make directories - run: mkdir build install pack - - #- name: List installed - # run: apt list --installed - - - name: Install cmake, ninja - run: sudo apt install cmake ninja-build - - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - - - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - - name: Install additional qt-related packages - run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev - # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install intel OpenCL sdk - if: matrix.gpu_api == 'OpenCL' - run: | - mkdir neo - cd neo - sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - - #- name: Install OpenCL - # run: sudo apt install nvidia-cuda-toolkit - #nvidia-cuda-dev ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - - # wget https://old-releases.ubuntu.com/ubuntu/pool/main/k/khronos-opencl-clhpp/opencl-clhpp-headers_2.2.0~~2.0.11+git9-g0192662-1_all.deb - #- name: List all packages - # run: apt list --installed - - - name: Install xz (Release as tar.xz) - run: sudo apt install xz-utils - - - name: Checkout repository - uses: actions/checkout@v2 - - - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - - - name: CMake build - run: cmake --build ./build --parallel - - - name: CMake install - run: cmake --install ./build - - - name: Run CTest - if: matrix.build_type == 'Release' - run: | - cd ./build - ctest -j20 --output-on-failure --stop-on-failure - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - - name: Make deb and tar.xz packs with cpack - run: | - cd build - cpack -G DEB -B ../pack - cpack -G TXZ -B ../pack - cd .. - - - name: Upload deb pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - path: pack/SlopeCraft*.deb - if-no-files-found: error - - - name: Upload tar.xz pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz - path: pack/SlopeCraft*.tar.xz - if-no-files-found: error \ No newline at end of file From fcbc1398f9d686e7a670fbd5bda825af2763abe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 18:29:39 +0800 Subject: [PATCH 0223/1123] remove intel opencl sdk installation --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index cd8bf912..c120de61 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -91,7 +91,7 @@ jobs: - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install intel OpenCL sdk + - name: Install OpenCL sdk if: matrix.gpu_api == 'OpenCL' run: sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers From 4d350e6c7afa14651d2941819095649309c0bc87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 18:29:55 +0800 Subject: [PATCH 0224/1123] add gpu api to package name --- cpack/make-packs.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 020386f8..9d109fd0 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -11,6 +11,8 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) endif() +set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-${SlopeCraft_GPU_API}) + if(${WIN32}) configure_file(${CMAKE_SOURCE_DIR}/cpack/pack_deployed_files.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake From aabdead1ee8482acdce96a6b051f913700cf2ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:11:27 +0800 Subject: [PATCH 0225/1123] format root cmakelist.txt --- CMakeLists.txt | 81 +++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcd1c584..f5032d44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,25 @@ cmake_minimum_required(VERSION 3.20) +# set version ----------------------------------------------------------------- set(SlopeCraft_version 5.0.1) +# set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) +if(${LINUX}) + message(STATUS "setting runpath for linux") + set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") + + # set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + # set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) +endif() + +enable_testing() + +# configure options ----------------------------------------------------------- set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") option(SlopeCraft_vectorize "Compile with vectorization" ON) @@ -17,53 +30,40 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) -# manage the install prefix +# manage the install prefix -------------------------------------------------- if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) endif() -# convert relative path to absolute +# convert relative path to absolute ------------------------------------------ cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX OUTPUT_VARIABLE CMAKE_INSTALL_PREFIX) message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") -if(${MSVC}) - add_compile_options("/Zc:__cplusplus") - add_compile_options("/wd4819") - add_compile_options("/utf-8") - -# add_compile_definitions("ZLIB_WINAPI") -# 1add_compile_definitions("Z_HAVE_UNISTD_H") -else() - add_compile_options(-Wall -Wreturn-type -Wsign-compare -Wextra) - add_link_options(-flto) +# Remove old compilation database -------------------------------------------- +if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) + # delete files here + file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) endif() -enable_testing() - +# warn if not gcc ------------------------------------------------------------ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") message(WARNING "MSVC or Clang are not fully supported. You MAY meet werid errors if you continue to build. Please use gcc.") endif() -if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) - # delete files here - file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) -endif() - +# configure global dependencies ---------------------------------------------- include(cmake/add_compiler_path_to_prefix.cmake) - -list(LENGTH CMAKE_PREFIX_PATH temp_L) - include(cmake/find_nlohmann_json.cmake) include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -include(cmake/install_if_is_shared.cmake) -add_definitions("-D_USE_MATH_DEFINES") -add_definitions("-DSCL_FIND_GlobalEnums_BY_PATH") +if(${WIN32}) + include(cmake/install_if_is_shared.cmake) +endif() +# Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) @@ -83,33 +83,45 @@ if(${SlopeCraft_vectorize}) # list(APPEND SlopeCraft_vectorize_flags "-O3") endif() -if(${LINUX}) - message(STATUS "setting runpath for linux") - set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") - - # set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - # set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) -endif() - if(${WIN32}) - add_compile_definitions("_CRT_SECURE_NO_WARNINGS") + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() +# Add global compile options ------------------------------------------------- # profile with gprof if(${SlopeCraft_gprof}) add_compile_options("-pg") add_link_options("-pg") endif() +add_definitions(_USE_MATH_DEFINES) +add_definitions(SCL_FIND_GlobalEnums_BY_PATH) add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) + +# Add compile options for different compilers +if(${MSVC}) + add_compile_options("/Zc:__cplusplus") + add_compile_options("/wd4819") + add_compile_options("/utf-8") + +# add_compile_definitions("ZLIB_WINAPI") +# 1add_compile_definitions("Z_HAVE_UNISTD_H") +else() + add_compile_options(-Wall -Wreturn-type -Wsign-compare -Wextra) + add_link_options(-flto) +endif() + +# Add global include dirs ---------------------------------------------------- include_directories(${CMAKE_BINARY_DIR}/utilities) +# Add global custom targets on windows --------------------------------------- if(${WIN32}) add_custom_target(SC_create_all_symlinks COMMENT "A interface target to create all symlinks on windows") endif() +# Sub dirss ------------------------------------------------------------------ add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) @@ -120,5 +132,6 @@ add_subdirectory(VisualCraftL) add_subdirectory(VisualCraft) add_subdirectory(vccl) +# install and pack ----------------------------------------------------------- include(cmake/install.cmake) include(cpack/make-packs.cmake) \ No newline at end of file From f4d27431c0d2eebeef692bdd32e26190de97c7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:11:51 +0800 Subject: [PATCH 0226/1123] try to fix opencl for opencl.hpp --- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 7746cebc..0cb4f268 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -126,12 +126,12 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { src.second = ColorManip_cl_rc_length; this->program = cl::Program{this->context, {src}, &this->error}; #else - // this works with opencl.hpp - this->program = cl::Program{ - this->context, - {this->device}, - std::string{(const char *)ColorManip_cl_rc, ColorManip_cl_rc_length}, - &this->error}; + // This is for opencl.hpp + std::string source_code{(const char *)ColorManip_cl_rc, + ColorManip_cl_rc_length}; + source_code.push_back('\0'); + this->program = + cl::Program{this->context, {this->device}, source_code, &this->error}; #endif if (!this->ok()) { From 0331e7bd811854ad836696b1e34f69d82700a3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:15:06 +0800 Subject: [PATCH 0227/1123] fix build --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5032d44..49bfc7f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,8 +94,8 @@ if(${SlopeCraft_gprof}) add_link_options("-pg") endif() -add_definitions(_USE_MATH_DEFINES) -add_definitions(SCL_FIND_GlobalEnums_BY_PATH) +add_compile_definitions(_USE_MATH_DEFINES) +add_compile_definitions(SCL_FIND_GlobalEnums_BY_PATH) add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) From 69801c6ae52ef7598d3515f2364bd2fbc55a158c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:22:56 +0800 Subject: [PATCH 0228/1123] hide None for linux-build --- .github/workflows/build-dev.yml | 2 +- CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index c120de61..cbf5a855 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -64,7 +64,7 @@ jobs: strategy: matrix: build_type: [Debug, Release] - gpu_api: [None, OpenCL] + gpu_api: [OpenCL] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 49bfc7f4..cc98129c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,8 @@ endif() # warn if not gcc ------------------------------------------------------------ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") message(WARNING "MSVC or Clang are not fully supported. - You MAY meet werid errors if you continue to build. - Please use gcc.") + You MAY meet werid errors if you continue to build. + Please use gcc.") endif() # configure global dependencies ---------------------------------------------- From b4354928df73af8f721ccbbd2682f2300399e8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:26:58 +0800 Subject: [PATCH 0229/1123] remove repeated packages --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index cbf5a855..efebd660 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -86,14 +86,14 @@ jobs: run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 libqt6concurrent6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL sdk if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers - name: Install xz (Release as tar.xz) run: sudo apt install xz-utils From d2723278c3f2f295e7bad3db6fd1e1703ac8ee96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 19:27:14 +0800 Subject: [PATCH 0230/1123] set deps by gpu api --- cpack/deb.cmake | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cpack/deb.cmake b/cpack/deb.cmake index c55cc417..dfde5333 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -2,14 +2,15 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "SlopeCraft group") set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE x86_64) set(SlopeCraft_debian_opencl_deps) -if(${SlopeCraft_GPU_API}) - set(SlopeCraft_debian_opencl_deps + +if(${SlopeCraft_GPU_API} STREQUAL "OpenCL") + set(SlopeCraft_debian_opencl_deps ocl-icd-libopencl1 - ) + ) endif() -set(CPACK_DEBIAN_PACKAGE_DEPENDS - libzip4 +set(CPACK_DEBIAN_PACKAGE_DEPENDS + libzip4 libpng16-16 libqt6core6 libqt6gui6 @@ -22,7 +23,7 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS libglx0 qt6-qpa-plugins ${SlopeCraft_debian_opencl_deps} - ) +) -set(CPACK_DEBIAN_PACKAGE_DESCRIPTION +set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Get your Minecraft pixel painting in multiple kinds of forms") \ No newline at end of file From 757787d29f7bf2480a9b29a5e8da90cec2bb3dca Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 20:19:49 +0800 Subject: [PATCH 0231/1123] fix opencl build with opencl.hpp --- utilities/ColorManip/tests/test_algo.cpp | 47 ++++++++++--------- utilities/GPUWrapper/GPU_interface.h | 29 +++++++----- utilities/GPUWrapper/OpenCL/GPU_interface.cpp | 20 +++++--- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 4 +- 4 files changed, 57 insertions(+), 43 deletions(-) diff --git a/utilities/ColorManip/tests/test_algo.cpp b/utilities/ColorManip/tests/test_algo.cpp index fba3fb89..3ac1a0ab 100644 --- a/utilities/ColorManip/tests/test_algo.cpp +++ b/utilities/ColorManip/tests/test_algo.cpp @@ -94,7 +94,6 @@ int list_gpu() noexcept { void fill_c3arr(std::vector> &dst, std::mt19937 &mt, SCL_convertAlgo algo) noexcept { - std::uniform_real_distribution randf(0, 1); for (auto &c3 : dst) { for (float &val : c3) { @@ -102,31 +101,35 @@ void fill_c3arr(std::vector> &dst, std::mt19937 &mt, } switch (algo) { - case SCL_convertAlgo::RGB: - case SCL_convertAlgo::RGB_Better: - break; - case SCL_convertAlgo::HSV: - RGB2HSV(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); - break; - case SCL_convertAlgo::Lab00: - case SCL_convertAlgo::Lab94: - RGB2XYZ(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); - XYZ2Lab(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); - break; - case SCL_convertAlgo::XYZ: - RGB2XYZ(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); - break; - default: - abort(); - break; + case SCL_convertAlgo::RGB: + case SCL_convertAlgo::RGB_Better: + break; + case SCL_convertAlgo::HSV: + RGB2HSV(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); + break; + case SCL_convertAlgo::Lab00: + case SCL_convertAlgo::Lab94: + RGB2XYZ(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); + XYZ2Lab(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); + break; + case SCL_convertAlgo::XYZ: + RGB2XYZ(c3[0], c3[1], c3[2], c3[0], c3[1], c3[2]); + break; + default: + abort(); + break; } } } -#define HANDLE_ERR(gi, ret) \ - if (!gi->ok_v()) { \ - cout << gi->error_detail_v() << " : " << gi->error_code_v() << endl; \ - return ret; \ +#define HANDLE_ERR(gi, ret) \ + if (gi == nullptr) { \ + cout << "failed to create gpu resource handle. gi==nullptr" << endl; \ + return ret; \ + } \ + if (!gi->ok_v()) { \ + cout << gi->error_detail_v() << " : " << gi->error_code_v() << endl; \ + return ret; \ } int run_task(task_t &task) noexcept { diff --git a/utilities/GPUWrapper/GPU_interface.h b/utilities/GPUWrapper/GPU_interface.h index 8eb068a4..731b9da4 100644 --- a/utilities/GPUWrapper/GPU_interface.h +++ b/utilities/GPUWrapper/GPU_interface.h @@ -33,14 +33,14 @@ namespace gpu_wrapper { static constexpr bool have_api = true; #else static constexpr bool have_api = false; -#endif // #ifdef SLOPECRAFT_GPU_API +#endif // #ifdef SLOPECRAFT_GPU_API const char *api_name() noexcept; size_t platform_num() noexcept; class platform_wrapper { -public: + public: platform_wrapper() = default; virtual ~platform_wrapper() = default; @@ -50,30 +50,33 @@ class platform_wrapper { // virtual size_t index() const noexcept = 0; - [[nodiscard]] static platform_wrapper * - create(size_t idx, int *errorcode = nullptr) noexcept; + [[nodiscard]] static platform_wrapper *create( + size_t idx, int *errorcode = nullptr) noexcept; static void destroy(platform_wrapper *) noexcept; }; class device_wrapper { -public: + public: device_wrapper() = default; virtual ~device_wrapper() = default; virtual const char *name_v() const noexcept = 0; - [[nodiscard]] static device_wrapper * - create(platform_wrapper *pw, size_t idx, int *errorcode = nullptr) noexcept; + [[nodiscard]] static device_wrapper *create( + platform_wrapper *pw, size_t idx, int *errorcode = nullptr) noexcept; static void destroy(device_wrapper *) noexcept; }; class gpu_interface { -public: + public: gpu_interface() = default; virtual ~gpu_interface() = default; [[nodiscard]] static gpu_interface *create(platform_wrapper *pw, device_wrapper *dw) noexcept; + [[nodiscard]] static gpu_interface *create( + platform_wrapper *pw, device_wrapper *dw, + std::pair &err) noexcept; static void destroy(gpu_interface *) noexcept; virtual const char *api_v() const noexcept = 0; @@ -82,9 +85,9 @@ class gpu_interface { virtual bool ok_v() const noexcept = 0; virtual std::string error_detail_v() const noexcept = 0; - virtual void - set_colorset_v(size_t color_num, - const std::array &color_ptrs) noexcept = 0; + virtual void set_colorset_v( + size_t color_num, + const std::array &color_ptrs) noexcept = 0; virtual void set_task_v(size_t task_num, const std::array *data) noexcept = 0; @@ -104,6 +107,6 @@ class gpu_interface { virtual size_t local_work_group_size_v() const noexcept = 0; }; -} // namespace gpu_wrapper +} // namespace gpu_wrapper -#endif // SLOPECRAFT_UTILITIES_GPUWRAPPER_GPUINTERFACE_H \ No newline at end of file +#endif // SLOPECRAFT_UTILITIES_GPUWRAPPER_GPUINTERFACE_H \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/GPU_interface.cpp b/utilities/GPUWrapper/OpenCL/GPU_interface.cpp index 7775e25a..2178d281 100644 --- a/utilities/GPUWrapper/OpenCL/GPU_interface.cpp +++ b/utilities/GPUWrapper/OpenCL/GPU_interface.cpp @@ -49,7 +49,6 @@ void ::gpu_wrapper::platform_wrapper::destroy(platform_wrapper *pw) noexcept { } ocl_warpper::ocl_device::ocl_device(cl::Device __dev) : device(__dev) { - this->name = __dev.getInfo(&this->err); } @@ -72,10 +71,11 @@ ::gpu_wrapper::device_wrapper * ::gpu_wrapper::device_wrapper::create( void ::gpu_wrapper::device_wrapper::destroy(device_wrapper *dw) noexcept { delete static_cast<::ocl_warpper::ocl_device *>(dw); } - -gpu_wrapper::gpu_interface * -gpu_wrapper::gpu_interface::create(gpu_wrapper::platform_wrapper *pw, - gpu_wrapper::device_wrapper *dw) noexcept { +gpu_wrapper::gpu_interface *gpu_wrapper::gpu_interface::create( + gpu_wrapper::platform_wrapper *pw, gpu_wrapper::device_wrapper *dw, + std::pair &err) noexcept { + err.first = 0; + err.second.clear(); ocl_warpper::ocl_platform *plat = static_cast(pw); ocl_warpper::ocl_device *dev = static_cast(dw); @@ -84,6 +84,8 @@ gpu_wrapper::gpu_interface::create(gpu_wrapper::platform_wrapper *pw, new ocl_warpper::ocl_resource(plat->platform, dev->device); if (!ret->ok()) { + err.first = ret->error_code(); + err.second = ret->error_detail(); delete ret; return nullptr; } @@ -91,8 +93,14 @@ gpu_wrapper::gpu_interface::create(gpu_wrapper::platform_wrapper *pw, return static_cast<::gpu_wrapper::gpu_interface *>(ret); } -void ::gpu_wrapper::gpu_interface::destroy(gpu_interface *gi) noexcept { +gpu_wrapper::gpu_interface *gpu_wrapper::gpu_interface::create( + gpu_wrapper::platform_wrapper *pw, + gpu_wrapper::device_wrapper *dw) noexcept { + std::pair temp; + return create(pw, dw, temp); +} +void ::gpu_wrapper::gpu_interface::destroy(gpu_interface *gi) noexcept { delete static_cast(gi); return; } diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 0cb4f268..3e371377 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -130,8 +130,8 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { std::string source_code{(const char *)ColorManip_cl_rc, ColorManip_cl_rc_length}; source_code.push_back('\0'); - this->program = - cl::Program{this->context, {this->device}, source_code, &this->error}; + this->program = cl::Program{ + this->context, std::vector{source_code}, &this->error}; #endif if (!this->ok()) { From cff35ed01401eabd66d01bf504fb5e204dfa31b3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 20:21:54 +0800 Subject: [PATCH 0232/1123] see clinfo in linux-build --- .github/workflows/build-dev.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index efebd660..57652950 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -64,7 +64,7 @@ jobs: strategy: matrix: build_type: [Debug, Release] - gpu_api: [OpenCL] + gpu_api: [None, OpenCL] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -93,7 +93,11 @@ jobs: # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL sdk if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers + run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + + - name: See clinfo + if: matrix.gpu_api == 'OpenCL' + run: clinfo - name: Install xz (Release as tar.xz) run: sudo apt install xz-utils From 33f104e8ed67362ba520a1d408cfb29279b314d6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 20:39:35 +0800 Subject: [PATCH 0233/1123] report if no opencl platforms --- utilities/ColorManip/tests/test_algo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/utilities/ColorManip/tests/test_algo.cpp b/utilities/ColorManip/tests/test_algo.cpp index 3ac1a0ab..96afdad5 100644 --- a/utilities/ColorManip/tests/test_algo.cpp +++ b/utilities/ColorManip/tests/test_algo.cpp @@ -146,6 +146,12 @@ int run_task(task_t &task) noexcept { eig_colorset = map_colorset.transpose(); } + + if (gpu_wrapper::platform_num() <= 0) { + cout << "No avaliable opencl platforms." << endl; + return 0; + } + auto plat = gpu_wrapper::platform_wrapper::create(task.platidx); auto dev = gpu_wrapper::device_wrapper::create(plat, task.devidx); From 4de7824a0dfd453c370f14062b62414e40890a97 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 20:40:41 +0800 Subject: [PATCH 0234/1123] run ctest only for None gpu --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 57652950..853208d3 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -139,7 +139,7 @@ jobs: if-no-files-found: error - name: Run CTest - if: matrix.build_type == 'Release' + if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') run: | cd ./build ctest -j20 --output-on-failure --stop-on-failure From a982dd3e9c4007419d2bc8715dcdca6c1a897407 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 21:07:26 +0800 Subject: [PATCH 0235/1123] try to install deb generated by linux-build --- .github/workflows/build-dev.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 853208d3..add7d8c2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -144,6 +144,29 @@ jobs: cd ./build ctest -j20 --output-on-failure --stop-on-failure + linux-test-deb: + runs-on: ubunut-latest + needs: linux-build + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None, OpenCL] + steps: + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + + - name: Download deb + uses: actions/download-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + + - name: ls + run: ls . + + - name: Try installing deb + run: sudo dpkg -i ./*.deb + + windows-build: runs-on: windows-latest strategy: From f9d90e0f7cc75718f5d57251140aafcd9cb478cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 19 Apr 2023 21:32:44 +0800 Subject: [PATCH 0236/1123] comment linux-test-deb --- .github/workflows/build-dev.yml | 47 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index add7d8c2..99dde311 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -143,29 +143,30 @@ jobs: run: | cd ./build ctest -j20 --output-on-failure --stop-on-failure - - linux-test-deb: - runs-on: ubunut-latest - needs: linux-build - strategy: - matrix: - build_type: [Debug, Release] - gpu_api: [None, OpenCL] - steps: - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - - name: Download deb - uses: actions/download-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - - - name: ls - run: ls . - - - name: Try installing deb - run: sudo dpkg -i ./*.deb - + - name: Test deb pack + run: sudo dpkg -i ./pack/*.deb + + # linux-test-deb: + # runs-on: ubunut-latest + # needs: linux-build + # strategy: + # matrix: + # build_type: [Debug, Release] + # gpu_api: [None, OpenCL] + # steps: + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Download deb + # uses: actions/download-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + # + # - name: ls + # run: ls . + # + # - name: Try installing deb + # run: sudo dpkg -i ./*.deb windows-build: runs-on: windows-latest From 6ab689428ce9a33639e908bcb646f7f095014b0f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 19 Apr 2023 23:19:20 +0800 Subject: [PATCH 0237/1123] fix deb packaging --- cpack/deb.cmake | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/cpack/deb.cmake b/cpack/deb.cmake index dfde5333..f745966a 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -1,5 +1,5 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "SlopeCraft group") -set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE x86_64) +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE amd64) set(SlopeCraft_debian_opencl_deps) @@ -9,21 +9,32 @@ if(${SlopeCraft_GPU_API} STREQUAL "OpenCL") ) endif() -set(CPACK_DEBIAN_PACKAGE_DEPENDS - libzip4 - libpng16-16 - libqt6core6 - libqt6gui6 - libqt6widgets6 - libqt6network6 - libopengl0 - libqt6opengl6 - libqt6openglwidgets6 - libqt6dbus6 - libglx0 - qt6-qpa-plugins +set(depend_list + "libzip4" + "libpng16-16" + "libqt6core6(>=6.2.4)" + "libqt6gui6(>=6.2.4)" + "libqt6widgets6(>=6.2.4)" + "libqt6network6(>=6.2.4)" + "libopengl0" + "libqt6opengl6(>=6.2.4)" + "libqt6openglwidgets6(>=6.2.4)" + "libqt6dbus6(>=6.2.4)" + "libglx0" + "qt6-qpa-plugins(>=6.2.4)" ${SlopeCraft_debian_opencl_deps} ) +unset(CPACK_DEBIAN_PACKAGE_DEPENDS) +foreach(depend ${depend_list}) + if(NOT DEFINED CPACK_DEBIAN_PACKAGE_DEPENDS) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${depend}") + else() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},${depend}") + endif() +endforeach(depend ${depend_list}) + +message(STATUS "CPACK_DEBIAN_PACKAGE_DEPENDS = ${CPACK_DEBIAN_PACKAGE_DEPENDS}") + set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Get your Minecraft pixel painting in multiple kinds of forms") \ No newline at end of file From cb34422f947d571085dcbc48e20cfa70585377fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 21 Apr 2023 12:24:11 +0800 Subject: [PATCH 0238/1123] add show-config to vccl --- cpack/make-packs.cmake | 3 +-- utilities/CMakeLists.txt | 21 ++++++++++++++++----- utilities/SC_version_buildtime.h.in | 11 ++++++++--- vccl/vccl.cpp | 20 +++++++++++++++++--- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 9d109fd0..db699340 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -11,8 +11,7 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) endif() -set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-${SlopeCraft_GPU_API}) - +# set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-${SlopeCraft_GPU_API}) if(${WIN32}) configure_file(${CMAKE_SOURCE_DIR}/cpack/pack_deployed_files.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 9837d208..f280dba9 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -1,10 +1,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -configure_file(SC_version_buildtime.h.in - SC_version_buildtime.h) - -include(install.cmake) - add_subdirectory(MCDataVersion) add_subdirectory(GPUWrapper) add_subdirectory(ColorManip) @@ -19,5 +14,21 @@ add_subdirectory(MapImageCvter) add_subdirectory(VersionDialog) add_subdirectory(VCLConfigLoader) +function(SC_process_boolean value_name) + if(${${value_name}}) + set(${value_name} "true" PARENT_SCOPE) + else() + set(${value_name} "false" PARENT_SCOPE) + endif() +endfunction(SC_process_boolean value_name) + +SC_process_boolean(SlopeCraft_vectorize) +SC_process_boolean(SlopeCraft_gprof) + +configure_file(SC_version_buildtime.h.in + SC_version_buildtime.h) + +include(install.cmake) + # add_subdirectory(libAbstractGUI) # add_subdirectory(libSCGUI) \ No newline at end of file diff --git a/utilities/SC_version_buildtime.h.in b/utilities/SC_version_buildtime.h.in index 92c541b2..5e3a5ce0 100644 --- a/utilities/SC_version_buildtime.h.in +++ b/utilities/SC_version_buildtime.h.in @@ -30,8 +30,8 @@ This file is part of SlopeCraft. #define SC_VERSION_PATCH_U16 @PROJECT_VERSION_PATCH@ #define SC_VERSION_TWEAK_U16 0 -#define SC_MAKE_VERSION_U64(major, minor, patch, tweak) \ - ((uint64_t(major) << 48) | (uint64_t(minor) << 32) | \ +#define SC_MAKE_VERSION_U64(major, minor, patch, tweak) \ + ((uint64_t(major) << 48) | (uint64_t(minor) << 32) | \ (uint64_t(patch) << 16) | (uint64_t(tweak))) #define SC_VERSION_STR "@PROJECT_VERSION@" @@ -40,4 +40,9 @@ inline constexpr uint64_t SC_VERSION_U64 = SC_MAKE_VERSION_U64(SC_VERSION_MAJOR_U16, SC_VERSION_MINOR_U16, SC_VERSION_PATCH_U16, SC_VERSION_TWEAK_U16); -#endif // SLOPECRAFT_SC_VERSON_BUILTTIME_H \ No newline at end of file +#define CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@" +#define SC_GPU_API "@SlopeCraft_GPU_API@" +#define SC_VECTORIZE @SlopeCraft_vectorize@ +#define SC_GPROF @SlopeCraft_gprof@ + +#endif // SLOPECRAFT_SC_VERSON_BUILTTIME_H \ No newline at end of file diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 3723f564..b3eff688 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -28,6 +28,9 @@ This file is part of SlopeCraft. #include #include +#include +#include + using std::cout, std::endl; bool validate_input(const inputs &input) noexcept; @@ -42,9 +45,11 @@ int main(int argc, char **argv) { input.prefer_gpu = true; } - app.set_version_flag("--version,-v", - std::string("vccl version : ") + SC_VERSION_STR + - ", VisualCraftL version : " + VCL_version_string()); + app.set_version_flag("--version,-v", SC_VERSION_STR); + bool show_config{false}; + app.add_flag("--show-config,--sc", show_config, + "Show buildtime configuration and exit.") + ->default_val(false); // resource app.add_option("--resource-pack,--rp", input.zips, "Resource packs") @@ -175,6 +180,15 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); + if (show_config) { + cout << fmt::format("Version : {}\n", SC_VERSION_STR); + cout << fmt::format("Build type : {}\n", CMAKE_BUILD_TYPE); + cout << fmt::format("GPU API : {}\n", SC_GPU_API); + cout << fmt::format("Vectorize : {}\n", SC_VECTORIZE); + cout << fmt::format("Gprof : {}\n", SC_GPROF); + return 0; + } + if (input.list_gpu) { return list_gpu(); } From 4e1b53f9e8eab1e78cfa45252c55372486f1f900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 21 Apr 2023 13:48:03 +0800 Subject: [PATCH 0239/1123] update translation --- SlopeCraftMain/mainwindow.ui | 8096 +++++++++++++++++----------------- 1 file changed, 4107 insertions(+), 3989 deletions(-) diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index 2274c618..433ae3b7 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -1,4062 +1,4180 @@ - TokiNoBug - MainWindow - - - - 0 - 0 - 960 - 540 - - - - - 0 - 0 - - - - - 960 - 540 - - - - - 16777215 - 16777215 - - - - - - - SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug - - - - others/SlopeCraftIconNew.icoothers/SlopeCraftIconNew.ico - - - - - - - 128 - 128 - - - - true - - - QTabWidget::Rounded - - - true - - - - - 0 - 0 - - - - QWidget#centralwidget{border-image: url(":/new/Pic/BG4.png");} - - - - QLayout::SetNoConstraint + TokiNoBug + MainWindow + + + + 0 + 0 + 960 + 540 + - - 4 + + + 0 + 0 + + + + + 960 + 540 + + + + + 16777215 + 16777215 + + + + + + + SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug + + + + others/SlopeCraftIconNew.icoothers/SlopeCraftIconNew.ico + + + - - 4 + + + 128 + 128 + - - 4 + + true - - 4 + + QTabWidget::Rounded - - + + true + + - - 0 - 0 - - - - - 0 - 0 - + + 0 + 0 + - #LeftScroll ,#LeftScrollArea{ - background-color: rgba(255, 255, 255, 0); -} - -QPushButton:enabled{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(255, 255, 255,128); - color: rgb(0, 0, 0); - font: 9pt "微软雅黑"; -} - -QPushButton:!enabled{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(191, 191,191,128); -color: rgb(64, 64, 64); -font: 9pt "微软雅黑"; -} - -QPushButton:hover{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(255, 255, 255,191); -color: rgb(0, 0, 0); -font: 9pt "微软雅黑"; -} - -QPushButton:pressed{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(255, 255, 255,223); -border-style: inset; -border-color: rgb(235, 235, 235); -color: rgb(0, 0, 0); -font: 9pt "微软雅黑"; -} - -/**/ - - - QFrame::NoFrame + QWidget#centralwidget{border-image: url(":/new/Pic/BG4.png");} - - Qt::ScrollBarAlwaysOff - - - true - - - Qt::AlignCenter - - - - - 0 - 0 - 152 - 757 - - - - - 0 - 0 - - - - - 0 - 0 - - - - false - - - - - + + + QLayout::SetNoConstraint + - 9 + 4 - 5 + 4 - 5 + 4 - 9 + 4 - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">地图画</span></p></body></html> - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - 开始 - - - - :/new/Textures/Slope/block/grass_block.png:/new/Textures/Slope/block/grass_block.png - - - - - - - - 100 - 30 - - - - 导入图片 - - - - :/new/Textures/Slope/items/book.png:/new/Textures/Slope/items/book.png - - - - - - - true - - - - 100 - 30 - - - - - - - 地图画类型 - - - - :/new/Textures/Slope/items/map.png:/new/Textures/Slope/items/map.png - - - - - - - - 100 - 30 - - - - 方块列表 - - - - :/new/Textures/Slope/block/waxed_cut_copper.png:/new/Textures/Slope/block/waxed_cut_copper.png - - - - - - - - 100 - 30 - - - - 调整颜色 - - - - :/new/Textures/Slope/items/amethyst_shard.png:/new/Textures/Slope/items/amethyst_shard.png - - - - - - - - 100 - 30 - - - - 导出为 - - - - :/new/Textures/Slope/items/iron_pickaxe.png:/new/Textures/Slope/items/iron_pickaxe.png - - - - - - - 0 - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 平面示意图 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 地图文件 - - - - - + - - 0 - 0 - + + 0 + 0 + - - 90 - 25 - - - - 投影文件 - - - - - - - - 0 - 0 - + + 0 + 0 + - - - 90 - 25 - + + #LeftScroll ,#LeftScrollArea{ + background-color: rgba(255, 255, 255, 0); + } + + QPushButton:enabled{ + border:2px; + border-radius:10px; + padding:2px 4px; + background-color: rgba(255, 255, 255,128); + color: rgb(0, 0, 0); + font: 9pt "微软雅黑"; + } + + QPushButton:!enabled{ + border:2px; + border-radius:10px; + padding:2px 4px; + background-color: rgba(191, 191,191,128); + color: rgb(64, 64, 64); + font: 9pt "微软雅黑"; + } + + QPushButton:hover{ + border:2px; + border-radius:10px; + padding:2px 4px; + background-color: rgba(255, 255, 255,191); + color: rgb(0, 0, 0); + font: 9pt "微软雅黑"; + } + + QPushButton:pressed{ + border:2px; + border-radius:10px; + padding:2px 4px; + background-color: rgba(255, 255, 255,223); + border-style: inset; + border-color: rgb(235, 235, 235); + color: rgb(0, 0, 0); + font: 9pt "微软雅黑"; + } + + /**/ - - 结构文件 + + QFrame::NoFrame - - - - - - Qt::Horizontal + + Qt::ScrollBarAlwaysOff - - - 40 - 20 - + + true - - - - + + Qt::AlignCenter + + + + + 0 + 0 + 152 + 757 + + + + + 0 + 0 + + + + + 0 + 0 + + + + false + + + + + + + 9 + + + 5 + + + 5 + + + 9 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" + "http://www.w3.org/TR/REC-html40/strict.dtd"> + <html><head><meta name="qrichtext" + content="1" /><meta charset="utf-8" /><style + type="text/css"> + p, li { white-space: pre-wrap; } + </style></head><body style=" font-family:'Microsoft + YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> + <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; + margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span + style=" font-weight:700; + color:#ffffff;">地图画</span></p></body></html> + + + + + + + + 0 + 0 + + + + + 100 + 30 + + + + 开始 + + + + :/new/Textures/Slope/block/grass_block.png + :/new/Textures/Slope/block/grass_block.png + + + + + + + + 100 + 30 + + + + 导入图片 + + + + :/new/Textures/Slope/items/book.png + :/new/Textures/Slope/items/book.png + + + + + + + true + + + + 100 + 30 + + + + + + + 地图画类型 + + + + :/new/Textures/Slope/items/map.png + :/new/Textures/Slope/items/map.png + + + + + + + + 100 + 30 + + + + 方块列表 + + + + :/new/Textures/Slope/block/waxed_cut_copper.png + :/new/Textures/Slope/block/waxed_cut_copper.png + + + + + + + + 100 + 30 + + + + 调整颜色 + + + + :/new/Textures/Slope/items/amethyst_shard.png + :/new/Textures/Slope/items/amethyst_shard.png + + + + + + + + 100 + 30 + + + + 导出为 + + + + :/new/Textures/Slope/items/iron_pickaxe.png + :/new/Textures/Slope/items/iron_pickaxe.png + + + + + + + 0 + + + + + + 0 + 0 + + + + + 90 + 25 + + + + 平面示意图 + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + 地图文件 + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + 投影文件 + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + 结构文件 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + WE原理图 + + + + + + + + + + 100 + 30 + + + + 完成 + + + + :/new/Textures/Slope/items/diamond.png + :/new/Textures/Slope/items/diamond.png + + + + + + + + <html><head/><body><p><br/><span + style=" font-weight:700; + color:#ffffff;">语言/Languages</span></p></body></html> + + + + + + + + 0 + 30 + + + + 简体中文 + + + + + + + + 0 + 30 + + + + English + + + + + + + + <html><head/><body><p><br/><span + style=" font-weight:700; + color:#ffffff;">联系作者</span></p></body></html> + + + + + + + + 0 + 30 + + + + GitHub + + + + + + + + 0 + 30 + + + + BiliBili + + + + + + + + 0 + 30 + + + + 检查更新 + + + + + + + + 0 + 30 + + + + 反馈Bug + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + - - 0 - 0 - + + 0 + 0 + - - 90 - 25 - + + 30 + 0 + - - WE原理图 + + - - - - - - - - - 100 - 30 - - - - 完成 - - - - :/new/Textures/Slope/items/diamond.png:/new/Textures/Slope/items/diamond.png - - - - - - - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">语言/Languages</span></p></body></html> - - - - - - - - 0 - 30 - - - - 简体中文 - - - - - - - - 0 - 30 - - - - English - - - - - - - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">联系作者</span></p></body></html> - - - - - - - - 0 - 30 - - - - GitHub - - - - - - - - 0 - 30 - - - - BiliBili - - - - - - - - 0 - 30 - - - - 检查更新 - - - - - - - - 0 - 30 - - - - 反馈Bug - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - - - - - 30 - 0 - - - - - - - /*QWidget#PageEnd{border-image: url(:/new/Pic/BG4.png);}*/ + + /*QWidget#PageEnd{border-image: url(:/new/Pic/BG4.png);}*/ + QWidget#PageStart,#PageEnd{ + background-color: rgba(255, 255, 255, 0); + } -QWidget#PageStart,#PageEnd{ - background-color: rgba(255, 255, 255, 0); -} + QWidget#PageImPic,#PageType,#PageBL,#PageAdjPic,#PageExLite,#PageExMcF,#PageExDat{ + background-color:#f0f0f0; + border:2px solid gray + } -QWidget#PageImPic,#PageType,#PageBL,#PageAdjPic,#PageExLite,#PageExMcF,#PageExDat{ -background-color:#f0f0f0; -border:2px solid gray -} + QPushButton:enabled{ + border:2px; + border-radius:10px; + border-style:groove; + border-color: rgb(136, 136, 136); + color: rgb(0, 0, 0); + padding:2px 4px; + background-color: rgb(225, 225, 225); + } -QPushButton:enabled{ -border:2px; -border-radius:10px; -border-style:groove; -border-color: rgb(136, 136, 136); -color: rgb(0, 0, 0); -padding:2px 4px; -background-color: rgb(225, 225, 225); -} + QPushButton:hover{ + border:2px; + border-radius:10px; + border-style:solid; + border-color: rgb(136, 136, 136); + color: rgb(0, 0, 0); + padding:2px 4px; + background-color: rgb(241, 241, 241); + } -QPushButton:hover{ -border:2px; -border-radius:10px; -border-style:solid; -border-color: rgb(136, 136, 136); -color: rgb(0, 0, 0); -padding:2px 4px; -background-color: rgb(241, 241, 241); -} + QPushButton:!enabled{ + border:2px; + border-radius:10px; + border-style:groove; + border-color: rgb(136, 136, 136); + color: rgb(80, 80, 80); + padding:2px 4px; + background-color: rgb(193, 193, 193); + } -QPushButton:!enabled{ -border:2px; -border-radius:10px; -border-style:groove; -border-color: rgb(136, 136, 136); -color: rgb(80, 80, 80); -padding:2px 4px; -background-color: rgb(193, 193, 193); -} + QCommandLinkButton:enabled{ + color: rgb(0, 0, 0); + border:0px; + background-color: rgba(255, 255, 255,128); + font: 11pt "微软雅黑"; + } -QCommandLinkButton:enabled{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,128); -font: 11pt "微软雅黑"; -} - -QCommandLinkButton:hover{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,191); -font: 11pt "微软雅黑"; -} -QCommandLinkButton:pressed{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,223); -font: 11pt "微软雅黑"; -} - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - - - - - - - - 30 - - - - - - 0 - 0 - - - - - 20 - false - - - - <html><head/><body><p><span style=" font-size:16pt; font-weight:700; color:#ffff7f;">Copyright © 2021-2023 TokiNoBug</span></p></body></html> - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - - - 0 - 0 - + QCommandLinkButton:hover{ + color: rgb(0, 0, 0); + border:0px; + background-color: rgba(255, 255, 255,191); + font: 11pt "微软雅黑"; + } + QCommandLinkButton:pressed{ + color: rgb(0, 0, 0); + border:0px; + background-color: rgba(255, 255, 255,223); + font: 11pt "微软雅黑"; + } - - - MV Boli - 26 - false - - - - <html><head/><body><p><span style=" font-size:40pt; color:#ffffff;">SlopeCraft</span><span style=" color:#ffffff;"> %1</span></p></body></html> - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - - - 0 - - - 0 - - - - - QLayout::SetDefaultConstraint + + QFrame::NoFrame - - 0 + + QFrame::Plain - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Flat.png - - - true - - - - - - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建平板地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">传统的地图画样式</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 + + 0 - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - - 260 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_3D.png - - - true - - - - - - - - 微软雅黑 - 11 - false - false - - - - - - - - - - - - - 创建立体地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">原版生存的最高画质</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + - - - - - - - - 0 - - - + + + + + 30 + + + + + + 0 + 0 + + + + + 20 + false + + + + <html><head/><body><p><span + style=" font-size:16pt; font-weight:700; + color:#ffff7f;">Copyright © 2021-2023 + TokiNoBug</span></p></body></html> + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + + 0 + 0 + + + + + MV Boli + 26 + false + + + + <html><head/><body><p><span + style=" font-size:40pt; + color:#ffffff;">SlopeCraft</span><span style=" + color:#ffffff;"> + %1</span></p></body></html> + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + + + 0 + + + 0 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 195 + + + + QFrame::StyledPanel + + + 2 + + + + + + :/new/Pic/cover_Flat.png + + + true + + + + + + + + 0 + 40 + + + + + 微软雅黑 + 11 + false + false + + + + 创建平板地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + <html><head/><body><p + align="center"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">传统的地图画样式</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 195 + + + + + 260 + 195 + + + + QFrame::StyledPanel + + + 2 + + + + + + :/new/Pic/cover_3D.png + + + true + + + + + + + + 微软雅黑 + 11 + false + false + + + + + + + + + + + + + 创建立体地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + <html><head/><body><p + align="center"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">原版生存的最高画质</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 195 + + + + false + + + QFrame::StyledPanel + + + 2 + + + + + + :/new/Pic/cover_Data.png + + + true + + + + + + + true + + + + 0 + 40 + + + + + 微软雅黑 + 11 + false + false + + + + 创建纯文件地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p + align="center"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + - - 0 - 0 - + + 0 + 0 + - - 16777215 - 195 - + + 65536 + 65536 + - false - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Data.png - - - true + false - - - - - - true + + - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建纯文件地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - - - - - - - 0 - 0 - - - - - 65536 - 65536 - - - - false - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - #ShowRawPic{background-image: url(:/new/Pic/Transparent.png);} - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 9 - - - - Qt::LeftToRight - - - false - - - 导入图片 - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - - - Qt::AutoText - - - true - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - - - 透明度相关设置 - - - 设置 - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 10 - - - - 下一步 - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - - - backgroundcolor: rgb(255, 255, 255); - - - <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> - - - true - - - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 10 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - 0 - - - - - 9 - - - - 游戏版本 - - - - - - - 9 - - - - 1.15 - - - false - + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + #ShowRawPic{background-image: + url(:/new/Pic/Transparent.png);} + + + QFrame::StyledPanel + + + + + + :/new/Pic/BG2.png + + + false + + + Qt::AlignCenter + + + + + + + 0 + + + + + + 0 + 0 + + + + + 100 + 30 + + + + + 5 + 2 + + + + + 9 + + + + Qt::LeftToRight + + + false + + + 导入图片 + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> + + + Qt::AutoText + + + true + + + + + + + + 0 + 0 + + + + + + + + + + true + + + + + + + + 0 + 0 + + + + + 100 + 30 + + + + + + + 透明度相关设置 + + + 设置 + + + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 5 + 2 + + + + + 10 + + + + 下一步 + + + + + + - - - - - - 9 - - - - 1.16 - - - false - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + + + backgroundcolor: rgb(255, 255, 255); + + + + <html><head/><body><p + align="justify">第二步,选择好你要什么样的地图画。</p><p + align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p + align="justify">立体地图画如右图,是我们的核心功能;</p><p + align="justify">平板地图画颜色相对少,但更容易建造;</p><p + align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> + + + true + + + + + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 10 + + + + 下一步 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + + 9 + + + + 游戏版本 + + + + + + + 9 + + + + 1.15 + + + false + + + + + + + + 9 + + + + 1.16 + + + false + + + + + + + true + + + + + + 1.17 + + + true + + + + + + + + + + 1.13 + + + + + + + + + + 1.12 + + + + + + + + + + 1.14 + + + + + + + 1.18 + + + + + + + 1.19 + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + + + + true + + + + + + + + 0 + 0 + + + + + + + :/new/Pic/BG3.png + + + true + + + + + + + + 0 + 0 + + + + + 10 + + + + 地图画类型 + + + + + + + 9 + + + + 立体地图画 + + + true + + + + + + + + 9 + + + + 平板地图画 + + + + + + + + 9 + + + + 纯文件地图画 + + + + + + + - - - - - true - - - - - - 1.17 - - - true - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 0 + + + + + + 10 + + + + 预设方块列表 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 9 + + + + 适合创造 + + + Vanilla + + + + + + + + 9 + + + + 适合生存早期 + + + Cheap + + + + + + + + 9 + + + + 适合生存后期 + + + Elegant + + + true + + + + + + + + 9 + + + + 适合光影 + + + Shiny + + + + + + + + 9 + + + + 自定义 + + + Custom + + + + + + + + + + + 0 + 0 + + + + + + + + + + true + + + + + + + 6 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 9 + + + + 下一步 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + + 120 + 0 + + + + + + + + <html><head/><body><p + align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p + align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> + + + true + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先混凝土 + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先羊毛 + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先染色玻璃 + + + + + + + + + true + + + QFrame::Box + + + 2 + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 551 + 378 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 1 + + + + + + + + - - - - - - - - 1.13 - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 0 + 15 + + + + Qt::DefaultContextMenu + + + + + + + + + false + + + + + + 1 + + + 0 + + + Qt::AlignCenter + + + %p% + + + + + + + 0 + + + + + + 0 + 0 + + + + + 100 + 40 + + + + + 32767 + 16777215 + + + + + 9 + + + + 转换为地图画 + + + false + + + + + + + + 0 + 0 + + + + + 80 + 40 + + + + + 150 + 1000 + + + + + + + 保存当前图片 + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 150 + 16777215 + + + + + 9 + + + + 显示地图画 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 16777215 + 16777215 + + + + 导出为 + 原版结构文件 + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 150 + 16777215 + + + + + 9 + + + + 显示原图 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 32767 + + + + + + + 导出为 + 地图文件 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 16777215 + + + + 导出为 + WorldEdit原理图 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 16777215 + + + + + 9 + + + + + + + 导出为 + Litematica投影 + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 + 六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 + 调整颜色可能会比较慢,下面的进度条指示了进度。 + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 150 + 300 + + + + + 9 + + + + 算法 + + + + 2 + + + 4 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 9 + + + + RGB欧式距离 + + + RGB + + + + + + + + 0 + 0 + + + + + + + 更好的RGB色差公式 + + + RGB+ + + + true + + + + + + + + 0 + 0 + + + + + 9 + + + + 不是简单的欧式距离 + + + HSV + + + + + + + + 0 + 0 + + + + + 9 + + + + Lab1994公式 + + + Lab94 + + + false + + + + + + + + 0 + 0 + + + + + + + Lab2000公式 + + + Lab00 + + + + + + + + 0 + 0 + + + + + 9 + + + + XYZ欧式距离 + + + XYZ + + + + + + + + 0 + 0 + + + + 遗传算法 + + + GACvter + + + + + + + + 0 + 0 + + + + + + + 用分辨率换颜色 + + + 抖动仿色 + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 440 + 440 + + + + true + + + QFrame::StyledPanel + + + + + + :/new/Pic/BG2.png + + + false + + + Qt::AlignCenter + + + + - - - - - - - - 1.12 - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 0 + + + 12 + + + + + QFrame::NoFrame + + + 其他选项 + + + + + + + 搭桥 + + + + + + + 方便建造,耗费玻璃 + + + 允许搭桥 + + + + + + + + + + 降低总高度,破坏连续性 + + + + + + + + + 无损压缩 + + + true + + + + + + + Qt::Horizontal + + + + + + + 用玻璃包围防火方块 + + + 防火 + + + + + + + + + + QFrame::NoFrame + + + 压缩高度 + + + + + + + true + + + 用玻璃包围可偷方块 + + + 防末影人 + + + false + + + + + + + true + + + + + + 降低总高度,微调颜色 + + + 智能有损压缩 + + + true + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p + align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p + align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p + align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p + align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p + align="justify">这个过程可能会很慢,请关注进度条</p></body></html> + + + true + + + + + + + + 0 + 30 + + + + + + + QFrame::StyledPanel + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 投影尺寸 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + + + QFrame::StyledPanel + + + + + + + + + + true + + + + + + QAbstractSpinBox::UpDownArrows + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 最大允许高度: + + + 14 + + + 32767 + + + 255 + + + + + + + false + + + + + + 搭桥间隔: + + + 4 + + + + + + + + + + 总方块数 + + + + + + + + + + + + + 0 + + + + Litematica + + + + + + + 9 + + + + 投影名称 + + + + + + + Pixel Paint by SlopeCraft + + + + + + + + 9 + + + + 投影区域名称 + + + + + + + Pixel Paint by SlopeCraft + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Structure + + + + + + 节省大量存储空间 + + + + + + + + + 用结构空位代替 + + + true + + + + + + + 空气处理方式 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + WorldEdit + + + + + + 0 + + + + + + + WEOffset(X,Y,Z) + + + + + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + offset(X,Y,Z) + + + + + + + 0 + + + + + + + 原理图名称 + + + + + + + 0 + + + + + + + 依赖mod名称 + + + + + + + + + + Pixel Paint by SlopeCraft + + + + + + + + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 20 + + + + + 10 + + + + 结束 + + + + + + + + + + 0 + 0 + + + + 1 + + + 0 + + + Qt::AlignCenter + + + false + + + Qt::Vertical + + + false + + + %p% + + + + + + + 0 + + + Qt::Vertical + + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 30 + + + + 导出平面示意图 + + + + + + + false + + + + 100 + 30 + + + + + + + 导出三维结构 + + + + + + + false + + + + 0 + 30 + + + + 预览 + + + + + + + false + + + + 0 + 30 + + + + + + + 构建三维结构 + + + + + + - - - - - - - - 1.14 - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 0 + + + 12 + + + + + 地图画起点坐标 + + + + + + + 地图画尺寸 + + + + + + + Y + + + + + + + X + + + + + + + 总命令数 + + + + + + + Z + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + + + + + + + + + 200 + 30 + + + + QFrame::StyledPanel + + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + 1 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + -64 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + -64 + + + + + + + + + 0 + + + + + + 100 + 20 + + + + + 10 + + + + 完成 + + + + + + + 0 + + + + + 0 + + + -1 + + + Qt::Vertical + + + + + + + + + + 100 + 30 + + + + + 0 + 0 + + + + + 10 + + + + 导出 + + + + + + + + 0 + 30 + + + + + + + 构建三维结构 + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p + align="justify">最后一步,导出为mcfunction!</p><p + align="justify">如果你不想导出为投影文件,也可以使用mc自带的数据包。</p><p + align="justify">导出的文件是一个mc中的“函数”,是数据包的一部分。</p><p + align="justify">你可以在单机存档中使用/reload命令来加载它,用/function命令调用它。</p><p + align="justify">如果地图画很大,超过了一个mcfunction的命令数,那么会将全部的命令分散在多个mcfuntion中。</p><p + align="justify">在导出前,你需要指定地图画的起点坐标,它是xyz负方向的方块的坐标。</p><p + align="justify">(如果不知道要放在哪里,请使用默认值-64,1,-64)</p></body></html> + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - - 1.18 - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 16777215 + 60 + + + + + + + + + + + + + 0 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML + 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <html><head><meta name="qrichtext" + content="1" /><meta charset="utf-8" /><style + type="text/css"> + p, li { white-space: pre-wrap; } + hr { height: 1px; border-width: 0; } + li.unchecked::marker { content: "\2610"; } + li.checked::marker { content: "\2612"; } + </style></head><body style=" font-family:'Microsoft + YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> + <p style=" margin-top:6px; margin-bottom:6px; margin-left:0px; + margin-right:0px; -qt-block-indent:0; + text-indent:0px;">0</p></body></html> + + + + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + map_0.dat + + + Qt::AlignCenter + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + <html><head/><body><p + align="justify">最后一步,导出为地图文件。</p><p + align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p + align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p + align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p + align="justify">例如,你可以使用/give @s + filled_map{map:3}来获得map_3.dat的地图。</p><p + align="justify">1.12版请使用/give @p filled_map 1 3</p><p + align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> + + + true + + + + + + + 0 + + + + + false + + + + 100 + 20 + + + + + 10 + + + + 完成 + + + + + + + 0 + + + + + 1 + + + 0 + + + Qt::Vertical + + + %p% + + + + + + + + + false + + + + 100 + 30 + + + + + 0 + 0 + + + + + 10 + + + + 导出 + + + + + + + + + 导出的文件名 + + + + + + + + 0 + 0 + + + + 地图文件起始序号 + + + + + + + 地图画行数 + + + + + + + 地图画列数 + + + + + + + 地图文件数量 + + + + - - - - - 1.19 - + + + + + + + 0 + 30 + + + + + + + 查看导出的文件 + + + + + + + true + + + + 0 + 30 + + + + + + + 联系作者 + + + + + + + + 0 + 30 + + + + + + + 退出 + + + + + + + + + + background-color: rgba(0, 0, 0, 48); + + + <html><head/><body><p + align="center"><span style=" font-size:16pt; + font-weight:700; + color:#ffffff;">地图画生成完毕!</span><br/></p><p + align="center"><span style=" font-size:11pt; + font-weight:700; + color:#ffffff;">关于SlopeCraft</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; + color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; color:#ffffff;">你可以访问:</span><a + href="https://github.com/ToKiNoBug/SlopeCraft/"><span + style=" font-weight:700; text-decoration: underline; + color:#ffffff;">SlopeCraft的github</span></a><span + style=" font-size:10pt; font-weight:700; + color:#ffffff;">,</span><a + href="https://github.com/ToKiNoBug/"><span style=" + font-weight:700; text-decoration: underline; + color:#ffffff;">我的github主页</span></a><span + style=" font-size:10pt; font-weight:700; + color:#ffffff;">,</span><a + href="https://space.bilibili.com/351429231"><span + style=" font-weight:700; text-decoration: underline; + color:#ffffff;">我的bilibili</span></a><span + style=" font-size:10pt; font-weight:700; + color:#ffffff;">。</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or + later)协议开放源代码。</span></p><p + align="justify"><span style=" font-size:10pt; + font-weight:700; color:#ffffff;">Copyright © 2021-2022 + TokiNoBug</span></p></body></html> + + + true + + + 20 + + + + - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - - - - true - - - - - - - - 0 - 0 - - - - - - - :/new/Pic/BG3.png - - - true - - + - - - - - 0 - 0 - - - - - 10 - - + + + + + + 0 + 0 + 960 + 22 + + + + + 关于 + + - 地图画类型 - - - - - - - 9 - - - - 立体地图画 - - - true - - - - - - - - 9 - - - - 平板地图画 - - - - - - - - 9 - - - - 纯文件地图画 - - - - - - - + 联系作者 + + + + + + + + + + - - - - 9 - - - 9 + + + - - 9 + + - - 9 + + Languages - - - - 0 - - - - - - 10 - - - - 预设方块列表 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 9 - - - - 适合创造 - - - Vanilla - - - - - - - - 9 - - - - 适合生存早期 - - - Cheap - - - - - - - - 9 - - - - 适合生存后期 - - - Elegant - - - true - - - - - - - - 9 - - - - 适合光影 - - - Shiny - - - - - - - - 9 - - - - 自定义 - - - Custom - - - - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - 6 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 9 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 0 - - - - - 0 - - - - - - 0 - 0 - - - - - 120 - 0 - - - - - - - <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> - - - true - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先混凝土 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先羊毛 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先染色玻璃 - - - - - - - - - true - - - QFrame::Box - - - 2 - - - Qt::ScrollBarAlwaysOn - - - true - - - - - 0 - 0 - 16 - 16 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 3 - - - 0 - - - 0 - - - 0 - - - 1 - - - - - - - - + + - - - - 9 - - - 9 + + + 地图画 - - 9 + + + 导出为 + + + + + + + + + + + + + + + + + 高级 - - 9 - - - - - - 0 - 0 - - - - - 0 - 15 - - - - Qt::DefaultContextMenu - - - - - - - - - false - - - - - - 1 - - - 0 - - - Qt::AlignCenter - - - %p% - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 40 - - - - - 32767 - 16777215 - - - - - 9 - - - - 转换为地图画 - - - false - - - - - - - - 0 - 0 - - - - - 80 - 40 - - - - - 150 - 1000 - - - - - - - 保存当前图片 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示地图画 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 16777215 - 16777215 - - - - 导出为 -原版结构文件 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示原图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 32767 - - - - - - - 导出为 -地图文件 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - 导出为 -WorldEdit原理图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - - 9 - - - - - - - 导出为 -Litematica投影 - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 -六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 -调整颜色可能会比较慢,下面的进度条指示了进度。 - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 150 - 300 - - - - - 9 - - - - 算法 - - - - 2 - - - 4 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 9 - - - - RGB欧式距离 - - - RGB - - - - - - - - 0 - 0 - - - - - - - 更好的RGB色差公式 - - - RGB+ - - - true - - - - - - - - 0 - 0 - - - - - 9 - - - - 不是简单的欧式距离 - - - HSV - - - - - - - - 0 - 0 - - - - - 9 - - - - Lab1994公式 - - - Lab94 - - - false - - - - - - - - 0 - 0 - - - - - - - Lab2000公式 - - - Lab00 - - - - - - - - 0 - 0 - - - - - 9 - - - - XYZ欧式距离 - - - XYZ - - - - - - - - 0 - 0 - - - - 遗传算法 - - - GACvter - - - - - - - - 0 - 0 - - - - - - - 用分辨率换颜色 - - - 抖动仿色 - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 440 - 440 - - - - true - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - QFrame::NoFrame - - - 其他选项 - - - - - - - 搭桥 - - - - - - - 方便建造,耗费玻璃 - - - 允许搭桥 - - - - - - - - - - 降低总高度,破坏连续性 - - - - - - - - - 无损压缩 - - - true - - - - - - - Qt::Horizontal - - - - - - - 用玻璃包围防火方块 - - - 防火 - - - - - - - - - - QFrame::NoFrame - - - 压缩高度 - - - - - - - true - - - 用玻璃包围可偷方块 - - - 防末影人 - - - false - - - - - - - true - - - - - - 降低总高度,微调颜色 - - - 智能有损压缩 - - - true - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> - - - true - - - - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - Qt::Horizontal - - - - - - - - - - 投影尺寸 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - true - - - - - - QAbstractSpinBox::UpDownArrows - - - - - - QAbstractSpinBox::CorrectToNearestValue - - - 最大允许高度: - - - 14 - - - 32767 - - - 255 - - - - - - - false - - - - - - 搭桥间隔: - - - 4 - - - - - - - - - - 总方块数 - - - - - - - - - - - - - 0 - - - - Litematica - - - - - - - 9 - - - - 投影名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - 9 - - - - 投影区域名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Structure - - - - - - 节省大量存储空间 - - - - - - - - - 用结构空位代替 - - - true - - - - - - - 空气处理方式 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - WorldEdit - - - - - - 0 - - - - - - - WEOffset(X,Y,Z) - - - - - - - 0 - - - - - - - 0 - - - - - - - 0 - - - - - - - offset(X,Y,Z) - - - - - - - 0 - - - - - - - 原理图名称 - - - - - - - 0 - - - - - - - 依赖mod名称 - - - - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 20 - - - - - 10 - - - - 结束 - - - - - - - - - - 0 - 0 - - - - 1 - - - 0 - - - Qt::AlignCenter - - - false - - - Qt::Vertical - - - false - - - %p% - - - - - - - 0 - - - Qt::Vertical - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 30 - - - - 导出平面示意图 - - - - - - - false - - - - 100 - 30 - - - - - - - 导出三维结构 - - - - - - - false - - - - 0 - 30 - - - - 预览 - - - - - - - false - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - 地图画起点坐标 - - - - - - - 地图画尺寸 - - - - - - - Y - - - - - - - X - - - - - - - 总命令数 - - - - - - - Z - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 200 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - 1 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - - 0 - - - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 0 - - - -1 - - - Qt::Vertical - - - - - - - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="justify">最后一步,导出为mcfunction!</p><p align="justify">如果你不想导出为投影文件,也可以使用mc自带的数据包。</p><p align="justify">导出的文件是一个mc中的“函数”,是数据包的一部分。</p><p align="justify">你可以在单机存档中使用/reload命令来加载它,用/function命令调用它。</p><p align="justify">如果地图画很大,超过了一个mcfunction的命令数,那么会将全部的命令分散在多个mcfuntion中。</p><p align="justify">在导出前,你需要指定地图画的起点坐标,它是xyz负方向的方块的坐标。</p><p align="justify">(如果不知道要放在哪里,请使用默认值-64,1,-64)</p></body></html> - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - 16777215 - 60 - - - - - - - - - - - - - 0 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -hr { height: 1px; border-width: 0; } -li.unchecked::marker { content: "\2610"; } -li.checked::marker { content: "\2612"; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:6px; margin-bottom:6px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Microsoft YaHei UI'; font-size:9pt;">0</span></p></body></html> - - - - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - map_0.dat - - - Qt::AlignCenter - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - QFrame::Plain - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> - - - true - - - - - - - 0 - - - - - false - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 1 - - - 0 - - - Qt::Vertical - - - %p% - - - - - - - - - false - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - - 导出的文件名 - - - - - - - - 0 - 0 - - - - 地图文件起始序号 - - - - - - - 地图画行数 - - - - - - - 地图画列数 - - - - - - - 地图文件数量 - - - - - - - - - - - - 0 - 30 - - - - - - - 查看导出的文件 - - - - - - - true - - - - 0 - 30 - - - - - - - 联系作者 - - - - - - - - 0 - 30 - - - - - - - 退出 - - - - - - - - - - background-color: rgba(0, 0, 0, 48); - - - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - - - true - - - 20 + + + 批量操作 - - - + + + + + 方块列表预设 + + + + + + + + + - - - - - - - - 0 - 0 - 960 - 27 - - - - - 关于 - - - - 联系作者 - - - - - - - - - - - - - - - - - - - - Languages - - - - - - - 地图画 - - - - 导出为 - - - - - - - - - - - - - - - - - 高级 - - - - 批量操作 - - - - - - 方块列表预设 - - - + + + + - - - - - - - - - - + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + false + + + 导出为投影文件 + + + 导出为投影文件 + + + 导出为投影文件 + + + + + false + + + 导出为mcfunction + + + 导出为mcfunction + + + + + false + + + true + + + 导出为地图文件 + + + + + false + + + 关于SlopeCraft + + + + + 简体中文 + + + + + English + + + + + GitHub + + + + + BiliBili + + + + + 反馈Bug + + + + + false + + + 检查更新 + + + 检查更新 + + + 检查更新 + + + + + 开始 + + + + + 导入图片 + + + + + 地图画类型 + + + + + 方块列表 + + + + + 调整颜色 + + + + + 投影文件 + + + + + 结构文件 + + + + + 地图文件 + + + + + 完成 + + + + + false + + + 测试方块列表 + + + + + 设置导出参数 + + + + + 保存预设 + + + + + 加载预设 + + + + + GACvter参数 + + + GACvter参数 + + + GACvter参数 + + + + + 输出当前颜色表 + + + + + WE原理图 + + + + + 使用教程 + + - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - false - - - 导出为投影文件 - - - 导出为投影文件 - - - 导出为投影文件 - - - - - false - - - 导出为mcfunction - - - 导出为mcfunction - - - - - false - - - true - - - 导出为地图文件 - - - - - false - - - 关于SlopeCraft - - - - - 简体中文 - - - - - English - - - - - GitHub - - - - - BiliBili - - - - - 反馈Bug - - - - - false - - - 检查更新 - - - 检查更新 - - - 检查更新 - - - - - 开始 - - - - - 导入图片 - - - - - 地图画类型 - - - - - 方块列表 - - - - - 调整颜色 - - - - - 投影文件 - - - - - 结构文件 - - - - - 地图文件 - - - - - 完成 - - - - - false - - - 测试方块列表 - - - - - 设置导出参数 - - - - - 保存预设 - - - - - 加载预设 - - - - - GACvter参数 - - - GACvter参数 - - - GACvter参数 - - - - - 输出当前颜色表 - - - - - WE原理图 - - - - - 使用教程 - - - - - - AdaptiveLabel - QLabel -
AdaptiveLabel.h
-
-
- - isMapSurvival - isMapFlat - isGame16 - isBLSurvivalCheaper - isBLSurvivalBetter - isBLGlowing - isBLCustom - NextPage3 - FirstConcrete - FirstWool - FirstStainedGlass - scrollArea - isColorSpaceRGBOld - isColorSpaceHSV - isColorSpaceLab94 - isColorSpaceXYZ - FinishExLite - ExportLite - NWPosY - NWPosX - NWPosZ - FinishMcF - _ExportMcF - isBLCreative - NextPage2 - - - - - - - + + + AdaptiveLabel + QLabel +
AdaptiveLabel.h
+
+
+ + isMapSurvival + isMapFlat + isGame16 + isBLSurvivalCheaper + isBLSurvivalBetter + isBLGlowing + isBLCustom + NextPage3 + FirstConcrete + FirstWool + FirstStainedGlass + scrollArea + isColorSpaceRGBOld + isColorSpaceHSV + isColorSpaceLab94 + isColorSpaceXYZ + FinishExLite + ExportLite + NWPosY + NWPosX + NWPosZ + FinishMcF + _ExportMcF + isBLCreative + NextPage2 + + + + + + + \ No newline at end of file From 337a8acf056973248384659d7feb8472d82f311a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 21 Apr 2023 13:54:59 +0800 Subject: [PATCH 0240/1123] Revert "update translation" This reverts commit 4e1b53f9e8eab1e78cfa45252c55372486f1f900. --- SlopeCraftMain/mainwindow.ui | 8102 +++++++++++++++++----------------- 1 file changed, 3992 insertions(+), 4110 deletions(-) diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui index 433ae3b7..2274c618 100644 --- a/SlopeCraftMain/mainwindow.ui +++ b/SlopeCraftMain/mainwindow.ui @@ -1,4180 +1,4062 @@ - TokiNoBug - MainWindow - - - - 0 - 0 - 960 - 540 - + TokiNoBug + MainWindow + + + + 0 + 0 + 960 + 540 + + + + + 0 + 0 + + + + + 960 + 540 + + + + + 16777215 + 16777215 + + + + + + + SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug + + + + others/SlopeCraftIconNew.icoothers/SlopeCraftIconNew.ico + + + + + + + 128 + 128 + + + + true + + + QTabWidget::Rounded + + + true + + + + + 0 + 0 + + + + QWidget#centralwidget{border-image: url(":/new/Pic/BG4.png");} + + + + QLayout::SetNoConstraint - - - 0 - 0 - - - - - 960 - 540 - - - - - 16777215 - 16777215 - - - - - - - SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug - - - - others/SlopeCraftIconNew.icoothers/SlopeCraftIconNew.ico - - - + + 4 - - - 128 - 128 - + + 4 - - true + + 4 - - QTabWidget::Rounded + + 4 - - true - - + + - - 0 - 0 - + + 0 + 0 + + + + + 0 + 0 + - QWidget#centralwidget{border-image: url(":/new/Pic/BG4.png");} + #LeftScroll ,#LeftScrollArea{ + background-color: rgba(255, 255, 255, 0); +} + +QPushButton:enabled{ + border:2px; + border-radius:10px; + padding:2px 4px; + background-color: rgba(255, 255, 255,128); + color: rgb(0, 0, 0); + font: 9pt "微软雅黑"; +} + +QPushButton:!enabled{ +border:2px; +border-radius:10px; +padding:2px 4px; +background-color: rgba(191, 191,191,128); +color: rgb(64, 64, 64); +font: 9pt "微软雅黑"; +} + +QPushButton:hover{ +border:2px; +border-radius:10px; +padding:2px 4px; +background-color: rgba(255, 255, 255,191); +color: rgb(0, 0, 0); +font: 9pt "微软雅黑"; +} + +QPushButton:pressed{ +border:2px; +border-radius:10px; +padding:2px 4px; +background-color: rgba(255, 255, 255,223); +border-style: inset; +border-color: rgb(235, 235, 235); +color: rgb(0, 0, 0); +font: 9pt "微软雅黑"; +} + +/**/ - - - QLayout::SetNoConstraint - + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + true + + + Qt::AlignCenter + + + + + 0 + 0 + 152 + 757 + + + + + 0 + 0 + + + + + 0 + 0 + + + + false + + + + + - 4 + 9 - 4 + 5 - 4 + 5 - 4 + 9 - + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">地图画</span></p></body></html> + + + + + + + + 0 + 0 + + + + + 100 + 30 + + + + 开始 + + + + :/new/Textures/Slope/block/grass_block.png:/new/Textures/Slope/block/grass_block.png + + + + + + + + 100 + 30 + + + + 导入图片 + + + + :/new/Textures/Slope/items/book.png:/new/Textures/Slope/items/book.png + + + + + + + true + + + + 100 + 30 + + + + + + + 地图画类型 + + + + :/new/Textures/Slope/items/map.png:/new/Textures/Slope/items/map.png + + + + + + + + 100 + 30 + + + + 方块列表 + + + + :/new/Textures/Slope/block/waxed_cut_copper.png:/new/Textures/Slope/block/waxed_cut_copper.png + + + + + + + + 100 + 30 + + + + 调整颜色 + + + + :/new/Textures/Slope/items/amethyst_shard.png:/new/Textures/Slope/items/amethyst_shard.png + + + + + + + + 100 + 30 + + + + 导出为 + + + + :/new/Textures/Slope/items/iron_pickaxe.png:/new/Textures/Slope/items/iron_pickaxe.png + + + + + + + 0 + + + - - 0 - 0 - + + 0 + 0 + - - 0 - 0 - + + 90 + 25 + - - #LeftScroll ,#LeftScrollArea{ - background-color: rgba(255, 255, 255, 0); - } - - QPushButton:enabled{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(255, 255, 255,128); - color: rgb(0, 0, 0); - font: 9pt "微软雅黑"; - } - - QPushButton:!enabled{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(191, 191,191,128); - color: rgb(64, 64, 64); - font: 9pt "微软雅黑"; - } - - QPushButton:hover{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(255, 255, 255,191); - color: rgb(0, 0, 0); - font: 9pt "微软雅黑"; - } - - QPushButton:pressed{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(255, 255, 255,223); - border-style: inset; - border-color: rgb(235, 235, 235); - color: rgb(0, 0, 0); - font: 9pt "微软雅黑"; - } - - /**/ + + 平面示意图 - - QFrame::NoFrame + + + + + + + 0 + 0 + - - Qt::ScrollBarAlwaysOff + + + 90 + 25 + - - true + + 地图文件 - - Qt::AlignCenter - - - - - 0 - 0 - 152 - 757 - - - - - 0 - 0 - - - - - 0 - 0 - - - - false - - - - - - - 9 - - - 5 - - - 5 - - - 9 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" - "http://www.w3.org/TR/REC-html40/strict.dtd"> - <html><head><meta name="qrichtext" - content="1" /><meta charset="utf-8" /><style - type="text/css"> - p, li { white-space: pre-wrap; } - </style></head><body style=" font-family:'Microsoft - YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> - <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; - margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span - style=" font-weight:700; - color:#ffffff;">地图画</span></p></body></html> - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - 开始 - - - - :/new/Textures/Slope/block/grass_block.png - :/new/Textures/Slope/block/grass_block.png - - - - - - - - 100 - 30 - - - - 导入图片 - - - - :/new/Textures/Slope/items/book.png - :/new/Textures/Slope/items/book.png - - - - - - - true - - - - 100 - 30 - - - - - - - 地图画类型 - - - - :/new/Textures/Slope/items/map.png - :/new/Textures/Slope/items/map.png - - - - - - - - 100 - 30 - - - - 方块列表 - - - - :/new/Textures/Slope/block/waxed_cut_copper.png - :/new/Textures/Slope/block/waxed_cut_copper.png - - - - - - - - 100 - 30 - - - - 调整颜色 - - - - :/new/Textures/Slope/items/amethyst_shard.png - :/new/Textures/Slope/items/amethyst_shard.png - - - - - - - - 100 - 30 - - - - 导出为 - - - - :/new/Textures/Slope/items/iron_pickaxe.png - :/new/Textures/Slope/items/iron_pickaxe.png - - - - - - - 0 - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 平面示意图 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 地图文件 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 投影文件 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 结构文件 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - WE原理图 - - - - - - - - - - 100 - 30 - - - - 完成 - - - - :/new/Textures/Slope/items/diamond.png - :/new/Textures/Slope/items/diamond.png - - - - - - - - <html><head/><body><p><br/><span - style=" font-weight:700; - color:#ffffff;">语言/Languages</span></p></body></html> - - - - - - - - 0 - 30 - - - - 简体中文 - - - - - - - - 0 - 30 - - - - English - - - - - - - - <html><head/><body><p><br/><span - style=" font-weight:700; - color:#ffffff;">联系作者</span></p></body></html> - - - - - - - - 0 - 30 - - - - GitHub - - - - - - - - 0 - 30 - - - - BiliBili - - - - - - - - 0 - 30 - - - - 检查更新 - - - - - - - - 0 - 30 - - - - 反馈Bug - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - + + + + - - 0 - 0 - + + 0 + 0 + - - 30 - 0 - + + 90 + 25 + - - + + 投影文件 + + + + + + + + 0 + 0 + - - /*QWidget#PageEnd{border-image: url(:/new/Pic/BG4.png);}*/ - QWidget#PageStart,#PageEnd{ - background-color: rgba(255, 255, 255, 0); - } + + + 90 + 25 + + + + 结构文件 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 90 + 25 + + + + WE原理图 + + + + + + + + + + 100 + 30 + + + + 完成 + + + + :/new/Textures/Slope/items/diamond.png:/new/Textures/Slope/items/diamond.png + + + + + + + <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">语言/Languages</span></p></body></html> + + + + + + + + 0 + 30 + + + + 简体中文 + + + + + + + + 0 + 30 + + + + English + + + + + + + <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">联系作者</span></p></body></html> + + + + + + + + 0 + 30 + + + + GitHub + + + + + + + + 0 + 30 + + + + BiliBili + + + + + + + + 0 + 30 + + + + 检查更新 + + + + + + + + 0 + 30 + + + + 反馈Bug + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + + + /*QWidget#PageEnd{border-image: url(:/new/Pic/BG4.png);}*/ +QWidget#PageStart,#PageEnd{ + background-color: rgba(255, 255, 255, 0); +} - QWidget#PageImPic,#PageType,#PageBL,#PageAdjPic,#PageExLite,#PageExMcF,#PageExDat{ - background-color:#f0f0f0; - border:2px solid gray - } - QPushButton:enabled{ - border:2px; - border-radius:10px; - border-style:groove; - border-color: rgb(136, 136, 136); - color: rgb(0, 0, 0); - padding:2px 4px; - background-color: rgb(225, 225, 225); - } +QWidget#PageImPic,#PageType,#PageBL,#PageAdjPic,#PageExLite,#PageExMcF,#PageExDat{ +background-color:#f0f0f0; +border:2px solid gray +} - QPushButton:hover{ - border:2px; - border-radius:10px; - border-style:solid; - border-color: rgb(136, 136, 136); - color: rgb(0, 0, 0); - padding:2px 4px; - background-color: rgb(241, 241, 241); - } +QPushButton:enabled{ +border:2px; +border-radius:10px; +border-style:groove; +border-color: rgb(136, 136, 136); +color: rgb(0, 0, 0); +padding:2px 4px; +background-color: rgb(225, 225, 225); +} - QPushButton:!enabled{ - border:2px; - border-radius:10px; - border-style:groove; - border-color: rgb(136, 136, 136); - color: rgb(80, 80, 80); - padding:2px 4px; - background-color: rgb(193, 193, 193); - } +QPushButton:hover{ +border:2px; +border-radius:10px; +border-style:solid; +border-color: rgb(136, 136, 136); +color: rgb(0, 0, 0); +padding:2px 4px; +background-color: rgb(241, 241, 241); +} - QCommandLinkButton:enabled{ - color: rgb(0, 0, 0); - border:0px; - background-color: rgba(255, 255, 255,128); - font: 11pt "微软雅黑"; - } +QPushButton:!enabled{ +border:2px; +border-radius:10px; +border-style:groove; +border-color: rgb(136, 136, 136); +color: rgb(80, 80, 80); +padding:2px 4px; +background-color: rgb(193, 193, 193); +} - QCommandLinkButton:hover{ - color: rgb(0, 0, 0); - border:0px; - background-color: rgba(255, 255, 255,191); - font: 11pt "微软雅黑"; - } - QCommandLinkButton:pressed{ - color: rgb(0, 0, 0); - border:0px; - background-color: rgba(255, 255, 255,223); - font: 11pt "微软雅黑"; - } +QCommandLinkButton:enabled{ +color: rgb(0, 0, 0); +border:0px; +background-color: rgba(255, 255, 255,128); +font: 11pt "微软雅黑"; +} + +QCommandLinkButton:hover{ +color: rgb(0, 0, 0); +border:0px; +background-color: rgba(255, 255, 255,191); +font: 11pt "微软雅黑"; +} +QCommandLinkButton:pressed{ +color: rgb(0, 0, 0); +border:0px; +background-color: rgba(255, 255, 255,223); +font: 11pt "微软雅黑"; +} + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + + + + + + + 30 + + + + + + 0 + 0 + - - QFrame::NoFrame + + + 20 + false + - - QFrame::Plain + + <html><head/><body><p><span style=" font-size:16pt; font-weight:700; color:#ffff7f;">Copyright © 2021-2023 TokiNoBug</span></p></body></html> - - 0 + + Qt::AlignHCenter|Qt::AlignTop - - - + + + + + + + 0 + 0 + + + + + MV Boli + 26 + false + + + + <html><head/><body><p><span style=" font-size:40pt; color:#ffffff;">SlopeCraft</span><span style=" color:#ffffff;"> %1</span></p></body></html> + + + Qt::AlignBottom|Qt::AlignHCenter + + + + + + + + + 0 + + + 0 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + + 0 + 0 + - - - - - 30 - - - - - - 0 - 0 - - - - - 20 - false - - - - <html><head/><body><p><span - style=" font-size:16pt; font-weight:700; - color:#ffff7f;">Copyright © 2021-2023 - TokiNoBug</span></p></body></html> - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - - - 0 - 0 - - - - - MV Boli - 26 - false - - - - <html><head/><body><p><span - style=" font-size:40pt; - color:#ffffff;">SlopeCraft</span><span style=" - color:#ffffff;"> - %1</span></p></body></html> - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - - - 0 - - - 0 - - - - - QLayout::SetDefaultConstraint - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Flat.png - - - true - - - - - - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建平板地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - <html><head/><body><p - align="center"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">传统的地图画样式</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - - 260 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_3D.png - - - true - - - - - - - - 微软雅黑 - 11 - false - false - - - - - - - - - - - - - 创建立体地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - <html><head/><body><p - align="center"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">原版生存的最高画质</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - false - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Data.png - - - true - - - - - - - true - - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建纯文件地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - - - - <html><head/><body><p - align="center"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - - - - + + + 16777215 + 195 + + + + QFrame::StyledPanel + + + 2 + + + + + + :/new/Pic/cover_Flat.png + + + true + + + + + + + + 0 + 40 + + + + + 微软雅黑 + 11 + false + false + + + + 创建平板地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + - - 0 - 0 - + + 0 + 0 + + + + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">传统的地图画样式</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 195 + + + + + 260 + 195 + + + + QFrame::StyledPanel + + + 2 + + + + + + :/new/Pic/cover_3D.png + + + true + + + + + + + + 微软雅黑 + 11 + false + false + + + + + + + + + + + + + 创建立体地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">原版生存的最高画质</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + 0 + + + + + + 0 + 0 + - - 65536 - 65536 - + + 16777215 + 195 + - false + false - - + + QFrame::StyledPanel - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - #ShowRawPic{background-image: - url(:/new/Pic/Transparent.png);} - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 9 - - - - Qt::LeftToRight - - - false - - - 导入图片 - - - - - - - - 0 - 0 - - - - - - - - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - - - Qt::AutoText - - - true - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - - - 透明度相关设置 - - - 设置 - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 10 - - - - 下一步 - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - - - backgroundcolor: rgb(255, 255, 255); - - - - <html><head/><body><p - align="justify">第二步,选择好你要什么样的地图画。</p><p - align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p - align="justify">立体地图画如右图,是我们的核心功能;</p><p - align="justify">平板地图画颜色相对少,但更容易建造;</p><p - align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> - - - true - - - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 10 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - 0 - - - - - 9 - - - - 游戏版本 - - - - - - - 9 - - - - 1.15 - - - false - - - - - - - - 9 - - - - 1.16 - - - false - - - - - - - true - - - - - - 1.17 - - - true - - - - - - - - - - 1.13 - - - - - - - - - - 1.12 - - - - - - - - - - 1.14 - - - - - - - 1.18 - - - - - - - 1.19 - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - - - - true - - - - - - - - 0 - 0 - - - - - - - :/new/Pic/BG3.png - - - true - - - - - - - - 0 - 0 - - - - - 10 - - - - 地图画类型 - - - - - - - 9 - - - - 立体地图画 - - - true - - - - - - - - 9 - - - - 平板地图画 - - - - - - - - 9 - - - - 纯文件地图画 - - - - - - - + + 2 + + + + + + :/new/Pic/cover_Data.png + + + true + + + + + + + true + + + + 0 + 40 + + + + + 微软雅黑 + 11 + false + false + + + + 创建纯文件地图画 + + + + + + + 2 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + + + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + + + + 0 + 0 + + + + + 65536 + 65536 + + + + false + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + #ShowRawPic{background-image: url(:/new/Pic/Transparent.png);} + + + QFrame::StyledPanel + + + + + + :/new/Pic/BG2.png + + + false + + + Qt::AlignCenter + + + + + + + 0 + + + + + + 0 + 0 + + + + + 100 + 30 + + + + + 5 + 2 + + + + + 9 + + + + Qt::LeftToRight + + + false + + + 导入图片 + + + + + + + + 0 + 0 + + + + + + + <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> + + + Qt::AutoText + + + true + + + + + + + + 0 + 0 + + + + + + + + + + true + + + + + + + + 0 + 0 + + + + + 100 + 30 + + + + + + + 透明度相关设置 + + + 设置 + + + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 5 + 2 + + + + + 10 + + + + 下一步 + + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + + + backgroundcolor: rgb(255, 255, 255); + + + <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> + + + true + + + + + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 10 + + + + 下一步 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + + 9 + + + + 游戏版本 + + + + + + + 9 + + + + 1.15 + + + false + - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - - - - 10 - - - - 预设方块列表 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 9 - - - - 适合创造 - - - Vanilla - - - - - - - - 9 - - - - 适合生存早期 - - - Cheap - - - - - - - - 9 - - - - 适合生存后期 - - - Elegant - - - true - - - - - - - - 9 - - - - 适合光影 - - - Shiny - - - - - - - - 9 - - - - 自定义 - - - Custom - - - - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - 6 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 9 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 0 - - - - - 0 - - - - - - 0 - 0 - - - - - 120 - 0 - - - - - - - - <html><head/><body><p - align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p - align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> - - - true - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先混凝土 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先羊毛 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先染色玻璃 - - - - - - - - - true - - - QFrame::Box - - - 2 - - - Qt::ScrollBarAlwaysOn - - - true - - - - - 0 - 0 - 551 - 378 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 3 - - - 0 - - - 0 - - - 0 - - - 1 - - - - - - - - + + + + + + 9 + + + + 1.16 + + + false + - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - 0 - 15 - - - - Qt::DefaultContextMenu - - - - - - - - - false - - - - - - 1 - - - 0 - - - Qt::AlignCenter - - - %p% - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 40 - - - - - 32767 - 16777215 - - - - - 9 - - - - 转换为地图画 - - - false - - - - - - - - 0 - 0 - - - - - 80 - 40 - - - - - 150 - 1000 - - - - - - - 保存当前图片 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示地图画 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 16777215 - 16777215 - - - - 导出为 - 原版结构文件 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示原图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 32767 - - - - - - - 导出为 - 地图文件 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - 导出为 - WorldEdit原理图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - - 9 - - - - - - - 导出为 - Litematica投影 - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 - 六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 - 调整颜色可能会比较慢,下面的进度条指示了进度。 - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 150 - 300 - - - - - 9 - - - - 算法 - - - - 2 - - - 4 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 9 - - - - RGB欧式距离 - - - RGB - - - - - - - - 0 - 0 - - - - - - - 更好的RGB色差公式 - - - RGB+ - - - true - - - - - - - - 0 - 0 - - - - - 9 - - - - 不是简单的欧式距离 - - - HSV - - - - - - - - 0 - 0 - - - - - 9 - - - - Lab1994公式 - - - Lab94 - - - false - - - - - - - - 0 - 0 - - - - - - - Lab2000公式 - - - Lab00 - - - - - - - - 0 - 0 - - - - - 9 - - - - XYZ欧式距离 - - - XYZ - - - - - - - - 0 - 0 - - - - 遗传算法 - - - GACvter - - - - - - - - 0 - 0 - - - - - - - 用分辨率换颜色 - - - 抖动仿色 - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 440 - 440 - - - - true - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - + + + + + true + + + + + + 1.17 + + + true + - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - QFrame::NoFrame - - - 其他选项 - - - - - - - 搭桥 - - - - - - - 方便建造,耗费玻璃 - - - 允许搭桥 - - - - - - - - - - 降低总高度,破坏连续性 - - - - - - - - - 无损压缩 - - - true - - - - - - - Qt::Horizontal - - - - - - - 用玻璃包围防火方块 - - - 防火 - - - - - - - - - - QFrame::NoFrame - - - 压缩高度 - - - - - - - true - - - 用玻璃包围可偷方块 - - - 防末影人 - - - false - - - - - - - true - - - - - - 降低总高度,微调颜色 - - - 智能有损压缩 - - - true - - - - - - - - 0 - 0 - - - - - - - - <html><head/><body><p - align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p - align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p - align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p - align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p - align="justify">这个过程可能会很慢,请关注进度条</p></body></html> - - - true - - - - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - Qt::Horizontal - - - - - - - - - - 投影尺寸 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - true - - - - - - QAbstractSpinBox::UpDownArrows - - - - - - QAbstractSpinBox::CorrectToNearestValue - - - 最大允许高度: - - - 14 - - - 32767 - - - 255 - - - - - - - false - - - - - - 搭桥间隔: - - - 4 - - - - - - - - - - 总方块数 - - - - - - - - - - - - - 0 - - - - Litematica - - - - - - - 9 - - - - 投影名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - 9 - - - - 投影区域名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Structure - - - - - - 节省大量存储空间 - - - - - - - - - 用结构空位代替 - - - true - - - - - - - 空气处理方式 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - WorldEdit - - - - - - 0 - - - - - - - WEOffset(X,Y,Z) - - - - - - - 0 - - - - - - - 0 - - - - - - - 0 - - - - - - - offset(X,Y,Z) - - - - - - - 0 - - - - - - - 原理图名称 - - - - - - - 0 - - - - - - - 依赖mod名称 - - - - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 20 - - - - - 10 - - - - 结束 - - - - - - - - - - 0 - 0 - - - - 1 - - - 0 - - - Qt::AlignCenter - - - false - - - Qt::Vertical - - - false - - - %p% - - - - - - - 0 - - - Qt::Vertical - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 30 - - - - 导出平面示意图 - - - - - - - false - - - - 100 - 30 - - - - - - - 导出三维结构 - - - - - - - false - - - - 0 - 30 - - - - 预览 - - - - - - - false - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - + + + + + + + + 1.13 + - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - 地图画起点坐标 - - - - - - - 地图画尺寸 - - - - - - - Y - - - - - - - X - - - - - - - 总命令数 - - - - - - - Z - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 200 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - 1 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - - 0 - - - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 0 - - - -1 - - - Qt::Vertical - - - - - - - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - - - - - 0 - 0 - - - - - - - - <html><head/><body><p - align="justify">最后一步,导出为mcfunction!</p><p - align="justify">如果你不想导出为投影文件,也可以使用mc自带的数据包。</p><p - align="justify">导出的文件是一个mc中的“函数”,是数据包的一部分。</p><p - align="justify">你可以在单机存档中使用/reload命令来加载它,用/function命令调用它。</p><p - align="justify">如果地图画很大,超过了一个mcfunction的命令数,那么会将全部的命令分散在多个mcfuntion中。</p><p - align="justify">在导出前,你需要指定地图画的起点坐标,它是xyz负方向的方块的坐标。</p><p - align="justify">(如果不知道要放在哪里,请使用默认值-64,1,-64)</p></body></html> - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + + + + + 1.12 + - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - 16777215 - 60 - - - - - - - - - - - - - 0 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML - 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> - <html><head><meta name="qrichtext" - content="1" /><meta charset="utf-8" /><style - type="text/css"> - p, li { white-space: pre-wrap; } - hr { height: 1px; border-width: 0; } - li.unchecked::marker { content: "\2610"; } - li.checked::marker { content: "\2612"; } - </style></head><body style=" font-family:'Microsoft - YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> - <p style=" margin-top:6px; margin-bottom:6px; margin-left:0px; - margin-right:0px; -qt-block-indent:0; - text-indent:0px;">0</p></body></html> - - - - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - map_0.dat - - - Qt::AlignCenter - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - QFrame::Plain - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - <html><head/><body><p - align="justify">最后一步,导出为地图文件。</p><p - align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p - align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p - align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p - align="justify">例如,你可以使用/give @s - filled_map{map:3}来获得map_3.dat的地图。</p><p - align="justify">1.12版请使用/give @p filled_map 1 3</p><p - align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> - - - true - - - - - - - 0 - - - - - false - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 1 - - - 0 - - - Qt::Vertical - - - %p% - - - - - - - - - false - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - - 导出的文件名 - - - - - - - - 0 - 0 - - - - 地图文件起始序号 - - - - - - - 地图画行数 - - - - - - - 地图画列数 - - - - - - - 地图文件数量 - - - - + + + + + + + + 1.14 + - - - - - - - 0 - 30 - - - - - - - 查看导出的文件 - - - - - - - true - - - - 0 - 30 - - - - - - - 联系作者 - - - - - - - - 0 - 30 - - - - - - - 退出 - - - - - - - - - - background-color: rgba(0, 0, 0, 48); - - - <html><head/><body><p - align="center"><span style=" font-size:16pt; - font-weight:700; - color:#ffffff;">地图画生成完毕!</span><br/></p><p - align="center"><span style=" font-size:11pt; - font-weight:700; - color:#ffffff;">关于SlopeCraft</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; - color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; color:#ffffff;">你可以访问:</span><a - href="https://github.com/ToKiNoBug/SlopeCraft/"><span - style=" font-weight:700; text-decoration: underline; - color:#ffffff;">SlopeCraft的github</span></a><span - style=" font-size:10pt; font-weight:700; - color:#ffffff;">,</span><a - href="https://github.com/ToKiNoBug/"><span style=" - font-weight:700; text-decoration: underline; - color:#ffffff;">我的github主页</span></a><span - style=" font-size:10pt; font-weight:700; - color:#ffffff;">,</span><a - href="https://space.bilibili.com/351429231"><span - style=" font-weight:700; text-decoration: underline; - color:#ffffff;">我的bilibili</span></a><span - style=" font-size:10pt; font-weight:700; - color:#ffffff;">。</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or - later)协议开放源代码。</span></p><p - align="justify"><span style=" font-size:10pt; - font-weight:700; color:#ffffff;">Copyright © 2021-2022 - TokiNoBug</span></p></body></html> - - - true - - - 20 - - - - + + + + + 1.18 + - + + + + + 1.19 + + + + + - - - - - - 0 - 0 - 960 - 22 - - - - - 关于 - - + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + + + + true + + + + + + + + 0 + 0 + + + + + + + :/new/Pic/BG3.png + + + true + + + + + + + + 0 + 0 + + + + + 10 + + - 联系作者 - - - - - - - - - - + 地图画类型 + + + + + + + 9 + + + + 立体地图画 + + + true + + + + + + + + 9 + + + + 平板地图画 + + + + + + + + 9 + + + + 纯文件地图画 + + + + + + +
- - - - - - + + + + 9 - - Languages + + 9 - - - - - - 地图画 + + 9 - - - 导出为 - - - - - - - - - - - - - - - - - 高级 + + 9 - - - 批量操作 + + + + 0 - - - - - 方块列表预设 - - - - - - - - - + + + + + 10 + + + + 预设方块列表 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 9 + + + + 适合创造 + + + Vanilla + + + + + + + + 9 + + + + 适合生存早期 + + + Cheap + + + + + + + + 9 + + + + 适合生存后期 + + + Elegant + + + true + + + + + + + + 9 + + + + 适合光影 + + + Shiny + + + + + + + + 9 + + + + 自定义 + + + Custom + + + + + + + + + + + 0 + 0 + + + + + + + + + + true + + + + + + + 6 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 100 + 30 + + + + + 100 + 30 + + + + + 9 + + + + 下一步 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + + 120 + 0 + + + + + + + <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> + + + true + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先混凝土 + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先羊毛 + + + + + + + + 0 + 25 + + + + + 9 + + + + 优先染色玻璃 + + + + + + + + + true + + + QFrame::Box + + + 2 + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 16 + 16 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 1 + + + + + + + + - - - - + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 0 + 15 + + + + Qt::DefaultContextMenu + + + + + + + + + false + + + + + + 1 + + + 0 + + + Qt::AlignCenter + + + %p% + + + + + + + 0 + + + + + + 0 + 0 + + + + + 100 + 40 + + + + + 32767 + 16777215 + + + + + 9 + + + + 转换为地图画 + + + false + + + + + + + + 0 + 0 + + + + + 80 + 40 + + + + + 150 + 1000 + + + + + + + 保存当前图片 + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 150 + 16777215 + + + + + 9 + + + + 显示地图画 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 16777215 + 16777215 + + + + 导出为 +原版结构文件 + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 150 + 16777215 + + + + + 9 + + + + 显示原图 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 32767 + + + + + + + 导出为 +地图文件 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 16777215 + + + + 导出为 +WorldEdit原理图 + + + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 150 + 16777215 + + + + + 9 + + + + + + + 导出为 +Litematica投影 + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 +六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 +调整颜色可能会比较慢,下面的进度条指示了进度。 + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 150 + 300 + + + + + 9 + + + + 算法 + + + + 2 + + + 4 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 9 + + + + RGB欧式距离 + + + RGB + + + + + + + + 0 + 0 + + + + + + + 更好的RGB色差公式 + + + RGB+ + + + true + + + + + + + + 0 + 0 + + + + + 9 + + + + 不是简单的欧式距离 + + + HSV + + + + + + + + 0 + 0 + + + + + 9 + + + + Lab1994公式 + + + Lab94 + + + false + + + + + + + + 0 + 0 + + + + + + + Lab2000公式 + + + Lab00 + + + + + + + + 0 + 0 + + + + + 9 + + + + XYZ欧式距离 + + + XYZ + + + + + + + + 0 + 0 + + + + 遗传算法 + + + GACvter + + + + + + + + 0 + 0 + + + + + + + 用分辨率换颜色 + + + 抖动仿色 + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 440 + 440 + + + + true + + + QFrame::StyledPanel + + + + + + :/new/Pic/BG2.png + + + false + + + Qt::AlignCenter + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 0 + + + 12 + + + + + QFrame::NoFrame + + + 其他选项 + + + + + + + 搭桥 + + + + + + + 方便建造,耗费玻璃 + + + 允许搭桥 + + + + + + + + + + 降低总高度,破坏连续性 + + + + + + + + + 无损压缩 + + + true + + + + + + + Qt::Horizontal + + + + + + + 用玻璃包围防火方块 + + + 防火 + + + + + + + + + + QFrame::NoFrame + + + 压缩高度 + + + + + + + true + + + 用玻璃包围可偷方块 + + + 防末影人 + + + false + + + + + + + true + + + + + + 降低总高度,微调颜色 + + + 智能有损压缩 + + + true + + + + + + + + 0 + 0 + + + + + + + <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> + + + true + + + + + + + + 0 + 30 + + + + + + + QFrame::StyledPanel + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 投影尺寸 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + + + QFrame::StyledPanel + + + + + + + + + + true + + + + + + QAbstractSpinBox::UpDownArrows + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 最大允许高度: + + + 14 + + + 32767 + + + 255 + + + + + + + false + + + + + + 搭桥间隔: + + + 4 + + + + + + + + + + 总方块数 + + + + + + + + + + + + + 0 + + + + Litematica + + + + + + + 9 + + + + 投影名称 + + + + + + + Pixel Paint by SlopeCraft + + + + + + + + 9 + + + + 投影区域名称 + + + + + + + Pixel Paint by SlopeCraft + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Structure + + + + + + 节省大量存储空间 + + + + + + + + + 用结构空位代替 + + + true + + + + + + + 空气处理方式 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + WorldEdit + + + + + + 0 + + + + + + + WEOffset(X,Y,Z) + + + + + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + offset(X,Y,Z) + + + + + + + 0 + + + + + + + 原理图名称 + + + + + + + 0 + + + + + + + 依赖mod名称 + + + + + + + + + + Pixel Paint by SlopeCraft + + + + + + + + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 20 + + + + + 10 + + + + 结束 + + + + + + + + + + 0 + 0 + + + + 1 + + + 0 + + + Qt::AlignCenter + + + false + + + Qt::Vertical + + + false + + + %p% + + + + + + + 0 + + + Qt::Vertical + + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 30 + + + + 导出平面示意图 + + + + + + + false + + + + 100 + 30 + + + + + + + 导出三维结构 + + + + + + + false + + + + 0 + 30 + + + + 预览 + + + + + + + false + + + + 0 + 30 + + + + + + + 构建三维结构 + + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 0 + + + 12 + + + + + 地图画起点坐标 + + + + + + + 地图画尺寸 + + + + + + + Y + + + + + + + X + + + + + + + 总命令数 + + + + + + + Z + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + + + + + + + + + 200 + 30 + + + + QFrame::StyledPanel + + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + 1 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + -64 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + -64 + + + + + + + + + 0 + + + + + + 100 + 20 + + + + + 10 + + + + 完成 + + + + + + + 0 + + + + + 0 + + + -1 + + + Qt::Vertical + + + + + + + + + + 100 + 30 + + + + + 0 + 0 + + + + + 10 + + + + 导出 + + + + + + + + 0 + 30 + + + + + + + 构建三维结构 + + + + + + + + + + 0 + 0 + + + + + + + <html><head/><body><p align="justify">最后一步,导出为mcfunction!</p><p align="justify">如果你不想导出为投影文件,也可以使用mc自带的数据包。</p><p align="justify">导出的文件是一个mc中的“函数”,是数据包的一部分。</p><p align="justify">你可以在单机存档中使用/reload命令来加载它,用/function命令调用它。</p><p align="justify">如果地图画很大,超过了一个mcfunction的命令数,那么会将全部的命令分散在多个mcfuntion中。</p><p align="justify">在导出前,你需要指定地图画的起点坐标,它是xyz负方向的方块的坐标。</p><p align="justify">(如果不知道要放在哪里,请使用默认值-64,1,-64)</p></body></html> + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 16777215 + 60 + + + + + + + + + + + + + 0 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:6px; margin-bottom:6px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Microsoft YaHei UI'; font-size:9pt;">0</span></p></body></html> + + + + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + map_0.dat + + + Qt::AlignCenter + + + + + + + + 0 + 30 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + 1 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> + + + true + + + + + + + 0 + + + + + false + + + + 100 + 20 + + + + + 10 + + + + 完成 + + + + + + + 0 + + + + + 1 + + + 0 + + + Qt::Vertical + + + %p% + + + + + + + + + false + + + + 100 + 30 + + + + + 0 + 0 + + + + + 10 + + + + 导出 + + + + + + + + + 导出的文件名 + + + + + + + + 0 + 0 + + + + 地图文件起始序号 + + + + + + + 地图画行数 + + + + + + + 地图画列数 + + + + + + + 地图文件数量 + + + + + + + + + + + + 0 + 30 + + + + + + + 查看导出的文件 + + + + + + + true + + + + 0 + 30 + + + + + + + 联系作者 + + + + + + + + 0 + 30 + + + + + + + 退出 + + + + + + + + + + background-color: rgba(0, 0, 0, 48); + + + <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> + + + true + + + 20 + + + + + + + + + + + + + 0 + 0 + 960 + 27 + + + + + 关于 + + + + 联系作者 + + + - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - false - - - 导出为投影文件 - - - 导出为投影文件 - - - 导出为投影文件 - - - - - false - - - 导出为mcfunction - - - 导出为mcfunction - - - - - false - - - true - - - 导出为地图文件 - - - - - false - - - 关于SlopeCraft - - - - - 简体中文 - - - - - English - - - - - GitHub - - - - - BiliBili - - - - - 反馈Bug - - - - - false - - - 检查更新 - - - 检查更新 - - - 检查更新 - - - - - 开始 - - - - - 导入图片 - - - - - 地图画类型 - - - - - 方块列表 - - - - - 调整颜色 - - - - - 投影文件 - - - - - 结构文件 - - - - - 地图文件 - - - - - 完成 - - - - - false - - - 测试方块列表 - - - - - 设置导出参数 - - - - - 保存预设 - - - - - 加载预设 - - - - - GACvter参数 - - - GACvter参数 - - - GACvter参数 - - - - - 输出当前颜色表 - - - - - WE原理图 - - - - - 使用教程 - - + + + + + + + + + + + + + + + + Languages + + + + + + + 地图画 + + + + 导出为 + + + + + + + + + + + + + + + + + 高级 + + + + 批量操作 + + + + + + 方块列表预设 + + + + + + + + + + + + + + - - - AdaptiveLabel - QLabel -
AdaptiveLabel.h
-
-
- - isMapSurvival - isMapFlat - isGame16 - isBLSurvivalCheaper - isBLSurvivalBetter - isBLGlowing - isBLCustom - NextPage3 - FirstConcrete - FirstWool - FirstStainedGlass - scrollArea - isColorSpaceRGBOld - isColorSpaceHSV - isColorSpaceLab94 - isColorSpaceXYZ - FinishExLite - ExportLite - NWPosY - NWPosX - NWPosZ - FinishMcF - _ExportMcF - isBLCreative - NextPage2 - - - - - - - \ No newline at end of file + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + 转到页面 + + + + + false + + + 导出为投影文件 + + + 导出为投影文件 + + + 导出为投影文件 + + + + + false + + + 导出为mcfunction + + + 导出为mcfunction + + + + + false + + + true + + + 导出为地图文件 + + + + + false + + + 关于SlopeCraft + + + + + 简体中文 + + + + + English + + + + + GitHub + + + + + BiliBili + + + + + 反馈Bug + + + + + false + + + 检查更新 + + + 检查更新 + + + 检查更新 + + + + + 开始 + + + + + 导入图片 + + + + + 地图画类型 + + + + + 方块列表 + + + + + 调整颜色 + + + + + 投影文件 + + + + + 结构文件 + + + + + 地图文件 + + + + + 完成 + + + + + false + + + 测试方块列表 + + + + + 设置导出参数 + + + + + 保存预设 + + + + + 加载预设 + + + + + GACvter参数 + + + GACvter参数 + + + GACvter参数 + + + + + 输出当前颜色表 + + + + + WE原理图 + + + + + 使用教程 + + + + + + AdaptiveLabel + QLabel +
AdaptiveLabel.h
+
+
+ + isMapSurvival + isMapFlat + isGame16 + isBLSurvivalCheaper + isBLSurvivalBetter + isBLGlowing + isBLCustom + NextPage3 + FirstConcrete + FirstWool + FirstStainedGlass + scrollArea + isColorSpaceRGBOld + isColorSpaceHSV + isColorSpaceLab94 + isColorSpaceXYZ + FinishExLite + ExportLite + NWPosY + NWPosX + NWPosZ + FinishMcF + _ExportMcF + isBLCreative + NextPage2 + + + + + + + From 70ddab3287407006f745dc619ed736c391a87273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 26 Apr 2023 19:33:38 +0800 Subject: [PATCH 0241/1123] improve windployqt working with cpack --- cmake/deploy_qt.cmake.in | 6 +++--- cpack/make-packs.cmake | 10 ---------- cpack/pack_deployed_files.cmake.in | 29 ----------------------------- 3 files changed, 3 insertions(+), 42 deletions(-) delete mode 100644 cpack/pack_deployed_files.cmake.in diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index 2b8e22dd..c9880c88 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -1,10 +1,10 @@ -# This file is expected to be run during installation +# This file is expected to be run during installation and cpack packaging if(${WIN32}) message(STATUS "Running windeployqt for @AppName@ ...") execute_process( COMMAND "@SlopeCraft_Qt_windeployqt_executable@" "@AppName@.exe" - WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@" + WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) @@ -21,7 +21,7 @@ if(${APPLE}) message(STATUS "Running macdeployqt for @AppName@ ...") execute_process( COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" - WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@" + WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index db699340..2cc6c32f 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -11,16 +11,6 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) endif() -# set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-${SlopeCraft_GPU_API}) -if(${WIN32}) - configure_file(${CMAKE_SOURCE_DIR}/cpack/pack_deployed_files.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake - @ONLY) - list(APPEND CPACK_PRE_BUILD_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/pack_deployed_files.cmake) - - # set(CPACK_PACKAGE_FILES) -endif() - include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) include(CPack) \ No newline at end of file diff --git a/cpack/pack_deployed_files.cmake.in b/cpack/pack_deployed_files.cmake.in deleted file mode 100644 index 4ef13ea7..00000000 --- a/cpack/pack_deployed_files.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# This file is expected to be run during cpack - -# message(STATUS "Copying qt deployed files") - -set(SlopeCraft_pack_dest ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/${CPACK_SYSTEM_NAME}/${CPACK_GENERATOR}/${CPACK_PACKAGE_FILE_NAME}) - -message(STATUS "Copying deployed files to ${SlopeCraft_pack_dest}") - -file(GLOB deployed_dlls "@CMAKE_INSTALL_PREFIX@/*.dll") -file(COPY ${deployed_dlls} DESTINATION ${SlopeCraft_pack_dest}) - -function(SlopeCraft_glob_and_copy sub_dir_name pack_dest) - message(STATUS "Copying @CMAKE_INSTALL_PREFIX@/${sub_dir_name} to ${pack_dest}/${sub_dir_name}") - file(GLOB temp "@CMAKE_INSTALL_PREFIX@/${sub_dir_name}/*") - - file(COPY ${temp} DESTINATION ${pack_dest}/${sub_dir_name}) -endfunction(SlopeCraft_glob_and_copy) - -SlopeCraft_glob_and_copy(platforms ${SlopeCraft_pack_dest}) -SlopeCraft_glob_and_copy(imageformats ${SlopeCraft_pack_dest}) -SlopeCraft_glob_and_copy(styles ${SlopeCraft_pack_dest}) -SlopeCraft_glob_and_copy(tls ${SlopeCraft_pack_dest}) -SlopeCraft_glob_and_copy(translations ${SlopeCraft_pack_dest}) - -# message(STATUS "CPACK_PACKAGE_DIRECTORY = ${CPACK_PACKAGE_DIRECTORY}") - -# message(STATUS "CPACK_PACKAGE_INSTALL_DIRECTORY = ${CPACK_PACKAGE_INSTALL_DIRECTORY}") -# message(STATUS "CPACK_INSTALLED_DIRECTORIES = ${CPACK_INSTALLED_DIRECTORIES}") -# message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}") \ No newline at end of file From dcb7b9091138f8b9b052551dc1a812544ab7d129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 26 Apr 2023 19:34:03 +0800 Subject: [PATCH 0242/1123] link to Eigen by interface targets --- MapViewer/CMakeLists.txt | 6 +- SlopeCraftL/CMakeLists.txt | 5 +- SlopeCraftMain/CMakeLists.txt | 2 +- VisualCraftL/CMakeLists.txt | 1 - VisualCraftL/add_test_executables.cmake | 8 +- cmake/find_Eigen3.cmake | 78 +++---------------- tests/test_libSchem/CMakeLists.txt | 5 +- utilities/ColorManip/CMakeLists.txt | 1 - .../GAConverter/CMakeLists.txt | 5 +- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 5 +- utilities/MapImageCvter/CMakeLists.txt | 1 - utilities/Schem/CMakeLists.txt | 7 +- utilities/libSCGUI/CMakeLists.txt | 3 +- 13 files changed, 31 insertions(+), 96 deletions(-) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index d7c18f51..58e1491f 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.5) project(SlopeCraft_MapViewer VERSION ${SlopeCraft_version}) set(CMAKE_CXX_STANDARD 17) -include_directories(${SlopeCraft_Eigen3_include_dir}) - set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) @@ -61,12 +59,14 @@ qt_add_executable(MapViewer # qt_create_translation(MapViewer_qm_files ${CMAKE_SOURCE_DIR} ${MapViewer_ts_files}) find_package(OpenMP REQUIRED) +find_package(Eigen3 REQUIRED) target_link_libraries(MapViewer PRIVATE ZLIB::ZLIB Qt6::Widgets - OpenMP::OpenMP_CXX) + OpenMP::OpenMP_CXX + Eigen3::Eigen) set_target_properties(MapViewer PROPERTIES VERSION ${PROJECT_VERSION} diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index d8febe54..ec1d5368 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -6,6 +6,7 @@ include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) +find_package(Eigen3 REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -62,7 +63,6 @@ target_compile_features(SlopeCraftL PRIVATE cxx_std_20) target_include_directories(SlopeCraftL INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(SlopeCraftL PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} - ${SlopeCraft_Eigen3_include_dir} ${SlopeCraft_HeuristicFlow_include_dir} ${CMAKE_SOURCE_DIR} @@ -77,7 +77,8 @@ set(SlopeCraft_SCL_link_libs NBTWriter Schem MapImageCvter - fmt::fmt) + fmt::fmt + Eigen3::Eigen) # link to dependents target_link_libraries(SlopeCraftL PUBLIC ${SlopeCraft_SCL_link_libs}) diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt index 00ba59d4..49d753c5 100644 --- a/SlopeCraftMain/CMakeLists.txt +++ b/SlopeCraftMain/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5) project(SlopeCraft_Main VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) -include_directories(${SlopeCraft_Eigen3_include_dir} +include_directories( ${CMAKE_SOURCE_DIR}/SlopeCraftL ${CMAKE_SOURCE_DIR}/utilities/BlockListManager) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 9f6f19a9..64963f14 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -84,7 +84,6 @@ find_package(fmt 9.1.0 REQUIRED) set(VCL_include_dirs ${SlopeCraft_Nlohmann_json_include_dir} - ${SlopeCraft_Eigen3_include_dir} ${SlopeCraft_HeuristicFlow_include_dir} ${CMAKE_SOURCE_DIR}) target_include_directories(VisualCraftL PRIVATE ${VCL_include_dirs}) diff --git a/VisualCraftL/add_test_executables.cmake b/VisualCraftL/add_test_executables.cmake index f2525dc5..34827d25 100644 --- a/VisualCraftL/add_test_executables.cmake +++ b/VisualCraftL/add_test_executables.cmake @@ -27,8 +27,7 @@ add_executable(test_VCL_project_image tests/test_VCL_project_image.cpp) target_link_libraries(test_VCL_project_image PRIVATE VisualCraftL PNG::PNG) target_include_directories(test_VCL_project_image PRIVATE ${cli11_include_dir} - ${SlopeCraft_Nlohmann_json_include_dir} - ${SlopeCraft_Eigen3_include_dir}) + ${SlopeCraft_Nlohmann_json_include_dir}) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_project_image) # test showing model @@ -36,8 +35,7 @@ add_executable(test_VCL_model tests/test_VCL_model.cpp) target_link_libraries(test_VCL_model PRIVATE VisualCraftL) target_include_directories(test_VCL_model PRIVATE ${cli11_include_dir} - ${SlopeCraft_Nlohmann_json_include_dir} - ${SlopeCraft_Eigen3_include_dir}) + ${SlopeCraft_Nlohmann_json_include_dir}) # internal test for rotation add_executable(itest_VCL_rotate tests/itest_VCL_rotate.cpp) @@ -60,6 +58,4 @@ add_executable(test_VCL_version tests/test_VCL_version.cpp) target_link_libraries(test_VCL_version PRIVATE VisualCraftL) target_compile_features(test_VCL_version PRIVATE cxx_std_17) - - add_test(NAME test_VCL_version COMMAND test_VCL_version WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/cmake/find_Eigen3.cmake b/cmake/find_Eigen3.cmake index 1b79264e..703c1c14 100644 --- a/cmake/find_Eigen3.cmake +++ b/cmake/find_Eigen3.cmake @@ -1,74 +1,18 @@ set(SlopeCraft_Eigen3_found OFF) +find_package(Eigen3 3.4.0) -function (SlopeCraft_examine_Eigen3_include_dir) - if(NOT DEFINED SlopeCraft_Eigen3_include_dir) - set(SlopeCraft_Eigen3_found OFF) - - else() - # examine whether the input is valid - if(EXISTS ${SlopeCraft_Eigen3_include_dir}/Eigen/Dense) - # the assigned Eigen3_include_dir is valid. nothing to do. - message("The value of SlopeCraft_Eigen3_include_dir is valid. SlopeCraft will have access to Eigen3") - #set(SlopeCraft_download_Eigen340 OFF) - set(SlopeCraft_Eigen3_found ON) - - else() - message(WARNING - "The value of SlopeCraft_Eigen3_include_dir is invalid. Failed to find file : " - ${SlopeCraft_Eigen3_include_dir}/Eigen/Dense) - #set(SlopeCraft_download_Eigen340 ON) - set(SlopeCraft_Eigen3_found OFF) - endif() - endif() - -endfunction() - - -SlopeCraft_examine_Eigen3_include_dir() - - # try to find Eigen3 by find_package -if(NOT ${SlopeCraft_Eigen3_found}) - find_package(Eigen3 3.4) - - if(${EIGEN3_FOUND}) - message(STATUS "CMake have found an libEigen by find_package") - set(SlopeCraft_Eigen3_include_dir ${EIGEN3_INCLUDE_DIR}) - set(SlopeCraft_Eigen3_found ON) - endif() -endif() - - - -# try to find Eigen3 in the 3rdParty directory -if(NOT ${SlopeCraft_Eigen3_found}) - if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/eigen/Eigen/Dense) - message(STATUS "Found Eigen in 3rdParty/eigen") - set(SlopeCraft_Eigen3_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/eigen) - set(SlopeCraft_Eigen3_found ON) - endif() +if(${Eigen3_FOUND}) + message(STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}") + return() endif() +include(FetchContent) -if(NOT ${SlopeCraft_Eigen3_found}) - message(STATUS "Cloning Eigen...") - execute_process( - COMMAND git clone https://gitlab.com/libeigen/eigen.git - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty - COMMAND_ERROR_IS_FATAL ANY - ECHO_ERROR_VARIABLE - ECHO_OUTPUT_VARIABLE - ) +FetchContent_Declare(Eigen3 + GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git + GIT_TAG 3.4.0 + OVERRIDE_FIND_PACKAGE) - message(STATUS "Successfully cloned Eigen. Checking out to tag 3.4.0") - execute_process( - COMMAND git checkout 3.4.0 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty/eigen - COMMAND_ERROR_IS_FATAL ANY - ECHO_ERROR_VARIABLE - ECHO_OUTPUT_VARIABLE - ) - message(STATUS "Eigen v3.4.0 is ready") +FetchContent_MakeAvailable(Eigen3) - set(SlopeCraft_download_Eigen340 OFF) - set(SlopeCraft_Eigen3_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/eigen) -endif() \ No newline at end of file +find_package(Eigen3 3.4.0 REQUIRED) \ No newline at end of file diff --git a/tests/test_libSchem/CMakeLists.txt b/tests/test_libSchem/CMakeLists.txt index c57fc79b..c7640205 100644 --- a/tests/test_libSchem/CMakeLists.txt +++ b/tests/test_libSchem/CMakeLists.txt @@ -1,12 +1,11 @@ set(CMAKE_CXX_STANDARD 20) -include_directories(${SlopeCraft_Eigen3_include_dir}) include_directories(${CMAKE_SOURCE_DIR}/utilities) add_executable(test_libSchem - + test_libSchem.cpp) target_link_libraries(test_libSchem PRIVATE Schem NBTWriter -lz) -add_test(NAME test_libSchem +add_test(NAME test_libSchem COMMAND test_libSchem) \ No newline at end of file diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 7d9ea4b5..f910e4dc 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -30,7 +30,6 @@ target_compile_features(ColorManip PUBLIC cxx_std_20) # get_target_property(cm_cxx_std ColorManip CXX_STANDARD) # message(STATUS "cm_cxx_std = " ${cm_cxx_std}) target_include_directories(ColorManip PUBLIC - ${SlopeCraft_Eigen3_include_dir} ${CMAKE_SOURCE_DIR}/utilities) target_include_directories(ColorManip PRIVATE diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index 266e8e82..b35b04a1 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -18,12 +18,13 @@ set(SlopeCraft_GAConverter_sources add_library(GAConverter STATIC ${SlopeCraft_GAConverter_sources}) -target_include_directories(GAConverter PUBLIC ${SlopeCraft_Eigen3_include_dir} +target_include_directories(GAConverter PUBLIC ${SlopeCraft_HeuristicFlow_include_dir} ../../ColorManip ) -target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX) +find_package(Eigen3 REQUIRED) +target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen) target_compile_features(GAConverter PRIVATE cxx_std_20) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 88fbd647..ee8dfaf1 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -18,11 +18,12 @@ endif() # convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) add_resource_config_time(ColorManip_cl_rc ColorDiff.cl) -target_include_directories(OCLWrapper PRIVATE ${SlopeCraft_Eigen3_include_dir}) target_include_directories(OCLWrapper PUBLIC ${CMAKE_SOURCE_DIR}) target_include_directories(OCLWrapper INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_features(OCLWrapper PUBLIC cxx_std_20) -target_link_libraries(OCLWrapper PUBLIC OpenCL::OpenCL ColorManip_cl_rc) + +find_package(Eigen3 REQUIRED) +target_link_libraries(OCLWrapper PUBLIC OpenCL::OpenCL ColorManip_cl_rc Eigen3::Eigen) message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index 05ef30bd..2ade1a97 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -9,7 +9,6 @@ add_library(MapImageCvter target_include_directories(MapImageCvter PUBLIC ${CMAKE_SOURCE_DIR}/utilities - ${SlopeCraft_Eigen3_include_dir} ${SlopeCraft_HeuristicFlow_include_dir} ) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 10861aba..f13d2f6a 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -1,8 +1,6 @@ project(Schem VERSION ${SlopeCraft_version} LANGUAGES CXX) # set(CMAKE_CXX_STANDARD 20) - -# include_directories(${SlopeCraft_Eigen3_include_dir}) add_library(Schem Schem.h @@ -10,11 +8,10 @@ add_library(Schem Schem.cpp bit_shrink.h bit_shrink.cpp) - -target_include_directories(Schem PUBLIC ${SlopeCraft_Eigen3_include_dir}) +find_package(Eigen3 REQUIRED) # target_compile_options(Schem BEFORE PUBLIC -std=c++17) -target_link_libraries(Schem PUBLIC NBTWriter) +target_link_libraries(Schem PUBLIC NBTWriter Eigen3::Eigen) target_compile_features(Schem PRIVATE cxx_std_20) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) diff --git a/utilities/libSCGUI/CMakeLists.txt b/utilities/libSCGUI/CMakeLists.txt index 1124fbd8..8634c045 100644 --- a/utilities/libSCGUI/CMakeLists.txt +++ b/utilities/libSCGUI/CMakeLists.txt @@ -2,8 +2,7 @@ project(SlopeCraft_libSCGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) include_directories(${CMAKE_SOURCE_DIR}/utilities/libAbstractGUI - ${CMAKE_SOURCE_DIR}/SlopeCraftL - ${SlopeCraft_Eigen3_include_dir}) + ${CMAKE_SOURCE_DIR}/SlopeCraftL) add_library(SCGUI STATIC libSCGUI.h libSCGUI.cpp) From 20062372d7cd5c994acc0b9977a383ea98674468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 26 Apr 2023 19:34:23 +0800 Subject: [PATCH 0243/1123] improve deb dep list --- cpack/deb.cmake | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cpack/deb.cmake b/cpack/deb.cmake index f745966a..751415aa 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -9,7 +9,7 @@ if(${SlopeCraft_GPU_API} STREQUAL "OpenCL") ) endif() -set(depend_list +set(CPACK_DEBIAN_PACKAGE_DEPENDS "libzip4" "libpng16-16" "libqt6core6(>=6.2.4)" @@ -25,14 +25,7 @@ set(depend_list ${SlopeCraft_debian_opencl_deps} ) -unset(CPACK_DEBIAN_PACKAGE_DEPENDS) -foreach(depend ${depend_list}) - if(NOT DEFINED CPACK_DEBIAN_PACKAGE_DEPENDS) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${depend}") - else() - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},${depend}") - endif() -endforeach(depend ${depend_list}) +list(JOIN CPACK_DEBIAN_PACKAGE_DEPENDS "," CPACK_DEBIAN_PACKAGE_DEPENDS) message(STATUS "CPACK_DEBIAN_PACKAGE_DEPENDS = ${CPACK_DEBIAN_PACKAGE_DEPENDS}") From 05bfb35e7e16d4e991947594c9bb379394ec8349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 26 Apr 2023 19:41:36 +0800 Subject: [PATCH 0244/1123] fix build --- utilities/ColorManip/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index f910e4dc..4bc54764 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -5,6 +5,7 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) # include_directories(../SlopeCraftL) find_package(OpenMP REQUIRED) +find_package(Eigen3 REQUIRED) add_library(ColorManip @@ -35,7 +36,7 @@ target_include_directories(ColorManip PUBLIC target_include_directories(ColorManip PRIVATE ${SlopeCraft_HeuristicFlow_include_dir}) -target_link_libraries(ColorManip PUBLIC OpenMP::OpenMP_CXX) +target_link_libraries(ColorManip PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen) # target_compile_options(ColorManip BEFORE PUBLIC "-std=c++17") target_compile_options(ColorManip PRIVATE ${SlopeCraft_vectorize_flags}) From 850bc3565e37d19a80f1a3282845ebca69ce71dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 26 Apr 2023 20:21:15 +0800 Subject: [PATCH 0245/1123] change data dir --- utilities/VersionDialog/VersionDialog.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/utilities/VersionDialog/VersionDialog.cpp b/utilities/VersionDialog/VersionDialog.cpp index dbe5b3f1..39073c9b 100644 --- a/utilities/VersionDialog/VersionDialog.cpp +++ b/utilities/VersionDialog/VersionDialog.cpp @@ -156,9 +156,14 @@ void version_dialog_private_fun_when_network_finished( try { info = extract_latest_version(content_qba.data()); } catch (std::exception &e) { - const QString home_path = QDir::homePath(); +#if WIN32 + const QString home_path = QDir::homePath() + "/AppData/Local"; const QString data_dir_name = "SlopeCraft"; - QString data_dir = QDir::homePath() + "/" + data_dir_name; +#else + const QString home_path = QDir::homePath(); + const QString data_dir_name = ".SlopeCraft"; +#endif + QString data_dir = home_path + "/" + data_dir_name; QString log_file = data_dir.append("/UpdateCheckFailure.log"); { if (!QDir(data_dir).exists()) { From 66317e3220c491388913ca36c63fcefe14e793ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 2 May 2023 15:01:57 +0800 Subject: [PATCH 0246/1123] add new SC ui --- CMakeLists.txt | 4 +- SlopeCraft/CMakeLists.txt | 58 + SlopeCraft/SCWind.cpp | 14 + SlopeCraft/SCWind.h | 25 + SlopeCraft/SCWind.ui | 1175 +++++++++++++++++ SlopeCraft/install.cmake | 145 ++ SlopeCraft/main.cpp | 11 + {SlopeCraftMain => SlopeCraft}/others/BG3.png | Bin {SlopeCraftMain => SlopeCraft}/others/BG4.png | Bin .../others/BlockTextures.qrc | 0 .../others/MCStyledNumbers.png | Bin .../others/Pics.qrc | 0 .../others/Slope/block/grass_block.png | Bin .../others/Slope/block/waxed_cut_copper.png | Bin .../others/Slope/items/amethyst_shard.png | Bin .../others/Slope/items/book.png | Bin .../others/Slope/items/diamond.png | Bin .../others/Slope/items/iron_pickaxe.png | Bin .../others/Slope/items/map.png | Bin .../others/SlopeCraft.icns | Bin .../others/SlopeCraft.ico | Bin .../others/SlopeCraft.png | Bin .../others/SlopeCraft.rc.in | 0 .../others/SlopeCraftIconNew.icns | Bin .../others/SlopeCraftIconNew.ico | Bin .../others/SlopeCraftIconNew.png | Bin .../others/SlopeCraft_en_US.ts | 0 .../others/Transparent.png | Bin .../others/cheap.sc_preset_json | 0 .../others/cover_3D.png | Bin .../others/cover_Data.png | Bin .../others/cover_Flat.png | Bin .../others/elegant.sc_preset_json | 0 .../others/shiny.sc_preset_json | 0 .../others/vanilla.sc_preset_json | 0 35 files changed, 1431 insertions(+), 1 deletion(-) create mode 100644 SlopeCraft/CMakeLists.txt create mode 100644 SlopeCraft/SCWind.cpp create mode 100644 SlopeCraft/SCWind.h create mode 100644 SlopeCraft/SCWind.ui create mode 100644 SlopeCraft/install.cmake create mode 100644 SlopeCraft/main.cpp rename {SlopeCraftMain => SlopeCraft}/others/BG3.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/BG4.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/BlockTextures.qrc (100%) rename {SlopeCraftMain => SlopeCraft}/others/MCStyledNumbers.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Pics.qrc (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/block/grass_block.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/block/waxed_cut_copper.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/items/amethyst_shard.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/items/book.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/items/diamond.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/items/iron_pickaxe.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/Slope/items/map.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraft.icns (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraft.ico (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraft.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraft.rc.in (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraftIconNew.icns (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraftIconNew.ico (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraftIconNew.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/SlopeCraft_en_US.ts (100%) rename {SlopeCraftMain => SlopeCraft}/others/Transparent.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/cheap.sc_preset_json (100%) rename {SlopeCraftMain => SlopeCraft}/others/cover_3D.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/cover_Data.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/cover_Flat.png (100%) rename {SlopeCraftMain => SlopeCraft}/others/elegant.sc_preset_json (100%) rename {SlopeCraftMain => SlopeCraft}/others/shiny.sc_preset_json (100%) rename {SlopeCraftMain => SlopeCraft}/others/vanilla.sc_preset_json (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc98129c..4bcfa211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,9 @@ endif() add_subdirectory(utilities) add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) -add_subdirectory(SlopeCraftMain) + +# add_subdirectory(SlopeCraftMain) +add_subdirectory(SlopeCraft) add_subdirectory(MapViewer) add_subdirectory(tests) add_subdirectory(VisualCraftL) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt new file mode 100644 index 00000000..06f74806 --- /dev/null +++ b/SlopeCraft/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 3.5) +project(SlopeCraft_NewGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) + +set(SlopeCraft_headers + SCWind.h) +set(SlopeCraft_sources + SCWind.cpp + main.cpp) +set(SlopeCraft_uis + SCWind.ui) + +set(SlopeCraft_project_files + ${SlopeCraft_headers} + ${SlopeCraft_sources} + ${SlopeCraft_uis}) + +qt_add_executable(SlopeCraft + MANUAL_FINALIZATION + ${SlopeCraft_project_files}) + +target_link_libraries(SlopeCraft PRIVATE + Qt6::Core + Qt6::Widgets + Qt6::Network + SlopeCraftL + AdaptiveLabel + VersionDialog) + +set_target_properties(SlopeCraft PROPERTIES + VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns + MACOSX_BUNDLE_GUI_IDENTIFIER "com.github.ToKiNoBug.SlopeCraft" + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +qt_finalize_executable(SlopeCraft) + +if(${WIN32}) + add_custom_target(SC_create_symlink_SC + COMMAND mklink SlopeCraftL.dll "..\\SlopeCraftL\\SlopeCraftL.dll" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS SlopeCraftL + COMMENT "Create symlink to SlopeCraftL.dll for SlopeCraft.exe") + add_dependencies(SC_create_all_symlinks SC_create_symlink_SC) +endif() + +include(install.cmake) \ No newline at end of file diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp new file mode 100644 index 00000000..96a017ea --- /dev/null +++ b/SlopeCraft/SCWind.cpp @@ -0,0 +1,14 @@ +#include "SCWind.h" +#include "ui_SCWind.h" + +SCWind::SCWind(QWidget* parent) + : QMainWindow(parent), + ui(new Ui::SCWind), + kernel(SlopeCraft::SCL_createKernel()) { + this->ui->setupUi(this); +} + +SCWind::~SCWind() { + delete this->ui; + SlopeCraft::SCL_destroyKernel(this->kernel); +} \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h new file mode 100644 index 00000000..b53b899b --- /dev/null +++ b/SlopeCraft/SCWind.h @@ -0,0 +1,25 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_SCWIND_H +#define SLOPECRAFT_SLOPECRAFT_SCWIND_H + +#include +#include +#include + +class SCWind; + +namespace Ui { +class SCWind; +} + +class SCWind : public QMainWindow { + Q_OBJECT + public: + explicit SCWind(QWidget* parent = nullptr); + ~SCWind(); + + private: + Ui::SCWind* ui; + SlopeCraft::Kernel* kernel; +}; + +#endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui new file mode 100644 index 00000000..98051367 --- /dev/null +++ b/SlopeCraft/SCWind.ui @@ -0,0 +1,1175 @@ + + + SCWind + + + + 0 + 0 + 800 + 750 + + + + SlopeCraft + + + + + + + 0 + + + + 地图画配置 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 游戏版本 + + + + + + 1.12 + + + + + + + false + + + 1.20 + + + + + + + 1.17 + + + + + + + 1.18 + + + + + + + 1.15 + + + + + + + 1.14 + + + + + + + 1.16 + + + + + + + 1.13 + + + + + + + 1.19 + + + + + + + + + + 地图画类型 + + + + + + 立体地图画 + + + + + + + 平板地图画 + + + + + + + 纯文件地图画 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + true + + + + + 0 + 0 + 633 + 549 + + + + + + + + + + 方块列表预设 + + + + + + 加载预设 + + + + + + + 保存当前预设 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 可用方块数量: + + + + + + + 0 + + + + + Vanilla + + + + + + + Cheap + + + + + + + Elegant + + + + + + + Shiny + + + + + + + Custom + + + + + + + + + + + + 0 + + + + + 优先混凝土 + + + + + + + 优先羊毛 + + + + + + + 优先彩色玻璃 + + + + + + + + + + 导入图像并转化 + + + + + + + 500 + 400 + + + + QTabWidget::East + + + QTabWidget::Rounded + + + 0 + + + + 原图 + + + + + + + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + 1 + + + + + + + + + + + 转化后 + + + + + + + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + 1 + + + + + + + + + + + + + + + 0 + 0 + + + + 转化当前图像 + + + + + + + + 0 + 0 + + + + 全部转化 + + + + + + + 转化算法 + + + + + + 抖动 + + + + + + + Lab00 + + + + + + + Lab94 + + + + + + + RGB+ + + + + + + + RGB + + + + + + + XYZ + + + + + + + GACvter + + + + + + + + + + + 0 + 0 + + + + 保存转化后图像 + + + + + + + + 当前 + + + + + 全部 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 24 + + + + + + + 0 + + + 0 + + + + + 项目池 + + + Qt::AlignCenter + + + + + + + 删除 + + + + + + + 添加 + + + + + + + + + + + + + 导出 + + + + + + 0 + + + + + Litematica + + + true + + + + + + + 结构方块文件 + + + + + + + WE原理图 + + + + + + + 平面示意图 + + + + + + + 地图文件 + + + + + + + + + 24 + + + + + + + 0 + + + 0 + + + + + + + + 项目池 + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + 0 + + + + Litematica + + + + + + + + + 投影区域名称 + + + + + + + 投影名称 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 结构方块文件 + + + + + + 用结构空位替代空气 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + WE原理图 + + + + + + offset + + + + + + + + 0 + 0 + + + + + + + + WEOffset + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + 原理图名称 + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + 依赖mod名称 + + + + + + + + 0 + 0 + + + + + + + + + 平面示意图 + + + + + + 方块 + + + 间距: + + + + + + + 垂直分割线 + + + + + + + 方块 + + + 间距: + + + + + + + 水平分割线 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 压缩高度 + + + + + + 有损压缩 + + + + + + + 无损压缩 + + + + + + + + + + 最大允许高度: + + + 14 + + + 32767 + + + 256 + + + + + + + + + + 预览 + + + + + + 预览材料表 + + + + + + + 预览压缩效果 + + + + + + + 预构建三维结构 + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + + + + + + + + 搭桥 + + + + + + 允许搭桥 + + + + + + + + + + 搭桥间隔: + + + + + + + + + + 全部导出 + + + + + + + 大小与方块数量 + + + + + + 大小: + + + + + + + 方块数量: + + + + + + + + + + 其他选项 + + + + + + 防火 + + + + + + + 防末影人 + + + + + + + + + + + + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 导出 + + + + + + + + + + + + 0 + + + + + 地图画起始序号: + + + + + + + 设置导出文件夹 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + 0 + 0 + 800 + 22 + + + + + 语言 + + + + + 高级 + + + + + 关于 + + + + + + + + + + + diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake new file mode 100644 index 00000000..5daa80a9 --- /dev/null +++ b/SlopeCraft/install.cmake @@ -0,0 +1,145 @@ + +file(GLOB SlopeCraft_install_jsons + "${CMAKE_SOURCE_DIR}/Blocks/*.json" + "${CMAKE_SOURCE_DIR}/Blocks/*.md") + +file(GLOB SlopeCraft_install_png_fixedblocks + "${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks/*.png") + +file(GLOB SlopeCraft_install_png_customblocks + "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") + +file(GLOB SlopeCraft_install_presets + "${CMAKE_CURRENT_SOURCE_DIR}/others/*.sc_preset_json") + +set(AppName SlopeCraft) +configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake + @ONLY) + +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + # Install for macOS + # Install app + install(TARGETS SlopeCraft + RUNTIME DESTINATION . + BUNDLE DESTINATION . + ) + + # Install icons + file(GLOB SlopeCraft_Icon + ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.icns) + install(FILES ${SlopeCraft_Icon} + DESTINATION SlopeCraft.app/Contents/Resources) + + # Install FixedBlocks.json, CustomBlocks.json and README.md + install(FILES ${SlopeCraft_install_jsons} + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks) + file(COPY ${SlopeCraft_install_jsons} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks) + + # Install all png files of fixedblocks + install(FILES ${SlopeCraft_install_png_fixedblocks} + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) + file(COPY ${SlopeCraft_install_png_fixedblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) + + # Install all png files of customblocks + install(FILES ${SlopeCraft_install_png_customblocks} + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) + file(COPY ${SlopeCraft_install_png_customblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) + + # Install presets + install(FILES ${SlopeCraft_install_presets} + DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/Presets) + file(COPY ${SlopeCraft_install_presets} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) + return() +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Windows") + # Install app + install(TARGETS SlopeCraft + RUNTIME DESTINATION . + ) + + # Run windeployqt at build time + add_custom_target(Windeployqt-SlopeCraft ALL + COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS SlopeCraft) + + # Run windeployqt at install time + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + + # Install FixedBlocks.json, CustomBlocks.json and README.md + install(FILES ${SlopeCraft_install_jsons} + DESTINATION Blocks) + file(COPY ${SlopeCraft_install_jsons} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) + + # Install all png files of fixedblocks + install(FILES ${SlopeCraft_install_png_fixedblocks} + DESTINATION Blocks/FixedBlocks) + file(COPY ${SlopeCraft_install_png_fixedblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) + + # Install all png files of customblocks + install(FILES ${SlopeCraft_install_png_customblocks} + DESTINATION Blocks/CustomBlocks) + file(COPY ${SlopeCraft_install_png_customblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) + + # Install presets + install(FILES ${SlopeCraft_install_presets} + DESTINATION Blocks/Presets) + file(COPY ${SlopeCraft_install_presets} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) + + return() +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + # set_target_properties(SlopeCraft PROPERTIES INSTALL_RPATH "../lib") + # Install for Linux + # Install app + install(TARGETS SlopeCraft + RUNTIME DESTINATION bin + ) + + # Install FixedBlocks.json, CustomBlocks.json and README.md + install(FILES ${SlopeCraft_install_jsons} + DESTINATION bin/Blocks) + file(COPY ${SlopeCraft_install_jsons} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) + + # Install all png files of fixedblocks + install(FILES ${SlopeCraft_install_png_fixedblocks} + DESTINATION bin/Blocks/FixedBlocks) + file(COPY ${SlopeCraft_install_png_fixedblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) + + # Install all png files of customblocks + install(FILES ${SlopeCraft_install_png_customblocks} + DESTINATION bin/Blocks/CustomBlocks) + file(COPY ${SlopeCraft_install_png_customblocks} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) + + file(GLOB SlopeCraft_Icon ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.png) + + install(FILES ${SlopeCraft_Icon} + DESTINATION bin/icons) + + # Install presets + install(FILES ${SlopeCraft_install_presets} + DESTINATION bin/Blocks/Presets) + file(COPY ${SlopeCraft_install_presets} + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) + + # Install platforms and imageformats plugins + include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) + + return() +endif() + +message(WARNING "No rule to install SlopeCraft and images, because the system is not Windows, linux or MacOS.") diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp new file mode 100644 index 00000000..11d196b0 --- /dev/null +++ b/SlopeCraft/main.cpp @@ -0,0 +1,11 @@ +#include +#include "SCWind.h" +int main(int argc, char** argv) { + QApplication qapp(argc, argv); + + SCWind wind; + + wind.show(); + + return qapp.exec(); +} \ No newline at end of file diff --git a/SlopeCraftMain/others/BG3.png b/SlopeCraft/others/BG3.png similarity index 100% rename from SlopeCraftMain/others/BG3.png rename to SlopeCraft/others/BG3.png diff --git a/SlopeCraftMain/others/BG4.png b/SlopeCraft/others/BG4.png similarity index 100% rename from SlopeCraftMain/others/BG4.png rename to SlopeCraft/others/BG4.png diff --git a/SlopeCraftMain/others/BlockTextures.qrc b/SlopeCraft/others/BlockTextures.qrc similarity index 100% rename from SlopeCraftMain/others/BlockTextures.qrc rename to SlopeCraft/others/BlockTextures.qrc diff --git a/SlopeCraftMain/others/MCStyledNumbers.png b/SlopeCraft/others/MCStyledNumbers.png similarity index 100% rename from SlopeCraftMain/others/MCStyledNumbers.png rename to SlopeCraft/others/MCStyledNumbers.png diff --git a/SlopeCraftMain/others/Pics.qrc b/SlopeCraft/others/Pics.qrc similarity index 100% rename from SlopeCraftMain/others/Pics.qrc rename to SlopeCraft/others/Pics.qrc diff --git a/SlopeCraftMain/others/Slope/block/grass_block.png b/SlopeCraft/others/Slope/block/grass_block.png similarity index 100% rename from SlopeCraftMain/others/Slope/block/grass_block.png rename to SlopeCraft/others/Slope/block/grass_block.png diff --git a/SlopeCraftMain/others/Slope/block/waxed_cut_copper.png b/SlopeCraft/others/Slope/block/waxed_cut_copper.png similarity index 100% rename from SlopeCraftMain/others/Slope/block/waxed_cut_copper.png rename to SlopeCraft/others/Slope/block/waxed_cut_copper.png diff --git a/SlopeCraftMain/others/Slope/items/amethyst_shard.png b/SlopeCraft/others/Slope/items/amethyst_shard.png similarity index 100% rename from SlopeCraftMain/others/Slope/items/amethyst_shard.png rename to SlopeCraft/others/Slope/items/amethyst_shard.png diff --git a/SlopeCraftMain/others/Slope/items/book.png b/SlopeCraft/others/Slope/items/book.png similarity index 100% rename from SlopeCraftMain/others/Slope/items/book.png rename to SlopeCraft/others/Slope/items/book.png diff --git a/SlopeCraftMain/others/Slope/items/diamond.png b/SlopeCraft/others/Slope/items/diamond.png similarity index 100% rename from SlopeCraftMain/others/Slope/items/diamond.png rename to SlopeCraft/others/Slope/items/diamond.png diff --git a/SlopeCraftMain/others/Slope/items/iron_pickaxe.png b/SlopeCraft/others/Slope/items/iron_pickaxe.png similarity index 100% rename from SlopeCraftMain/others/Slope/items/iron_pickaxe.png rename to SlopeCraft/others/Slope/items/iron_pickaxe.png diff --git a/SlopeCraftMain/others/Slope/items/map.png b/SlopeCraft/others/Slope/items/map.png similarity index 100% rename from SlopeCraftMain/others/Slope/items/map.png rename to SlopeCraft/others/Slope/items/map.png diff --git a/SlopeCraftMain/others/SlopeCraft.icns b/SlopeCraft/others/SlopeCraft.icns similarity index 100% rename from SlopeCraftMain/others/SlopeCraft.icns rename to SlopeCraft/others/SlopeCraft.icns diff --git a/SlopeCraftMain/others/SlopeCraft.ico b/SlopeCraft/others/SlopeCraft.ico similarity index 100% rename from SlopeCraftMain/others/SlopeCraft.ico rename to SlopeCraft/others/SlopeCraft.ico diff --git a/SlopeCraftMain/others/SlopeCraft.png b/SlopeCraft/others/SlopeCraft.png similarity index 100% rename from SlopeCraftMain/others/SlopeCraft.png rename to SlopeCraft/others/SlopeCraft.png diff --git a/SlopeCraftMain/others/SlopeCraft.rc.in b/SlopeCraft/others/SlopeCraft.rc.in similarity index 100% rename from SlopeCraftMain/others/SlopeCraft.rc.in rename to SlopeCraft/others/SlopeCraft.rc.in diff --git a/SlopeCraftMain/others/SlopeCraftIconNew.icns b/SlopeCraft/others/SlopeCraftIconNew.icns similarity index 100% rename from SlopeCraftMain/others/SlopeCraftIconNew.icns rename to SlopeCraft/others/SlopeCraftIconNew.icns diff --git a/SlopeCraftMain/others/SlopeCraftIconNew.ico b/SlopeCraft/others/SlopeCraftIconNew.ico similarity index 100% rename from SlopeCraftMain/others/SlopeCraftIconNew.ico rename to SlopeCraft/others/SlopeCraftIconNew.ico diff --git a/SlopeCraftMain/others/SlopeCraftIconNew.png b/SlopeCraft/others/SlopeCraftIconNew.png similarity index 100% rename from SlopeCraftMain/others/SlopeCraftIconNew.png rename to SlopeCraft/others/SlopeCraftIconNew.png diff --git a/SlopeCraftMain/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts similarity index 100% rename from SlopeCraftMain/others/SlopeCraft_en_US.ts rename to SlopeCraft/others/SlopeCraft_en_US.ts diff --git a/SlopeCraftMain/others/Transparent.png b/SlopeCraft/others/Transparent.png similarity index 100% rename from SlopeCraftMain/others/Transparent.png rename to SlopeCraft/others/Transparent.png diff --git a/SlopeCraftMain/others/cheap.sc_preset_json b/SlopeCraft/others/cheap.sc_preset_json similarity index 100% rename from SlopeCraftMain/others/cheap.sc_preset_json rename to SlopeCraft/others/cheap.sc_preset_json diff --git a/SlopeCraftMain/others/cover_3D.png b/SlopeCraft/others/cover_3D.png similarity index 100% rename from SlopeCraftMain/others/cover_3D.png rename to SlopeCraft/others/cover_3D.png diff --git a/SlopeCraftMain/others/cover_Data.png b/SlopeCraft/others/cover_Data.png similarity index 100% rename from SlopeCraftMain/others/cover_Data.png rename to SlopeCraft/others/cover_Data.png diff --git a/SlopeCraftMain/others/cover_Flat.png b/SlopeCraft/others/cover_Flat.png similarity index 100% rename from SlopeCraftMain/others/cover_Flat.png rename to SlopeCraft/others/cover_Flat.png diff --git a/SlopeCraftMain/others/elegant.sc_preset_json b/SlopeCraft/others/elegant.sc_preset_json similarity index 100% rename from SlopeCraftMain/others/elegant.sc_preset_json rename to SlopeCraft/others/elegant.sc_preset_json diff --git a/SlopeCraftMain/others/shiny.sc_preset_json b/SlopeCraft/others/shiny.sc_preset_json similarity index 100% rename from SlopeCraftMain/others/shiny.sc_preset_json rename to SlopeCraft/others/shiny.sc_preset_json diff --git a/SlopeCraftMain/others/vanilla.sc_preset_json b/SlopeCraft/others/vanilla.sc_preset_json similarity index 100% rename from SlopeCraftMain/others/vanilla.sc_preset_json rename to SlopeCraft/others/vanilla.sc_preset_json From 2169f19f1b6a17c7eee12c2e9a4464506857f482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 2 May 2023 15:09:43 +0800 Subject: [PATCH 0247/1123] add rc --- SlopeCraft/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 06f74806..95e9c244 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -9,11 +9,19 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) +set(SlopeCraft_rc_files) + +if(${WIN32}) + configure_file(others/SlopeCraft.rc.in ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.rc) + set(SlopeCraft_rc_files ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.rc) +endif() + set(SlopeCraft_headers SCWind.h) set(SlopeCraft_sources SCWind.cpp - main.cpp) + main.cpp + ${SlopeCraft_rc_files}) set(SlopeCraft_uis SCWind.ui) From b572040fb7344c94270bd8445079cc424e201454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 2 May 2023 15:09:55 +0800 Subject: [PATCH 0248/1123] remove redundant files --- SlopeCraft/install.cmake | 2 +- SlopeCraft/others/BG3.png | Bin 59770 -> 0 bytes SlopeCraft/others/BG4.png | Bin 679944 -> 0 bytes SlopeCraft/others/BlockTextures.qrc | 11 ----------- SlopeCraft/others/Pics.qrc | 11 ----------- SlopeCraft/others/Slope/block/grass_block.png | Bin 695 -> 0 bytes .../others/Slope/block/waxed_cut_copper.png | Bin 417 -> 0 bytes .../others/Slope/items/amethyst_shard.png | Bin 199 -> 0 bytes SlopeCraft/others/Slope/items/book.png | Bin 212 -> 0 bytes SlopeCraft/others/Slope/items/diamond.png | Bin 227 -> 0 bytes SlopeCraft/others/Slope/items/iron_pickaxe.png | Bin 187 -> 0 bytes SlopeCraft/others/Slope/items/map.png | Bin 177 -> 0 bytes SlopeCraft/others/Transparent.png | Bin 1613 -> 0 bytes SlopeCraft/others/cover_3D.png | Bin 95364 -> 0 bytes SlopeCraft/others/cover_Data.png | Bin 52986 -> 0 bytes SlopeCraft/others/cover_Flat.png | Bin 117339 -> 0 bytes .../others/{ => presets}/cheap.sc_preset_json | 0 .../{ => presets}/elegant.sc_preset_json | 0 .../others/{ => presets}/shiny.sc_preset_json | 0 .../{ => presets}/vanilla.sc_preset_json | 0 20 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 SlopeCraft/others/BG3.png delete mode 100644 SlopeCraft/others/BG4.png delete mode 100644 SlopeCraft/others/BlockTextures.qrc delete mode 100644 SlopeCraft/others/Pics.qrc delete mode 100644 SlopeCraft/others/Slope/block/grass_block.png delete mode 100644 SlopeCraft/others/Slope/block/waxed_cut_copper.png delete mode 100644 SlopeCraft/others/Slope/items/amethyst_shard.png delete mode 100644 SlopeCraft/others/Slope/items/book.png delete mode 100644 SlopeCraft/others/Slope/items/diamond.png delete mode 100644 SlopeCraft/others/Slope/items/iron_pickaxe.png delete mode 100644 SlopeCraft/others/Slope/items/map.png delete mode 100644 SlopeCraft/others/Transparent.png delete mode 100644 SlopeCraft/others/cover_3D.png delete mode 100644 SlopeCraft/others/cover_Data.png delete mode 100644 SlopeCraft/others/cover_Flat.png rename SlopeCraft/others/{ => presets}/cheap.sc_preset_json (100%) rename SlopeCraft/others/{ => presets}/elegant.sc_preset_json (100%) rename SlopeCraft/others/{ => presets}/shiny.sc_preset_json (100%) rename SlopeCraft/others/{ => presets}/vanilla.sc_preset_json (100%) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 5daa80a9..aa7497be 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -10,7 +10,7 @@ file(GLOB SlopeCraft_install_png_customblocks "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") file(GLOB SlopeCraft_install_presets - "${CMAKE_CURRENT_SOURCE_DIR}/others/*.sc_preset_json") + "${CMAKE_CURRENT_SOURCE_DIR}/others/presets/*.sc_preset_json") set(AppName SlopeCraft) configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in diff --git a/SlopeCraft/others/BG3.png b/SlopeCraft/others/BG3.png deleted file mode 100644 index fdab448a76c600abcbab73b859805334d2b615aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59770 zcmV(*K;FNJP)Tc3nVPefmaS)Sj)%nRg1hB}h@&w( zSDex8jfRt}OmL!~v!u)CxWC!QyvUu`@<3RChL^j#$m6Z&`hj?by0XELlB*nC;YhH4c(C;QhcN_bMZU6x2P)S5VRCwCVy^C)0NY|!q1-r3%Mp(ugqlh80 zQG!gj2S|4e?}rj`{%19{wzbMO&!)TIU%w%Q5RwqMxYxE;MfJ}e37+M1!Y8_LN1T;q z_gYoe>9k+Dqj1N@9IMr-s>(8}WBeI7|2K~H-~%q~*?+?waU7Rr`RpDtJmAd_j-ptt z_NPIerfxiMyWU45cCn&nx~r_*A+lbA^9co>2G2>h#>X7b~XUm+<93;!MtR8dA0% z^5?&C1vcUsXmF3&J>bn_0#knZ;Ym9=WL_D(^6M*h{}3IHGr;ev4+j6jl@X*f-VuJV ze02=E*V-Wn3_1$&ZEK&gbQ97yucfNG#=g@-zmwCIc}{ z>brb_?*n)wuN}Uf@K0@4{{4&}j=;)23HY$-H~bR_?+>v2z5=d2x*$*P`HX?UlO-@6 zkk3lAa+P`r{FKI78{@7nN>h5)Wq zNA@gms{w%^D=IMXG829k%b((h3JC0w20pX+A%5_6yn|3QySPA68tI!9R}Z6md-SpxC$j`v9Np;=aqBnfo?48ND*)!MA|*-XU> zI}NM{@clgq*974jNu(?Es^3-U?)2S2{z4;s1sqEE`k(aCrUL|x9bAzFo}S@Vviv2i zb!2_l!g^w4ka)kc3KD{RyaI@h0elmLk0A~5D+*(JS0^~1fH~ATMi9SA_>sf_TP%N> z(uV}bB^Y5R8mPnFGttNPSGbFrIHE5e7+-KGI^l09e;f0(A%1_H@G+kLKn46m6tE@& z>pa(sB+uC}!xfZ7l)GGIP~h~BCadA?1PZtk2@GFG_fYoLGwS=u4A;M;e0LAwJ+W;0 z`>gMY=Roe|xljpA@F{#ADqy-9cw^$o0)Z7NpjzG}z9#m!u04u!vvP<8)?m25VzS}{ zA-;9JCpw{i1u3BQ?%2c{1tc!%G{CP!PZik{35)4{0DrrC75qx~O0tcLz2Bcq`F>7B z>qq+cJO2;vY5hYz0(n!2^<@*B*As@96;HfD(#YUmbp2k7L->`UKlRKucta=ulBVzi zIybOn|27HWtA9=WJcjFOx6m`W_9$4x%mD)UWaI@Ff$?MX41Xj)_@cg&OvDHj3!Gza ztzPHVeDdBXK`1dvO(6-(;VZs%SC0Z9^5P5gQmzy`dP&g%JbCjg#+UJ9S;MzJx^v(( z@t^KIe!x^5lk|BR45Co0gPD8tt~NIONX7c51MiO>(`v*Yn&4bCP`yB>ZN?`=y~`)# z;#?kLCULMhf!43r$FqkQFZNM1ai|Q||G)#BB6U5))~n)`Z?C}%4Amz!3P`SWAb}K6 zn!s00?3z(b)+PW7v@l^6Oa#H217r6X)Ci|j^5>pS;{clI17A<}04W6C(;LO$2dLp+ zOJaTEnL$=yGQOENzv5aYu?n7nj|4P!@0(En*!-sY$VvYG@Gf6?JYx_-rq=5mT;#d9 zc`SChT+4tpxv|!7kQ3Nx9)<+42ow+lkq!fq3Ha{+Ec?P(+B{1jj1#wFAPinKs81NQ zn?y*u@lmikf#mzKT^*QTzT)jX2PSNYuOWvus&EOesPZ?+zCifv;}4L(JWP#n!qW`zw1m@R7A0U5!tmskiC+QOfWPgu+ zKovfqG7&J<_+}72WsG2LoxnPypdOx+l^_`SRcM6S4O9^{QOGYF`nG9a7`?Rz@U2&=mm}yuweYW z0E+mT1LbdTk{u_5Una>HgpZ$hVUQ8TJ4uGZWPBfI0G-p1@kjbd|2SsSSOIgJ z3e0Wzk!y&O@Lj;v#-$?YWzxw!n_zt+HZ~I8h!J+LUlxyyaBU*u`XAWcd*J>hLlC_p zX)-#4_suDYn$m|7h|ij{YhQJ2Y_DpbHO3|gNrI4AQ!`gZ5NzSA^F%iz^(({y^vS)w zCis-U(>}z{0Z9CTRpsnU5_mrB<^h`-pRD@%yvt7Q=KJ|b4y|Cc_LKaGAl@f_0kY@^^H1>+S^$;*94 z+Bty0UkMjkW};zANtP97bq#@og2IaO(XlP0cvtW)R@pOn{{=a`ep1+?_#wW^=Or!L@ECRNa^bU>;)I%k3t zfv3GCuo%?1-21cYl)#Y{wkml4`$gmRk4(0=!9ZZ;oxp(|-VC17J^6rWf~}(Y1mIOs zGXeM780%|z-Iruet1$Fn27Lm0+5itKa9FXHYK>Mu#x9R%PyjXfCEuz2Qq}8Z_!~yQ zntchQk7vUjepIZ020?#Tvm8|9Q2*%2LQjw~(O3;$4K%PAmh|E2AuCKz$lX3GVSJo$ ze0)#-8wV&LJe`;W!Pk2NL3!vRfS@j4HCKO=fh#yw81&z}PUt0TpqgM+K!T4Pz(OM6 zF@DDXBSVcH6P$e^A20O&25kmO&~A{_-|aoXBuGi^2VVa;`Ruhj%txA|8i*hzqLsO^ zDIVYl1rO(a;)!GTjO7t)AvO;);Rw>}xW~qrGVEsn-a^F-zxpq=&%jIn1^EOnhM>bW zECdI&U}zc%qToq)^Q!T&3B9j@?3q$A=`fq%&;o<^H&DQ_{++o0L)}zNRf3~lS`TpI zR1c!wAK=FohmQD5zpsCPV8csbf2$KTAGvt{`GkEy5(VcLK9#>I&yW<*@ka={FIfaL z3{T3}A%L5K2*R`J9zyq84&RtiQ~|XM>Lf|ny!G$vAiOrvokI0s^tm>Z6|q8GK+FS* z2_D;38(~=CTaPp{co(PwrndNN(=V&lr2Q2EEbM!Pn+kwFlk&0}Xp+s7q8Cq^Ur0V@ z_)Zc18+m_)x4-)Vegqv5QepeoX{><3=Q{UkLB5iqr{^p!ly67`9d`~s69!kO&?g4N zP!!(26&R&;Rs%y0iMzX8zq2+zDwX_0ZN##?)Pu>06^fvizH z159s&k`!=Yf^Gh9rOhv62N2~C^qX47sQZ9ko46jEU=xER_3*3jn%@i_C%AtsfazrO z0qEa;WP$~|%E@5$%#s+X{N;fe4w5ro1T*U4=?sG831(q2Zs-THdDB?33f;gk6v-LA z+A1JbO72r0Vg1icFc=l?3gkD;z#U9Q0skPU`niH2YRK00dzghx4sMC5Gx2#}Y;4+* z@hgV*cL*Ro#~bNZAo~I@OpFD%dWt>UWf1s(-^u@FSZwIvVS4?0n~r`Z9cisEb{#_N z*>lBTYY<`ytV5^J$0Fhdf(0%SKeoeYhOt1R5{S=>#Sq@d*igyuQg<)bz=Yen@-PI! z&#HhXRM9-m{TBZF+l=plAeZgM9st7>XkRdELU)%_#@-GZ8R# zpszGl&P9;eIf2^vGK4P~(f8wnvoHIN=wGVwN1FPU#SM2~h4P1*$0is&L10jVkl_(V zB!L2E6b2)H(7;FtQf&_118wrQ)k%IuNeT;*Kz0K?f;Hy>;VZ9)`Lx8<|CSY&Kp1TT zJ>>mrWwJ+DkCRpe5pb5kbOS;*skYM86dTN@*(c7xZ3P0X$g;P_r)708VO1F5o`O@;uA)Nel!1!?Wrf64*f- zV}}VRK#+QDQ35N;&|4MUsD;Cxk_vv*boyX>p-@JJ}y`RYV4b%_Q9~7t) zdE?f5DVO^NAJ+RL!%GlWg5PQtJ>V}7&9HoxQ6d`5ulq;g+@S;#f~1bv-)&L^p(&OE zAsLEV7nx{ADwj~iY9Ww7oP56`i?Za?yF9w)f`{E$c;6-mhU-AR-qgS>%VU$D;VCv&v)2yKx7+n%@(wYYg z;Iny(L6IV5PmV`|$e3Caj2hT+*%1{GvXmXYk}89PcuhKrDq5#mTVJHU=d~K+I|<;O zbAt@xpl_x&m%kpB#Nq_jv|19)13x(&2Z!*z$6MOYjSY4Z*dKc}!^#f0+1t^WtaaZ{u5Fyt7dG z0*HDKDt`cAZU{6CX0^RS;)gmYErD1NCRecI20>~-Llx9Og=KPp;E5E_d5>8(VGi!J zNZDVS5e-Q&ui+kMt_KQ8H{844sob#nAD7#}+TQNiKo~-cBXqimGk}MAYAvvP+i#lr zTy5}c8TZY6cc9;uBwzc}+sppf?J%bSpZDPsfWq>(nx-#+51b)PEW}wI*Cyxk%Nb|s zu;c0$HrcHTZw7{I-@*W7wI8~Gr;|kx<*(R?oT>s&C}C!$kex$kma|$lkPzgy1QNm0 z5J;BT38fn3Qx!aCrG_DSey<1XOyv0^lkD@<9>C@R)so@zl95Gjw)5-`KbM$$;(}|) zoge1Md5NpUO0qQ^f;8^-DD(mQCORJR>E9I239JtNe7lS4HM)`RX@7frSy6k{PY2+5 z#u#MJnqW(D4**=T_ow7}{4y$kJa+SvpQF#1U(`Q&aOv3j+fbp^Mk`3&aT zoxi@<4w1gTo4$@=bc`R_d_F(+fJxYnj@iHRbePY#$Er>+!wIXZ@IAU|`lF*QN;M7h zmLB@UcDtq9iqos(uZgzX^R{&Q8bb)`{PUMIS=T=&f|7(m2eeZcP}6{80pvC3+L`a^ z!#BEwA3=PZi~`^v(wAebDZR&?dq%|kS~ob|4C3F7@7W$ppiP8qNdJCM#Rtr$AhZgY z8BZ{yHwOaNG#xTlYMXw^3Wz~5GYH1|)kGy8Kzz$)_=a;VH4Dd8Fki8EUna~*m1u~rH_owr=N^n^ruc8Og5PP_Azoj9c$5~s34c{0J^OY04 zebXI|bNA=K@!K8TT|1CZLhzWDU$2`NtP(g4EIGbNYzt#;(~~iqUuuQvd@GD9pa3}3 zKPh=YdJD%2b;kSqHRa3ws>VEsKcuOIGV;=pF)_3i@GDFSPRAAcH%-CIRW{+U3^liP#Yln>%8vjEipI z>4DH8Q0`kGrN_N{R8H;o4z}YQ-w^=dao#z>>r&+Hi2pSFqH4RtP&tA)d;9Ds^}M`P z&I-q(g307W&f2evdOj7K!5k0+;C?uJ7Xj=r^(W)6>R(MX=L6p_=lEBPAC>P3N;it1 zUAes4SO<_N)a?Ce3|iexvNuGKRdo|(YJ=S+e7>%wmymQo1 zURoi%mj@+`M9y75yN8Jt4;NPyPUs+zQK{P=TX>u7N!&o~B1lNjce|o2d#7_Cqll{u zP*xoR2*C;(>&=U<(|LQTCK@3ugmog*F)~?@B(HE`_%lOz_mc`JLv?>i{&fD2S#t(2 zR-V;nWyPL@R$HM-gPBRT1)951Cl)oJ1R{IEtRTFIL;&p}?9sP!>mdq|4Qf@S7pxV= z5@$AM77Z*_0~tW@Us|xh6e(=qpPsh6r+4?^1m+%?3I7!0oArSH8OR_9Fmp)fW%uCO z?wdU*;2a=<`v8dUYJ=W&-&c(jwIfm%5r9XstzFk6Sz98@{p9)FlwEY*@&S_SL_gXA zqe!^B_$r@Xuvh8jEq!_4Bteb34r7p7+`u~aE8+$Ypp@IVp1KdZDNzCaqMTpDPlryC z`eiJE__@TEIvO`W7#o|0Lz8U!1t024UB7T3Mj`RaX!g4*Aj%)>pC>YxuL1=`13aXU z&Q6M&E~8RNJwy;2rc2BRLL4k%a0j6T1(WXccK7ZgQqY;FZC@w(crqqi;5nIAr3V*O`cl4K01hdQ6(~CF5n>g&ssqGvvpOVCB^(S7DWQ%apvQeqk2mpLm104T^ z`WaCQ3*(((?M=WSb&;?+YpP#i(d#gGq}HJI!me+$(NJbn0Z5ksf5S_kjn8Z$S* z)sZ!7OCr3Rcka7bn)z}ONYx-RAaHYxDp0*#+!5_DH?Bgr6_VY5aE{7s<=zM?g6@Qo z)&XD?;6VG5^FCMj&E>D?go!*J6sH?WjvpB(P8b zE6qP=KOc4sPZ=vhv0eC>8m&TMX<&hPN5op)(p))EV6wth#eMx-c$&tS&}G-4|`KhSFo z*LTjXqcNG`CKB!{#}pueBu4K@3!Iy>=Hz!%_01XUw@0$Fz#&`fEn3=U>y-}8Xatz< zwx{BZ%7_;JD3&-bcU#t4A~U|Mn;od*`+2uLzh17F`0ZVXro5zaFx+8SBur$~JTJGf z89?$-UNs;+1twUV4}Qk}=GO1C6lM~B&{a;FaSFzo;Nif`U|xu?6|(PF3?>~be4FtE zvLf=N8B-iOhPOZj;R*(zk@B~VB6QrKps?M(K+Y}NQ}eWsqwCCwAQDKOTs@HlViu7@ zhuKB4hmhgxf^;dj4R%}n8OqXuJ{_4Pw5A8nJN6Z1PEaM0O|{h#lyF=3b|}v8TM;=X zmvt_@z6uqZFli{z3v>8D2TiAa=l)z>3d4~7)S^P#D!}KtOCM% zGZYT7zdB%}(}k{kS=NP?87jctkM++Qk3jkATD1>#FyjmI0ENKeY%>l%%)mINPnVu~ z(Hv$CR~&{E_J$&QWPt-o3#pJp8?lH)Xv_e?W&y)wOhTvjy@YbO>j!y} zw~^%3@Yewa_)L zyk$Z$7E!G`R?fKk$eEqNczwCHXZYdwGdimA`nq11&OO9?b(b{|=z?KcIQ#Ne-s6cm zu=F(zM3hF7MD0st=fV}ik3mW?31bsTphHlRRwy+sBObK;THx49Jeaw~(} z%?kE6>s6F6px82kTlT{H8K*z z3aRO4em+th8_gwDq3nx;sROlxzYi7`^v(g8tk=C$Jj$BSoe91s>q~q*qimL!H4wNy zy=W)`1lA#QeojWr6Mr)5d6)TWdq3jYsoXPfe^vx*S}Peq^vD8F&NpLYt2Q_H@UZ}j zlf-4Xkidc$E03myXyv0QY?UKKa3u-BLax)Y%*8_l12r_qfnMm80gRZ(13GW5T2J6{ z-es(Uwv1wj47y*|vePFBvXlR=5kLfm7K(`Z`Ruk7eo!q0e#Xbb6r;LGqRKjFVhLq2 zug4>&`&in_4lJ$zVbQv+1MpJMLG7aL+36i9WrVvftV@SC-#x~Wl$RuhJ345u*X#Ov zxjetTq?(d0lZmM#W;P^l*Wu?Xvc5?J$1}8puFRZ#3Ql-et+LL35c57}kl6E4Vr?=N zl&T0NkmnT^0emN(cf}%D_&%4xh+}dMIT>v__@m4cxG)^vtms(-+|Lg!(KqMfnY zPWVOVT~TIeVhKD@tvMBLw-P!ZlS_HrNtFbnXt31oR9+HiU0n!6X>58MxLX`>mm1PB zsI~Rw3i}|f*VWGbXyp`e4GdmhmB94ny-b2$9lKIUw;FvFGpl%Y?EgtRxY!g%0NDW? z$zLAC9OKcqwHG~5z}!{~C|SEG%g_rf?8H{_5%yt2EZ%o-`5S8>&*@u*D@Y=N&WPaR zdjfca1l*xL=u5^T$hR;6RHNhMbYJHA2tmRyZ_m_Da3l`#hsmf$=m$n@Tpbp>7D~kE zxMY|Seph8XB7$2?uiz&#-EIc}f&v18UvDou!6I5D6Z1)Zy%3#1dI?$nDE#33 z3y;3?(eX(gz<|Hp#A;&$oabKqu){rP1ZANGzBF|pfw&fl%4wp1X7FFdab#!u7Dmel zZQE*~e{w`Ddkg)%AO;tYjPikn4xK(u17bV?x4;MHli?Ps?7~allQZZk^a*W>S&sB0 zh+jm-FO7teND!tcXgH|BSt;L5?nJEcmIGN6?H=c)3nk`9W1vM{@dtN}BWmqL@QinY z&=?v3;n&3%R=XCG&-B|GXM$-6KJW&=#{tO0@h{o#a}Nr*Mg%YM8z%%EfPXHM!Dh>~ z?%GD}SR{2^Ab+J9w6EF^RrvY{FX`viZ`pKbRbY5+sZHch>TY?Uf6~9X5FecYEH(ju z==D{SM$;7+)o^SAcW{LYxC-sB`)!e7ZmfXgZ`^u^SPQORd$1BnNjv~kqG2qH2vqZ? z!)C*Q3f9eT%hfULN7z!Y6XlH!G2n=S;63e{3<|;h8InE9oW!saM2Lsykik$w0mOm} z!McNz%We0OJ0@m-w7skUqXh z-=#GC=bs<3_56khue=Zibe5L@9P?*Az>ND(^O5=)!z-gzGMza}>w9v~9tmLPo99YI z5b@vdB{>u-u)tUHeSy?A^+PMusdd9c_^^F264_fA1zdP3G!~j@L|?Bp)i3PHi=s$U zDBEajj!2@4W7KE4Z}noEjEqvEn6&HNSHBE_sDyC0?I(08`aM~ zwTn^v-HvL-bJD)|Guzqi8N4>&2Sku47U=}afFt+4ukCq@rrYV|+V4f!o_9_sc{eza z#kjm&Q2;>#-9_=v>FDL3e=df@Fyg=md}RyFU6O=f#|W{O`T=xwnbKZvp(V^?e&IT(>Ld1_a{X!KY}E4G=U6 z7-%1zn@FQvO2APz5VcU6nj;8+U$ztm&$)Xka^6@|h6vV;FYZU2LnK59Bs9p_0(w*) zcTe-qiJJR*%Y}`|zZtv)lJr7iB)MF&gA+Jvu5zyA)Age(?b!vB-Pn@dt3QE z;O?z?-1sHg?{<)kIUru7co2Aeo@2V#8t-^T{scg0+E1u~FK^2ar-61Pv)%ZQOL07E z=tKn&?6eOvA=G=fm-%a1ng1Z)l54Ro_w?z?p4!ltXF;U^BauZZ02WgFU8zD7eC}=; z-tV+3($sDm!gFKnxM5y75^VZ}11j5oj9`GHYN5N9_wN*AYT&D7GigbI^b0lDQ7FRS zhdvZ1BnR&dVo%rmHaL!yh|vg_B<-kK6Q-l5$o0qpPbkMn``gfyTRS`KVhN;GelwR$ zvI`P~Zk>y4c3X~akLVmGS4_LySs>4Qx-V~l>5TJJb}`#ji~O+wI!Dk2!(f%ZIRKHs zVBW3W_JvSW4TKk&5+OYLPq(=60vKmp&Zz6jT#LGWImf!RzPncRLj3Y93pJ2^z*SKc zh3Ajs4kQ%uL;aJPMQ=k3JeV99^lwrBKIl`^FD!x!vA+vXpWFn(L5(k4gbUR#5+f;^ zIJ}Htyf^DmlNDE6XMdY-Z0jKU9?2Q>QOCwpX$fik=X- z;D!VN&{%)K-&x*l0cUr=Q&Fh=MRsaiuyC_jjTeuQ0wO0(7Yg4{5$V&dIa6j%3c+*s z**PUM=NGn}^C~wljFEVTPiJ)o*_D%0tWqb7G$;eNr5c^Lw8w)3%6WFj9lL&9NycAv ze%d{~?_LP^GwK*4m^p;-cPp@JXxA)bm#+vjGTY-01KO+K``pRh=jZA|P>Kx4blXeS<^(Ln77C?pG4$Y9To)_`P_{Vk@+PbW&%nOWHF z;md<%7`aK0(V~!E22iW~A%B3K;@4FT*x$&S-#429EXHf+41cFcP-*%OFk589lM=be zI_bXR4rcz6deV2?&}7;PTKZtY!4Sh;KApGd4CdXL#Sa4*S(S9u2pHQ`)v2R2GEO;w zV3QHV9xDoycaW%ge{uw3_01{Sxx0u2UK3}BBS27-DswcnYuQs8c09k_yB&CfM~qGo zHl^)Sp4&^Jf=AGyfu>-2&C=)1Fr{PCmzM(r_-B^r$WcE8h!pU&_jOecHM##v_w1rJ z7%2f~roqoUeS>sgCLpTz)x#A&BmAgV%0Vy+a}mlP^H&moE7iYfI{XMbr$hW4fN;!P z%&8!Q4r{RPBM3nSsSA)LP(b8{7|x4ClmZk44_ug#gdVjm0D_A=KXAq{nww&-_bHEa ziH)V1h4P9=3^pOSsGIGX8j?AWynR3Jv?*qO+{FwaQHFsA*Wr-zW90!wm2>BK4wUY? zi`wA3YD6nYb*Er>O|d39pcB{U)OW|JKQubEWz28 zORI2t^odO=)HV+D?eXB;!P`g#Sr_{!&YFlB=FgfAMhK78Uk~tMVulv+Xlhw9D$eT9 zcgM&_)W`YgI7-s^sI8&Lqd0DGT(aVPre0HcG)L+^J#y^>aw!TRGIOa@K#-h42WTfw z-IeSr0#)styGP+MiyQrP?EOE>A8mq^*H_g*xpt*s__~=ZfajvFwSJLwWfBxZWZwl_ zbM87 zxa+Qh;BksSbOGlY(_(=ZuQZ-2XNXHsEc6nrd%xnA|$x0?zTiecgW#z6^1*C8T zkh-tqm(S0VOz@g2y~g9a3xSCVNKnkK)&TpAwDT4^;qTAGX_Ya8NnLGUI`jcy&ul+4 zXSMRXnn@CnJV04QlVu`&rk#%_*s|K844OjQK>X^=t}q+mmq{9We`>@j;MDU1%`ci> zCw|qw@#(*}>A``;CfI9sH5goZszjI4IThBT<2x+t7%+$swmxU_VpGjziMd`6$vlcs z&MTrmOj}$PSb8idfgK>T1wr!y7=Kh{n z!R~D6!%Q>Xc}t~`EhlHFwUi$ zj`IRY(S?hsOyV07UO@mZF2%(-x4oW;Z=h8J}AU5ixR=`L3v;a+18oBT{| z1K_nxOoAJA!ZnQV8rk6W*VmDiPwyssxc<-;N*!`pAGkm*o^vQU&aq=&n zkiXM#o4bno2%oFykji)s&DD{cw|kFVNFoSk%@bA1UbxW!Nx@lBnu|7OG@45hgK8TT z7;I^25atVeg~%c3oI$GJazFt;{j!suR8l{hR50IlfdDcPmut8Eq$X+VH-MtYfz4|u za@e|(RJ+gfXG@XB6+Juo?v>m-`a*snfyH@@;2kxOhjb-0Lax3`p%<+%!p9IgPvcZv z;xZ0R0>|mkDCHX19PZ=57T}5K>PCV zaFzkRirrYoioT!fa#Rr)>Srm`=Z`#VhyZ6gFx0U5!R7<{1$E+VMzVAjb93Ws3i z3%v8NZ%PboMCm!1xUm(V>&Oeq-S;yCk#hz+h$XnR8&O3A?|kHHGG&nAY%OqN5KOA= zc}KAbEg?GhbkDmFLwpQ-iPKMRpGx>%KE0QC*_7L9fIo-7^i{1>816Yv?jljVvL{HU z7_{`#|EJu?`~Us%@$tV-4!nE$Ug5p7sJbWhs;{*b-U(njb-+y4f+SF;PSo1bEd70c zn({;4d#rs1zeX}aaHW^{mm0L3=f{>;n$4{L=a&#$<4Y4$hja6J?}kXb>*w6(62Y{K zmi6%cyggu4e293lhn5l|&t5yuppZAW$gXPL8STOmf_=?$3d%bk*=rRjt;0=lIi0(^M^qX zjO6yh7}&%ZT*zp4XK88(5l2g$m{tPl##e;zUIP;%NfOgUTz=>ANRGCgZjhl#cZ4YC zt3n{Ue-1xPm%k+L%Kh@!|NWmnt18GtcNoVu5w7-2nhG}IgTAIsFbn)G+!)3YSSf*u zU;bG4e&qBGdJlTr{DSqjrfS#%OUWa8Ge?kqNrTyjh05P}Tr}_4APT56F;LIA-~K>f zKz+o0U0xt(*MRX%t(tVS>GPw_eu{L2NcXD0p}A^R5gV?JQU)>!GuUa+lK@P{wba=o%k{5dFV9 zwxQf}8J`&r4&ky0@OL2q>1}g~=ZELI1oI241?!}bxIMlKEbyCEKilI8+a%&t*(}h# z$9`WhdGsNNWPGUv)4CJ4|22|uIXP+X~$_leTr5Jb3diDaB!XOT^sq z(vE{*c)*C&A-Ima!_ijHjPOP5^r6X(j_)vV;0ankckej0W2-#5zqN~MQovBnu7n^u zgIgYaMkARc$rBD^;6MWf!K{7yJU@L_mr(!iT*=`3f~8H!$CH%Hor-F#Zit|}k@QV3 zWOgQgedk+2A#uh(iC~^npTfnRoe7S&^#yIYPm8R3VRO1|bPf)*rBp%NBrbTO25<~SK z9HVin__8jG^XG2+vXiU|x`ov4myH0tYeS1TcaWL>JbzL-_a59e@tz$ujCgK|L&hs- zt-~@Ki=D3WA@X!o$lbTW>)PcyhsyDVp0;~^{OiKC>-4oLK{&h4QJ0nH?v4>{SCR#u zh(X?rB?c=DZlE9i^g#H0%yIjH`CVk#c;!^9#f)Rxrpg~?16LUKde0B#?`^PaNI2eF z_?y;0Pajmi{i-5A?%;3`!-{4Y`aiK~0g?sbD!GGJ2l+Gg8SoH-ckVn!ySv*)RA3_w z%rLJ@3OF>xh+ur$VTb&YGdkSCyqjMi2;f!1iG=caWpu7D7SSYd^U$%QR*@vAa10ld ziK?-i2l~cv!u31fU1nP6x!>Rf)b#=an0&3DGGsBSv$Rb13-^OvcQ3oF`D?XEzzTPr z>_@(t;?Jad3pK)%^r`Uu!0XeM78rc^)E<)5%7j8F_O_uzJA^N+lPQ&&Z)Ey>S4cVR8loD%KZKKuh6OLt4Nbl#}NY zpbM$(D{I59x_61M&cW`L?s?DeA=)O=%}w)q0yg~4SQ1$Gsi6YK6O=h|Vyzj*+-x!7 zehDgI+;x|-sV{X|UoP#ddw5XH@3Ov&>nyqMVTMyzWk>>T$q`sMjSc2qH+bMsL`j!z z$E`<~z+^%jfzv1uDW;WeIL{hAn$_jQR9-_Gb@8e?sBH*>_Yxvn+mw2pjzKWOH4+F6 za#1Q-dp_@S2NJ;CL&&`@H=Q9M-(>giZq{3X#N~7&izI*BOyRqea3;=N+`AIqP5e|ua$Woh-IDM?#`81b# zjRYRLIN?^&Yt>~{Ps0Vc`-%t{(T8y`?$%xgQzmjd$oBR<)wB3vlT+6de-Smc*pv$W z-RL{ww+SZ@6`=*zU9|n#Z&gY2EWrna?icAo&~AgRTIFr2%}AHaMOEwK`v_Vn!OC<5 z87wp`U_?d^4>T!7e%EChK@LjSYv&A}am1C2ru$o#7^~}hS?(IaNI64yd%xxRNCE4B zJwY(o9KI&0tMA?@%R=wL3N%47G4YEo)|hoy$iO&Td#NfH!BubYzt(*j>q?C}>Ds2k z4N3q&Nrj}NK=Y0F%HE>_4nmH6G}-YXdou3=0uWeI$s!jdlvCgA62u4G*KCZBaL;PfA6qM8&&>7 zSnq+E_7gBnWRsPEWd9eY8teS(p1Q93`s=UAT`Q~dQg*dg(XM6RSDhckg7WvEDBPkC zXvWA}ckhSv*_Gbq!a0Daf>bWpikiGo9|Exq4)NPeY@1{NG;wcbiXSq{jhhXlu*X^Y z0cog)<0-yl(E!S*#Gjnj+Rg4vadv|G#c{i}D@2ZVaj+jYI_E)o;{J&O3RZVh+R)zj zGWz`7Jw@bT-|BIAs}&D=x3B=-R0V6Utl?d5`A;165K435#V|Mc8U4%e4zPRHe?gS& z_#+1<`%fG@H@2$c%e9{`5^0ZjadOmlJdLkF0c=P5r^az_0sM(^jwAYXowtjH_AMru zqlw5?li=f`hc~?GSpHV~FauKs>1Q0lC10%jcL{7N zuh5WQC`PcZ7B?BAe$yo1-H0K2ctC9pJK%W*^a#4|-s}AD9ksE?b`|bGC+VhSaq5IW zdE#Jt?|<4pra7v;dqd&$SlA`Djyp=bu@Bgq6b#$MR-3ZO1^mTh5ez%yb(Iyiw?q?Z zm9P$D;EnV>ggeNu(K27s?LIBV2+erGHkI~UIHXpYcZT`*Gg~tjg?%jh8xcf?kS!4JfQIaEri#*$)C^zxbxeYPq+J>+{n8&?uiiwKywg57Q&mx zy6c}bz>n|?nF~ZO_*7?Y>F|rOH^u{aN&XXG*4Ox&#H-`>+~hP6EiS7St_8sW1T!(# z0&|TF%VaH7LVm&U2D2@K!52K#z$Cd%R__6X)A*U$m8<=91I%ffztbs_foLdLTi^c~ z&D(7+5r~Gtl8yFB!LXUdnc@`;fZ={X8gyz#R&BQ>14uE5#37gasB_?|CY2sVe61~g zU{^53A~~45kmv*unUfQ1A)S)H$=@%-n#WgnC5ErooWgRSzp8Btn>i$L+#e6~^E|H| zesQ^nPGjf!ZRoTaHAJIT#su-|feU#1PQ1Ga4e)}N9`*ZGn~v=(hqq%dV3Usbo+JnZ>do}k~JGRQA2h&Tl;PVYlg>3;X7q!aG@Kn5$DC?+lXhs><&~X zb;q4zYF5BOU@I#%?zUI{w(tNlhPPTnV70*{fH&5^EN2?oA-v^Q691b=Ors)EcBzcM z?oM%gdVXFz{&1%g+}A0talioYOHLLz=*rrV1cCx?zy&N9KVffg!@+t1ehUX+e`<ePpxURdy z_PoO#5oorMFu3bzMy*q+MJ|~b5xt9~j5*Jjc>9V=C9@HKf?#4BTGl!8m)+C^s}?ed zxhmv;m%y0Jv3SYX>UDjYKVPa9C}4R!w)5k;N;0T{6lh@K3=%kS0b9Hg04+e$zXcFn z!16l*?#+x=UW`0HUFHq?ciM-XD|ze(Y&Jd{Gure+M&^f8^C#P%CG;KZU)7)bNPIr& zKWMqV{%~y8ewTU3o_Phltbc$Y^w(E&XzRnQv`*F7MLZ@H9Jb~h897&`xLU4#^K&DB77uazt3{w4ou<8BYz z7`iZcemvCOyv(rOxJ`}6mk!BDF){%Kl<|DS;3BNCEdt%Mjvz0t1pSk2kLRxy@hgI0 zd=soTXT!T0?%6Qie=se6r{=WpD|d>Ryu(~tQ4cWv8HBLDs{v+(@fLXfAQUm{$)JTA zyPM5GnO((0x}5;RJ8^+&<+1q{bEFNO6c@H{%5~brHS8bTWnI4-di)XOeTku z2Nu4!B(MQr1@~eF1Qwo7gWoEMYJX&U8+XE`o_*JMvu+j(2K>@oVq|@1EWrgx{>A?L9d3J+#t{KaaAzK@Vp`-Bkj$F>w9R5#-Da)zS7ZpPx^# z$hee!f^ttEn_>)J?nVf8H4*3bZscO$_;TWOgEby?<_$BEh~LTNJQBm32}y2~3OKr- zVbzB=x7_|rrisX`zQ)yahV~?`lX4f+u)*KE`L6G9=ZWsb%Wa9ch}#2<4Q_3VKA%ZM`V1YsR7NmiTDOb>WlnI+(`5^c*RzR`20f%F_ZutPN&`-2iZ{|yj zV3vsvW?gwIlM>&@PNcJK37$=pvGFEASBo$>`R0BmjaHkIO}? zN(4SYkG(&fJ?iwYhZRVpV=NF= z0xyt0aQF~EG{>emhsQ$n&s%0tJ-#vLi(KO5u@;7&;fTxI$Wa{JCSQ{R!u77Ks!JDh zN`U|b1nY90?T(F$gsCFt*o&CJNE)P~afLQg1f8PLb{z};R89{0<|i0(e|Q0d{hC!% zG{jT0a@SV{X_Si%Dhv*wOPb#es(=NrHyWy+S>;g;9Y12Phf`p9XQY7W1KO6+mbWWE zcK5*lyUS`aZ-Y6#KaxO$p!StgF&WqD&;*riu^1pI7u02N*PcLaa=x+uhYTWqUJ4gC z%Nx@uU))3nIUKnKBB(Kl$z4mjW+;sVt9u*RYI8Si(W4-!E0cwD_avoNW^dBq;h>BU zkgl(qjaL1w0#3K5FoKT2h9hFZa4^u;Uu6YE1W5p4^qQkk{4%FbCyERJ5qAg2U&LdF z1VHirLjKg_<936+!LNbA9;cq2KA}(e69weWJc8L)FuA4n0*D0MeI~{@fPmqBvQ7T( z)5%=Ry~;ir5Q6A4V(_CIZpmE(87YNe47@<;Q!^~&34IG+qhk!cFUbC2Xt47eCu{^u zo3(kIx*6UwFyfMN%qaZH;yN$)Wz9v+uP)g(7xJmQI9Xr&^KJ{PZpqpre$iXxTSTKU zGB$yV3r2vz0Kt*dXP;YA!5Qo$->6+AKIp_FINWFLQFt>xpiMi6{8gtt5@^GY2H`{Y zI>Nf^XYS1G>F0>HHj)xB?fY@eF#l4k0lp`!NlDn0I^hIL2H8#}phX&2-n7&TpgBB( zS$>z^=DYNe-WWgr$e6`UlyD&kE=D3~u)BH3kgn$(GphtutM*}VrNdpF*R3jPWK~%;Y5?>HmSo9XVkb@$2I<~LkaC;pn7FrU6Zy$Kcy^j z0CjoZGI^+OEPzuE;M)L6=fELCLQpx4Uumq(!oB7wfgV1%MSyT-+_{LfOwM*Gw8jOb zr5u`inZi#34t4lEdoyEwNdaYh$gK`Y*haFkV=M@+wIkuSTx7}m63lgh0Tf(DyASQ~ zU1vJ-SVsroZSmbhWKhQgxnEi@gt!HvC?SXvxv=iw!b_n|$`}z;Wt4Ir8D()1IgPE{ z35`Z2jb8c>KBEFU{&KSP#R3Z>>!j;r=yj}`>m|8>V+b3}eIarY@%6?=I30U{(V%kx z;*f^TCm7BdtDG-;i1_I>By84`TSg8fQRhzXJcDyD8_)PRz-Zp?-mJRZTliLc^eij( z_(qCn!e0qO1iPc6xGT-}^05s>97lw0R^Km!)UgNh&L!Q%cN6$2Qy{EAq)%ipXL#@H zTm{n8#$TZBStX=|AtAW9g`OelqG!>7>7x|PU)yiwLM2P3mYRi4{gMI3-YDn&@n5Jq zG|5@l@e+gbP+zX7fV8V74&39m_~`o`%E9sw1#qZ<{4AD=o^m+D3FDd#0U!ZA{?v6% z)3)+PNUaOFq4Jxtz$ZB?eZ_u-ex<>$^I{i>pU@e}q-Pxwvx9O)%weLstu77_2#%pEGPf9U!DXLcH*~T5_*sfbg#J=z%o#~a%hCb z3!HUCERu(x=~i+7#3eAZIzkg{36!c_Q-Jz0em&wR9|H+A_^|?R&3FWCSgAP+QxD3) z-2r|-{uTHwOUGcMees^WyX|O6)>_Q?WdURc?+hN9mm6Ks*;A;oiJmgP3^F#>`3wBR zY>eO##hXd#m;_@!R8P7NE+Dbkcehzp*7#5|-k5IPH7gimS-RI2W{IU3bVN)cA=b8! z2oyTofLsR?$6mZ7;k@=0@Yz9W~+Z2Ni1is+i3{m}hdvt=Bx3>hI zxm^^{k3)!d^Tfq&F({zmrxdQU1NfMjMQoK^AfxH=)TSF9yjx)<3RY*co17kc^z-&nCEwtdFLC?b<1g7{bg$1$^! z#B4gs4zAbK8ZrA%2}@BHH{SLe_oiE~V+Y`Cy7_(c0uuQ2;;SL151Q7Aq?-W2C@2dz zm309vc%4x{3N_?3Gbb>agkQupXxoKD11n7<42d9K<7!^fFnkE1_X5e{dhm$Cjz0IS zfV3hL=J-9mzi*#l(OS$FSP`UvcwM^x)$s>gkkG5F#724Cq6oXdylX1C(w=x_x%?TR1g)B1eHC%HNW({xI zKsHAm+QCikeF=UCfS7UW2tF?o=uM5|uT}ax0Qf{lWW}x3Ry}Wr)7DyG{@gaum4I4T zTJ7ts?8cB!$$>xNx_{ zc$|KBubr4+a07!7gSaac!BHea1j0f&uYknbzzkEe1x+wM*PX+!(N{7`BR>So4(Z^B zuqj%D9`K6i0~lXvWaQ!?e0#+bIFpkop1IzuNsg+G;||(IVX%BE9m|@0rVi2=7$gHs z@0XNBkTj6(@PdPqJRt@XZLXIQ8%_)sV+EZ3BmJ`o8ry6I@ivN<#YrS9%r^vCYbDYc zaJ=QVP#@A~x;?N9^CNNtnq3zZbFOINByoZKRkHes74W6C5iZi_PMd-Su(e6SNc&g8 z844>Jfzvk=?)VE6aG>r*k)kI7h+l{Tf0>|jv^Ai1d=Q10v&Mi$6GJVEAX{LofSx(J z0pWBCcv;8g>1}()%ILw_fdCt+pP6PbT46}V)>}VZ0kzG2{f{2J;B-EGRL>zn(-2E3t!0#Llt6WDvRwI@(i-sH8QCpxS($^fw#Z_v$yH~ zJY={Qv~n`8Uss@i4!@T_R-cIAdmw&b24TvD;$8Lm zULrq#GMv%Y(s&LwwX``f6$>Ml&QxP&`(q@5nhczISI}K7-5I|@m+n(U)A+C|eo3SR zLYt9dN}6z7mvi(0o0i{_l8R9qycn5c3XBt3E(t-%Vm5giacHgc-*5|Wp1hkTYX;WY zYM~XvamZq{O!bbv!B9Cf@f3%K-n24Gt7!JsJ?~NfUeee2`U*z)^T`(AcoAl+VP9y2 zxnCwCCvcCP;WH*3FFohw5J9F8oWC@RRJNq`Ro%eBqz)vq$I*a?yeWHYmny7a$HgG`*ETOCergV%Gv@ zWME{0x6;!P&iD;H^U15(KZ{WG>djK*EBkb=**?{R1X>mQLf{wk9`Mp>b;+B~n) zmzVw5^$G#;HQszm9)@yU8~|**{IU8)bc%cwO!=@*!dcHlfzU}o!Q z-$&!@%V2@LzhfkVCyVw1_!K}5LV&oX7+!a6sDS-94v0M!BoS@OFqF2DbowUA%f_NK#bqn1_PoxD&ZXZN0*>{*V zm1%{~RIa;pb1L38CE*7IUY|cT3TZ_HH)?aq|0CC*)ynk5P;-bpanx3zA%xav4>XT= zYgJDaY+C$ig&zJyIH~+?u!)_q*xm<3?i4>%zi+*`rr$yZ6cwyl0o4wp1+F5r1qTYT zi$=?TP2cz5&I32J-uKPjS2S>_)jcnj)%6WQ;uNn#NyV0cttP!7J@(>4C%Dc~>g z>|5^D69ek&Us@5x?B9$l9sX!ss7TSTi+SEm#1W<6@BDwW8`W^X_VmFcgeh`AFo49} zH)ijf|H7N$W~6{??Z%>X3{0{r;a`yF0G|z~gNH``3~At!Q2hC0VPO<6Fbqw`ams8^ z!TXnjlSwLrwBoS;CWu~wX6+EaY+-uH?2?yT4bUY79$Z|nuYaVUPiY&C`%Y8OpZaiS zb!LxEPW)_j7z0}ZomRM?-M+oNY~9aBk0Xwe?(+UjWbfY|?Hs{-#ibN7VWhyC*EquP zqhW(9GRP|EPSIdz1lB;wzaWL2gJ%Bb@}6V_ZD0*n|A){iYkK)%V-mh$lq59n-yksg zSHk4S!OCqIM~4?f$8tge9~5gu_pWq&Z8pC@eSW^Rwk3v(?r2J}S@gvxO(Y43br7t4 z&;@q)nX)a$9*(}3=*368(F8^`3_ab9_v%b-u5W6qxKu`4wgqwl=L4MJs{^`gKq8Sx zXyUz^XuS0}FCVW_{+s}IWO5Ipfav_r$r>LT6H$L7gS;evZ#oh|*k<}^!BGr@q^rJ8rgmU zuYfCFh{5=w1#S*T0o@O79eyt_kp7DXYo3e)Cv&LNcJqVvc$?vg@T0^LAPD3g4lSMz z1R&t{jbxAmSiCtJ4>;BJb}!aJyRCpf62RzfyeSCp0htaW37|s^|8il{2XMf|EEn--hguSWHZ@<57V349aN3DrHsL8Vx1@!nuw)om` zA3O;R$Lp9vW_6 zjktyb-;Bod)l3}X%y8C{tp*j;UKo6f%u}fbQ%KXW2tq8vW_YRgcxlb@pWjhPjE?1k zL{AX>@brDa4Ie|#&<4%_t{ndN2&@Ue>>1pw-(Q|S@nn6!!>Xa4`Dn_3a!}|S;TulD zq$qw6`Mx*>BPWdm$;lD~BBtZecGXBfa2L|?uBrx?61ZCBl12un27htd~35x^; z`&rFFTUYqScJVKM4DrQ~H{6(Eq=39BCY#%h9hcv3LIISnS@`So)Tha${(J`*}qm*{m`NdcHD(%UtfKk_L z!i@WkdJQgYq)GgNDo}2tW$|MN(B}=Kk@F{Oj(F!I4I_;7nVsR_=RkZK^(oiNEZR20>?5;Dt`QZTRj^X`=DTB3~)E=vU2mn z0KUKdK??XH89m4?@Msm=VX$d!Q#vNu@Cz}%sTIJfVw>N4j_51Ik&_gQd{e$%_{}l( zrb5NDCHgeU;@f3((+S_q8YCj4`YX=*Zyl{6(urzBV0n-fB3WS!a|J<4>@)}s}@49iL+s-LP5&XdW3X0Z;+QaY0g9SD3P^W2Ba8~a8LZJ|*z+oTq=9P0d` zeTzi;q9AL7xfe2;(D9G#m>{?nVYHhjvDNiEB{7I?AtqcFxTn&!N>g8T<;dG)5*!pT zi@&}(U#{=7EV=5E-ny*g{-B;Pm6dxr_5OC?@0+qGM;~A~GjeFYoYq2OZ)Rg=bqtrJ zd&>`uj%VT(&iIn@gG=idvJIYjar6|1tD-)9rG-s2U;mI#!xek8A9{LWDLYsPC>8PU z^uqZ4@g=R%pHIAwG3>UaXqe^^(7Ff?k{bzqCH3NShQk#eyx^0)Kf{-eH;Nx0{3C#% z>M`mr!>3)Yym%=cD4*ndKmp^pJUDrSfTAx&3a^P?>4&fIEscj5UPDh3FG5SLS3fwo`7poO z<2@T&T=^6#AYP_WqRf%b&(GUrk;S6!5E#XY5HJgtUYssrv)^e0WCtE9@zR z4d1k+lS6Mt@DYku2WLYN!`o)wUQY<3+TafpoqUKUlC9RD881FU0*wGt^zxx!Ef*TP zAX%hqY@!XFf~fZs88`dkIp!Z+njVV9RGZms=3A!3K<(I>cM6y;-pUZ{eGL@S6MMJtTToX^-S z7d~nx1*G;GmdDw0QVqS0{s`k2_;nu(`HmQDx3$D3?Wt6|S4F8^VS;$BF^mh7E z`e=Q~AM?eJ`YCy_<80Ztb0W{I8&U)#zjDN{DyEHxzh`KfIzNa_)o??zYEqt5qwAz> zdPRYIn=B*`0d!G_Gs4uNC8qYJiL-%8rdtl~Lih^V567TA@k|Kzj zU^{Bk!&j_E2gx6{Z4LJi^I5*1#8099!vO9-FUXWI_ne6v08Pg0DM4NUFG4dXqdG#VRaM18f#kMm+e& zZ0g3zlP~J{Fr$mF${zMcuQr>f&lh~iwp6qnDj+z3hqcny}x>4z29q zdFlkdW@Sd;d+%?&f1RdY9<{9o^o6z`0Cf1pm<@zTLyW3|)*C4#*+U7`o0f79jo8GdO2)sfO0zrN`)tr58yP7n5-g zK%6-Jv_T%xI2$K&ChN>{O1W=1K&(OKB)EPyU2a-G*Hu-N}k5%3#~1(@2VQO z>}t~+y?3t{_C`mu*(f(<&d&UR0NR!VNxnpbRYt=O0i%E*bPdA?uuLENM%Pm_PIdU#bStZxDH0vK*1}&8z~>#G(94!*tJ z1O&D|g70gxhI>{At2fiZnkA!p8?)Vdu+;+{kvP9u{FU_~V}bCEZ&kmrw`N=1M&fNK zhW`38xMFgLzhISvQge{SQ4ALzQZ~pqtj1^*U3@TiOTA?#3i-je;5}wmG?)BCGZi}0 zy5&rNG4*vDIpp6fWO~=`+v1AhVEK%%;M)^+B^<)WHe1}p`g?QGs)q(1Z_3|;T}E1~ zf4H?OFxDV=4SxuJh^Is;R3wIm!I2E64>Em0esLVx5P%srg~wooT?7(H+K9qOmRWwH z`Sz_*Q!e<~^Q0Pn`)T|hacCNEmV;!XzQ&|_;0WTKK1c?aB8EPoUW$+B4YW$7zZQPh zFN|~wsDp6AE1Ah@E@$A3XYs2Y+v{TCeh`K&O|iXqE?^r;i@Piq@%T}@mN00ye~>H; zLWkNn+kYu8`vhZLe2!i)FBr z9R4u>@~{VzAA!*LCH(oZz0M09{gb}&15I#5We{${dkgwNwRurJ!E%JAe$KiXEsh&SJ9jInV50&!!yI#LR*1+B9pF^ zV1PH`(Bt+=pIcMVoQ+9@HiWs~u^}3-D3)XHokE$s3Rsc!HFmFGw!9FE=yqJb1kwfz zNT^ME;PMs0zBUixqa!l(l}-e|i3aNVw{JgnXwcGl1zl>GvQ$A_etTq)zYQEjVexP4 zp)Irobw68R@vULP%m+g$s>s+0(;u@j3;}I|qQX8iX(QvL+FUx`nmPVfG7Terr>z_M z3Gq`TzmW|#b~hT~cVPbLo2`$3o&9Zmx=(#S!cW+1Yzf43*XlC3uv0%s@jcjCa}WCq z!$!jc04X0>I^Y_Bj<};sC93%mhK+n0iR99NXz=@Ps^*)ClfNzhrX)_1`4QG!^z*{_ zT8r7Rt#;VR6RMdNT}68~c1msd9z2W%>{lQ&snQpk8||VH=1#iKgQuiF9Iy>AN+-n+ z1{1(B$FbxRfSCNBWC8a!>$1Y&*GnKrzjht)hfs+Mj~M-C%vd`m4^qI->3X zpPJv`3engwkIm0%;l!~tm)0^bzkOE?)fRtS+7$NRXEDfV&rJL>$aRmuZw#$B)-xl1 zL8K5y4gsLEA=3D{iz}bleZiT%E({*m)_pD?TpdRs&#Gw6Fa?8ObC}PmRfYl7E#9cb zWnVNauYV0jBq)6F4bs1s7t9f5Z82CGN9=7LvloC@;h8T^(e>*4fSdxlIOM>THQ)ZH z$IKwg;BWua{N^?BpB&yW2ZFdXG){?OfZ|V=^stZTSGk<*8JmssKcQ)#AU6=W*>^&C zy75(eIN#q^CCuz~VenG=eNEz&i=Fs{G)~`eeWqE=Zp05W)jXIe;&BAF5urhuV=r*k zNDKnGXl)0??V7j{XBLEDAM|vJ59nJB=&L494#3y|2nsku!E>kPe|~HDI!d8PASvT- z-c0`^6s;~UL$7hlK8N1nz*LV9(1(NcZ2wYH=R4n>1sXRXb~eTEa%AwQ-z*!fX}!I? zq^Ga=dVPf@axcrN_oBZA0^virR!PyE1)3wg^3sd@4(T>ZybjZa=-PzsR;Ih-*5k% z!cmy~IDaGG4LTbJ7s}r^dKoxVwEX}1@eTQVdE2~Fe-?Jb)zyj%9dJ-(5xSu~tNFvzFf6f+e_{+z;Wn2JCKSm+SD_VBCaMuWS;q3EQh-YzNI zG994F(-l%Vm!c#esvqbdmS!7bc_PTx%gK&lls}xa)m|v%@P>YxRDM00M9|l?s}p$; zVt1r~Y5dHR>vn|(CXfleED>vn+|)>5Nmyd{p>_vL2ESh$u3QM0FErv<6{K2p%c+sn z8`0MN=a6Rti`rC(Uy(AS3(2BiWE{=NLoPu6o1M9b7gW!+OjRtTK|mm zH+=^Ev+#+rMow9_M-g>c__)!}u=i}@UTb;T>9esgvYDGJcb6ap0jw(v3~ILo#Zxy{ z{6Gz-Zp(~=p8--n(#H801S_5b-Z(K!c2gp`fKwjClF9@7kH9FifNHX72`^BrZDQ~% zD*T?Cqf<`$$Fg6^Z`a&#?r+({DweEcG3Rd)QX?fKDV9+Szs}0Db?hx zZR_3V&v)GBa_35)bPDfsr|sye2^0c@CE!mh;PMSfTM}kVD|~b{C3Q5Lr&0#B0`l!I z3YxPUvmJBfy5}eeoJA{|vn7LmV$M(Xyrj))&5a)9XQ%qU@i%`tp z-ee$nli3kqH4xfga>G&1D=Dqp0jE4=I>Oh~wpWjKyS4KZ+FWPq^03Uw;hRB>qZx0xZ<-q=x~6B zsb>7_MYC68{ziJ7ZqDRqJyJig2|g(9z?MEe5$fYDc$2!yhEDG1Uc7;4en|%%7f|=L zX{#%n0&O6C#{h2g+bvR<&*z83T$!R^U=Qg->C-nLgiE1=7giIk_@>#m+?0M@BjSyJ zWNt(d?HOp_M$5q2?*(*;Nj<7L4Z|6k6~3-sO$ZWS_(S2qfk^8PREH+g{DwUOf?qC| zm#`v!xuG5+Vn>INf?;DH3g9i({vPnu*zm_8H4XNx*s*n@x6O{zZ2FzQq6JWg!kBHOx?{;K+2jNe>87zxl!;@x4l5!GsLeVC$!PQ^S~Rpe(RQtx%HD?I2K0f z^VzcivI^p#p%Ao?eL#S)w0t83iN2-2Q!*FdS4@+axy=or-)g^Pxe?Nr_8R>(u}o3Q zOqXzj&ztO_>oPot~;vm zD_6?piZirb)bemf65Hy$Y@i)Ge8KU{0+0={$KdJ92b4ejW8E|QCl%1xXA>sd+uA!g zmfX{uOKCVgv3%ogZ?2_&6WFRplE}B49|+{H{7>maQYHQ=6xHX))CIruMPME`vIOpM6j(mA=nTi+&Xe&>^}H(BU@@A9U}eDlzL ztG#`DpkJ#h{!DSl3Z1}&5PpvI&w4R5{z%E;M` zqOZaz1Ls=lO>_pn$+qq^K5s%YN>?qm)W0|3SY`>W0n6q1{U)RLeTh=7^=xK~UMxn~ zMtd5$JxzYY0=5CB=z|H1%G$3prkL7U_>N_-MEpILbEe3k7{{3^Q91A$rEg7gD!G7n z*bnmg&P|A6{O}JhxeWWO*VCe)@M{&&2ulhb8PxaWb2ax?$YYiiN~5i>-Z9Yj0KEAP zIVA&P?M=vCMiY2;%;Ex3*z8%H9?UFXc}a!5rzbZyXQ;z;a|1_ zvIm&&D+@eP8n~}p1I!Y*%mhz9tkI)d$p^FMA)2LtrR#oTsU$jAQem{;o}+z7w>$dH zai-o}XgqOylWy0WLvqQzm^Z;!%6`Z<8P}I;t`p&%T}zu9-6|A{#rf!TIxTH0e;PmF zZ!;W@ayAYI`k22Gu_X*`xr}^1YWQef)|UXKQ`h{_)KO@9DOl<1Z3ELxs9RxJ0n-+k z@XG>FH^YDc!a&ue+Nv(=*6c1F(%j7+jGi7|*_y8!m~y&pJKpP-sFFvdrjc z;#M(;Kd|XrfSY?@hsULXOdBM zGR(y&c$A_~3*a0)z^WoJS^IQ34&btszFl6#@hY1&%bw)2mhN@AV5aR6PRB1LFIPt& zbBDq=!Jt z;cubaVHAFBeKU?1a;B{_kypn*xLBW&8?QB4ddz0i8OrGwQf+GOdlqS^zWh1OFr#cA z@KnJLA*F%UR$<@4FJ8yXHOu=A&|Si?c44byx8>z6qvxeWEYLr`2`Z)bI0yWVaWV+O zTkzY6*S*!8x4al4y}74FO@ASgk>NgDl1i(8MH4LV#3|cbc-+)#u8*wUoMj0ez@ct? zLF<|$|IQv6XaDL}7a@LxpW29Rfy`g!QK!%7p(8M2SPmpkkHR#azjxoTpa~xN4S=YC z^8ywtAuEjR(T}MsgIq6}4d0-3%O8fa%gZv^;j*4^m0UosqUH4VdP6Wjr`lfLZ-^dwJt5iy9H0OKg9+4(sDt#? zQ2_ae)bTOjmheh87%qQY5x>P+r{ZQ0Lej^yMrv--ZIG5^BQ$SrQ1m8rSKXQqa?SzP zPs?fPGJhA(61ABSMEW2zYXDVy^Bc!GsTq&1EL&f6(~E4nO&^V=Y)>Ql@S5WggS45I z9cw8}Z(Rbtx*OE=qOLQdj&JD+$qNB&!5~e95Z67y2jK`_>SU3%64nipjALda;jdk4 ze)Li+`3*Uik}SiW?kf}w*6hFFf0vBj$&Y(WZ!+J@4WFDAc%MMGK?=9jZ>oo4kuw7) zeXQE65G;FVB-qZf0nj%58Trd#(CR~7D60cC_LxQS9`6eq7f!nGmcC4u9)X^B%pq8x1*r=QK+g z|4%K|TVrJPEh{p5GjHoGZytU%uU8T@)iI!HTJ61h{R4?$wNRZ8FfR)U^gonaRmvRq zg7MVeU8XC*VP`4yL4XsQo4=70|r-48PZ;L~rDN z;#*c*e9h75w3y2m)ISzz=L3HVz&v%y`F50q3!OH|qN3QtQ$4eRtgJplT2NFN!*5g8 z$%La}=KO+>6+4-sHpXmte`v{F62Jq%2SqEffGK31tRC*=V(H zJXNb>6wIAyIVafhju`TTZmHUW;JhZ+^aNj z|6>4VWWj7%0HIhBOd^8T7@MQ(b^fY#R<^oi&SwzMGWaK_vg z1j_Z2xMTHDMA82^jGi23KKu_Z^%|V_t$|L9g0z^^i)jzzHZc<#Y8fjTStyafvAYLP z>L{aJ=UXt?9UXdX)JomJW_sz|B9|H%eETT6-qk{%JT%L~4du8e?uFXQ7a#|A;jHiA$A=_Hxlc41@Er^{y$R zU`x9!m0U-h+V#Y42bt?2Y8&V{2HZAf{Wv!q4sANaVnM^{gziyBzpSf8V>_Y0_p=w_ ze#=5Vb-7WN0QMO^F@-~+)gcAcywSxl$mltg)di2vD)0E0l4r2%|7IFnkQr#^g5mLT z)_7BZb^1ryi?&P(^FV<4CwY+g8tDrW(STF(bQ`7-* zh#ujm=b94}Dxt}x%79oJ_0be{quSDnzUkc^1R(q8Os{W!tsPoM!NvkB0TlAb6AG_8 zb)$ghiXNBh+72%bklw{zmznVSB-Z`?EUw&_{-VR}zDwP1km~HVw%1dF?W(y)t9akK z*E&#=uCaOM!=2#|5@fJ?zzexI4*%Q`t38_~O5LWcO>BouF>E3)PZKx71O|GvfUwt0 zx$aJAW7D83dTe`>rg@N+*zR;3ycc=TSMUSb%%vM)APvh~lnXfR)U^USS6T{7avRg> zP>6rldh>(#HSwZ8irA&@38dpsewzueOIYl?r4ULV_Y_6GG-jaU(dW%aWI!VyR_#UJQ29pwRKtkhz#WD8$nzBPI82)) zgLZhDoq~T+{GPF9Ob%5Y2LbD@;L}`89?wP?J-~Vg{0h8rWw34}u+Cnf#mxfhMJ$rU z46VE%jG0h6fwrqJb?I5U|KzJ^-PKyXt?mL-cO@_V1+y%3-KVXTWx;(~)un9Ut9)L! z3I)teEtj&4i0gclw}({{DAcXfLkKn?Z^i;=C;FmH8atNLRFUDDsbZQ;tnu+E6YvQ^ zFvp*@2(GVbA9p3+=91mKIanz0PBblm5+M{B<0;vog4>`!cyS zgvt1&?kgbkS*lCszEc^~n0eBZDMyY;_g_>mWxVG*-|pRW#ch+i_%-Pc6ippfZtq&8 z2F1eN_H=*YWVQPd0}#95ap9I0XW*R4yM+^EFSOHi2_e22NnFYcPTNss^)OGMbShv70@%@*l|cka06T`gCH+_-hps3t zFS6+BpA^K@{gMNxAIW$!;34LTm4lXl@LjHq%TV&%2J?v}_nW$klsdooL&^YQK%T!T z)#@zk^)#sUdTm`T7IfLvV&TwgHY@qlu;ZSJwkg7~D@$vRmaHI4LeM1Kb0rv>PgC7I z;$V;*4+s%udI#7XsOMP1d6eiLrb<6g{fq=x44=)cusrXap4TSVMFL+*2G!M$Cg_2h zm7}Ktad^-I*Z~RbbUG-79gMA55%mRHtI<|p=k42;(mPL<95Y?2XNsgB<4E~T|C@7N z@*b635B7q4;2>uvwVN&d>4gW18w)Wl+mdvIgM3%>C`{i2_^5SVB6`mEjj!1>X$5&&!q1y%hW53 zNvOKb<`M02MT~4ur(oGRX_`9xm{J6?xA^UiH73LB3>`_$CV~p6AygRdPG)3go;jrO zcnihaHszRq2%x9^L9Klq0+AmtHG=fx%ingU{(7an!bB0 zW#MdgIxWaaf{x)kQ!y~#xxPo2nqG|`A1wbsbm|-)R~-86*x<)>X%1s~i9WQxpGE5m zHBRq&M$Bnb^U4G3s4_LJxmRI=K>+inI)|y%W{Rg84nYq|@5hKtUZpSgoMhx{H zuu%S{rQ|;-rJ-}$AUy{!1FzC={D$dM(IF7`*SY{{F@@GMdSf)1_2%N2>eN&FTX|0% zQdxGM*onet;te*>lq-6rVI`ulWoAhPl)pXre|oOD>8+drjEey4dDk^~a#p4(n_vy$ z>%&Qw2sGnE%&oxiKHkKgPF=3_qr_c9Wrv$_43wSvJHhjxyZq*_jdG|g4G4`df9J{mUnMhu^AG*7BemGEf&qpKhRbTw0{*yWB~}c)UlK{3y0;hgzJKje74@PXKKe)#Lhn^HGihOZie|6$T-N8-MJqPVJWw& z)mF2jYgS@r>Q?SUvqznM3*5zwAN>*!EMDTXX+|e~|Uq0gBGKX!@6a-5FG(}SL{%T;%=kE$@mOydSA<{H) z;!$dK%(K&$T^ehjaF>X>aYLliq#Mwm#1DPd__|g0ikBlHf2=tk{ zgglu}*W$+l=#P^#Sqef5;p$YWwpz=!rB7?1hK@{gruuc#vM9B(UQcZ>`}&XY0{JUq zGt@79*Yak#rS+cjMUg(p5m>iwxnw0~rh@&+$7U~e^moxGyJ9a^mfPe!<46#p5gIgb z5VZvZW)VL1;&?-aK16$EHgFH0Wni8>vjKMEs>pn0#E%Fc!^=@ zcy8?v1}z=!|80jRKXf!C3O4GpH;Jj3o`p`}#yzp6ucN-3;t!;AQ`QRCv7mO0EZ`wS z5md-_=(S2ZDQ(Lc5G<4NZ@B?bPc6)HsHgr?>+SUMQ3utw*9F_Y5k72425P_u)C8{b zexahwvTf`Po)$@~)k^klfmX*Jo_fb+ts~UYdA<7*m#_^>pvLaCYh`yY4xj zoqFo+?02H?td101VmQWe-08T1ea07dzqZGULv|UULGDbIKU@?=GBK4hQ&0DG*V!>& zl&mkl4deql{*hdefSCSbXDxG6w4L5Tqc^2FZlf96-aD(Kv=XQ1jI^eb!UYJig+?Ra!u_Cp;^ z1n#628)yrK>vBhQLORhv{i4$=Unrh{9l6Pg3iozVN6fGXxq;8OShm-k&<=j;64SU3 zLKh=lXP47wfl9`-Y$#eGR}ueNk5A(ASdX@GuSqi-%1Iu`$7^z&F`YhQ1y)n#O|!?H zx#f=KBt{d=7FY@3H3byo)-ePg0evl~-1dV@J*|*g`}2~i_8w#?Vdmj?P^)LL>i7Wy zk9yq*2ap$o4wgHebhKZWM(+Ce5+@TVPrPw^B8&hkrJ%gj#qBdBrWTXt_H>HVyNs^O znqiN8Mrpyv&c(|n&6Z0UV96R@>;Z2{!%2+tcSlf(n?FVy)*tztlS^Bi#{`-PX*iW#XQc_8FFa} zGA?Jk6G!*=_mN?db{#rSoqD~~aXr{}=9|9rbx>C!Xl37v^Q1VZS-oU2%2k?otyY2S zwiOHgMO613AG6nhC;r!z)m8Y#(8>sL_Hbw^#E-{DpDm1;gNfEhBa@!5dqdV^)&F7EJ6+z|ji<&iyNFdIVA0+ZjiplMWHs_Xbi>8oE6Mi)HO z(&IXl7p!+$f;yQ#T{`^fAVBT9arhK_oBR8hm%Lhsj@O#uRp7ts+ji>X+MZJ)e*oYN z7{Dk=EbxN((Sm+vd7Ts{ke50!nSrfEbZHlwUX;{cMx6!7fIkSbaa>#u!6PW4n~V9w z@-TL?20PW#BRAx6Yu=+)J#N*UZUOSpX4dCl8zhwY5exs~58Sa?Np9T;D zL;X}0hs1Fk-m4RLe%(^f^cOp6A(ZMTk7)hEJJlu0j7tZv+D5+G`qlAJN#Fg;7S{aB zrY+yb2Al>zgC1_t_xU4ICx!h19W7g%jnb;Y{+8` zWB^|ePkHr)-b2u~Md#-ekU*fY+M-X0JLUs^C4L!?{otnUlA2+m-DA!;)Z6yYa3!DX zbT;>(72ErfT8G>FP2BFl+7Z7p7QeUc%3E8rO*a{mU-wU@GBL{{GwcXpCVKUSJ$LUhL=)945ytk2E@1RQt_Y`2(Mi5PZ}%J~)1fE%9+j zs~*y)EqvVZS7Cxd07tlNHHX?5rz;mh2vVW)fmpxyuED=dzp*j+|HM-F+kNo5Ep@N$ z2ooO7dZ%NBN;4t^tc_HISU|5V6%GJ3+$acD>=>Qb?afAE#}* z^XV>r(0{RUAhh@6c71|-oGWGxuuph+QS{2O4mpuO?Asf1{UJRb$qtLtREi-Y?&NZS z-W1{ua{21IDUYn4mNctytbQ~S6yj{$#!^_OcKl5a$H2YL^CP=#`8oqaUQdex;)nH9 z*My&rqSOb*^wVQ!2evOGa~-JnU;0gal9xw-(5;Xuw5w*D{XE+)q8;@uXd<4{xC1i~ zbXZ2{+5*iE8}W9Q_No1MKO~`w&EAW}-40G1RHcfQG?nn_K5PH9*#Pnz56zNe0PegQ*p=OM@V3QAOu$+nK4Nq+~KHyjs!mC4SQRrFG~S+ z3=Gwas$99U@CY5=_!%3}a6HMZ3i3_6gMy(o!#xUZ-eUG+Tg!-ijjJr}i@dg-hvH7# z=#jo{cjP03iFpWt!A491&5Pwve}ol2=S#z;wlTpOUkmm~n)Z^pvxlWm+vaHqdAxS&|l=?SHx4}T|gi(R2_hJ!W=<|llkjC7TRM1yz z6M3DsaG2V$zz>mZcl^h8i)6EHcdx!{?>W1^ZI49Vyn{560EU4~pxAakK!>JwI4$#6 zrZ#BUrIx+6K$yQ>+fbSM4fG}A=zbV&qK$UdQKGm(WEf`{4a`hk^IYmUmGCJaciequ ze?qKfT(nDz!NDQ}|M5{zYRKJZOM~B3*NPR6Frrg=uU&Oa zJ$(!V=hF_24EM$&%h54Yz9b_`n#V(#vM!?e&EsK;r7VI~7z)@f7J zz>J-1_zmyX`68Bh1Ca)3TYLv zdN~%2p|gwjoT>a^O%?3KHtHVi479^B-N`_&-MO^t1AXCj^3t(1c(AuS7vH~aY%(tL z#To&y#z3IrPn;n3L%kD9zfs%&Y{Pjxq-NiHZPbC24H|tk!x+!uuhI6T-CipGI4`xL zD+b=<9&HQBZS%gu4QTL0!*GmkGN!w?Ooo@T2b>OQp1K+frw%vT|G2luw!ERBqD&-i zjPWJI&j_Lt5`G&dHKynon?0NT`ED^9T`<8JZGbR`%^_(~1-GgSLAVG`j`^bkIG9L2 z)O(RUz_??`!-s8Sj#CJA+L>3*(`f=P5PbcPE*7MgxuYi+W!FfkBpa7U0XKE{Z%=p&#I0lhDp z*}={yoTH;>eBLszxnX)yRv^dtVZU-28~PYN(;gQ)HdpjK6SDYExz%bu*p4vwI>Q2w zGMfQglLYaDo8`vqcBV51A`&JLZ8749QV4<=qe;NiWXc@p)2`Jia57l<3ohH&D z%73DrMm?LucItz)&BTr|N8H3BHgufL0z2`R&^D5zls{)2sWYax0V80oC9gscu*Ym1)ow#*_z2VciNrwlm&3VhqE2i+Rep(>@8Hw?2svbbll?+H z7Vgm$&!QPebgbfNVlKC_?j%PeB;R_$Z)^~3n~;T_40t_yrI>;f=XU)kVl2Z1r-Kj@ zKnD2$liFCD#)I_$fM6DUp#jac>Vb0m95xegecttjf9yB8^7K<=A%xd%U@ihHBL? z>HQUxWlljvdn(r6L)`wprPKahOMI0;$lL;hnt#CnH;Ul$qOOi{`{=#YwEJ!OkG(-8 z1AcQS?)bkaM)F3v#pCVWy47mkL5J{_)54>VZeo(39JdqereaYxKb2I)k2g~Lv|}gW zW6jel7+d{=?lKBf@LESKxx=nMhfzsTn=RSR`_HRNMWKkz&4xy4girm01#o|+^Pp@b zFjuxeCZ}l}ViP}{i;GIo zzL1Yc{xJWxjc#@xQ6fJ1S=h2cUVYXlR0g+*9_M8hi^=owh{49uHNUapE)8UdjG+w+ zfV@r4G}K60)V`HXK5)G|afDd&@VX%hr37+hPs7N5W3Djoub$_H*KYTf7N`rDB+0zr zZw@L8KoLseXd3e@fK)m#=``A=%~5`9c`{){veC_}_n6vrKXm+4j+Ql+Y5FLP`EwZb zm*cU0jE@nfZsj@C4n^&Lo5y6X7Z~XVCn5U7{OdOC0y@J#HnDNvvsC<8-dBr7of4xi zNvqY&zeEI}!R{y>!6R-x;zeyZ>Jxus^vgA^vF^lWEvEKl3V1sy_{z318h%xS(1R;z zVvpEH$BZD^U@MslK!w`sVJB(?9yE&wWD#T$QN%L7r`@ZqT)93sq^U2Ly^wfgd_s+& z9`b)roh5D4Cd3Wb4FQ@xvpRo@_9@RUj*mVQXm(*=t6#RIbas|BJ^u!o*AWL~^yAPk zM?WQ}JHyHxdBiE@I$C`@c1r6i(uaRElkn-~9xyxdi{rL_bmV_Mwh=$|?ST!Vgw;ud z#C^2(kmS(4$5?^eTslT2j=uUGiMiM^xG`&NS_M;!@&Q2t`+e#Y_7)g12Q+qB78Q$w z{tin9;!^Lm@uQCx!Ps|JH)YvyE?YD=)=l7@5XI*E9}U-hB#ysV!H(}dt)6d0Xhow< zgTK#_j&BU7(>)c^80k@Moa4mkEo^(AJ-OH$(`_N-W8sO|h%I$|Wmr<{dE6;XXd2Vj zWKI*go=*2j-VxPUf4BI^(ubd=p@}%9EET$T;^Prt#cqH!yBlp|kIb40Gt^as-aCpn zP8XeY0#n8se&$gDSZFB%n@R%{D2IxLdHGKFAd9CSx?M2Sb7hOS5PvCZKPx>@wCFPr zq$=)keGwl*bYR&zWD+;(-_xd6lL+6A%?R#Pb1vJfqrp-fsN;9S3i~rs($;VpB}Wg<;vPj)rAjm);;T7gp#2~S^p#iAyO0|>X#<9WgrtZU0IyQhnRu6+* z1FUaE))#uaH|F^UUy$RRvZg!b?X8;qU4gOd9t3=*covgM(?y{%rn36Vp#xbMHlhaF z&kl{evorO?u47B7GqAuHj5WHkCh=&#W+Og&r@mc}?Q3hsQS<&+152Na&Pp5|Ep=+A zYE?YOnEnTSwk%>1#I_B3aueYbBg(ep&MjJXM=Sa8==8_2rsQ}OXHsm>sMz`P^o`u_ z4!7q$4oOt}QKKLRI`jhEX>mj8G#=qLV#Q!Jd>umD$xoZBqikF*3sJ)tG>AQQi}z3u zwF1&{+eFG9khM^r$&ea9z(r9D-+>Ex0+111n6F?$?$twL#%Nmn4larFldMwYR?FHF zi>q^#R~I9Q2wxAqVZEPO5W-tQw6R5BMwv2*wsTxU+c#2l&&C^dYz*WrVe z_Tl-?-=)!@m&5L%*R^9%Yw9<{4l?ld^6KlV=af~3_+lglkh{2YWuCsAtSbw9gpy&t zorY0d8OV(Hc9bmAgY%LGL)=l1+ybkJHjea_)%!Q_j3PBXnhzvzDHgl7&Fsaje~4e> z=zDk?KSHj77t}wzKB8DC`H8Uk6OSf2B*fch7_r{qbu=XHp|6-D!Gk84T`Nfr4uY=& zLB4%DIpBHq+Qc&KG@P~~O3G$A+!z9f3cM{eUF2V==?rxAXbdkMgxH19IZl@@ZQLhP zK=8;nlu!e54Ib_GLS0}Hrg`8!Xh4Qn$A$@QfU$#ngRg>!7QXchRBImUat6rf(DWo! zY+%_&SP2R`((;Fhlk8|g^B%O#ty<0<5J2D$Tcw}2#s{g0%a1R9XnAP(UcFO3H5XV|Go9tD`1FD6bYe?*43ffl(zThV3Afn&!}Z`T%! zwgrns@ir=9PFbnjtyaQp2v39knNOrm#-b72a1}fpd&cWMwB5!>V>+@IaWvYVj^K5} zxEt^QQKWE{0|_t_AZiLFYMTV-4!((kq+#9^_j&{bZp;u`*1FL>wv@i0zTt`Ltis;4F^HIiiP<3E2> z@hZ0e=o5hjjmENU*hew%pmwpco9esYo1sV>Ff-g)X5BvOp3iN_3_}{mP=Iy5_ATSa zj{$hzL%lY;uoIZMG>+EL3h**kyu@@v8_X@lm~3fT@Q^?<52CwmbA>kY6wQh_=g{=%fdLM(K!afA2~?q z1d<)zaQoNBU`GC2j<1IN7#%0%0zI}3`Ztl$M-W4B2B|HHygu7n2EC9tAu7C)L(B1e zJ|BPSa;`U_c&PvovSQfRa8%FeUgHXRM**C^8xwR5iZ9><-Vl6vhtRVPw~hFng@rQ~ zH}J+e=v7RhYwf@m*lUTF0$9lB-Kni5i*9hD-ga$HB?m#7x1F(WVn-2~!42(-@8;07 zF`zHE!C*sM1Jcd4A_JTKavsiEx(h%`PLwI?OG=Wm)B1TP6*g)zc9oQP+ z5W2{=`dKaG_Pq=gnYvhC%%bk+!cYlS+$qrg=mr(VrI0mZ`QD+?rJQH+dXJ$^E__e6rTGyMR*QeQ~IsF>|F3_&^+pzqY+-GJqr zbt30ti_Nk}LlrCF*-B!=Ly&oEL~>#G4jKv~HnEZRVB&_5JBOo;g-MGqKC7S0#hr#i zu+i&{X&LNHpIp}`aFoAPGs{!JQy&1Fj`{PBd`?A|ducYZU)vBEn+EH9mqOgLc+}3m zcAO1CXLFQcH?!w5#6}oLbg08#{x|<0-O`I1k#S48MM;!@!po9|`YXOIecVSJ;ZPm` z@a&+6?+zEDO>c$IqTfm^(9hAk64MRi#*om%M9u{z2A+(x(QD6UNAdQvaqBdLn!g77 zbasjT)#})^$LJdLoGDn9$3h4w-tV+6TZ64#0cs*41X=50uGt_ zI@tbFX+Gbr=gN(0&6|sSudUwW2s;GcO6?gy?o2n0Gog8I=zB~byK(?FncNt^ab%Rv z!uK1N+}E#PyT$504zTCuSm8dotYwkETD#K5BBucqPu&XvG-oCG7JNt|${mhrWUL%y z>gD|C4n^{%@X*|Ag8@fQXop))mM#q=uiVrS7YLyF5dk^y^}^UA499fNKzGOq=G9@MlM9dp&c%rxtCl@A<4E(0IR4L)%9FVDdoF zOvmvO%4Jbn)}+w7YxYN{{L2dn-uZ0VJ0I=dH~e`ZW-dLv{B8jM`dWnLYZ1kIGz*T?JMKBBH)88lrB<+VE;X-ANikoG1T$+NxwvBetY zW9IX2G{qIkID$D+Qv=#DlU=5T%e-9!VqM3LTKWu%Lt0-e=9tj`b?dWip3J%_VMd!E8NSD z+POUBl722dfVu9m*CXF^-i49Lo8|GYToGCp4v(h%`hB;wq z#J=E0_$ZF}1AukPis5+-A5|=zS2nn(SAvjte9z(sH@$|p3ikZRE}XqA1baSak-;zW zsS~dP1q1~5Dh>{pnzq*bc{OORL^uKhD2u12@Dl=9DYTNwx+i6uPaAWdou%Zvi)@x> zTa6dnkQp~3l1(@u%8fer^zr{jOn!D54y^*-6{@YtG!$nBpLsoUJd6>r zCV@`X9`3dt?IQe7eHM9Vj%j-*R|k$Ka)sAd0mD7t`vqz@#?`<$rVsA{Iq)Mz@IfEf z7!B)!6hZizGPb8xF(A4FKMZ9S;ya#?DL_}%SdK8{(V zovlf<_~~7*H#M@T^j0`DJ^b@oi=4y9hcIeLSp)?H31k5*9*{q{%oTyRgOwgB(mjmw zx_F>0rk_25NK!4d;;}hpdghKn4eqlUIJ3o|bMh=#W|Ch5l0mLDIM;aH6Bi~x3ygkb zZuquGai};pXM)1MQSYK^j?cX@{(nzAVKMBn{+Z`Ar9JWa^qKgB`IFUaFdzo}fIziI z>4h@^?765O1oz<{%LOhfqF&nzwCe#?s^`Akz;^`9hTy!?~o73 z9w72ZnwP*}^;J`kReF8Mr^}~qvx^5dp>E)M?06GBPu2NCJdnq%#n0}lbMNdt>goGu ztCaF}lDgF6vDT{I`78nK=_kkfC1dxYxK;l(R!3c3jY-J#Tkt#gz#)hXc=mtI6@Be7 z{f;r*fxARYG>$GWj{Rz2=!J?IPOH_s$Aziqj8O=Fksn(c?tP<>O4jkO7tvO{i42JR zSQuh)xq=@DAzdkej9>y|)Ca~5q!OxITe)bIX@04EbTTO{XTIvW@@{`^L!6logy&v* zV2!Z$S6P2;7)hqs@2+ z|4%*AA3)z9L@UzdMCZtLk$d!^h;J_#n_nH)F)i9GP%tpx`{|`&4~|4K(kvR}6m$q4 zB1t}$RYBJ)j64J*ZGyoA?2!O!7Z9!!u)>39l)%?rKC6JBKZ6K%!!0IYfg9t7;LiCK z&f`YLuRlv^>v>kI=joqNLUE80I6U@91KG~8y)i4kfc{T!k0-ZZX0j+58 z`OrZ1CMJ7CSTE9S>Mag`kz_N+0@zR?FxNX^BYa5ueH<*O2<#5>8MOmPSq*`wJ1p5T z<}<}W=$uQ9AKWdD>xPfU0!UUKhR_n^JjlR|9`S{4dUm6IzzG}lFGLjm1EV!&zRunq z=FZ$Vuf!*UaTJULeobTu)$i!Pxkk@m2{oQ!E*YN98pa8{{5*g?NB7JDBNdJ;kP#i@ z$ZSOBh)R-1w#%A3)7BXo1?*0GffB$qm3*;gScSrUh=h~EYqGsoz0y`L0wWC7%O~Zq z;ZxT5UewMPeP$9jmKc3=HrHC~dOfK-J&hLMM~0XYx^I`WcS|S`acBLwXE1d6;FpT$ z#{9s(S5G1+-e0_KY<}Zd{Mug6xvQ3;EmsM%E#Nqn-Y;GPD|jh33Cf6{k2H^{fQ_4ux0E6~rN{{32CAdXzPP0~8O0auI3|ML(r=t_hMm zTx{|$nx>wSJa-)%Zs@^zJaz#1mc_i3|L-iB65Q#J8%qi;XJa97?gnAJC42Hrk~?L* z!Fi2zULfY?pMEufk#ifRpVA1DM+l-9vGn!Wd&S2A#wn5DFUnPu7DQRWT3g<(9wE{_ zaF0lmc=~s#9R@7$8~~h#jZ5dukKiX9pRu4%92Iw)6eEdWFHO_gU@`u70xuvbKSO|a z_5XXWb2#qxoacJu3#* zBS6yVvEdS=u*cv9I-)`nb6cLF6+MW-pow*2=8%xkO0Y*nd4U5cVlFgrJ4$m+w_bLpv_; zAPn?{?5e%1pMbT8|7~ zyV0=h2G(MO2EC*;hYpc+3G+*nh@3uyAzzOJ;~D&f#kJSpfnU#hQi8evD1N^JTzyZ) zE3N|xPlREN1maS?+kc$C42Sm`zCZ|}i=T^NU^a*+&Gv}4zzyn~rqzfdwPiMl)<`QL zB|55m2rTm$@MCx`mpv~M^4P*U(DV7=sj|TOsh8^@n1;Xv09=Ono#FD+( zbC+#yinzd4jGl$A=eYI%6-z*z1s1u$-r_F}#08(6eNg08)kXcS_vuE5750My6~SO+(yq~_aAR)FodXkbfsJH8|3~4jYukBdTK(PjRxCg zT2GY$G)H%71o11DY2y(~sF6v6WI|2V75I;jVHDg4f%-y0FNiLwUEpay{OWP)ZyfM_ ziJ#qW;R*zoV{zo1V;cNvI+wXUaK3+FHknHxw$P55br3$Ke|wl!Yg)eF3?q0(?>i}P z>S54xS1Eo0!DKf?VtWAp%A1+Xh#t@lJ&uCNSlJ+AM$z`d!v?-8B5lmMIW87KoQwgh z;kWuw!BT}JUWzn^%S7a>E~%O~RoiI6BFUI?4u8Q5f+<8W@TFhk2dMP|0~haXt#nLO zZ)^;dFjMvj+oKtzk9r_q_Uo2Vt>2_^@^i)a2t3YQ@a)>tujqx1Dk$JzANM$^+kOdy zS?P?WR&EKHx%dp~XN}FJTLP>X7?gVYPQZ#61w>dBXflIjY+f5G~zFIMh7kSc|i|g3v3!cJePm8rT_QA4u0$1>YvHxTS z2;V{#U4^`wJL%QDGF$b63_}~xzgVm5pF4qkZQ$Yw>j$NO)iq5jI0YMgKP3Em#9&~g zZ|oo_E*^=!AP~eNQG6FQ4j)8XE+cJ^BWsHzA&4Y|sCgPk{Ojc|OihztKu!zyjT8?> zK(0$=6S$6Q*A}fbATCbtOTCdtxLmZ5-zlV;yp11o@r!%)Cy)G=#sgz;M0UIpM1D4YU- z!_C<6)??zvd~27Ub88!9ur2-t<3foI(kjiy-}z0Y?A7eMd(tLw<&C;G2g+gyFXcIc9R~HUDz_tlkpQ zTY?qdF9E>KCNR&7CCy-Zk=R*xFcKPQ2@6bYj9e0f0y23g@aT(-3D&vJtbzHFjzIRa zhVDx4h0FAabrFYP>5jZRKu$DK>&N$Fd-`Z^MDHa_;sw4^D#&UV3R%=T!WU^$gR!u5 zM1*EhT*fY5f>{fgyJ2kKLgMZHCwv)$w|$LfF5oXtn1q2L_>Elz-(7kaAN5E9jV1=n7V%{snCGJudScDF_^|}$pY>c^ao95n z4MFo#(GGF}pH5z_tW?!3w7_;Zm|bH|WOIIA#?BYJfUO-KjxY$Vo5u$^5bV*hlW4e* z&_8JfG^o(MK)>Dt%zYbiE4T7va_AVNP+bS1W=h=hBND_wKGqAf8yEz`SZQBv33eEk zN1PpP9AxnK?Mp9XTO{s87C-x3FOXUnIj@L<6p1-6%LO$sKjJ39!&(Sn5W}2a#Y-Ca znwU~qnFwkN>^Q)}EgAb}MLa3Yh+~GV??f6w)+o?+*C3~nU?CaHgYI$^rX!0KSwbyc z1YLCX7WY-=-|c@Bj{$%0khu)Za{y_G%-Q!g6b72q2;~oEXi-FboJWCCL+KCZ{5%)z-PJ9C>yW!puwAi<3Htn0S_4zXvrGv~N#G^)e06io4eWSr zxCk+GSV+u5Iym^Ov2eHrpVG*fz#uT{;*u1mFccg*@|R+09J;94*MyImO1ZS@0Jn z1>#uSzb1dHrS<94r^U?B7Y0H2TaB>m5e6bOiG=+%H#wPU%Atr&L$IAK>ZVnIoS1pP z|NPuf*AT=4=GTh15t8@c=?srq?E>K`Y5ylQ-jP%XK0NjannSA(ILqHPHoj%~$$!sS z(x-@4ME-HkDP}>myJhy_>(|NG3E=njufIS65x{;JdI}i)MsLt%GD_L&NJ5%J{uUC! z{NP{(Q0Fm3v*n>sEJER;XB@Gf_!U&4bi%dLf!l4aQmI5&ez>p?Y+=ONE=-3!>FJOd z7e25uXsz>q!(z{vz+49@8a?9D>umpZGWkmQ{iXi?RtPEpKfQ!uN&&-v2tsLcU0H+& zo&rh%EEaUrH8g&Q)h>-xQW~fLTzS*GzRoZ3XBiv~?$*;Vyo#T*Q_Kz%cGYu-GLKc@ z9?>jq`R`nU%q^0@SqByHE5i2|0QmPu05CUm@cSneFuHKhX`0pwD3|;|_rmRGfk|~h z0aW~f2EttGektkhQ+|7?avOPn+r?e0x}06X&($}xMZ4zyE3DK>7wLb5wF~%Vgd`?< zfy*rVYeMn|2x1iSH%Q=MX7^?o24Xh`(kTD-R+?1k9OYm@-$GKDpC4EN8zE;bC5xqps^tgDN zG{UbB`HZAir*!40*=nuB3+y>3r|V`Ddx7x5Im!rAMm7llclGZb6!nRzqL7KQydZxH zz^_Ok*x+!Mavr6h9oPUzy4b%B!^rr7DFs9UJb(bkv&b|Y&h}khHs-)1)|>r#K~~Ve zlv=H=aHa(g9cRy&;=nmQy+(=PeVzN4V3^?w&X!-%_4{hB2tafKGuF`8!O)Qf5jOv( zMF6-E0$3fG0Au(DQVG#*;S9x2zEt|m6?Yz1Ut~bJjog zs18=2c}9_Lf$LUYtR1K<@N=s=on5BSdL%aN4P_%tAm9sv|JS_CMnWZlAO6PJ<14P# z2EWW)yDN>aY(g+QJV*&bDs=vy<(~h16mxpMMPd*H5GAm?oZ&c53W3Y0iNyn6as5hY zkEZH@UirYx`hoAoz;45zIq{^oBKxF*e^J2k?d{mGLuNJG6O0TRCvY|k{WdP|ybn`; zUnmI-vzjV?-UnP*4P0zT30dG`A<$!;)K$3d7K*lTAd;wz@IVvjln?aEcCY|K4BYCy z`^{6GOTN!6_I2?8&Yv5X;XawgH?(~C8(IV>V1^SQQ0c{RCLHd}{p)l=`5jZgx(%C> z5yYg&3czRf0K3x}k0Vhsh;1-P;K5>uWy~o*tDB^&2ig{CN{3Mvcru*@-=u&S;JeTP z68ygs3L^{%&So!aJ(auAa@H*>xj+IxeX7i4OP3TtA40#gF8tL&aU>M*$=Kl0DB+ft zLNH^s1y!du7;1+u>b96<4pWIVl?1{R4qiIL$eTlCt1NJ}JbV9(dA~Ub9f#0q1oV1O z|KIv*tMEc&$QlJB7M~78;4Dl{H}rZyvUE^- zgTenJm}-SLCo7z!3G^I52Fc-5fdIUpd6xD?-F<<(FAj))uZYty@yooxNGc$z;K=lC zV4<(SaQ*tVcrYHIX^Vywz@*<_HJ|&*ZY!IzGkZgn1upD^NKW*}>n6T`In7QdfHCl! zrJbagEN{>R#6j?{w8b_U^V*d|$czEWC|dpd^l3Ot>0Md~9YY*?{@|~GFOpKI6tJQY zgmtkUm}VA?qKbTd;J!J=ugKY21*pb37~DQroZ^*E!Bna?c*-xcEpLL=&H3| z-`(APzJ0`Hx{T$ImKj%m*NEKh7n`O36_(eJ!YqW)DWVim$zS&qToAy)%xmllvhZ^e z3!PTlUzyZO3RtO7p*66;J3YXtXqT_z9`M-x`uZ2nKh4t-DB&7`dJ4hQje?8Of=ai; zWDkgJs{m6wwvfKoN1Rq&p;)Eq&Z_%#u2woTFwC~eL6{DX|0N1&n@rtSgxRJ*@~2Gj z0TL1ta02aXUR*~fLj+w^Jp_MJ{`75b@KnKd@iZEkS}zQnvlPEhidcbj5}#C%H9KLf z_3~0K-w%hw`+jS_YwcP%-D{%r8FWVplyob$7(BcdI>^f!dWyqTdyMHG@~M+fVBmL2 z1^*WF>-CB|=jMF^{3Qy$11VqvP9W~x7dn||&Jw1Y{K5?F3w}{woK`?(M4tu~sDZlO z=_+eo5ImTK8?5AduI%L9^XJcCZwELh$|F>hzHP$NZyg}RV0NTJZB#t4i;F3DPPc`Y zWzHa|LHr1M$nDgw>uXbo(l*%1es)@`{{==laITG?BC}KPfI5X<*LZ=s88>VIZ{hv0 zGH5pGsOECHDD+#Mz2M`QFz5^>RzBbgs-0p4GAJCBc&|Box0VaXur;<^_G8L1ee(LT&-v~rGtY^DzW z=Uu;4KbqT|JevZ3Nf#m1P9UOpzgbiUt54ptnuQrXA7Ki*pFuEHQz3_wOH^PskUr%j z7*B4onsfF`5&MB9c+~>aR47hoFvPrdsbm7LuZI@FM_wRz3b+Bck9|PaKoGqYd3uRF?y@@Ne!LYXk~#Tih;R<%ErBwW zhZRJ^Bhx6o81!3(>_y>Mm?RT`r~rA>y)fQojaWBRj=X{e7V?L&uzt)M=q3w>sl@0& z2F0$u$!H{$S*yYS40diNs@EdwMQG|#5B)y2!|yLid6t!X@Dlun2-s%B6m<7m((gYH zo=j@O;%NZ6E|~xVe$_%%Avl4t>%AbXIN7Pz{t|*fV4*c>K@_Z|Q!8L%!eX1M5N1lf z+gcx{y61wlDB4z>|1k-4@-nRF;br&D`kyR*?=x7qn}si;i5eTIuh`x2$K1cjsb!Qa zn25CiookjrWQvlr4jCE<6{M>;bQ8La2hHc*bqNHuY!y)cs+PfI!WOvYCJTnnbxHws zp1u%28GzWh*$83qUyohjr2Pd>_ixHK=6$vK)W7@m?MssG@30*Lp_f1SgU+8{LMA5~ zOca4l6?}}4!6(QwC};#T?JyQ_3&LI$ZeV8NM9j2liwA-Ls=yd%)d-?`dI3qbHO)@f z4}1l5+N1+Pq8Ks~rW>@v;D15~1K08fVa8Z>`?De9D1YU8QtxS?ia>KSZlp=IJ>TPe zZa*FW`aK~Cpuk3HV1;|;Dp34@*DMuObSjX#dl10zvH$!GlY8wF?F)9DAOvDyMo`)9 z0wP#o3|rhjQ@@<9pB}&zy19dfuE1+KbnSC!&*uLczc27I4noiI3qvt%HMMt?8ICBG z9dzK6PK&vO;B@A6hP>!K`@)5#Mw{@*+gJzdHhnu##7N+)T9Zkk$_Q2y6GK-ERsk>9ObB(0sk+ICP5k7IlmZ4R1q}Y1t#IHL zNw8^Ej+Hb&e744kpdl&iJvT5(LlEBQ!y0geR2Z_ z$^(=Nc<>uyPy-JwD4#W(5~TC~>K5h~mN5tk;475e2bZymwfB=M$Y7x$30z;{FNor@ zS~hVU`wfCYdYrY>#xI&^W;Sc#k8LK*?A~>&b@=17+~KPJXc}dPKX*X`yUF`T_*1f( zS=r-06M-l^-n`MmU_p8T*ArY$Lu`E3woD5HOws+i`7kG{Ke?2Ukv1zmeQPqK_x9qGJ1L3uHTdbdgo;r;T%`c7EN7pmt}B1Uz}cq_~j8lGxrsEf{X96!BJM^8`(Gn zk`Xvtz-r*G-&6vqT{%w!53T^NXN>@>cFmL-5Z=aUL*{c z(>nu`f>1e|~L>l#tTE`tY#Db*-qX72rAwt)OE}#B97FRf(#b++59z>=~dYE z`*WBDQT?@A@9n8RN`S@+7H*A!?&?b`K+rD;fX>#E2A=09VU1HZpF z$hZVfCSeB-Ba%S!{73=aX?efH35?vjY-t6=D3~LV zSLp_-BfZlCc#y833t_hklZecg2U9Ttj4(6_+D2(qz(ZofmMURb#qK-`LXeGY0m~>f z*B3C10KnF+HD9;Z>*u?>>2&D~*Gem37yx~V3dz^~erw%t?aKuu5~?Rx)upb^7z^(QvYmscY1`m+k!l+e4>P`Lm|`kds_72#DtWX$^dLI;+Ln3 zKg(4ZesAcTZG;Vv1mNqdobfG5T1g_3?~Mw25{Qj}fwI6x0l9u9M8aL$57ITMGkC29 z5CUS;935XMThxH6@8!5$ovg{A%)*OJg$!Y%Jl#*1XmodqyIpw+0$2qu_xsv(+6ZN) zLg2NvxdA{BWU11xLoc1<68QZb{;+Xz)`;Pi*@^Y!Mjt7__@r|ZB!jEP{cN@@tUqJs zaHX=yv+mJFn_g{(f3`@fPbDfKNEDf1qk*;vdBNgW^d#_bh`_;*&3H}Lz~=#4aHD{) zzU79FWa`P|7^GELU-E6k8IE9zi^b9`^a{;hD)52rFQv&}lL>l``=G2ec2`|jk2D@C zaC(eoU!GqOE^x z;xcfCB?f*>sUHMxmSGsCHi%IGm&gk;5(qpa?``uFECMgT(REZ))r)=nY~%c0R@2LB z^b&FcAdU{N;HsR!Y~%Z#{6&6~vlIP_XL2+P>#LpnEsH|O6*L0KgO)I3&|G0#wsHeo z1?vKOIjq_tq~2jrz)6|LXwJ;>;`^Ggee0q|LQ72)Z(_JuLq3ZkpBsXf`C1PHSQkFb zWaD+{r7!s{GJ!8!ZtitzV4BPqa6LK?rA+vO%rOU9mHnOSEh98&Kq{z0sJ$_v~3{qh%GZitb+a7bj1ddgmPAe=>@i{F706byeHFPkyL z31n0^Spzc#uv(Zfe%c2tHy)Rd<;TZ(15s8Z!hxI1SdWfxtXrQixW8c-m!I!cm;%eA z@DStjzFJtvac^DN?Wzy!onmk~3%xenw1IO+9S0`UCP*iwNS`b}0i2C(s$1=O3HR!Pd|hY5*$>J&Y_<{l3@xv-2U5=4uZRv5IndFcrXH3{A%QnhpiW=Yz$NnL_zFkTHs_t{USOqaJNf#5bdt}cl-VR zZjCek-0eB!oyDzIc3ltX9lqOv*x{gob!>AElyCjD*ip(F@9&_i@9j(d=nwYy5;!x5 zeFn~*;ED;&=(ljS^OBo)b#;xg``zW(HLs>xYILC<3Nq7yoRrCE`1$U+c?*#+Ocdie zf8Xu>N$HE+il~v76$1dmrArEU0l|W?!&(IaIT$)uEQ3)=#52vlp0?Ir8=UXi$NP0{eqmZtg7Z>A|fuHnCxq_&hfZ|#%_Mh%>wVK)0v z+|Mv4X_@9MzvTA!;EQ2{EpSE!=4hORFvS#-37h-R>2E0UX@Wf$f+Fh zz5>3R$Ty28Doj%Ve*XMC@C5J&OOdC9F!J-EaZJc7n_y({)#gxTB52#BK>)joKz>No zJ4gY$-C_cf@ZfHze$iToEyYwWP0N^IEs9Ci3>98aD_d#}c!9R%wTyW=dW&XbXmJMr z@1ef~1l8YNQeCYEPfz9N`TY4|{&}GkFrF0SSvuD@30(1egngHHw@~Y1q%H4{ncv8hJ})S7Cy>iAczmO+u&aZ`gWoSK z1Q6_R0S8_JVvsPfUQf%pXakkqI32B+8dF!GE@3vn_$;T!V4rU@w>1q>r$QHN*Kl7f?2xD<+#znz#ueJf6wBS_UTlHYLaLRd_eqkiG=22Dn4TQMA8Y3& zmAGhzzk9ucX7G*z{!HO2f<`-?=_8~Lp-UQU*rH#paQwT&>{cS2zk zh8(yNu=};BE?>J79%_$2zSn~;Vw~Z%2P4)q2R0>?gpl9`t*=RXx!a!P4D0#4asgXW zP-yL|)w||;uB2|I8T&#v4__y{hlhv$!%9D+?yMeG{Z${*v_VzlFe8;ZqYKL|vf}4m z2jM>gVRpLry9)R-<0ZogJA*4&_G0**_(fS^NaUxYx&woCMl=iHtJ56V6}C7P4kLlx zE-D}`uODVTUa+h*PO*;l&4Zwt>O`iDELlE=OUCdJrRK4e(E=>2~2Tu2@+ohFNo8mV?7hb54 zcvS&^X1FB%SFWO$$I*B27hOs_@cZ2^Dxd=&K=*pM9E9j57virAS4s;zA%ch0^>Att zE-dkRP6F2 zi3gG2@0*$(GjKgYPDXeY8i-z?9!#EPi8)863jmS=D*U>W0A{rA(bTRzXZ+*Rj=7_f zMO{Ax zIq<1o{O|zQy03UFKr%u`OJZu0w9p&;=_{a5Z&pp$pN>KtZ3{ELQ|LJh!LO0PAO{Np zxc%;)-ze4Z>!kffq60*>2HGIRX%5VYgiSPz`p5i{5q`ayIYZ8RDoQPvm&^Trt-^&C z4-CP2S#(7k6zZh4{U%i2qAG=0o5tZU56P%~%^lN+E*>nahZb}%LxW;#2PSw@*x?g% zrGgLe%Kn!x&#gqQgD`7ge;D{-l+>UwM5wbqp|HDB#T1x&~2!7pV}{Mhg7_{|#kD}alf z*O^sB!Q2pSgs_|0FM6FgPWHrHGQm`rYQeN7S6k0Gu`oJ*rcxG3Y!|Ut zOFwUCbJ&{uS_e-H$TNVj0+emO+pSREpxa|UPt+|^xO-5mS{_#9DFT2fkgKOJNwYa$ zx03ajyZSqOcI@08+iLv1MniWpk29f5RaFkIM;KX?1NsH1E-Ti%M(+(4z1%h@-a z+!8(TCOUDwzATlNow%nH0mnW9S?HxIY6d}8e{RNXfo{T%*Sq^q^YyJ(H_FKU(=K4( z`F)bZ+-rsncDv<#W86h>Oy^l*n~=FDm)5)6MgBBWCKASH^l_YsNYg*C3wSu}wigzh zVMGDAT0v)<0&WKm;Cu&>$OG6}1>^&OrvQY}?yUmIBgmja6$51y%U#l6^!rK!3(5%N zZ_jAA7&`_CC~L&+PQ6|#m8P}Q64u%jAZ+xcg&O?GCP*bSgDsjtV`H5Gv_e(Y`@ zn)%BF!ip_@^MoP}rGs?4Bb8I~r|fTn5{M@FL3xS5=?dXfmn50@p#t$-#oDXs;LG|v z^Hp#x&|?@Ug%cI@B#lQy}Q)z68Ju# zn{sMKVM+yzbZpED=!l?ejk{h*g8Y&EDVHCsq+-1ducu=@7%6&ahsnk6j z1cC6}B7cRxe14>qE_pyJtPDAH`_2iy`KKM$Lr->QfdCjHkOve(Y_?JSsV}lv_501y zsf+!F$eny3D9Q31x6q0e@4F z@w*{(%xq=@v=axLgjC@OzKUSP_R)29{g^{K!!%trrqy34h$?!V9ZoN-jc}Kny8-3G zd~{U-PfrkgJWOU%nS=J+UbAZr z&wsS?W%jzId_Y5;>A=YkReg@tfib_tn2Br|>-` zbXrWl2dpsoqbZD}_5~Mwz$nPz(OYu|M*v^Fm_(3A8BYZ^-b$)o6~Pu9CXv6}PWo0HWa9S?>=xr01xA1T6K# zld``Mmpsk;qo)x#f~(4Qv|F4`+o#I5vi`6K`--HMh`k!>pSt^@hK}I=LkW!S%^tQ* zKPc^E@X!b&tb}l>+-4;V#~F=^+3FU)-yr_y@)u?0BX~AfxPTcAfVLUNp-+H^fi7^D z&}hn*m?^;8xh-p&sKr+kpN%PghOmNLpUAqvD6i&%XS>L%r>q$NT z071wO`aQteQ&t#C%kEU9LSQ0ITlu*X6PFVPqNci{ES8K;q7cqpR^ zc}Cwyh7V||gEE?G1@QEgG)dBG&F}6$R~D`8)C6sS4~_+fzO_WQA9Cd^>J#B+=z@w( zw{mqw5QAXIXnAPO*X!12%#sF!{Iuhy=VV87gRLG^Afkfg1kqceg@#^}FQ}Ni(bE8C zvwP|fwkKtQN87=NJt`oYQ(C6AlD?x95dFXX2YU1YyujL8-G|#6UPuI445#E1)=V2s zN&~~+A#UM+#`kkW-&8E(r#*X}zn(SD9VB~&#Mo5D-EQ80hN|UYP1T{FyZH$PksXt= z!~F_bU{SLit8O(P5_$`QK3NU6G|6?!2ylRR@Ie;|sp1@E@cCh}eOf3A^ZCW{xCs^Ry{5Wo$R3BqFJddup@#C z)#Ok47Uf~3Rj`n*T+~`Aa|agKc_kz#W8u~Aff~9G{pSi>U`e6jPhDCC>Ro|!t#xyY zWlKf?)m+(hXl?m4M{A5cViTcq1``NIcF+j3!=@V`bO3JPNCnZ0QDwVO_RSlSy+oWhnpMAY?iqZj@!Q5d;JhTJIlf&!Y? zMVBow6e-tpTNZZn=ckG~OnRPQ9+E*?^xQ2J(xXMZ@@<+yh=E6Wh=FC;Qox4e1KZ$N z5I_}!=xMI?T-VYCJXHz_4LV=9T6ZHFDWV7jo10)$OM+&XOzwP+W_h(r$nfqU1_nnF zJV;sH_4EX})*yq=AC>&6zYibxNRl$O#-=LGE7d+K;@~A8*Kqlu{*=vL?=5Id+umGF zwII?xR>EnCQy8wN-uxHZ-^j($$-B>T0WSw3N@C`#%7O<0UF?(?P)1cZGfCP6!mNP_ zHp28#GY^Fe^g#&HA8d{M`3i_J$oxP}Kq>&S1C?N~@CqZ}1e35H9v~e-nO*qQ{77w8 zq3>?BT|l;A(udrc`O{*6AM^CI{Xgo?zPC{%iNg~hv&Ni3Yjl&aAjC*;zNNjg5QiN_ zM)Uo@)zw=!-9T*5?d|TYo!A&`PyTr3S1(;vUFK+h5x?V>fC3f?DU3M=fRE6_o9`2T zDIBIKmjgjXXxWPSb%-W5zecuwCa3U`b-TZj@)b|Zexs)+XQksi5d8FWQyR(p_~vEe z0lwU5mUCS|kM>^==9OIX9cR}98~jR#zizxx%|q6BQX69!#Avq3wM9}(8KPyv`uQU;s_QGDc}v+v-m67n>#NGrEMp0 zn#_Som?l`NA64#wY2;(!fJ8y<2)ZB7sNp1O2Zk zf;M}C-*is=!LOP?j8M=mgrhk6>f~ttM#{Iku=cblG$@>f;Mpq3#{hPZ+^%~P!1LvU zKBZ|vc*OF*J%ln4wV1iRv=bs#OZ8Mz)w2nPXxqVWp@CP00=VyH@<)PwZF(w&;mQ~E z`)CXT_!3w61~ne=dz!K(!(5N#6;SUwSYX78Ei2kqQM}0ClIY26yqr$Ypo7Pl6wu-? zjzARQC^qNp2isN;5eLYNio(Bv@Dm?2nLUr)kv1>eB^NASh%;q48W!yI!* zy+{pNV?{)kicB#j0?RT>Q=c`B1&;VSPQLT}q((Y%qsq#1x;5^6mYBQ-S@P*JArpj?2q! zhaRTaHCUWlQe7eZQ!3BW+Se9VqTH>G93BvM!eff}ka!)oN1HtY3Pmv{#!v?1!J*OQ zYX-|o)4Na#Uw_aXO|hhKS$tnOMK80R7#@;7vDuFSNFm7C+D}Awmcs-`U1uk?SJ+nB z@>at{Q;QklgHlu~pdrM-gP!m!*ad71fL0co_eUuk3C_EfyGP$oqKXBBWdr|&D$%IZ z0v=f2maxNppS){_9^hVOSlD`Gog=C=aB}F&K`0kOcoW~@z#qcnK(H}uF_N@p6U_J- z)9i8>MU&w+_8UI)nVrHP+xc7Z0dJ-N*Y3Yp0lji$0B6&)f{{vG^1R(NdY@}^LjX~s zSoB6tm!DO%OC3=$QJH3GG5eG5|Wwa!?!m zvswI550z>**$DW3slTM!vZmW`;teTd@WL>ZcZBpCri9`a^EN~hu!oGnLyQ?iR78Hw zm*hQ@APy#VXrdNv#}UFG%qJ|C1FmM}&eMopSNk3oKT7}~0+2%xr#|{c2I8x{5%_qU z^|BF@+EFbE688&N30uubcO{voKOO0E7Wk)fxf|(IH!p$&9+bW3&rUGE<6KcK>`W2Jl z4cl$xBWN*6;-H_jT^`tETQ+zKm>ERyAwU0+=D1j|e4dw=KFyas9`gOBr-u}YCuX`z^{ft_{9tOxcP`FGO7L9e~w_fQ?p?yr`@Vh&cZGTLCa<5n>*d%kah zo%P{Q-xGqIU#xyj+26Wtn%04k1?_Mdb-^e}ALf&BgjI0pM@bN#u_3dB&@`)26jAg@ zT6JyMc(T_6y?MQUOMSp7dOV?xN6K7P3q~9R;Z4iAXVAk8SCjFcrTsA^tqZk%wV;!; z`nA647sohFk+cE*KA)+JFn`15m<=%7U^de5oh| zu%m)KoF@4E?fIFf_a*T2?b|aBG5|@;RO96|oo%s5eAY2a^YI#uhxV3=W4c2P$Z@a? z%=hs3fF$B#N!Nf^*yTOAeRYuH0P`aOnA!rj)sPw9wuU$wSS?4g*{hE}TZnaBG5Ufr z_<(>P^F;C&YxR?7W1bU~Kb&NggvaAs+fv8@h&bgk+OO1N7#vO? z0!Vp5#t&?7PJuHRT!jH~cWAt}Bmh-;Z4Nk9A;tM^xM>${*rhQO-!F8@bF6RZz=%KF z0V@CQjZJO9qFplN6E=nvfX_5F@LY>-A3!IA&G$ zvo^P4G4a0mzUcR9=R*1E!4TxU7@EKc24ki+jpYY2ftAqrTz#WEh+z07Z%Vu9#`DHG zffwDaiT#@DqmE(eSnserwdoNy3^i~V2X5(IV;084Mc}qnIKe!nxgE5f13|QkSom(? z_da2VTNhZjB#cswP>87`1SJ6A0H!%cE9^6BKDmGR%k23^_DK4CErcYRWXI!J(%Yho zWW6UT{38)`t>>)6XyN7+vohzkd29Fd?|T){Yov=~)-bFQ4EhtsA*IA1L|~_wzHikt z1s=Ey$f@b9vIk=5TAye3cj`~UVG1|?DEKhMyI7%$N8tPQs=?Xr5Of^)EpYJmhC2Pam{d-VHri{)`G1G@s+s{Sf3OSP0SGA~@nf^^NNUE~jyUCx|U@0n<#+2=Wwm1Xo zYW4?9bVC2r5443%fMWwe2-yH@mu@2OowZFrCSj83i$?w`_h5^D;5H!zq*5AGLI#U8 zk4dCdjsEeqItrY`Buk_YpZ!QDZl)AAej@tGf$;VJYsc> z?28zZF-9y!0Z||IlXe;L3P;6gpNB!Ga>!|v%+2umSG{ic$_T#xe(@`wW(K&J+1}Oq zQg`6wUGdZMx3i!0<@+Ys%Z+DtKCf-88B9@#_5-`zOmD*$^^Iqi(kAw}sxPn=@WpZg z`~4}KnuV9L+@M#7jY{c>axq+rnyHR^SybI!ySJbZaqD;V0Ko!}Xn`l<68)Qm@9>zBxGqP7T+x*`3n5f`zwuNigH-72v*3gABO%Ak`K6zDLjr)`N#k> zh$Mx^*2*b9h{Y<4F=mkzZxOk(GCIVdF~@oyjaI_f|0T^lYh9c9fW_L@ZpC-IeinQ? z>tJT7Kiw~dzL+sF3qwp6ST*gYH9jB?AQ(jfYut6rTjHm6%=my~-}Bdr3s|dDmUni$ zusbv1dg2{gkLg~EX?Hkq(;OzFTkp`*9$?h+m*VisAP^x-G-HM|zTxw`;gU&1_~5xh z>zgD2zXl`|BoN+-;Q9WffDE0__E%%*`#MA(jFHxY=nIaN)JQ-Wt&O+%Ej22n%gzglhq{BTzTyml&}Q;Xkg%|w?*X5 z!6u0#ezXlXSPF-U5J#b#wdap9>SCXFf z#ngn6YX8T~aw%Em1ZT93D;wZI#*B<4XgE1z2DC?V|=d@Okb%OGo@91W5z6kF^Yd6W})iI@6f?JiChI3DC!Dr_QxdH@Iu zgpd(jlfq&S)w00A-BNW?iC|6^w*rqf`0SjsWq@}^0C#tNK%Q@P)+4hP8hF0+2eoPQ zyoI|E*fhb*Shrk<*R7P?o3hhscvh|UG(1oSb{tOBF49fy>SgIRE0JLhzPOEY9wlNL z5JPTJXUp5`p@qm5TUTRpnLPbS=jewxOGxi3F}n<3!skO;SY+*lIE15NfsJpm^%Tn? zs-L+&#Ktm{W@_&I*kBkDk@7$Y8YF$G^n#E6`p@5{D zDOlz8U^<#Il`GXx0thk4$zj(WoOR7{eo~Nem6jD(d)HER4cK$s+l!(gvq4>uP#Ps6 z23f!=E{~YV;~Qay(FfVz1of}dx~Da;qW7Z)@`_%B%OkM^pP_MZc#M7bZN83@i8M0e zu^h|6#N8x>5j%^+Kw4|9+X*;UfU?{p#@)`E#ksL)WKV;p8?Rnu?oTO3S)2 z+itg9hE8Ty8V^%%Y=|oThuR0EQA)B!UugS22Pib66$jIb;TeDj91(agazlHVUZkgBC)c7foW4Li7pa=-1D`{bs`B z*|_jkhtH;MFIJqw84)4?Hng?vbeKUV6nReV98=+|asP>1!_=JYUK?<@XvBy@glNjOG*+8p>9iA!RJnDUy5QEYXFA+ty{c2HRvRcdF31M^c|^_HJ3q_Q6i~q;N@e1aJL+0`n1wZ>1y25 vLzRBJh1b24=1a~KBf(Chco^$TK=hXN9 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

anejj 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

;lME8O(r~0c+cC zVj@BYsXz*5WQKqgl!m(QwS=+;gSbAy1Tb5`?#r{B)JrYeQ!$n`Rv;9;lV_sPDpp(4U^Vln!}rX(4>?pk`O{kW14Du z@^-twyu99wE`*R$Vi3ldX5LIdt+d57UH4oGJ^2AgkRdpwQA$zOMNXVjrkqYz%eMF3 zc1*0A*=n;nefRwb-+BA>{jN_LW(zHa^*K@&L

uGS-$UjVUEl%9N6GG3N^9&E(>Z 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≥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⪻wMI}sWENJP$6T2ob75%k{YOoR?G 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�ymAdCg9eof<*F%HgG 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 diff --git a/SlopeCraft/others/BlockTextures.qrc b/SlopeCraft/others/BlockTextures.qrc deleted file mode 100644 index a20bfdbe..00000000 --- a/SlopeCraft/others/BlockTextures.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - Slope/items/map.png - Slope/items/amethyst_shard.png - Slope/items/book.png - Slope/items/iron_pickaxe.png - Slope/items/diamond.png - Slope/block/grass_block.png - Slope/block/waxed_cut_copper.png - - diff --git a/SlopeCraft/others/Pics.qrc b/SlopeCraft/others/Pics.qrc deleted file mode 100644 index 19d6db90..00000000 --- a/SlopeCraft/others/Pics.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - Transparent.png - BG3.png - MCStyledNumbers.png - BG4.png - cover_3D.png - cover_Data.png - cover_Flat.png - - diff --git a/SlopeCraft/others/Slope/block/grass_block.png b/SlopeCraft/others/Slope/block/grass_block.png deleted file mode 100644 index 3aaebc55e422f77519d509653ebb3669f1a9027d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 zcmV;o0!aOdP)UP(5$cP!zrIxlo(DG`6G2PLYY56gos{LMt(#2BKC- z6;e?bma=qaW?^7st^_Mg{R^-nMJl2!K#2I1>NLewZ8vS~I=1uD;)LNzS-8u)ALpKP z-bGK|-p3fnaop?m06-7~&-0SWq%6yn(jW-pIK~)LN?q60Gz}w!q9{@>OINRCG@=}D z9SVXFMbW{*fku=Y8J!S9DNQ62ilPjML#$59r!Op7md(I9>Yo4r&-49PXPHdqB=#}J zv*~N}wcqJ<27^KOrOl=HFVf|e@7wP#K2h;bI{0uF?)m^QnEQLYbx7xjKc9coRq1Ru ziocxes>D5haEm(or9yW3X5szzuWES)BP0^xbjJsP=wmNkUYQK7QX%`t@kAnU^SMmh zc5|xa27QcBittUt@&XC~x+;l8u#6uf5&V#fM5tBr+_Oh_y@2{5^+P(fu-4gYibPmn zDpqEv+qPS)00f1U1ud7mY^gBg(KcsEjjYp%VVI>p18}u2SricK* zZ7i3@2-ES#3mBnNAqxPe;{gBwGz|+Q#Lee2nj*4-b-jSq|xEXML%tt5UtuV#Z+ZUT3e#Z7i3VXgnIZL4V=;biL6^5k6EGCxRn(x~5^} zRH?JqY}+n+`tWw!cB|zX)A8813R$_{Xu*F`tK2$x?ij0H&++yjaIch0{~;q3HEHRE{=((7S{C7Zw#x; dMq{gt_aEnkTxF1yhgSdq002ovPDHLkV1lhoK$idj diff --git a/SlopeCraft/others/Slope/block/waxed_cut_copper.png b/SlopeCraft/others/Slope/block/waxed_cut_copper.png deleted file mode 100644 index 022dab560b3eab66e172ce7f77784e147ba9ea21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 417 zcmV;S0bc%zP)UlCf$6K@>%=gD}G`tGLA!+GrtI*x048$S0)EH{>hw z8TowkZ2PRCTy; z%^WV%AW?^ln33rfhl^K1uK;do04koCba8OvJEl{kebXu*Dxm=s2bUTh(>ycvZmmMU zeZI?bB?tCjP3Hi*q=n|=ZiCkx;(P$~ULNkU#IP@|O9Jwni4NcwnvxsjTi}yy00000 LNkvXXu0mjfFMYN5 diff --git a/SlopeCraft/others/Slope/items/amethyst_shard.png b/SlopeCraft/others/Slope/items/amethyst_shard.png deleted file mode 100644 index 4dce791567ca601a0808d912926e31ac681d5613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`eV#6kAr_~T6C{Kb?$>{f$R z=aTS``LA^U*&p$nVc~qibW!r0wg;D9EIQSCUm&GdAw6lc=v@Jk_X(GK&W4p33drYh zX!^BxHW!qXe5n`F&$+)(HvNEN_8iM%wFun~HfaU516QO5CoXyLF)%ci@>iV+_|pb-CWEJ| KpUXO@geCwn#7?vT diff --git a/SlopeCraft/others/Slope/items/diamond.png b/SlopeCraft/others/Slope/items/diamond.png deleted file mode 100644 index 8ce901e9cc1a877bf0c998abc54d6fa74b21cd34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`t2|vCLo7}wCrE5@*s$W2y^&g^ zvC)oS|D`{+9WbfhyO;AAcl~|_=>-KPuj?o7c<|pPn=P{?lkK8{VN;ueG()jfPuot8 z<%}<8P29_HC}{Px=2(VB8>O0Z7|yuONE4Vg)1upg*@0n+K&0^rg9(fZXDfIezG?dy z@-*|XCQfj)ILxTRc$w!i!(ju%JsTM&U8yW!Ue2iSUciT2fmI=W(Q&3gPR^SGIWyE| b@-a-a@cHstebH~As~J39{an^LB{Ts5gMm<8 diff --git a/SlopeCraft/others/Slope/items/iron_pickaxe.png b/SlopeCraft/others/Slope/items/iron_pickaxe.png deleted file mode 100644 index ac75a0101b5b852a0ab5b2216c5637c6c675434b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`O`a}}Ar_~T6C}1AIC}J{y_K4$ zF~^-9g^&LqY-T?wafGe2dRFJZ^B*Sv_Mf6CBqUV8W4yvR_V4~SneX+J_Ofh}e5N#^ zQ6-zrQaZ)>jJ1n2)1{s_IWx*Tj2LdF&5*drw%~S84uhk9!e+^v3<3u-8T4jf`3;L}&m2 diff --git a/SlopeCraft/others/Slope/items/map.png b/SlopeCraft/others/Slope/items/map.png deleted file mode 100644 index 45019a54f2bc9009ae2f1cc3519b2e0650693a4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`6`n4RAr_~T6C{KZescBySMb^P zEPQ?6|NW)qqM2<6a#%C}e10x0(afWCN?^uXgWeMoDGAl>PwN-u9&K~XGT>> zOFMu^(bZT-#~_A5NFjwo$E=`@(at$x+oLNzrv(J|{!Xw=?7ab0tKw%boFyt=akR{0P0jdWB>pF diff --git a/SlopeCraft/others/Transparent.png b/SlopeCraft/others/Transparent.png deleted file mode 100644 index 1b4bdb109de449925bc66fd26f7f2a77bd905b68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1613 zcmeAS@N?(olHy`uVBq!ia0y~yU}^wi4rZW;wXmfikdiEMjVKAuPb(=;EJ|f?Ovz75 zRq)JBOiv9;O-!jQJeg_(RKynG6XN>+|Nk>*&RD!!)y%-ade_s%F{I+wn_C+>85}rR z9N+HGoSf~*GV{Dzt=Qt#r(WAU6%@Pv|&oV^1mj83ECP5aEOxf)GJg^M?6`+=QF#Agk`0WpyczG5g6ErR0|PNMM}r`)gaR4w}vx%^034YPCg(J zMGO(FY7oXSr2zBD^nR!pAn6h$0?k!mgYm0@C-2+LM!Rc3SrMv9OaUYU%#mm!xYdAD z_X}rW{v$iHfh>nd9XXi|k&r;?1{QS`BqU^GC`?G8bOVbz3KJ4I!a-42?I3@c{DcHI j23WvhCZxCz90m+b{0e%!J6)aui+%=AS3j3^P6 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 diff --git a/SlopeCraft/others/cover_Data.png b/SlopeCraft/others/cover_Data.png deleted file mode 100644 index a05472a9ef4e9cfa07b9de2e7ff3553d65519270..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52986 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 yw%uqn2*E;#CPuzj!IUUv5QeZ zaB^>EX>4U6ba`-PAZ2)IW&i+q+NGUamh8H%W&hQR+XV3?QqAE@V^j~S`86kFpHsH4 z?}w|-w)Z15GD0GOg|$Ecy7vG6U*Gj#|Mg#?rk1ZObDX*uOvj{QPej`2Xc^x&8BH|F?fv zR&NzPC&jo^NH@Qy^ydPS|BqMdd?TFSxhQ|<@A-V?PJi7J3-a&Q>F@tuuITep^S^!3 zKkdrje+&Qq>({^TR*rvOlKy3ppTGb7w_m?P`Im2`zdtAb<0t3#=Wp?!zy7{C{;ud> zR^R`B-)i5vXYQishoyf0+|*yUa{k8a1|Q)^w~I@A?#llQZ&A;$mtPI5o|wYA=RNo} z!y6*o^@SW(=-~_d{5iwq5_8;Fto$X$8PoYIm&U-G1?}QL{dN7PKk$9JLI`*Jd#$*x7+q{G!=3YYUdE1u@6V!^ zv%r7-`q%&5*TfDMS6LT%S=jM=i&4V=MS^rTI`P87pFbZAb^Un*mWYooTnwI(1G^Sd z2~W6dj5P!nvavy(OOGkX!48B{;^HD>PU&H9TJ)p&ks8iRV~KqE;_HAJJ5kb;fI4=l zvspP8?5F024fT>rE~PxBmR8=D@?)-G;1-*|r(#WG+;~90d@s2(*pP6Tw&#be}clH%mTHwce zR$XnqtM9NerJZ-#&#t@eclQrd`_lF0uYAu}zxKUf|9jW|Z0mpf^&jk7__J&A?36F8 zfA1P!t@W?B2*OEm&)Bed<-m?tw*Z5V?%CZ!&e5H7&+a$k6(w?!#XVcW9b*Uc4zYaU zuf4nCZ%5s^|F3UDP|_ePgAkr5!_g z_kJpG&VPfuneRQuRWcW|pZ<)p?lhkj`>bi!zDHsy(gD7GlPZ=JVd%<+$JW z^|-$m0J^_xrug*lc_Y{Syl)yGci7gBeJ3Jgi}`zVs=nunqn1!cneRwtguc>#c_qR4 z+1CP2XI}4ayj59i)bCC#TG-tAo(rHWE3$}$!5Z_(<*VbvbcS0vSvmqh4DZ!Wgxb@O^VQ2EUo@YPti@W0fYs{x^B00;{@o_iu+L)IP z6?$zCwZ2#!KJXHe-|&7|!ZX(5gI;_N@6SYHpa$>idF(g0 zjdyU#uG;zv#>xv=2_ifOfLl$jtnBj6itAt)IKgMg?rzS`Z`!SW6(kya+- z_sHiLK4pMzpbOXELx?zeYCs(O_OktV%WNK&INpH&VMT-Axv&^OncTlszs{S@4FdG? zX09_mun9nPH`WmHQP}Nk02wvJXO~bXxbcl1)`z$C!Rz)tUUz}l^J35=?x`cL$({_1 zf!$6Y`?fBfG(7DE!$X?5RK53_oh!z>l57C`;-#I%!d}GT8tUHf{6^*NSo-umZC&+= zYb+3a=YoX;xLoQeEDGLCtl)LwVf#~GwPNQT=&0=c&i!#E?lzyhz3F;hKp*!8i*5n| z>y~$0_me=(42TSH0?(_9U5aJa76z9FzW|QelP0nP7m+A362=IlZ-Kvl`%7hx*6{mI z#OMT)FZC~v_~AVv0RInW#ty}T{3w`e?{oC4KMng~%{HJu<^psc0^fV@kL&w-z?ph| zOU_T{$~ydS?E*W=fb;zjZEy>2_IiPjUI)gWuot#nlj2?_q`fv5 z3)>p2aYc=H#M*C`H)3{=6nm71=!+dLY$1Qo{2n7>jsyX=3FO0u_*>X%?NNdCD-ecC z+5|*57H|Rq$`^a)RprL2>m3J9&vtwb3&qU9m-#fde=SgR-=&0EFSQ5P`RGaj1TObA z0@E`#yK)cW5tgAYd~%5V<^3`-2>VR6m79nR5yWV?wfTJf^s~1%eC}xj)NEF%bJwzR zV>jjvhhI02-{&#U?)JDx)knN#4Ud%c?8yLZr6PPC>`S3gS4@-b)wN)WK{;0R+!iu*?3S3;>iUxK!3D%vppC}%nQE8t+19aBssBQ?8{z> ziv$oZT=@p@2ngTiZ;=}|fMTnF03vkgRhth1yyRGH4gnIj@rpaoVUcV@xKN&p8-vW? z`CrCJ0MwS|#Lclb%$j(x3B1o-pkWOKl2iD{+pvUpEY_$JX|4_H1PeDeN>q~gfE_r@ zlP7jDK;Ky*DDYOXb^?zrKxh{vUT8rv<9S@n#iopJvvF)Y?uEfd)_Lm6y6N6{*?tc) z@*1{j+$!eBFtv7`06)uE%2kMBU@sJuyF=f9Bf(}tImj1G32FzA1M3rZ(pUll>%iO= zS4{LI{#8C_!2IDV&{rrNAJVpT96X61Y$2dfSQU(MahGg2tZsmcm1~BjgDf2=k67so zXk3t{wNhDLJva-E#?9D9!U((_5`)DPWZ{-$lm>1fX%;vNKZ^CkBj$_^&U3Lf?LoZ) zGWm%k%W#QP5OYlb!Qz3ySAK#-fu!|_HXC1>H?f7AidF)8RRL$%a8Xv?{QDwq;Kq>37e66#7uL2m?&U235ajJpvRnZn9(D>j zKn7xG(A{Qio3{{G-{;!MH{t|W+u;B);mxW>F2$LO|kg4_<1ICQK5bYw81XG7OAh*Cw!rRzaP%~--2GYI^{YLPN%3{+YB1_Bo_eYqfn7H|eCly5>8 zUX~McePH5H_W&u@^E1-z>FC$~m8<1EWjaKd`-QOr{wVDSAA?&FLjZg>8fFdGVl$#P zcK2nby|K$|Wq%c|SJm0k(||yP(O?E(YeaDnf#)b}`~;D}y$Ct0aEF3a=?{G7fu~~% zQ6f#`n-GXOa7jqbGWdLklX6Ft9x4`Yb&ojZKzsI2k-^rZa?B4RVp_v#LE!>A z#nfNqirR!A0+jJ^)50ceVcTMg!2U-@%XMb9sw!XXsk9S$w{cif<$@Lo7zQt6<~cvk}SLO3Gqu)dvv zBKY~dpN|FZo&pdIf`5=?|x`xO`*j0uLoM#*o97zWe2#$5VlqGjw&zggXA$A^PC%G%6O7jiGYA*hnsz4fr37lOp!o16G{RC5x~9?`D*-(6TX?30P3u30v||5 z_&;h1m7sQ%$S!kS4YJ}OL(28l50p>s=9>_g0 z7fZ$t;4$ zO^TVjX-4h;hEK_16tN;XP!f0dZste`9oYT@LowBvp$wQ2_OWtrSI1VkI~aRK+p|B3 z7&Z;CP$0s^`q(Due7=+W_uYhObaEd=A*fZ9_(zDz1&?I8yF?0{$_5VZ2`|PqP{|XW zc7xm#q(r(vKnt$|pI&LzNmk|a`vv`l^n_3pNX0}gyl_73O$5$8XEIbFR52Nd`B(c? zxgr%Xg`KgcT`L=RVRCOxh7MM(LZr9i3H&0`BI_~Q4ne9J!G-B@%LYo*+-SrOkeR4% zq2=o)POmK1Wt{0l$H78yHS|wZ8l#7aokS-T!K7f9(lC=+NJdLgkWhbh$HT zmPSa#Qur1OWJVXFaMo}dByLW~`G*n#KE%#M**SpA`NrDs;m5$2 znz_wkxIhfx5tk>Guv_^1Ox*U3H4%{O**}3hdTg=G>1?wg5zMN<3|3k+FR+d4f`nWw z2(Aob?9wO1j_~%G0h03!Q~+jx=ptGx0MS+um0mHbR&MMi)HEufH;Mg_t_;pZXgpYl z&9lXUz2fcpIn0KusM4)O#EKBChKz z@D!9kI|w08fIVC{BC`lscp&f_ebsEK%{ut_%5K3l7Wa=|vD8lm&Yv<(l2lb|z2hsj zMXP-Mg73p=j~C;Lv7&Vz-bl|U!e;!C7?344Cn!;4+1N!zgYgC!hYC#3WT9BEt(&n%SwMe_k^;m1_B>RDco;Y0 zv?6#wj~qY@^W$6BOQw^+9KtZh2KGWC2F`XXTRuDq8AYgsKSTHN^NuV+Pkzul9o0ip8^v{Vzuc!*i#ZVMJP+7qPbfUg!4>4-){SiZ z2C>=mOFE6@`24}4D+6*kB$wX^e*#ch83Y{TF~14Yx|iw2gOF!zBc^PwoW=gC8TUL3 zA?fbFRCvaH2sQXMvIr$;N{wY@7#k=8 z8RNn>#Lwgj){b|8b!bY@vRK;;Ut?u3-Ecv!kmm>@=xZf%!x-RrMDBP);t^{}EHlpw zz`@U8l`DBr2FLJP@br^Xy9je;7NN=}^pRD>cmR@nSx|t(wh6R=-pxwBm}>&jggoF} zZj8-B+TRV)g4yADMZsE#6BCw(ZRU)X5=gr_Jlq8|^%$_Y<{h5}-hhot zgt;|I7=bdCJAXJ~8h6FfEXg1u7PJfDIY86zv$#+rcnaumUhF9k%pdb(uaPeWD}g1% zn#9KCAzw9Pfe1YrKiGFHxt$Z3H^V##*bpStouc5q9$6F@34|m9Lsm)(-4pFOh>WWu zNISH!4MYyNjNpTp8$)3u_V~rJ)BFfM5Wzf|l!{OD$2iSdKn*cW?XBaNNmz4o$o=flYm6rswdClM+Qagcp4;PE!6$%bDjK^QDirKN5ZNs&u{0k9dS zS#b_CM{kkyaupa{F)x9tNe=|WB$9_H>>7|!jX>Oe!EaGbQEeb}$BY!m(M19?rPj(;B zKUbKP$k3x%;NbmZr?C(s^??!OHau@h8Q2u=ieQjoIF+wMq8Drv=LP&BV=c1II4?>8 zUxZJ>C@`3MiRNgOHw_>;o2lTo&Chi8oCq=$64P}B5WL^9-*CCi~dHs`Z|YC#k0joY=5nR zx#u}zBZMHD*cW`9=wLK!8GeE&GP6b$B1*!(Uzp%!x&u3F9tD4dpf3^UP`l6{wyG8Z z#`9{zFb>pnep#0-spHb%&D|s~`*L->noxxrc^)VZRHEYWVt9K`c$!F9;@o?z-_tvc zofmzmEVL$eg-Kw07y53iJl|qTT_8e5zJtU8x;^Uy1Tg^*Ie;Pl+%R;OkgLAow%oXd zH^AQo5)dqarYG}0T*l;Afldu1OY%B*hbZr0We)nma))T@HAN^1tbD`2a!42N5fRVw zxbCUzi) zvlPAW1Ql3MHHpPL-~(g^7JVmf>PW zOz;G39Sr@jnuVa)W<5Y@)FevfSC#abUAhB~A=$>B;d&-GAvM_W^$b%W^U)jOsOc15 zAVsWYc_4(LV~jU6s7S#-bCCSK;C|%>O=K!~-Loz*#gGNpXDc61pjij}H+a%=lKP$l z;q~l)-2FbhXnv3{nEq_0NwT$?h?)c(z)h1h1~Gkm_yQLKZ`s^Q*x;UeUqOF|%NI`< zUQH4Fhi7<-`tEUg7UOwKwu%WYfL%3Y)~?BG3?$LcM-J z803NvZqPv88%!PoLOboKT+JT#+&yB`-z=UtEaX%ho*muIbD=FeSoy|9bR0m%@(OV^ z_B}xwJU0i10HU$k>okzzv3jJ#!-u8{$pybzZ`c#a0f@g>)tB&CJ;m z=RJw?q;cZN9ui#y752PAK3_!<5*6s?L$+C655)>T%sUevp{e=Ce61r&gwy^LzbTo1 zy>`sW93x7so0~3#nwRM8Yaqw~fcZwSY|4r;S~L_+!W+!&drZ&7Awt(@o#1m0$%#%N zcu3~XHbz&H91aFwS(f+aLh-;TI~Amm--eIuXxuZogiuY@6Rj3hv*iUyA( zj965%t?^W70NSq&0Nd>B1^u?Z!z$gT@kQWqM@w-^lC=`m;A}|YZX&T+q4dre@9ioR z0V`+;!o#zLRfwVK-5a%vP3$hrppA)day!@xj9f4SMG*lf>B4Fda4eDRcY$wQ7Wo?J z38jtu8Bmh<3$3*7Nh{1}sZt@vGvUm_U5gkHpurbZ8Ymp_bzXJr17p}8QF?5xC-95^ zsufJ|7NZ5SeX1{5t~&vE)`GNYsp|NweBzz1Xvsw+ievHU+GtKOZhY7CJ*d~j$)`KZ zr^=+4#N}4bps@pch~5EU+7&|TY*MVO5bk9}XD^m@zXm8ayx**F`(6+8A@l(f)UD~9 zig-R1mXGy#E<&`-9d(Y@uOl|hW>?R|A7l^g2b=ivx}#NAkXv;goXG<&Yk?7}nLw1U zm&+a1>+PoClc_O8CmIO*tJ2O9 zR7N*MshRRPJxUnn-|9JV=Hgvsv;SkqEchzWW=j#v?Ge&r!E82cqfu__i3a~APl~Ik z26eFB=aZZU*67B`@CVsCqU`k)@6be)BX5~r%@)Y!@~xQzZaz!{v&^1{ST_*OQpI@X zJHN^}Gnl7DGFxKvHGPPXF;}&|HbG@QgTyA9>HL5IkS7r*c7`*&C`jZw{&>n@*aqxw zw`69Z_Xoc#7J1!Z_7l-Acpoo{{JcjVC!@qVu?#C+m<0M@!W{hdz69?){ovuH~2jhn3GW79WqbgxA+mN zP55n|$inyv#txzd6(n&7_KlT1tRo+~Ub`&_Y+#02u^?8G@z*R>AwBe2?0T0zj=sh`Krgk5*PPcKpPxx6o zD8RcBNlk!x-UlT-<=871L(@VLd;`@ppv~AQjIG>O!#4@Qvc`ljqm^Ex=qW(2H<+d` zWH~Fk!9KkZ%C_FQB>dGR>WcWbbzw|WhvSgFhAa;~C_z(;DKHFfP7%gzYIYre4WFq+9A*+G!wqCvKVF{|);BjHl zEGCwP8T#QF`XaOdbQm2U&WG}H@P&n9S=z9w#nWcX{C2MgSP*{wdo3(rH@clXnUI1y zAaeCXMgc8sDe`7Pl@5hKY^09}h*Y*1-QIx&f4v5ruT^d|2WzghJTCRK<3wZTBQay- zhGz+p=!*5W2t@~LFo>`q$8zL!bsJz(F-r�O?%2bzek=L$}5$VaXMlWF>Z4>J;-T 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∨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 Hu0mjfIba9j diff --git a/SlopeCraft/others/cheap.sc_preset_json b/SlopeCraft/others/presets/cheap.sc_preset_json similarity index 100% rename from SlopeCraft/others/cheap.sc_preset_json rename to SlopeCraft/others/presets/cheap.sc_preset_json diff --git a/SlopeCraft/others/elegant.sc_preset_json b/SlopeCraft/others/presets/elegant.sc_preset_json similarity index 100% rename from SlopeCraft/others/elegant.sc_preset_json rename to SlopeCraft/others/presets/elegant.sc_preset_json diff --git a/SlopeCraft/others/shiny.sc_preset_json b/SlopeCraft/others/presets/shiny.sc_preset_json similarity index 100% rename from SlopeCraft/others/shiny.sc_preset_json rename to SlopeCraft/others/presets/shiny.sc_preset_json diff --git a/SlopeCraft/others/vanilla.sc_preset_json b/SlopeCraft/others/presets/vanilla.sc_preset_json similarity index 100% rename from SlopeCraft/others/vanilla.sc_preset_json rename to SlopeCraft/others/presets/vanilla.sc_preset_json From 5b3f763e0de6e8a02bc6dfd67fed998b233b2ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 2 May 2023 21:08:51 +0800 Subject: [PATCH 0249/1123] display cvt task pool --- SlopeCraft/AdaptiveListView.cpp | 17 ++++ SlopeCraft/AdaptiveListView.h | 14 +++ SlopeCraft/CMakeLists.txt | 10 +- SlopeCraft/PoolModel.cpp | 25 +++++ SlopeCraft/PoolModel.h | 42 ++++++++ SlopeCraft/SCWind.cpp | 87 ++++++++++++++++- SlopeCraft/SCWind.h | 14 +++ SlopeCraft/SCWind.ui | 124 +++++++++++++++++++++--- SlopeCraft/cvt_task.cpp | 18 ++++ SlopeCraft/cvt_task.h | 20 ++++ SlopeCraft/main.cpp | 1 + SlopeCraft/others/no_use/PoolWidget.cpp | 14 +++ SlopeCraft/others/no_use/PoolWidget.h | 25 +++++ SlopeCraft/others/no_use/PoolWidget.ui | 79 +++++++++++++++ 14 files changed, 472 insertions(+), 18 deletions(-) create mode 100644 SlopeCraft/AdaptiveListView.cpp create mode 100644 SlopeCraft/AdaptiveListView.h create mode 100644 SlopeCraft/PoolModel.cpp create mode 100644 SlopeCraft/PoolModel.h create mode 100644 SlopeCraft/cvt_task.cpp create mode 100644 SlopeCraft/cvt_task.h create mode 100644 SlopeCraft/others/no_use/PoolWidget.cpp create mode 100644 SlopeCraft/others/no_use/PoolWidget.h create mode 100644 SlopeCraft/others/no_use/PoolWidget.ui diff --git a/SlopeCraft/AdaptiveListView.cpp b/SlopeCraft/AdaptiveListView.cpp new file mode 100644 index 00000000..7c13e11f --- /dev/null +++ b/SlopeCraft/AdaptiveListView.cpp @@ -0,0 +1,17 @@ +#include "AdaptiveListView.h" + +inline QSize compute_size(QSize widget_size, double ratio = 0.8) noexcept { + const int new_w = widget_size.width() * ratio; + return {new_w, new_w}; +} + +AdaptiveListView::AdaptiveListView(QWidget* parent) : QListView(parent) { + this->setIconSize(compute_size(this->size())); +} + +AdaptiveListView::~AdaptiveListView() {} + +void AdaptiveListView::resizeEvent(QResizeEvent* event) { + this->setIconSize(compute_size(event->size())); + QListView::resizeEvent(event); +} \ No newline at end of file diff --git a/SlopeCraft/AdaptiveListView.h b/SlopeCraft/AdaptiveListView.h new file mode 100644 index 00000000..818845fa --- /dev/null +++ b/SlopeCraft/AdaptiveListView.h @@ -0,0 +1,14 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_ADAPTIVELISTVIEW_H +#define SLOPECRAFT_SLOPECRAFT_ADAPTIVELISTVIEW_H +#include +#include + +class AdaptiveListView : public QListView { + public: + explicit AdaptiveListView(QWidget* parent = nullptr); + ~AdaptiveListView(); + + void resizeEvent(QResizeEvent* event) override; +}; + +#endif // SLOPECRAFT_SLOPECRAFT_ADAPTIVELISTVIEW_H diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 95e9c244..e6f2de00 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -17,11 +17,19 @@ if(${WIN32}) endif() set(SlopeCraft_headers - SCWind.h) + SCWind.h + cvt_task.h + PoolModel.h + AdaptiveListView.h) + set(SlopeCraft_sources SCWind.cpp + cvt_task.cpp + PoolModel.cpp + AdaptiveListView.cpp main.cpp ${SlopeCraft_rc_files}) + set(SlopeCraft_uis SCWind.ui) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp new file mode 100644 index 00000000..ca44f951 --- /dev/null +++ b/SlopeCraft/PoolModel.cpp @@ -0,0 +1,25 @@ +#include "PoolModel.h" + +CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) + : QAbstractListModel(parent), pool(poolptr) {} + +CvtPoolModel::~CvtPoolModel() {} + +QVariant CvtPoolModel::data(const QModelIndex& idx, int role) const { + if (role == Qt::ItemDataRole::DisplayRole) { + return this->pool->at(idx.row()).filename; + } + + if (role == Qt::ItemDataRole::DecorationRole) { + auto raw_image = + QPixmap::fromImage(this->pool->at(idx.row()).original_image); + auto img = raw_image.scaledToWidth(this->listview->size().width()); + return QIcon{raw_image}; + } + + return QVariant{}; + + // return QVariant{}; + + return QVariant{}; +} diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h new file mode 100644 index 00000000..d0bb2a1b --- /dev/null +++ b/SlopeCraft/PoolModel.h @@ -0,0 +1,42 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_POOLMODEL_H +#define SLOPECRAFT_SLOPECRAFT_POOLMODEL_H + +#include +#include +#include +#include + +class CvtPoolModel : public QAbstractListModel { + Q_OBJECT + public: + explicit CvtPoolModel(QObject* parent = nullptr, + task_pool_t* poolptr = nullptr); + ~CvtPoolModel(); + + int rowCount(const QModelIndex&) const override { return this->pool->size(); } + + QModelIndex parent(const QModelIndex&) const override { + return QModelIndex{}; + } + + QVariant data(const QModelIndex& idx, int role) const override; + + void refresh() noexcept { + emit dataChanged(this->index(0, 0), this->index(this->pool->size(), 0)); + } + + private: + task_pool_t* pool{nullptr}; + QListView* listview{nullptr}; + + public: + task_pool_t* attached_pool() noexcept { return this->pool; } + const task_pool_t* attached_pool() const noexcept { return this->pool; } + void set_pool(task_pool_t* _pool) noexcept { this->pool = _pool; } + + QListView* attached_listview() noexcept { return this->listview; } + const QListView* attached_listview() const noexcept { return this->listview; } + void set_listview(QListView* lv) noexcept { this->listview = lv; } +}; + +#endif // SLOPECRAFT_SLOPECRAFT_POOLMODEL_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 96a017ea..0a278bd7 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -1,14 +1,99 @@ #include "SCWind.h" #include "ui_SCWind.h" +#include +#include +// #include "PoolWidget.h" -SCWind::SCWind(QWidget* parent) +SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind), kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); + this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; + + this->ui->lview_pool_cvt->setModel(this->cvt_pool_model); + this->cvt_pool_model->set_listview(this->ui->lview_pool_cvt); + + connect(this->ui->lview_pool_cvt->selectionModel(), + &QItemSelectionModel::selectionChanged, this, + &SCWind::when_cvt_pool_selectionChanged); } SCWind::~SCWind() { delete this->ui; SlopeCraft::SCL_destroyKernel(this->kernel); +} + +void SCWind::on_pb_add_image_clicked() noexcept { + auto files = + QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;;*.jpg"); + + if (files.empty()) { + return; + } + + QString err; + for (const auto &filename : files) { + auto task = cvt_task::load(filename, err); + + if (!err.isEmpty()) { + auto ret = QMessageBox::critical( + this, tr("打开图像失败"), + tr("无法打开图像 %1 。\n详细信息: %2").arg(filename).arg(err), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, + QMessageBox::StandardButton::Ignore}); + + if (ret == QMessageBox::Ignore) { + return; + } else { + abort(); + } + } + + this->tasks.emplace_back(task); + } + this->cvt_pool_model->refresh(); + if (this->ui->lview_pool_cvt->viewMode() == QListView::ViewMode::IconMode) { + this->ui->lview_pool_cvt->doItemsLayout(); + } +} + +void SCWind::on_pb_remove_image_clicked() noexcept { + auto selected = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + + if (selected.empty()) { + return; + } + + for (const auto &qmi : selected) { + const int idx = qmi.row(); + this->tasks.erase(this->tasks.begin() + idx); + } + + this->cvt_pool_model->refresh(); +} + +void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { + this->ui->lview_pool_cvt->setViewMode( + (this->ui->cb_lv_cvt_icon_mode->isChecked()) + ? (QListView::ViewMode::IconMode) + : (QListView::ViewMode::ListMode)); + + this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); +} + +void SCWind::when_cvt_pool_selectionChanged() noexcept { + auto sel = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + + if (sel.size() <= 0) { + this->ui->lb_raw_image->setPixmap({}); + this->ui->lb_cvted_image->setPixmap({}); + return; + } + + const int idx = sel.front().row(); + + this->ui->lb_raw_image->setPixmap( + QPixmap::fromImage(this->tasks[idx].original_image)); +#warning load converted image here } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index b53b899b..cbac08d5 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -5,6 +5,11 @@ #include #include +#include + +#include "cvt_task.h" +#include "PoolModel.h " + class SCWind; namespace Ui { @@ -16,10 +21,19 @@ class SCWind : public QMainWindow { public: explicit SCWind(QWidget* parent = nullptr); ~SCWind(); + private slots: + void on_pb_add_image_clicked() noexcept; + void on_pb_remove_image_clicked() noexcept; + void on_cb_lv_cvt_icon_mode_clicked() noexcept; + + void when_cvt_pool_selectionChanged() noexcept; private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; + + task_pool_t tasks; + CvtPoolModel* cvt_pool_model{nullptr}; }; #endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 98051367..39c01150 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -6,7 +6,7 @@ 0 0 - 800 + 804 750 @@ -18,7 +18,7 @@ - 0 + 1 @@ -109,6 +109,9 @@ 1.19 + + true + @@ -125,6 +128,9 @@ 立体地图画 + + true + @@ -169,7 +175,7 @@ 0 0 - 633 + 637 549 @@ -241,6 +247,9 @@ Elegant + + true + @@ -320,13 +329,16 @@ - + 0 0 + + true + QFrame::Box @@ -339,6 +351,12 @@ + + false + + + Qt::AlignCenter + @@ -349,13 +367,16 @@ - + 0 0 + + true + QFrame::Box @@ -368,6 +389,9 @@ + + Qt::AlignCenter + @@ -513,6 +537,59 @@ 0 + + + + true + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ExtendedSelection + + + Qt::ElideLeft + + + QListView::Snap + + + QListView::TopToBottom + + + false + + + QListView::Fixed + + + 10 + + + QListView::IconMode + + + 0 + + + true + + + true + + + + + + + 删除 + + + @@ -523,23 +600,26 @@ - - + + - 删除 + 添加 - - + + + + true + - 添加 + IconMode + + + true - - - @@ -610,7 +690,7 @@ 0 - + @@ -1145,7 +1225,7 @@ 0 0 - 800 + 804 22 @@ -1170,6 +1250,18 @@ + + + AdaptiveLabel + QLabel +

AdaptiveLabel.h
+ + + AdaptiveListView + QListView +
AdaptiveListView.h
+
+ diff --git a/SlopeCraft/cvt_task.cpp b/SlopeCraft/cvt_task.cpp new file mode 100644 index 00000000..c795e81c --- /dev/null +++ b/SlopeCraft/cvt_task.cpp @@ -0,0 +1,18 @@ +#include "cvt_task.h" +#include + +cvt_task cvt_task::load(QString filename, QString& err) noexcept { + err.clear(); + cvt_task ret; + + ret.filename = filename; + + QImage temp; + if (!temp.load(filename)) { + err = QObject::tr("加载图片 %1 失败。").arg(filename); + return {}; + } + + ret.original_image = temp.convertToFormat(QImage::Format_ARGB32); + return ret; +} \ No newline at end of file diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h new file mode 100644 index 00000000..e8ca07dd --- /dev/null +++ b/SlopeCraft/cvt_task.h @@ -0,0 +1,20 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_CVT_TASK_H +#define SLOPECRAFT_SLOPECRAFT_CVT_TASK_H + +#include +#include + +struct cvt_task { + QString filename{""}; + QImage original_image; + + bool is_converted{false}; + bool is_built{false}; + bool is_exported{false}; + + static cvt_task load(QString filename, QString& err) noexcept; +}; + +using task_pool_t = std::vector; + +#endif // SLOPECRAFT_SLOPECRAFT_CVT_TASK_H \ No newline at end of file diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index 11d196b0..d4612c59 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -1,5 +1,6 @@ #include #include "SCWind.h" + int main(int argc, char** argv) { QApplication qapp(argc, argv); diff --git a/SlopeCraft/others/no_use/PoolWidget.cpp b/SlopeCraft/others/no_use/PoolWidget.cpp new file mode 100644 index 00000000..b6503769 --- /dev/null +++ b/SlopeCraft/others/no_use/PoolWidget.cpp @@ -0,0 +1,14 @@ +#include "PoolWidget.h" +#include "ui_PoolWidget.h" + +PoolWidget::PoolWidget(QWidget* parent) + : QWidget(parent), ui(new Ui::PoolWidget) { + this->ui->setupUi(this); +} + +PoolWidget::~PoolWidget() { delete this->ui; } + +void PoolWidget::set_task(const cvt_task& task) noexcept { + this->ui->lb_image->setPixmap(QPixmap::fromImage(task.original_image)); + this->ui->lb_name->setText(task.filename); +} \ No newline at end of file diff --git a/SlopeCraft/others/no_use/PoolWidget.h b/SlopeCraft/others/no_use/PoolWidget.h new file mode 100644 index 00000000..36416c3b --- /dev/null +++ b/SlopeCraft/others/no_use/PoolWidget.h @@ -0,0 +1,25 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H +#define SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H + +#include +#include "cvt_task.h" + +class PoolWidget; + +namespace Ui { +class PoolWidget; +} + +class PoolWidget : public QWidget { + Q_OBJECT + private: + Ui::PoolWidget* ui; + + public: + explicit PoolWidget(QWidget* parent = nullptr); + ~PoolWidget(); + + void set_task(const cvt_task& task) noexcept; +}; + +#endif // SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H \ No newline at end of file diff --git a/SlopeCraft/others/no_use/PoolWidget.ui b/SlopeCraft/others/no_use/PoolWidget.ui new file mode 100644 index 00000000..b3b4d99a --- /dev/null +++ b/SlopeCraft/others/no_use/PoolWidget.ui @@ -0,0 +1,79 @@ + + + PoolWidget + + + + 0 + 0 + 373 + 346 + + + + + 0 + 0 + + + + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + Qt::AlignCenter + + + + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + AdaptiveLabel + QLabel +
AdaptiveLabel.h
+
+
+ + +
From d774dcc1a10ce8b0fb453bfd6f4eb81018a54ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 3 May 2023 16:10:48 +0800 Subject: [PATCH 0250/1123] add task pool dragging --- SlopeCraft/AdaptiveListView.cpp | 3 + SlopeCraft/PoolModel.cpp | 161 +++++++++++++++++++++++++++++++- SlopeCraft/PoolModel.h | 21 +++++ SlopeCraft/SCWind.cpp | 10 +- SlopeCraft/SCWind.ui | 17 +++- SlopeCraft/cvt_task.h | 3 + 6 files changed, 205 insertions(+), 10 deletions(-) diff --git a/SlopeCraft/AdaptiveListView.cpp b/SlopeCraft/AdaptiveListView.cpp index 7c13e11f..7021ac97 100644 --- a/SlopeCraft/AdaptiveListView.cpp +++ b/SlopeCraft/AdaptiveListView.cpp @@ -7,6 +7,9 @@ inline QSize compute_size(QSize widget_size, double ratio = 0.8) noexcept { AdaptiveListView::AdaptiveListView(QWidget* parent) : QListView(parent) { this->setIconSize(compute_size(this->size())); + this->setDragEnabled(true); + this->setAcceptDrops(true); + this->setDropIndicatorShown(true); } AdaptiveListView::~AdaptiveListView() {} diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index ca44f951..76bb0772 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -1,4 +1,7 @@ #include "PoolModel.h" +#include +#include +#include CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) : QAbstractListModel(parent), pool(poolptr) {} @@ -11,6 +14,9 @@ QVariant CvtPoolModel::data(const QModelIndex& idx, int role) const { } if (role == Qt::ItemDataRole::DecorationRole) { + if (this->listview->viewMode() == QListView::ViewMode::ListMode) { + return QVariant{}; + } auto raw_image = QPixmap::fromImage(this->pool->at(idx.row()).original_image); auto img = raw_image.scaledToWidth(this->listview->size().width()); @@ -18,8 +24,159 @@ QVariant CvtPoolModel::data(const QModelIndex& idx, int role) const { } return QVariant{}; +} + +Qt::DropActions CvtPoolModel::supportedDropActions() const { + return Qt::DropActions{Qt::DropAction::MoveAction, + Qt::DropAction::CopyAction}; +} - // return QVariant{}; +Qt::ItemFlags CvtPoolModel::flags(const QModelIndex& index) const { + Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); - return QVariant{}; + if (index.isValid()) + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + else + return Qt::ItemIsDropEnabled | defaultFlags; +} + +QStringList CvtPoolModel::mimeTypes() const { + return QStringList{"text/plain", "image/png"}; +} + +const char mime_data_type[] = "application/slopecraft_pool_index"; + +QByteArray encode_indices(const std::vector& temp) noexcept { + QByteArray qba{reinterpret_cast(temp.data()), + qsizetype(temp.size() * sizeof(int))}; + return qba; +} + +std::vector decode_indices(const QByteArray& qbav) noexcept { + if (qbav.size() % sizeof(int) != 0) { + return {}; + } + + const int size = qbav.size() / sizeof(int); + + const int* const data = reinterpret_cast(qbav.data()); + + std::vector ret{data, data + size}; + return ret; } + +QMimeData* CvtPoolModel::mimeData(const QModelIndexList& indexes) const { + std::vector temp; + temp.reserve(indexes.size()); + + for (const auto& midx : indexes) { + temp.emplace_back(midx.row()); + } + + QMimeData* ret = new QMimeData; + + ret->setData(mime_data_type, encode_indices(temp)); + + return ret; +} + +bool CvtPoolModel::canDropMimeData(const QMimeData* data, Qt::DropAction, + int row, int col, + const QModelIndex& parent) const { + if (parent.isValid()) { + return false; + } + + if (col > 0) { + return false; + } + + if (data->hasFormat(mime_data_type) && + data->data(mime_data_type).size() % sizeof(int) == 0) { + return true; + } + + return false; +} + +template +void iterator_add(it_t& it, int n) noexcept { + assert(n >= 0); + for (int i = 0; i < n; i++) { + ++it; + } +} + +template +void map_indices(std::vector& pool, std::vector moved_indices, + int begin_idx) noexcept { + std::list temp_pool; + for (T& t : pool) { + temp_pool.emplace_back(t); + } + + std::sort(moved_indices.begin(), moved_indices.end()); + std::vector::iterator> src_it_vec; + src_it_vec.reserve(moved_indices.size()); + { + int idx = 0; + auto it = temp_pool.begin(); + for (int sidx : moved_indices) { + const int offset = sidx - idx; + assert(offset >= 0); + iterator_add(it, offset); + + src_it_vec.emplace_back(it); + } + } + + auto begin_it = temp_pool.begin(); + + iterator_add(begin_it, begin_idx); + + for (auto srcit : src_it_vec) { + temp_pool.emplace(begin_it, *srcit); + } + + for (auto srcit : src_it_vec) { + temp_pool.erase(srcit); + } + + pool.clear(); + for (auto& t : temp_pool) { + pool.emplace_back(t); + } +} + +bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, + int row, int column, + const QModelIndex& parent) { + if (!this->canDropMimeData(data, action, row, column, parent)) { + return false; + } + + if (action == Qt::IgnoreAction) { + return true; + } + + int begin_row; + + if (row != -1) + begin_row = row; + else if (parent.isValid()) + begin_row = parent.row(); + else + begin_row = this->rowCount(QModelIndex()); + + { + auto src_indices = decode_indices(data->data(mime_data_type)); + + if (src_indices.size() <= 0) { + return true; + } + map_indices(*this->pool, src_indices, begin_row); + } + this->refresh(); + + return true; +} \ No newline at end of file diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index d0bb2a1b..cdb26c8f 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -25,6 +25,27 @@ class CvtPoolModel : public QAbstractListModel { emit dataChanged(this->index(0, 0), this->index(this->pool->size(), 0)); } + Qt::DropActions supportedDropActions() const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + QStringList mimeTypes() const override; + + QMimeData* mimeData(const QModelIndexList& indexes) const override; + + bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, + int column, const QModelIndex& parent) const override; + + bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, + int column, const QModelIndex& parent) override; + /*/ + bool setData(const QModelIndex& index, const QVariant& value, + int role) override; + Qt::DropActions supportedDragActions() const override; + + + bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, + int column, const QModelIndex& parent) const override; + */ private: task_pool_t* pool{nullptr}; QListView* listview{nullptr}; diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0a278bd7..6c4ffca2 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -74,12 +74,14 @@ void SCWind::on_pb_remove_image_clicked() noexcept { } void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { - this->ui->lview_pool_cvt->setViewMode( - (this->ui->cb_lv_cvt_icon_mode->isChecked()) - ? (QListView::ViewMode::IconMode) - : (QListView::ViewMode::ListMode)); + const bool is_icon_mode = this->ui->cb_lv_cvt_icon_mode->isChecked(); + this->ui->lview_pool_cvt->setViewMode((is_icon_mode) + ? (QListView::ViewMode::IconMode) + : (QListView::ViewMode::ListMode)); this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); + + this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 4); } void SCWind::when_cvt_pool_selectionChanged() noexcept { diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 39c01150..cc13cae5 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -175,8 +175,8 @@ 0 0 - 637 - 549 + 98 + 28 @@ -540,14 +540,23 @@ - true + false - QAbstractItemView::NoEditTriggers + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed true + + false + + + QAbstractItemView::InternalMove + + + Qt::CopyAction + QAbstractItemView::ExtendedSelection diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index e8ca07dd..686186a3 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -3,6 +3,7 @@ #include #include +#include struct cvt_task { QString filename{""}; @@ -15,6 +16,8 @@ struct cvt_task { static cvt_task load(QString filename, QString& err) noexcept; }; +Q_DECLARE_METATYPE(cvt_task); + using task_pool_t = std::vector; #endif // SLOPECRAFT_SLOPECRAFT_CVT_TASK_H \ No newline at end of file From 98608ec7ec48bbffeb108a42925bc4b71d9939ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 3 May 2023 16:26:02 +0800 Subject: [PATCH 0251/1123] disable dragging multiple items --- SlopeCraft/PoolModel.cpp | 20 +++++++++++++++----- SlopeCraft/SCWind.cpp | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 76bb0772..7ef55542 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -91,8 +91,18 @@ bool CvtPoolModel::canDropMimeData(const QMimeData* data, Qt::DropAction, return false; } - if (data->hasFormat(mime_data_type) && - data->data(mime_data_type).size() % sizeof(int) == 0) { + if (!data->hasFormat(mime_data_type)) { + return true; + } + + const int bytes = data->data(mime_data_type).size(); + + if (bytes % sizeof(int) != 0) { + return false; + } + + // disable moving multiple items, because the behavior is incorrect + if (bytes / sizeof(int) == 1) { return true; } @@ -112,7 +122,7 @@ void map_indices(std::vector& pool, std::vector moved_indices, int begin_idx) noexcept { std::list temp_pool; for (T& t : pool) { - temp_pool.emplace_back(t); + temp_pool.emplace_back(std::move(t)); } std::sort(moved_indices.begin(), moved_indices.end()); @@ -144,7 +154,7 @@ void map_indices(std::vector& pool, std::vector moved_indices, pool.clear(); for (auto& t : temp_pool) { - pool.emplace_back(t); + pool.emplace_back(std::move(t)); } } @@ -166,7 +176,7 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, else if (parent.isValid()) begin_row = parent.row(); else - begin_row = this->rowCount(QModelIndex()); + begin_row = this->rowCount(QModelIndex{}); { auto src_indices = decode_indices(data->data(mime_data_type)); diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 6c4ffca2..ced5f07b 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -81,7 +81,7 @@ void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); - this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 4); + this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 0); } void SCWind::when_cvt_pool_selectionChanged() noexcept { From b46aedaf6f55a6ccf6aa173ea696b4217e98dac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 14:11:26 +0800 Subject: [PATCH 0252/1123] add bxzstr, cereal and chocobo1 hash --- cmake/configure_bxzstr.cmake | 20 ++++++++++++++++++++ cmake/configure_cereal.cmake | 16 ++++++++++++++++ cmake/configure_hash.cmake | 17 +++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 cmake/configure_bxzstr.cmake create mode 100644 cmake/configure_cereal.cmake create mode 100644 cmake/configure_hash.cmake diff --git a/cmake/configure_bxzstr.cmake b/cmake/configure_bxzstr.cmake new file mode 100644 index 00000000..98a9d3e7 --- /dev/null +++ b/cmake/configure_bxzstr.cmake @@ -0,0 +1,20 @@ +find_package(bxzstr) + +if(${bxzstr_FOUND}) + return() +endif() + +include(FetchContent) + +set(BZIP2_FOUND off) +set(LIBLZMA_FOUND off) +set(ZSTD_FOUND off) + +FetchContent_Declare(bxzstr + GIT_REPOSITORY https://github.com/SlopeCraft/bxzstr + GIT_TAG v1.2.1-fork + OVERRIDE_FIND_PACKAGE) + +message(STATUS "Configuring bxzstr ...") + +FetchContent_MakeAvailable(bxzstr) \ No newline at end of file diff --git a/cmake/configure_cereal.cmake b/cmake/configure_cereal.cmake new file mode 100644 index 00000000..fcf61d78 --- /dev/null +++ b/cmake/configure_cereal.cmake @@ -0,0 +1,16 @@ +find_package(cereal) + +if(${cereal_FOUND}) + return() +endif() + +include(FetchContent) + +FetchContent_Declare(cereal + GIT_REPOSITORY https://github.com/USCiLab/cereal + GIT_TAG v1.3.2 + OVERRIDE_FIND_PACKAGE) + +message(STATUS "Configuring cereal ...") + +FetchContent_MakeAvailable(cereal) \ No newline at end of file diff --git a/cmake/configure_hash.cmake b/cmake/configure_hash.cmake new file mode 100644 index 00000000..a24d0dbe --- /dev/null +++ b/cmake/configure_hash.cmake @@ -0,0 +1,17 @@ +# https://github.com/Chocobo1/Hash + +set(SlopeCraft_Chocobo1_Hash_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/Hash/src) + +if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/Hash/.git) + return() +endif() + +file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/3rdParty/Hash) + +message(STATUS "cloning https://github.com/Chocobo1/Hash.git") + +execute_process(COMMAND git clone https://github.com/Chocobo1/Hash.git + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty + COMMAND_ERROR_IS_FATAL ANY) + +# execute_process(git checkout ) \ No newline at end of file From 07288bc78187d7a0e481dcd88a5f6cc6598aee77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 14:12:49 +0800 Subject: [PATCH 0253/1123] add hashing and serialization for ColorManip --- utilities/ColorManip/CMakeLists.txt | 17 +- utilities/ColorManip/colorset_maptical.hpp | 22 +- utilities/ColorManip/hash.cpp | 37 ++++ utilities/ColorManip/imageConvert.hpp | 185 +++++++++-------- utilities/ColorManip/newColorSet.hpp | 60 ++++-- utilities/ColorManip/newTokiColor.hpp | 224 +++++++++++---------- utilities/ColorManip/seralize_funs.hpp | 29 +++ 7 files changed, 353 insertions(+), 221 deletions(-) create mode 100644 utilities/ColorManip/hash.cpp create mode 100644 utilities/ColorManip/seralize_funs.hpp diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 4bc54764..49db36e8 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -7,6 +7,10 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) find_package(OpenMP REQUIRED) find_package(Eigen3 REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) +find_package(cereal REQUIRED) + add_library(ColorManip ColorManip.h @@ -17,6 +21,7 @@ add_library(ColorManip newColorSet.hpp newTokiColor.hpp StaticMembers.cpp + hash.cpp colorset_maptical.hpp imageConvert.hpp @@ -26,17 +31,17 @@ add_library(ColorManip target_compile_features(ColorManip PUBLIC cxx_std_20) -# set_target_properties(ColorManip PROPERTIES CXX_STANDARD_REQUIRED ON) - -# get_target_property(cm_cxx_std ColorManip CXX_STANDARD) -# message(STATUS "cm_cxx_std = " ${cm_cxx_std}) target_include_directories(ColorManip PUBLIC - ${CMAKE_SOURCE_DIR}/utilities) + ${CMAKE_SOURCE_DIR}/utilities + ${SlopeCraft_Chocobo1_Hash_include_dir}) target_include_directories(ColorManip PRIVATE ${SlopeCraft_HeuristicFlow_include_dir}) -target_link_libraries(ColorManip PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen) +target_link_libraries(ColorManip PUBLIC + OpenMP::OpenMP_CXX + Eigen3::Eigen + cereal::cereal) # target_compile_options(ColorManip BEFORE PUBLIC "-std=c++17") target_compile_options(ColorManip PRIVATE ${SlopeCraft_vectorize_flags}) diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 2d993c3c..6ccd974a 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -37,7 +37,7 @@ This file is part of SlopeCraft. #endif class newtokicolor_base_maptical { -public: + public: using TempVectorXf_t = Eigen::Array; @@ -48,25 +48,25 @@ class newtokicolor_base_maptical { // 记录与result的深度值不同的两个有损优化候选色(升序排列),Depth=3时无效 std::array sideResult; - uint8_t Result{0}; // 最终调色结果 + uint8_t Result{0}; // 最终调色结果 -public: + public: static bool needFindSide; static std::array DepthCount; // static ::SCL_convertAlgo convertAlgo; -public: + public: inline bool is_result_computed() const noexcept { return (Result != 0); } }; class alignas(32) colorset_maptical_basic { -private: + private: Eigen::Array __rgb; Eigen::Array __hsv; Eigen::Array __lab; Eigen::Array __xyz; -public: + public: /// The default constructor is deleted colorset_maptical_basic() = delete; /// Construct from color source @@ -117,11 +117,11 @@ class alignas(32) colorset_maptical_basic { }; class alignas(32) colorset_maptical_allowed { -public: + public: using color_col = Eigen::Array; static constexpr uint8_t invalid_color_id = 0; -private: + private: std::array __rgb; std::array __hsv; std::array __lab; @@ -130,7 +130,7 @@ class alignas(32) colorset_maptical_allowed { // std::array __map; int _color_count; -public: + public: inline int color_count() const noexcept { return _color_count; } inline float RGB(int r, int c) const noexcept { @@ -244,7 +244,7 @@ class alignas(32) colorset_maptical_allowed { return true; } -private: + private: inline int allow_list_counter(const bool *const allow_list) const noexcept { int result = 0; for (int idx = 0; idx < 256; idx++) { @@ -258,4 +258,4 @@ class alignas(32) colorset_maptical_allowed { } }; -#endif // COLORMANIP_COLORSET_MAPTICAL_HPP \ No newline at end of file +#endif // COLORMANIP_COLORSET_MAPTICAL_HPP \ No newline at end of file diff --git a/utilities/ColorManip/hash.cpp b/utilities/ColorManip/hash.cpp new file mode 100644 index 00000000..e1c4b6a0 --- /dev/null +++ b/utilities/ColorManip/hash.cpp @@ -0,0 +1,37 @@ +#include "newColorSet.hpp" +#include "imageConvert.hpp" + +#include + +std::vector internal::hash_of_colorset( + const hash_temp &temp) noexcept { + Chocobo1::SHA3_512 stream; + + for (const auto &cptrs : temp.color_ptrs) { + for (const float *fptr : cptrs) { + stream.addData(fptr, temp.color_count * sizeof(float)); + } + } + + stream.addData(temp.color_id_ptr, + temp.color_count * + (temp.is_maptical ? sizeof(uint8_t) : sizeof(uint16_t))); + stream.addData(&temp.color_count, sizeof(temp.color_count)); + + return stream.finalize().toVector(); +} + +std::vector libImageCvt::hash_of_image( + Eigen::Map> img) noexcept { + Chocobo1::SHA3_512 stream; + { + const auto rows{img.rows()}; + const auto cols{img.cols()}; + stream.addData(&rows, sizeof(rows)); + stream.addData(&cols, sizeof(cols)); + } + + stream.addData(img.data(), sizeof(uint32_t) * img.size()); + + return stream.finalize().toVector(); +} \ No newline at end of file diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 05f5506f..8ac57a5d 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -33,6 +33,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "../SC_GlobalEnums.h" #include "ColorManip.h" @@ -41,30 +42,31 @@ This file is part of SlopeCraft. #ifdef RGB #undef RGB -#endif // #ifdef RGB +#endif // #ifdef RGB namespace libImageCvt { using ::Eigen::Dynamic; -static const Eigen::Array - dithermap_LR({{0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, - {3.0 / 16.0, 5.0 / 16.0, 1.0 / 16.0}}); +static const Eigen::Array dithermap_LR( + {{0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, + {3.0 / 16.0, 5.0 / 16.0, 1.0 / 16.0}}); -static const Eigen::Array - dithermap_RL({{7.0 / 16.0, 0.0 / 16.0, 0.0 / 16.0}, - {1.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0}}); +static const Eigen::Array dithermap_RL( + {{7.0 / 16.0, 0.0 / 16.0, 0.0 / 16.0}, + {1.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0}}); -template struct GPU_wrapper_wrapper { +template +struct GPU_wrapper_wrapper { constexpr bool have_gpu_resource() const noexcept { return false; } }; -template <> struct GPU_wrapper_wrapper { - -protected: +template <> +struct GPU_wrapper_wrapper { + protected: gpu_wrapper::gpu_interface *gpu{nullptr}; -public: + public: bool have_gpu_resource() const noexcept { return this->gpu != nullptr; } void set_gpu_resource(gpu_wrapper::gpu_interface *gi) noexcept { @@ -81,7 +83,7 @@ template <> struct GPU_wrapper_wrapper { template class ImageCvter : public GPU_wrapper_wrapper { -public: + public: using basic_colorset_t = colorset_new; using allowed_colorset_t = colorset_new; using TokiColor_t = @@ -93,15 +95,16 @@ class ImageCvter : public GPU_wrapper_wrapper { static const basic_colorset_t &basic_colorset; static const allowed_colorset_t &allowed_colorset; -protected: + protected: Eigen::ArrayXX _raw_image; ::SCL_convertAlgo algo; + bool dither{false}; std::unordered_map _color_hash; Eigen::ArrayXX _dithered_image; // Eigen::ArrayXX colorid_matrix; -public: + public: uiPack ui; // SCL_convertAlgo convert_algo{SCL_convertAlgo::RGB_Better}; @@ -118,6 +121,8 @@ class ImageCvter : public GPU_wrapper_wrapper { inline ::SCL_convertAlgo convert_algo() const noexcept { return this->algo; } + inline bool is_dither() const noexcept { return this->dither; } + inline int64_t rows() const noexcept { return _raw_image.rows(); } inline int64_t cols() const noexcept { return _raw_image.cols(); } inline int64_t size() const noexcept { return _raw_image.size(); } @@ -147,11 +152,12 @@ class ImageCvter : public GPU_wrapper_wrapper { } } - bool convert_image(::SCL_convertAlgo __algo, bool dither, + bool convert_image(::SCL_convertAlgo __algo, bool _dither, bool try_gpu = false) noexcept { if (__algo == ::SCL_convertAlgo::gaCvter) { __algo = ::SCL_convertAlgo::RGB_Better; } + this->dither = _dither; ui.rangeSet(0, 100, 0); @@ -163,30 +169,30 @@ class ImageCvter : public GPU_wrapper_wrapper { } ui.rangeSet(0, 100, 50); - if (dither) { + if (this->dither) { switch (this->algo) { - case ::SCL_convertAlgo::RGB: - this->template __impl_dither<::SCL_convertAlgo::RGB>(); - break; - case ::SCL_convertAlgo::RGB_Better: - this->template __impl_dither<::SCL_convertAlgo::RGB_Better>(); - break; - case ::SCL_convertAlgo::HSV: - this->template __impl_dither<::SCL_convertAlgo::HSV>(); - break; - case ::SCL_convertAlgo::Lab94: - this->template __impl_dither<::SCL_convertAlgo::Lab94>(); - break; - case ::SCL_convertAlgo::Lab00: - this->template __impl_dither<::SCL_convertAlgo::Lab00>(); - break; - case ::SCL_convertAlgo::XYZ: - this->template __impl_dither<::SCL_convertAlgo::XYZ>(); - break; - - default: - abort(); - return false; + case ::SCL_convertAlgo::RGB: + this->template __impl_dither<::SCL_convertAlgo::RGB>(); + break; + case ::SCL_convertAlgo::RGB_Better: + this->template __impl_dither<::SCL_convertAlgo::RGB_Better>(); + break; + case ::SCL_convertAlgo::HSV: + this->template __impl_dither<::SCL_convertAlgo::HSV>(); + break; + case ::SCL_convertAlgo::Lab94: + this->template __impl_dither<::SCL_convertAlgo::Lab94>(); + break; + case ::SCL_convertAlgo::Lab00: + this->template __impl_dither<::SCL_convertAlgo::Lab00>(); + break; + case ::SCL_convertAlgo::XYZ: + this->template __impl_dither<::SCL_convertAlgo::XYZ>(); + break; + + default: + abort(); + return false; } } else { this->_dithered_image = this->_raw_image; @@ -250,10 +256,10 @@ class ImageCvter : public GPU_wrapper_wrapper { converted_image(dest.data()); } - inline void - converted_image(ARGB *const data_dest, int64_t *const rows_dest = nullptr, - int64_t *const cols_dest = nullptr, - const bool is_dest_col_major = true) const noexcept { + inline void converted_image( + ARGB *const data_dest, int64_t *const rows_dest = nullptr, + int64_t *const cols_dest = nullptr, + const bool is_dest_col_major = true) const noexcept { if (rows_dest != nullptr) { *rows_dest = this->rows(); } @@ -288,7 +294,7 @@ class ImageCvter : public GPU_wrapper_wrapper { } } -private: + private: void add_colors_to_hash() noexcept { // this->_color_hash.clear(); @@ -298,8 +304,7 @@ class ImageCvter : public GPU_wrapper_wrapper { auto it = _color_hash.find(cu); // this key isn't inserted - if (it == _color_hash.end()) - this->_color_hash.emplace(cu, TokiColor_t()); + if (it == _color_hash.end()) this->_color_hash.emplace(cu, TokiColor_t()); } } @@ -308,7 +313,6 @@ class ImageCvter : public GPU_wrapper_wrapper { this->match_all_TokiColors_cpu(); return true; } else { - if constexpr (gpu_wrapper::have_api) { // If converter have gpu resources, compute by gpu if (try_gpu && this->have_gpu_resource()) { @@ -331,8 +335,7 @@ class ImageCvter : public GPU_wrapper_wrapper { tasks.clear(); for (auto &pair : _color_hash) { - if (!pair.second.is_result_computed()) - tasks.emplace_back(&pair); + if (!pair.second.is_result_computed()) tasks.emplace_back(&pair); } const size_t taskCount = tasks.size(); @@ -373,7 +376,8 @@ class ImageCvter : public GPU_wrapper_wrapper { } } - template bool match_all_TokiColors_gpu() noexcept { + template + bool match_all_TokiColors_gpu() noexcept { static_assert(!is_not_optical, "GPU boosting is only avaliable for VisualCraftL."); // static_assert(gpu_wrapper::have_api, "No avaliable GPU api."); @@ -412,7 +416,6 @@ class ImageCvter : public GPU_wrapper_wrapper { if (gpu_task_count > 0) { std::vector> task_colors(gpu_task_count); for (size_t tid = 0; tid < gpu_task_count; tid++) { - if (tasks[tid]->first.algo != algo) { return false; } @@ -434,30 +437,30 @@ class ImageCvter : public GPU_wrapper_wrapper { std::array colorset_ptrs{nullptr, nullptr, nullptr}; switch (algo) { - case SCL_convertAlgo::RGB: - case SCL_convertAlgo::RGB_Better: - colorset_ptrs = {TokiColor_t::Allowed->rgb_data(0), - TokiColor_t::Allowed->rgb_data(1), - TokiColor_t::Allowed->rgb_data(2)}; - break; - case SCL_convertAlgo::HSV: - colorset_ptrs = {TokiColor_t::Allowed->hsv_data(0), - TokiColor_t::Allowed->hsv_data(1), - TokiColor_t::Allowed->hsv_data(2)}; - break; - case SCL_convertAlgo::Lab94: - case SCL_convertAlgo::Lab00: - colorset_ptrs = {TokiColor_t::Allowed->lab_data(0), - TokiColor_t::Allowed->lab_data(1), - TokiColor_t::Allowed->lab_data(2)}; - break; - case SCL_convertAlgo::XYZ: - colorset_ptrs = {TokiColor_t::Allowed->xyz_data(0), - TokiColor_t::Allowed->xyz_data(1), - TokiColor_t::Allowed->xyz_data(2)}; - break; - default: - abort(); + case SCL_convertAlgo::RGB: + case SCL_convertAlgo::RGB_Better: + colorset_ptrs = {TokiColor_t::Allowed->rgb_data(0), + TokiColor_t::Allowed->rgb_data(1), + TokiColor_t::Allowed->rgb_data(2)}; + break; + case SCL_convertAlgo::HSV: + colorset_ptrs = {TokiColor_t::Allowed->hsv_data(0), + TokiColor_t::Allowed->hsv_data(1), + TokiColor_t::Allowed->hsv_data(2)}; + break; + case SCL_convertAlgo::Lab94: + case SCL_convertAlgo::Lab00: + colorset_ptrs = {TokiColor_t::Allowed->lab_data(0), + TokiColor_t::Allowed->lab_data(1), + TokiColor_t::Allowed->lab_data(2)}; + break; + case SCL_convertAlgo::XYZ: + colorset_ptrs = {TokiColor_t::Allowed->xyz_data(0), + TokiColor_t::Allowed->xyz_data(1), + TokiColor_t::Allowed->xyz_data(2)}; + break; + default: + abort(); } if (gpu_task_count > 0) { @@ -505,24 +508,25 @@ class ImageCvter : public GPU_wrapper_wrapper { template inline static ARGB ColorCvt(float c0, float c1, float c2) noexcept { switch (algo) { - case ::SCL_convertAlgo::RGB: - case ::SCL_convertAlgo::RGB_Better: - case ::SCL_convertAlgo::gaCvter: - return RGB2ARGB(c0, c1, c2); - case ::SCL_convertAlgo::HSV: - return HSV2ARGB(c0, c1, c2); - case ::SCL_convertAlgo::Lab00: - case ::SCL_convertAlgo::Lab94: - return Lab2ARGB(c0, c1, c2); - case ::SCL_convertAlgo::XYZ: - return XYZ2ARGB(c0, c1, c2); + case ::SCL_convertAlgo::RGB: + case ::SCL_convertAlgo::RGB_Better: + case ::SCL_convertAlgo::gaCvter: + return RGB2ARGB(c0, c1, c2); + case ::SCL_convertAlgo::HSV: + return HSV2ARGB(c0, c1, c2); + case ::SCL_convertAlgo::Lab00: + case ::SCL_convertAlgo::Lab94: + return Lab2ARGB(c0, c1, c2); + case ::SCL_convertAlgo::XYZ: + return XYZ2ARGB(c0, c1, c2); } // unreachable abort(); return 0; } - template void __impl_dither() noexcept { + template + void __impl_dither() noexcept { std::array dither_c3; for (auto &i : dither_c3) { i.setZero(this->rows() + 2, this->cols() + 2); @@ -638,6 +642,9 @@ class ImageCvter : public GPU_wrapper_wrapper { } }; -} // namespace libImageCvt +std::vector hash_of_image( + Eigen::Map> img) noexcept; + +} // namespace libImageCvt -#endif // COLORMANIP_IMAGECONVERT_HPP +#endif // COLORMANIP_IMAGECONVERT_HPP diff --git a/utilities/ColorManip/newColorSet.hpp b/utilities/ColorManip/newColorSet.hpp index f326ae4b..a9b164df 100644 --- a/utilities/ColorManip/newColorSet.hpp +++ b/utilities/ColorManip/newColorSet.hpp @@ -33,6 +33,19 @@ This file is part of SlopeCraft. // using Eigen::Dynamic; +namespace internal { + +struct hash_temp { + std::array, 4> color_ptrs; + const void *color_id_ptr; + int color_count; + bool is_maptical; +}; + +std::vector hash_of_colorset(const hash_temp &) noexcept; + +} // namespace internal + template class colorset_new : public std::conditional_t< is_not_optical, @@ -40,7 +53,7 @@ class colorset_new : public std::conditional_t< colorset_maptical_allowed>, std::conditional_t> { -public: + public: template colorset_new(const float *const src) : colorset_maptical_basic(src) { static_assert(is_basic, @@ -54,21 +67,40 @@ class colorset_new : public std::conditional_t< inline float color_value(const SCL_convertAlgo algo, const int r, const int c) const noexcept { switch (algo) { - case SCL_convertAlgo::gaCvter: - case SCL_convertAlgo::RGB: - case SCL_convertAlgo::RGB_Better: - return this->RGB(r, c); - - case SCL_convertAlgo::HSV: - return this->HSV(r, c); - case SCL_convertAlgo::Lab94: - case SCL_convertAlgo::Lab00: - return this->Lab(r, c); - case SCL_convertAlgo::XYZ: - return this->XYZ(r, c); + case SCL_convertAlgo::gaCvter: + case SCL_convertAlgo::RGB: + case SCL_convertAlgo::RGB_Better: + return this->RGB(r, c); + + case SCL_convertAlgo::HSV: + return this->HSV(r, c); + case SCL_convertAlgo::Lab94: + case SCL_convertAlgo::Lab00: + return this->Lab(r, c); + case SCL_convertAlgo::XYZ: + return this->XYZ(r, c); } return NAN; } + + template + std::vector hash() const noexcept { + internal::hash_temp temp; + temp.color_count = this->color_count(); + temp.color_ptrs[0] = {this->rgb_data(0), this->rgb_data(1), + this->rgb_data(2)}; + temp.color_ptrs[1] = {this->hsv_data(0), this->hsv_data(1), + this->hsv_data(2)}; + temp.color_ptrs[2] = {this->lab_data(0), this->lab_data(1), + this->lab_data(2)}; + temp.color_ptrs[3] = {this->xyz_data(0), this->xyz_data(1), + this->xyz_data(2)}; + + temp.color_id_ptr = this->map_data(); + temp.is_maptical = is_not_optical; + + return internal::hash_of_colorset(temp); + } }; -#endif // SCL_NEWCOLORSET_HPP \ No newline at end of file +#endif // SCL_NEWCOLORSET_HPP \ No newline at end of file diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 59c894d5..69447c92 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -33,6 +33,7 @@ This file is part of SlopeCraft. #include #include #include +#include #ifdef SC_VECTORIZE_AVX2 #include @@ -72,13 +73,13 @@ inline __m256 _mm256_acos_ps__manually(__m256 x) noexcept { } // #warning rua~ -#endif // SC_VECTORIZE_AVX2 +#endif // SC_VECTORIZE_AVX2 // using Eigen::Dynamic; namespace { inline constexpr float threshold = 1e-10f; -} // namespace +} // namespace struct convert_unit { explicit convert_unit(ARGB _a, ::SCL_convertAlgo _c) : _ARGB(_a), algo(_c) {} ARGB _ARGB; @@ -92,36 +93,45 @@ struct convert_unit { Eigen::Array3f c3; const ::ARGB rawColor = this->_ARGB; switch (this->algo) { - case ::SCL_convertAlgo::RGB: - case ::SCL_convertAlgo::RGB_Better: - case ::SCL_convertAlgo::gaCvter: - c3[0] = std::max(getR(rawColor) / 255.0f, threshold); - c3[1] = std::max(getG(rawColor) / 255.0f, threshold); - c3[2] = std::max(getB(rawColor) / 255.0f, threshold); - break; - - case ::SCL_convertAlgo::HSV: - RGB2HSV(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, - getB(rawColor) / 255.0f, c3[0], c3[1], c3[2]); - break; - case ::SCL_convertAlgo::Lab94: - case ::SCL_convertAlgo::Lab00: - float X, Y, Z; - RGB2XYZ(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, - getB(rawColor) / 255.0f, X, Y, Z); - XYZ2Lab(X, Y, Z, c3[0], c3[1], c3[2]); - break; - default: - RGB2XYZ(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, - getB(rawColor) / 255.0f, c3[0], c3[1], c3[2]); - break; + case ::SCL_convertAlgo::RGB: + case ::SCL_convertAlgo::RGB_Better: + case ::SCL_convertAlgo::gaCvter: + c3[0] = std::max(getR(rawColor) / 255.0f, threshold); + c3[1] = std::max(getG(rawColor) / 255.0f, threshold); + c3[2] = std::max(getB(rawColor) / 255.0f, threshold); + break; + + case ::SCL_convertAlgo::HSV: + RGB2HSV(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, + getB(rawColor) / 255.0f, c3[0], c3[1], c3[2]); + break; + case ::SCL_convertAlgo::Lab94: + case ::SCL_convertAlgo::Lab00: + float X, Y, Z; + RGB2XYZ(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, + getB(rawColor) / 255.0f, X, Y, Z); + XYZ2Lab(X, Y, Z, c3[0], c3[1], c3[2]); + break; + default: + RGB2XYZ(getR(rawColor) / 255.0f, getG(rawColor) / 255.0f, + getB(rawColor) / 255.0f, c3[0], c3[1], c3[2]); + break; } return c3; } + + template + void save(archive &ar) const { + ar(this->_ARGB, this->algo); + } + template + void load(archive &ar) { + ar(this->_ARGB, this->algo); + } }; struct hash_cvt_unit { -public: + public: inline size_t operator()(const convert_unit cu) const noexcept { return std::hash()(cu._ARGB) ^ std::hash()(uint8_t(cu.algo)); @@ -132,7 +142,7 @@ template class newTokiColor : public ::std::conditional_t { -public: + public: using Base_t = ::std::conditional_t; @@ -140,13 +150,13 @@ class newTokiColor using result_t = typename Base_t::result_t; // Eigen::Array3f c3; // color in some colorspace - float ResultDiff; // color diff for the result + float ResultDiff; // color diff for the result // These two members must be defined by caller static const basic_t *const Basic; static const allowed_t *const Allowed; -public: + public: explicit newTokiColor() { if constexpr (is_not_optical) { this->Result = 0; @@ -188,22 +198,22 @@ class newTokiColor const Eigen::Array3f c3 = cu.to_c3(); switch (cu.algo) { - case ::SCL_convertAlgo::RGB: - return applyRGB(c3); - case ::SCL_convertAlgo::RGB_Better: - return applyRGB_plus(c3); - case ::SCL_convertAlgo::HSV: - return applyHSV(c3); - case ::SCL_convertAlgo::Lab94: - return applyLab94(c3); - case ::SCL_convertAlgo::Lab00: - return applyLab00(c3); - case ::SCL_convertAlgo::XYZ: - return applyXYZ(c3); - - default: - abort(); - return result_t(0); + case ::SCL_convertAlgo::RGB: + return applyRGB(c3); + case ::SCL_convertAlgo::RGB_Better: + return applyRGB_plus(c3); + case ::SCL_convertAlgo::HSV: + return applyHSV(c3); + case ::SCL_convertAlgo::Lab94: + return applyLab94(c3); + case ::SCL_convertAlgo::Lab00: + return applyLab00(c3); + case ::SCL_convertAlgo::XYZ: + return applyXYZ(c3); + + default: + abort(); + return result_t(0); } } @@ -215,19 +225,17 @@ class newTokiColor } } -private: + private: auto find_result(const TempVectorXf_t &diff) noexcept { int tempidx = 0; this->ResultDiff = diff.minCoeff(&tempidx); if constexpr (is_not_optical) { this->Result = Allowed->Map(tempidx); - if (Base_t::needFindSide) - this->doSide(diff); + if (Base_t::needFindSide) this->doSide(diff); return this->Result; } else { - this->result_color_id = Allowed->color_id(tempidx); // std::cout << tempidx << '\t' << this->result_color_id << '\n'; return this->color_id(); @@ -246,8 +254,7 @@ class newTokiColor } if constexpr (is_not_optical) { this->Result = Allowed->Map(minidx); - if (Base_t::needFindSide) - this->doSide(diff); + if (Base_t::needFindSide) this->doSide(diff); return this->Result; } else { @@ -256,7 +263,8 @@ class newTokiColor } } - template void doSide(const TempVectorXf_t &Diff) { + template + void doSide(const TempVectorXf_t &Diff) { static_assert(is_not_optical); int tempIndex = 0; @@ -269,60 +277,59 @@ class newTokiColor // using Base_t::DepthCount; // using Base_t::needFindSide; - if (!Base_t::needFindSide) - return; + if (!Base_t::needFindSide) return; // qDebug("开始doSide"); // qDebug()<<"size(Diff)=["<Result % 4) { - case 3: - return; - case 0: // 1,2 - if (Base_t::DepthCount[1]) { - this->sideSelectivity[0] = - Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) - .minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); - } - if (Base_t::DepthCount[2]) { - this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], - Base_t::DepthCount[2]) - .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + - Base_t::DepthCount[1] + tempIndex); - } - break; - case 1: // 0,2 - if (Base_t::DepthCount[0]) { - this->sideSelectivity[0] = - Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(0 + tempIndex); - } - if (Base_t::DepthCount[2]) { - this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], - Base_t::DepthCount[2]) - .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + - Base_t::DepthCount[1] + tempIndex); - } - break; - case 2: // 0,1 - if (Base_t::DepthCount[0]) { - this->sideSelectivity[0] = - Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(0 + tempIndex); - } - if (Base_t::DepthCount[1]) { - this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) - .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); - } - break; + case 3: + return; + case 0: // 1,2 + if (Base_t::DepthCount[1]) { + this->sideSelectivity[0] = + Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) + .minCoeff(&tempIndex); + this->sideResult[0] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); + } + if (Base_t::DepthCount[2]) { + this->sideSelectivity[1] = + Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], + Base_t::DepthCount[2]) + .minCoeff(&tempIndex); + this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + + Base_t::DepthCount[1] + tempIndex); + } + break; + case 1: // 0,2 + if (Base_t::DepthCount[0]) { + this->sideSelectivity[0] = + Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); + this->sideResult[0] = Allowed->Map(0 + tempIndex); + } + if (Base_t::DepthCount[2]) { + this->sideSelectivity[1] = + Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], + Base_t::DepthCount[2]) + .minCoeff(&tempIndex); + this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + + Base_t::DepthCount[1] + tempIndex); + } + break; + case 2: // 0,1 + if (Base_t::DepthCount[0]) { + this->sideSelectivity[0] = + Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); + this->sideResult[0] = Allowed->Map(0 + tempIndex); + } + if (Base_t::DepthCount[1]) { + this->sideSelectivity[1] = + Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) + .minCoeff(&tempIndex); + this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); + } + break; } // sideSelectivity[0]-=1.0;sideSelectivity[1]-=1.0; // sideSelectivity[0]*=100.0;sideSelectivity[1]*=100.0; @@ -819,6 +826,21 @@ class newTokiColor return find_result(Diff); } + + public: + template + void save(archive &ar) const { + static_assert(is_not_optical, + "Serialization is only avaliable for maptical maps"); + ar(this->sideSelectivity, this->sideResult, this->Result, this->ResultDiff); + } + + template + void load(archive &ar) { + static_assert(is_not_optical, + "Serialization is only avaliable for maptical maps"); + ar(this->sideSelectivity, this->sideResult, this->Result, this->ResultDiff); + } }; -#endif // NEWTOKICOLOR_HPP \ No newline at end of file +#endif // NEWTOKICOLOR_HPP \ No newline at end of file diff --git a/utilities/ColorManip/seralize_funs.hpp b/utilities/ColorManip/seralize_funs.hpp new file mode 100644 index 00000000..97332f41 --- /dev/null +++ b/utilities/ColorManip/seralize_funs.hpp @@ -0,0 +1,29 @@ +#ifndef SLOPECRAFT_UTILITIES_COLORMANIP_SERIALIZEFUNS_HPP +#define SLOPECRAFT_UTILITIES_COLORMANIP_SERIALIZEFUNS_HPP + +#include +#include +#include +#include + +namespace cereal { +template +void save(archive &ar, const Eigen::ArrayXX &img) { + ar(cereal::make_size_tag(img.rows())); + ar(cereal::make_size_tag(img.cols())); + ar(cereal::binary_data(img.data(), img.size() * sizeof(ARGB))); +} + +template +void load(archive &ar, Eigen::ArrayXX &img) { + Eigen::Index rows{0}, cols{0}; + + ar(cereal::make_size_tag(rows)); + ar(cereal::make_size_tag(cols)); + + img.resize(rows, cols); + ar(cereal::binary_data(img.data(), rows * cols * sizeof(ARGB))); +} +} // namespace cereal + +#endif // SLOPECRAFT_UTILITIES_COLORMANIP_SERIALIZEFUNS_HPP \ No newline at end of file From f31804c24f484d935d91ea94d7e370f5eb94bfac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 14:13:24 +0800 Subject: [PATCH 0254/1123] add save function for mapimagecvter --- utilities/MapImageCvter/CMakeLists.txt | 12 ++++++++- utilities/MapImageCvter/MapImageCvter.cpp | 21 +++++++++++++++ utilities/MapImageCvter/MapImageCvter.h | 33 +++++++++++++++++++---- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index 2ade1a97..e3b2f1b2 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -2,6 +2,11 @@ set(CMAKE_CXX_STANDARD 20) find_package(OpenMP REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_bxzstr.cmake) +find_package(cereal REQUIRED) +find_package(bxzstr REQUIRED) + add_library(MapImageCvter STATIC MapImageCvter.h @@ -12,7 +17,12 @@ target_include_directories(MapImageCvter PUBLIC ${SlopeCraft_HeuristicFlow_include_dir} ) -target_link_libraries(MapImageCvter PUBLIC ColorManip GAConverter OpenMP::OpenMP_CXX) +target_link_libraries(MapImageCvter PUBLIC + ColorManip + GAConverter + OpenMP::OpenMP_CXX + cereal::cereal + bxzstr::bxzstr) target_compile_options(MapImageCvter PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_features(MapImageCvter PUBLIC cxx_std_20) diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index 0bd477ff..08c2131e 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -24,6 +24,9 @@ This file is part of SlopeCraft. #include #include +#include +#include +#include using namespace libImageCvt; @@ -67,4 +70,22 @@ void libMapImageCvt::MapImageCvter::convert_image( Base_t::convert_image(::SCL_convertAlgo::RGB_Better, dither); this->_raw_image = raw_image_cache; +} + +bool libMapImageCvt::MapImageCvter::save_cache( + const char *filename) const noexcept { + bxz::ofstream ofs{filename, std::ios::binary, bxz::Compression::z, 9}; + if (!ofs) { + return false; + } + + { + cereal::BinaryOutputArchive boa(ofs); + + boa(*this); + } + + ofs.close(); + + return true; } \ No newline at end of file diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index ff73d2f9..df2d2c6b 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -25,7 +25,9 @@ This file is part of SlopeCraft. #include #include - +#include +#include +#include #include namespace GACvter { @@ -39,10 +41,10 @@ struct GAOption; namespace libMapImageCvt { class MapImageCvter : public ::libImageCvt::ImageCvter { -private: + private: std::unique_ptr gacvter; -public: + public: using Base_t = ::libImageCvt::ImageCvter; using TokiColor_t = typename Base_t::TokiColor_t; @@ -91,7 +93,28 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { dest[r] = &it->second; } } + + public: + friend class cereal::access; + template + void save(archive &ar) const { + ar(this->_raw_image); + ar(this->algo); + ar(this->_color_hash); + ar(this->_dithered_image); + } + + template + void load(archive &ar) { + ar(this->_raw_image); + ar(this->algo); + ar(this->_color_hash); + ar(this->_dithered_image); + } + + public: + bool save_cache(const char *filename) const noexcept; }; -} // namespace libMapImageCvt -#endif // SCL_MAPIMAGECVTER_MAPIMAGECVTER_H \ No newline at end of file +} // namespace libMapImageCvt +#endif // SCL_MAPIMAGECVTER_MAPIMAGECVTER_H \ No newline at end of file From 89ec18947d34029489ef5cf7351338ec4a339737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 15:20:32 +0800 Subject: [PATCH 0255/1123] add task_hash to imageCvter --- utilities/ColorManip/imageConvert.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 8ac57a5d..3f0c282c 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -640,6 +640,20 @@ class ImageCvter : public GPU_wrapper_wrapper { } return; } + + public: + uint64_t task_hash() const noexcept { + return this->task_hash(this->algo, this->dither); + } + + uint64_t task_hash(SCL_convertAlgo a, bool d) const noexcept { + const auto &img = this->_raw_image; + return std::hash()( + + std::string_view{(const char *)img.data(), + img.size() * sizeof(uint32_t)}) ^ + std::hash()((char)a) ^ std::hash()(d); + } }; std::vector hash_of_image( From 571f427029c5bba8754bd4ca09634b84dd673a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 15:20:54 +0800 Subject: [PATCH 0256/1123] add save hash to SCL --- SlopeCraftL/CMakeLists.txt | 2 + SlopeCraftL/SlopeCraftL.h | 17 ++++++++ SlopeCraftL/TokiSlopeCraft.h | 11 +++++ SlopeCraftL/TokiSlopeCraft_cache.cpp | 65 ++++++++++++++++++++++++++++ SlopeCraftL/WriteStringDeliver.h | 24 ++++++++++ 5 files changed, 119 insertions(+) create mode 100644 SlopeCraftL/TokiSlopeCraft_cache.cpp create mode 100644 SlopeCraftL/WriteStringDeliver.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ec1d5368..9bdf2084 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -33,6 +33,7 @@ set(SlopeCraft_SCL_sources simpleBlock.h SlopeCraftL.h SlopeCraftL_global.h + WriteStringDeliver.h AiCvterOpt.cpp Colors.cpp @@ -44,6 +45,7 @@ set(SlopeCraft_SCL_sources TokiSlopeCraft_static_funs.cpp TokiSlopeCraft_build.cpp TokiSlopeCraft_convert.cpp + TokiSlopeCraft_cache.cpp WaterItem.cpp imagePreprocess.cpp lossyCompressor.cpp diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 99568d19..83469206 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -55,6 +55,19 @@ using errorFlag = ::SCL_errorFlag; namespace SlopeCraft { +struct StringDeliver { + StringDeliver() = default; + StringDeliver(char *p, size_t cap) : data(p), capacity(cap) {} + char *const data{nullptr}; + const size_t capacity{0}; + size_t size{0}; + bool is_complete{true}; + + constexpr bool is_valid() const noexcept { + return this->data != nullptr && this->capacity > 0; + } +}; + class AbstractBlock { public: AbstractBlock() = default; @@ -248,6 +261,10 @@ class Kernel { virtual const unsigned short *getBuild(int *xSize = nullptr, int *ySize = nullptr, int *zSize = nullptr) const = 0; + + // extra functions + virtual bool saveCache(const char *cache_dir, + StringDeliver &err) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 6e9a558c..b24ce43e 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -52,6 +52,7 @@ This file is part of SlopeCraft. #include #include #include +#include "WriteStringDeliver.h" /* namespace SlopeCraft @@ -296,6 +297,16 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string Noder(const short *src, int size) const; Kernel *toBaseClassPtr() { return this; } + + bool saveCache(const char *cache_dir, + StringDeliver &_err) const noexcept override { + std::string err; + this->saveCache(cache_dir, err); + write(_err, err); + return err.empty(); + } + + void saveCache(std::string_view cache_dir, std::string &err) const noexcept; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp new file mode 100644 index 00000000..26fba5d1 --- /dev/null +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -0,0 +1,65 @@ +#include "TokiSlopeCraft.h" +#include +#include +#include +#include +#include + +std::string write_hash(std::string_view filename, + const std::vector &hash) noexcept { + std::ofstream ofs{filename.data(), std::ios::binary}; + + if (!ofs) { + return fmt::format("ofstream failed to open hash file: {}", filename); + } + + ofs.write((const char *)hash.data(), sizeof(uint8_t) * hash.size()); + ofs.close(); + return {}; +} + +const std::string_view hash_suffix{"*.sha3_512"}; + +void TokiSlopeCraft::saveCache(std::string_view cache_dir, + std::string &err) const noexcept { + if (this->kernelStep < SlopeCraft::step::converted) { + err = "Can not save cache before the image is converted."; + return; + } + + const std::string task_dir = + fmt::format("{}/{}", cache_dir, this->image_cvter.task_hash()); + + namespace stdfs = std::filesystem; + std::error_code ec; + if (!stdfs::create_directories(task_dir, ec)) { + err = fmt::format( + "Failed to create dir named \"{}\", error code = {}, message = {}", + task_dir, ec.value(), ec.message()); + return; + } + + err.clear(); + std::string temp_err{}; + // write colorset hash + { + const std::string name_hash_colorset = + fmt::format("{}/{}{}", cache_dir, "colorset", hash_suffix); + + temp_err = write_hash(name_hash_colorset, TokiSlopeCraft::Allowed.hash()); + if (!temp_err.empty()) { + err = fmt::format("Failed to save colorset hash. Detail: {}", temp_err); + return; + } + } + + const std::string convert_cache_file = + fmt::format("{}/convert.sc_cache.gz", task_dir); + + if (!this->image_cvter.save_cache(convert_cache_file.c_str())) { + err = fmt::format("Failed to save image cvter cache."); + return; + } + + return; +} \ No newline at end of file diff --git a/SlopeCraftL/WriteStringDeliver.h b/SlopeCraftL/WriteStringDeliver.h new file mode 100644 index 00000000..d696ca2b --- /dev/null +++ b/SlopeCraftL/WriteStringDeliver.h @@ -0,0 +1,24 @@ +#ifndef SLOPECRAFT_SLOPECRAFTL_WRITESTRINGDELIVER_H +#define SLOPECRAFT_SLOPECRAFTL_WRITESTRINGDELIVER_H +#include "SlopeCraftL.h" +#include + +namespace SlopeCraft { +inline void write(StringDeliver& s, std::string_view sv) noexcept { + if (!s.is_valid()) { + return; + } + + const size_t move_bytes = std::min(sv.size(), s.capacity); + memcpy(s.data, sv.data(), move_bytes); + s.is_complete = move_bytes < sv.size(); + + if (!s.is_complete) { + s.data[s.capacity - 1] = '\0'; + } + + s.size = move_bytes; +} +}; // namespace SlopeCraft + +#endif // SLOPECRAFT_SLOPECRAFTL_WRITESTRINGDELIVER_H From 69864c38dabdf77bcc7ca0f6b0eda2f2946d9789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 15:56:41 +0800 Subject: [PATCH 0257/1123] set cache dir for SlopeCraft --- SlopeCraftL/SlopeCraftL.h | 5 +++-- SlopeCraftL/TokiSlopeCraft.h | 20 ++++++++++++-------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 28 ++++++++++++++++++++++------ 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 83469206..b1dd2ae0 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -263,8 +263,9 @@ class Kernel { int *zSize = nullptr) const = 0; // extra functions - virtual bool saveCache(const char *cache_dir, - StringDeliver &err) const noexcept = 0; + virtual void setCacheDir(const char *) noexcept = 0; + virtual const char *cacheDir() const noexcept = 0; + virtual bool saveCache(StringDeliver &err) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index b24ce43e..f767d44e 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -66,11 +66,11 @@ namespace SlopeCraft using namespace SlopeCraft; #include -#define mapColor2Index(mapColor) (64 * (mapColor % 4) + (mapColor / 4)) -#define index2mapColor(index) (4 * (index % 64) + (index / 64)) -#define mapColor2baseColor(mapColor) (mapColor >> 2) +#define mapColor2Index(mapColor) (64 * ((mapColor) % 4) + ((mapColor) / 4)) +#define index2mapColor(index) (4 * ((index) % 64) + ((index) / 64)) +#define mapColor2baseColor(mapColor) ((mapColor) >> 2) #define index2baseColor(index) (mapColor2baseColor(index2mapColor(index))) -#define mapColor2depth(mapColor) (mapColor % 4) +#define mapColor2depth(mapColor) ((mapColor) % 4) #define index2depth(index) (mapColor2depth(index2mapColor(index))) class PrimGlassBuilder; @@ -270,6 +270,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { compressSettings compressMethod; glassBridgeSettings glassMethod; libSchem::Schem schem; + + std::optional cache_dir{""}; // Eigen::Tensor Build; // x,y,z // for setType: @@ -298,15 +300,17 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { Kernel *toBaseClassPtr() { return this; } - bool saveCache(const char *cache_dir, - StringDeliver &_err) const noexcept override { + void setCacheDir(const char *) noexcept override; + const char *cacheDir() const noexcept override; + + bool saveCache(StringDeliver &_err) const noexcept override { std::string err; - this->saveCache(cache_dir, err); + this->saveCache(err); write(_err, err); return err.empty(); } - void saveCache(std::string_view cache_dir, std::string &err) const noexcept; + void saveCache(std::string &err) const noexcept; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 26fba5d1..891a5582 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -20,15 +20,30 @@ std::string write_hash(std::string_view filename, const std::string_view hash_suffix{"*.sha3_512"}; -void TokiSlopeCraft::saveCache(std::string_view cache_dir, - std::string &err) const noexcept { +void TokiSlopeCraft::setCacheDir(const char *d) noexcept { + this->cache_dir = d; +} +const char *TokiSlopeCraft::cacheDir() const noexcept { + if (this->cache_dir.has_value()) { + return this->cache_dir.value().c_str(); + } + + return nullptr; +} + +void TokiSlopeCraft::saveCache(std::string &err) const noexcept { if (this->kernelStep < SlopeCraft::step::converted) { err = "Can not save cache before the image is converted."; return; } - const std::string task_dir = - fmt::format("{}/{}", cache_dir, this->image_cvter.task_hash()); + if (!this->cache_dir.has_value()) { + err = "cache dir is not set."; + return; + } + + const std::string task_dir = fmt::format("{}/{}", this->cache_dir.value(), + this->image_cvter.task_hash()); namespace stdfs = std::filesystem; std::error_code ec; @@ -41,10 +56,11 @@ void TokiSlopeCraft::saveCache(std::string_view cache_dir, err.clear(); std::string temp_err{}; + // write colorset hash { - const std::string name_hash_colorset = - fmt::format("{}/{}{}", cache_dir, "colorset", hash_suffix); + const std::string name_hash_colorset = fmt::format( + "{}/{}{}", this->cache_dir.value(), "colorset", hash_suffix); temp_err = write_hash(name_hash_colorset, TokiSlopeCraft::Allowed.hash()); if (!temp_err.empty()) { From b3057288ad0c60e580aaa8d8ce881950dad54793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 16:09:05 +0800 Subject: [PATCH 0258/1123] remove commented codes --- SlopeCraft/PoolModel.h | 8 -------- SlopeCraft/SCWind.ui | 8 ++++---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index cdb26c8f..f49a024e 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -37,15 +37,7 @@ class CvtPoolModel : public QAbstractListModel { bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - /*/ - bool setData(const QModelIndex& index, const QVariant& value, - int role) override; - Qt::DropActions supportedDragActions() const override; - - bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, - int column, const QModelIndex& parent) const override; - */ private: task_pool_t* pool{nullptr}; QListView* listview{nullptr}; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index cc13cae5..7b5a4383 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 1 + 2 @@ -175,8 +175,8 @@ 0 0 - 98 - 28 + 637 + 549 @@ -722,7 +722,7 @@ - 0 + 1 From 5788041d1a581e27451d6403b3429e2fcb7866f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 16:11:40 +0800 Subject: [PATCH 0259/1123] add update-sc-ui to actions --- .github/workflows/build-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 99dde311..49f849e2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - update-sc-ui jobs: From a9dcb0c99ad75e0eecc83b0c8e27a4ecdf65b87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 16:23:03 +0800 Subject: [PATCH 0260/1123] skip performance comp for cereal --- cmake/configure_cereal.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/configure_cereal.cmake b/cmake/configure_cereal.cmake index fcf61d78..643c2420 100644 --- a/cmake/configure_cereal.cmake +++ b/cmake/configure_cereal.cmake @@ -1,3 +1,5 @@ +set(SKIP_PERFORMANCE_COMPARISON ON) + find_package(cereal) if(${cereal_FOUND}) From 3fb3d81ecabe8423df892b29d61e6133c183316b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 16:30:30 +0800 Subject: [PATCH 0261/1123] fix build without boost --- cmake/configure_cereal.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/configure_cereal.cmake b/cmake/configure_cereal.cmake index 643c2420..c16c8d12 100644 --- a/cmake/configure_cereal.cmake +++ b/cmake/configure_cereal.cmake @@ -1,4 +1,7 @@ set(SKIP_PERFORMANCE_COMPARISON ON) +set(BUILD_SANDBOX OFF) +set(BUILD_DOC OFF) +set(CEREAL_INSTALL OFF) find_package(cereal) From d4f23cb3a5d6de8a3d4b3fd43e582c9bea059d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 17:02:01 +0800 Subject: [PATCH 0262/1123] fix build --- SlopeCraft/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index e6f2de00..01929390 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -50,6 +50,8 @@ target_link_libraries(SlopeCraft PRIVATE AdaptiveLabel VersionDialog) +target_include_directories(SlopeCraft PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + set_target_properties(SlopeCraft PROPERTIES VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns From 5bfc7f697bf816e1d64d366fc6cfd2de36642402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 17:07:24 +0800 Subject: [PATCH 0263/1123] fix build --- SlopeCraft/SCWind.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index cbac08d5..0b91b543 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -8,7 +8,7 @@ #include #include "cvt_task.h" -#include "PoolModel.h " +#include "PoolModel.h" class SCWind; From 1c34f1731618576ea208a13b61f5536dfa7441de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 18:47:05 +0800 Subject: [PATCH 0264/1123] enable export pool listview --- SlopeCraft/PoolModel.cpp | 16 ++++++++++----- SlopeCraft/PoolModel.h | 43 ++++++++++++++++++++++++---------------- SlopeCraft/SCWind.cpp | 12 ++++++++--- SlopeCraft/SCWind.h | 1 + SlopeCraft/SCWind.ui | 25 ++++++++++++++--------- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 7ef55542..050c18e3 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -3,29 +3,35 @@ #include #include -CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) +PoolModel::PoolModel(QObject* parent, task_pool_t* poolptr) : QAbstractListModel(parent), pool(poolptr) {} -CvtPoolModel::~CvtPoolModel() {} +PoolModel::~PoolModel() {} -QVariant CvtPoolModel::data(const QModelIndex& idx, int role) const { +QVariant PoolModel::data(const QModelIndex& idx, int role) const { if (role == Qt::ItemDataRole::DisplayRole) { return this->pool->at(idx.row()).filename; } if (role == Qt::ItemDataRole::DecorationRole) { - if (this->listview->viewMode() == QListView::ViewMode::ListMode) { + assert(this->_listview != nullptr); + if (this->_listview->viewMode() == QListView::ViewMode::ListMode) { return QVariant{}; } auto raw_image = QPixmap::fromImage(this->pool->at(idx.row()).original_image); - auto img = raw_image.scaledToWidth(this->listview->size().width()); + auto img = raw_image.scaledToWidth(this->_listview->size().width()); return QIcon{raw_image}; } return QVariant{}; } +CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) + : PoolModel(parent, poolptr) {} + +CvtPoolModel::~CvtPoolModel() {} + Qt::DropActions CvtPoolModel::supportedDropActions() const { return Qt::DropActions{Qt::DropAction::MoveAction, Qt::DropAction::CopyAction}; diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index f49a024e..9a6e42ca 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -6,12 +6,15 @@ #include #include -class CvtPoolModel : public QAbstractListModel { +class PoolModel : public QAbstractListModel { Q_OBJECT + protected: + task_pool_t* pool{nullptr}; + QListView* _listview{nullptr}; + public: - explicit CvtPoolModel(QObject* parent = nullptr, - task_pool_t* poolptr = nullptr); - ~CvtPoolModel(); + explicit PoolModel(QObject* parent = nullptr, task_pool_t* poolptr = nullptr); + ~PoolModel(); int rowCount(const QModelIndex&) const override { return this->pool->size(); } @@ -25,6 +28,25 @@ class CvtPoolModel : public QAbstractListModel { emit dataChanged(this->index(0, 0), this->index(this->pool->size(), 0)); } + public: + task_pool_t* attached_pool() noexcept { return this->pool; } + const task_pool_t* attached_pool() const noexcept { return this->pool; } + void set_pool(task_pool_t* _pool) noexcept { this->pool = _pool; } + + QListView* attached_listview() noexcept { return this->_listview; } + const QListView* attached_listview() const noexcept { + return this->_listview; + } + void set_listview(QListView* lv) noexcept { this->_listview = lv; } +}; + +class CvtPoolModel : public PoolModel { + Q_OBJECT + public: + explicit CvtPoolModel(QObject* parent = nullptr, + task_pool_t* poolptr = nullptr); + ~CvtPoolModel(); + Qt::DropActions supportedDropActions() const override; Qt::ItemFlags flags(const QModelIndex& index) const override; @@ -37,19 +59,6 @@ class CvtPoolModel : public QAbstractListModel { bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - - private: - task_pool_t* pool{nullptr}; - QListView* listview{nullptr}; - - public: - task_pool_t* attached_pool() noexcept { return this->pool; } - const task_pool_t* attached_pool() const noexcept { return this->pool; } - void set_pool(task_pool_t* _pool) noexcept { this->pool = _pool; } - - QListView* attached_listview() noexcept { return this->listview; } - const QListView* attached_listview() const noexcept { return this->listview; } - void set_listview(QListView* lv) noexcept { this->listview = lv; } }; #endif // SLOPECRAFT_SLOPECRAFT_POOLMODEL_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index ced5f07b..56cb261b 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -3,20 +3,24 @@ #include #include // #include "PoolWidget.h" - SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind), kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); - this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; + assert(this->ui->lview_pool_cvt != nullptr); + assert(this->ui->lview_pool_export != nullptr); + this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; this->ui->lview_pool_cvt->setModel(this->cvt_pool_model); this->cvt_pool_model->set_listview(this->ui->lview_pool_cvt); - connect(this->ui->lview_pool_cvt->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SCWind::when_cvt_pool_selectionChanged); + + this->export_pool_model = new PoolModel{this, &this->tasks}; + this->ui->lview_pool_export->setModel(this->export_pool_model); + this->export_pool_model->set_listview(this->ui->lview_pool_export); } SCWind::~SCWind() { @@ -82,6 +86,8 @@ void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 0); + + this->cvt_pool_model->refresh(); } void SCWind::when_cvt_pool_selectionChanged() noexcept { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 0b91b543..db5d2d01 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -34,6 +34,7 @@ class SCWind : public QMainWindow { task_pool_t tasks; CvtPoolModel* cvt_pool_model{nullptr}; + PoolModel* export_pool_model{nullptr}; }; #endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 7b5a4383..f0556eee 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -6,8 +6,8 @@ 0 0 - 804 - 750 + 920 + 740 @@ -18,7 +18,7 @@ - 2 + 0 @@ -175,8 +175,8 @@ 0 0 - 637 - 549 + 753 + 539 @@ -699,7 +699,14 @@ 0 - + + + QListView::IconMode + + + true + + @@ -722,7 +729,7 @@ - 1 + 0 @@ -735,7 +742,7 @@ - 0 + 2 @@ -1234,7 +1241,7 @@ 0 0 - 804 + 920 22 From 9456b5858d71ae3faba938fafbae5323a6dd3331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 6 May 2023 21:42:55 +0800 Subject: [PATCH 0265/1123] hide old implement --- .../BlockListManager/BlockListManager.cpp | 475 ++++-------------- utilities/BlockListManager/BlockListManager.h | 121 +---- utilities/BlockListManager/CMakeLists.txt | 32 +- .../BlockListManager/removed/BLM_preset.cpp | 100 ++++ .../removed/BlockListManager.cpp | 385 ++++++++++++++ .../removed/BlockListManager.h | 132 +++++ .../{ => removed}/BlockListManager_en_US.ts | 0 .../{ => removed}/BlockListManager_global.h | 0 .../{ => removed}/TokiBaseColor.cpp | 0 .../{ => removed}/TokiBaseColor.h | 0 .../{ => removed}/TokiBlock.cpp | 0 .../{ => removed}/TokiBlock.h | 0 12 files changed, 736 insertions(+), 509 deletions(-) create mode 100644 utilities/BlockListManager/removed/BLM_preset.cpp create mode 100644 utilities/BlockListManager/removed/BlockListManager.cpp create mode 100644 utilities/BlockListManager/removed/BlockListManager.h rename utilities/BlockListManager/{ => removed}/BlockListManager_en_US.ts (100%) rename utilities/BlockListManager/{ => removed}/BlockListManager_global.h (100%) rename utilities/BlockListManager/{ => removed}/TokiBaseColor.cpp (100%) rename utilities/BlockListManager/{ => removed}/TokiBaseColor.h (100%) rename utilities/BlockListManager/{ => removed}/TokiBlock.cpp (100%) rename utilities/BlockListManager/{ => removed}/TokiBlock.h (100%) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 18bb154a..5e03be4f 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -1,385 +1,92 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - #include "BlockListManager.h" -#include "TokiBaseColor.h" -#include "TokiBlock.h" -#include -#include -#include -#include - -BlockListManager::BlockListManager(QHBoxLayout *_area, QObject *parent) - : QObject(parent) { - isApplyingPreset = false; - area = _area; - qDebug() << ((area == nullptr) ? " 错误!_area 为空指针" : ""); - QGroupBox *qgb = nullptr; - QGridLayout *qgl = nullptr; - TokiBaseColor *tbc = nullptr; - tbcs.clear(); - // qDebug("方块列表管理者开始创建 QGroupBox"); - for (uchar baseColor = 0; baseColor < 64; baseColor++) { - if (baseColorNames[baseColor].isEmpty()) break; - qgb = new QGroupBox(baseColorNames[baseColor]); - // qDebug("create QGroupBox"); - qgl = new QGridLayout; - qgb->setLayout(qgl); - // qDebug("create Layout"); - tbc = new TokiBaseColor(baseColor, qgl); - // qDebug("create TokiBaseColor"); - area->addWidget(qgb); - // qDebug("add QGroupBox to layout"); - tbcs.push_back(tbc); - - connect(this, &BlockListManager::translate, tbc, &TokiBaseColor::translate); - connect(tbc, &TokiBaseColor::userClicked, this, - &BlockListManager::receiveClicked); - } - // qDebug("Manager 构造函数完毕"); -} - -BlockListManager::~BlockListManager() { - for (uchar i = 0; i < tbcs.size(); i++) delete tbcs[i]; -} - -void BlockListManager::setVersion(uchar _ver) { - if (_ver < 12 || _ver > SlopeCraft::SCL_maxAvailableVersion()) return; - TokiBaseColor::mcVer = _ver; - for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->versionCheck(); -} - -bool callback_load_image(const char *filename, uint32_t *dst_row_major) { - QImage img(QString::fromLocal8Bit(filename)); - - if (img.isNull()) { - return false; - } - - QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); - - memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); - return true; -} - -bool BlockListManager::setupFixedBlockList(const QString &filename, - const QString &imgdir) noexcept { - return this->impl_setupBlockList(filename, imgdir, this->BL_fixed); -} -bool BlockListManager::setupCustomBlockList(const QString &filename, - const QString &imgdir) noexcept { - return this->impl_setupBlockList(filename, imgdir, this->BL_custom); -} - -bool BlockListManager::impl_setupBlockList( - const QString &filename, const QString &dirname, - std::unique_ptr - &dst) noexcept { - std::string errmsg; - errmsg.resize(4096); - SlopeCraft::blockListOption opt; - opt.errmsg = errmsg.data(); - opt.errmsg_capacity = errmsg.size(); - size_t msg_len{0}; - opt.errmsg_len_dest = &msg_len; - - auto img_dir_local8bit = dirname.toLocal8Bit(); - opt.image_dir = img_dir_local8bit.data(); - - opt.callback_load_image = callback_load_image; - - SlopeCraft::BlockListInterface *bli = - SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), opt); - - errmsg.resize(msg_len); - - if (!errmsg.empty()) { - if (bli == nullptr) { - QMessageBox::critical(dynamic_cast(this->parent()), - tr("解析方块列表失败"), - QString::fromUtf8(errmsg.data())); - return false; - } else { - QMessageBox::warning(dynamic_cast(this->parent()), - tr("解析方块列表失败"), - QString::fromUtf8(errmsg.data())); - } - } - dst.reset(bli); - - std::vector blockps; - std::vector basecolors; - basecolors.resize(dst->size()); - blockps.resize(dst->size()); - - dst->get_blocks(blockps.data(), basecolors.data(), blockps.size()); - - for (size_t idx = 0; idx < dst->size(); idx++) { - this->tbcs[basecolors[idx]]->addTokiBlock(blockps[idx]); - } - return true; -} - -void BlockListManager::setSelected(uchar baseColor, ushort blockSeq) { - isApplyingPreset = true; - tbcs[baseColor]->setSelected(blockSeq); - isApplyingPreset = false; -} - -void BlockListManager::setEnabled(uchar baseColor, bool isEnable) { - isApplyingPreset = true; - tbcs[baseColor]->checkBox->setChecked(isEnable); - isApplyingPreset = false; -} - -void BlockListManager::receiveClicked() const { - if (isApplyingPreset) return; - emit switchToCustom(); - emit blockListChanged(); -} - -void BlockListManager::setLabelColors(const QRgb *colors) { - for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->makeLabel(colors[i]); -} - -void BlockListManager::getEnableList(bool *dest) const { - for (uchar i = 0; i < tbcs.size(); i++) dest[i] = tbcs[i]->getEnabled(); -} - -void BlockListManager::getSimpleBlockList( - const SlopeCraft::AbstractBlock **SBL) const { - // qDebug("void BlockListManager::getSimpleBlockList(simpleBlock * SBL) - // const"); - - for (uchar i = 0; i < 64; i++) { - SBL[i] = nullptr; - } - for (uchar i = 0; i < tbcs.size(); i++) { - SBL[i] = (tbcs[i]->getTokiBlock()->getSimpleBlock()); - } -} -std::vector -BlockListManager::getSimpleBlockList() const { - std::vector SBL(64); - const SlopeCraft::AbstractBlock *p; - for (uchar i = 0; i < tbcs.size(); i++) { - p = tbcs[i]->getTokiBlock()->getSimpleBlock(); - SBL[i] = p; - } - return SBL; -} -std::vector BlockListManager::getTokiBlockList() const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getTokiBlock(); - else - TBL[i] = nullptr; - } - return TBL; -} - -std::vector BlockListManager::getQRadioButtonList() - const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getTokiBlock()->getTarget(); - else - TBL[i] = nullptr; - } - return TBL; -} - -std::vector BlockListManager::toPreset() const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getSelected(); - else - TBL[i] = 0; - } - return TBL; -} - -bool isValidBlockInfo(const QJsonObject &json) { - return (json.contains("id") && json.contains("nameZH") && - json.contains("nameEN") && json.contains("baseColor")); -} - -void BlockListManager::getTokiBaseColors( - std::vector *dest) const { - dest->clear(); - dest->reserve(tbcs.size()); - for (const auto it : tbcs) { - dest->emplace_back(it); - } -} - -int BlockListManager::getBlockNum() const { - int result = 0; - for (auto it : tbcs) { - result += it->tbs.size(); - } - return result; -} - -void BlockListManager::getBlockPtrs(const SlopeCraft::AbstractBlock **dest, - uint8_t *baseColor) const { - int idx = 0; - for (auto it : tbcs) { - for (auto jt : it->tbs) { - baseColor[idx] = it->baseColor; - dest[idx] = jt->getSimpleBlock(); - idx++; - } - } - dest[idx] = nullptr; -} - -bool BlockListManager::loadPreset(const blockListPreset &preset) { - if (preset.values.size() != this->tbcs.size()) { - QMessageBox::warning(dynamic_cast(this->parent()), - tr("加载预设错误"), - tr("预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符") - .arg(preset.values.size()) - .arg(this->tbcs.size())); - return false; - } - - std::vector blocks_arr; - - for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { - auto tbc = this->tbcs[basecolor]; - const auto &pre = preset.values[basecolor]; - - this->setEnabled(basecolor, pre.first); - - // find block - int matched_block_idx = -1; - blocks_arr.clear(); - tbc->getTokiBlockList(blocks_arr); - for (int bidx = 0; bidx < (int)blocks_arr.size(); bidx++) { - const char *const blkid = blocks_arr[bidx]->getSimpleBlock()->getId(); - if (QString::fromUtf8(blkid) == pre.second) { - matched_block_idx = bidx; - break; - } - } - - if (matched_block_idx < 0) { - QMessageBox::warning( - dynamic_cast(this->parent()), tr("加载预设错误"), - tr("预设中为基色%1指定的方块 id 是\"%2\",没有找到这个方块 id") - .arg(basecolor) - .arg(pre.second)); - return false; - } - - this->setSelected(basecolor, matched_block_idx); - } - - emit blockListChanged(); - - return true; -} - -bool BlockListManager::loadInternalPreset( - const blockListPreset &preset) noexcept { - return this->loadPreset(preset); -} - -blockListPreset BlockListManager::currentPreset() const noexcept { - blockListPreset ret; - ret.values.resize(this->tbcs.size()); - for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { - ret.values[basecolor].first = this->tbcs[basecolor]->getEnabled(); - ret.values[basecolor].second = QString::fromUtf8( - this->tbcs[basecolor]->getTokiBlock()->getSimpleBlock()->getId()); - } - return ret; -} - -const QString BlockListManager::baseColorNames[64] = {"00 None", - "01 Grass", - "02 Sand", - "03 Wool", - "04 Fire", - "05 Ice", - "06 Metal", - "07 Plant", - "08 Snow", - "09 Clay", - "10 Dirt", - "11 Stone", - "12 Water", - "13 Wood", - "14 Quartz", - "15 ColorOrange", - "16 ColorMagenta", - "17 ColorLightBlue", - "18 ColorYellow", - "19 ColorLime", - "20 ColorPink", - "21 ColorGray", - "22 ColorLightGray", - "23 ColorCyan", - "24 ColorPurple", - "25 ColorBlue", - "26 ColorBrown", - "27 ColorGreen", - "28 ColorRed", - "29 ColorBlack", - "30 Gold", - "31 Diamond", - "32 Lapis", - "33 Emerald", - "34 Podzol", - "35 Nether", - "36 TerracottaWhite", - "37 TerracottaOrange", - "38 TerracottaMagenta", - "39 TerracottaLightBlue", - "40 TerracottaYellow", - "41 TerracottaLime", - "42 TerracottaPink", - "43 TerracottaGray", - "44 TerracottaLightGray", - "45 TerracottaCyan", - "46 TerracottaPurple", - "47 TerracottaBlue", - "48 TerracottaBrown", - "49 TerracottaGreen", - "50 TerracottaRed", - "51 TerracottaBlack", - "52 CrimsonNylium", - "53 CrimsonStem", - "54 CrimsonHyphae", - "55 WarpedNylium", - "56 WarpedStem", - "57 WarpedHyphae", - "58 WarpedWartBlock", - "59 Deepslate", - "60 RawIron", - "61 GlowLichen", - "", - ""}; +#include + +std::string_view basecolor_names[] = {"00 None", + "01 Grass", + "02 Sand", + "03 Wool", + "04 Fire", + "05 Ice", + "06 Metal", + "07 Plant", + "08 Snow", + "09 Clay", + "10 Dirt", + "11 Stone", + "12 Water", + "13 Wood", + "14 Quartz", + "15 ColorOrange", + "16 ColorMagenta", + "17 ColorLightBlue", + "18 ColorYellow", + "19 ColorLime", + "20 ColorPink", + "21 ColorGray", + "22 ColorLightGray", + "23 ColorCyan", + "24 ColorPurple", + "25 ColorBlue", + "26 ColorBrown", + "27 ColorGreen", + "28 ColorRed", + "29 ColorBlack", + "30 Gold", + "31 Diamond", + "32 Lapis", + "33 Emerald", + "34 Podzol", + "35 Nether", + "36 TerracottaWhite", + "37 TerracottaOrange", + "38 TerracottaMagenta", + "39 TerracottaLightBlue", + "40 TerracottaYellow", + "41 TerracottaLime", + "42 TerracottaPink", + "43 TerracottaGray", + "44 TerracottaLightGray", + "45 TerracottaCyan", + "46 TerracottaPurple", + "47 TerracottaBlue", + "48 TerracottaBrown", + "49 TerracottaGreen", + "50 TerracottaRed", + "51 TerracottaBlack", + "52 CrimsonNylium", + "53 CrimsonStem", + "54 CrimsonHyphae", + "55 WarpedNylium", + "56 WarpedStem", + "57 WarpedHyphae", + "58 WarpedWartBlock", + "59 Deepslate", + "60 RawIron", + "61 GlowLichen"}; + +BlockListManager::BlockListManager(QWidget* parent) : QWidget(parent) {} + +BlockListManager::~BlockListManager() {} + +void BlockListManager::setup_basecolors(SlopeCraft::Kernel* kernel) noexcept { + for (auto bcp : this->basecolors) { + delete bcp; + } + this->basecolors.clear(); + this->basecolors.reserve(64); + constexpr int num_basecolor = + sizeof(basecolor_names) / sizeof(basecolor_names[0]); + + uint32_t bc_arr[64]; + + kernel->getBaseColorInARGB32(bc_arr); + + for (int bc = 0; bc < num_basecolor; bc++) { + BaseColorWidget* bcw = new BaseColorWidget(this, bc); + this->layout()->addWidget(bcw); + this->basecolors.push_back(bcw); + bcw->setTitle(QString::fromUtf8(basecolor_names[bc].data())); + + bcw->set_color(bc_arr[bc]); + } +} \ No newline at end of file diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index dd066cf2..cd34baf3 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -1,42 +1,10 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef BLOCKLISTMANAGER_H -#define BLOCKLISTMANAGER_H - -#include -#include -#include -#include -#include -#include - -#include "../../SlopeCraftL/SlopeCraftL.h" - -#include "TokiBaseColor.h" -#include "TokiBlock.h" - -#define DispLine qDebug() << "File = " << __FILE__ << " , Line = " << __LINE__; +#ifndef SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H +#define SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H +#include +#include +#include +#include "BaseColor.h" struct basecolorOption { uint8_t baseColor{0xFF}; bool enabled{false}; @@ -52,81 +20,16 @@ blockListPreset load_preset(QString filename, QString &err) noexcept; QString serialize_preset(const blockListPreset &preset) noexcept; -class BlockListDeleter { - public: - void operator()(SlopeCraft::BlockListInterface *ptr) noexcept { - SlopeCraft::SCL_destroyBlockList(ptr); - } -}; - -class BlockListManager : public QObject { +class BlockListManager : public QWidget { Q_OBJECT - - public: - explicit BlockListManager(QHBoxLayout *_area, QObject *parent = nullptr); - - ~BlockListManager(); - - bool setupFixedBlockList(const QString &filename, - const QString &imgdir) noexcept; - bool setupCustomBlockList(const QString &filename, - const QString &imgdir) noexcept; - private: - bool impl_setupBlockList(const QString &filename, const QString &dirname, - std::unique_ptr &dst) noexcept; + std::vector basecolors; public: - void setSelected(uchar baseColor, ushort blockSeq); - - void setEnabled(uchar baseColor, bool isEnable); - - void setLabelColors(const QRgb *); - - void setVersion(uchar); - - void getEnableList(bool *) const; - void getSimpleBlockList(const SlopeCraft::AbstractBlock **) const; - std::vector getSimpleBlockList() const; - std::vector getTokiBlockList() const; - std::vector getQRadioButtonList() const; - std::vector toPreset() const; - - void getTokiBaseColors(std::vector *) const; - - int getBlockNum() const; - void getBlockPtrs(const SlopeCraft::AbstractBlock **, uint8_t *) const; - - bool loadPreset(const blockListPreset &preset); - - bool loadInternalPreset(const blockListPreset &preset) noexcept; - - blockListPreset currentPreset() const noexcept; - - public slots: - - signals: - void translate(Language); - void switchToCustom() const; - void blockListChanged() const; - - private: - bool isApplyingPreset; - QHBoxLayout *area; - std::vector tbcs; - - std::unique_ptr BL_fixed{ - nullptr}; - std::unique_ptr BL_custom{ - nullptr}; - - static const QString baseColorNames[64]; + explicit BlockListManager(QWidget *parent = nullptr); + ~BlockListManager(); - private slots: - void receiveClicked() const; + void setup_basecolors(SlopeCraft::Kernel *kernel) noexcept; }; -bool isValidBlockInfo(const QJsonObject &); - -#endif // BLOCKLISTMANAGER_H +#endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 96176f9f..1c08ec55 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -8,29 +8,29 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools REQUIRED) - -include_directories(${CMAKE_SOURCE_DIR}) +find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) +# include_directories(${CMAKE_SOURCE_DIR}) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) set(BlockListManager_header_files - BlockListManager.h - BlockListManager_global.h - TokiBaseColor.h - TokiBlock.h) + BaseColor.h + Block.h) set(BlockListManager_source_files - BlockListManager.cpp - TokiBaseColor.cpp - TokiBlock.cpp + BaseColor.cpp + Block.cpp BLM_preset.cpp) +set(BlockListManager_ui_files + BaseColorWidget.ui +) + set(BlockListManager_ts_files - ${CMAKE_CURRENT_SOURCE_DIR}/BlockListManager_en_US.ts + + # ${CMAKE_CURRENT_SOURCE_DIR}/BlockListManager_en_US.ts ) if(${SlopeCraft_update_ts_files}) @@ -43,14 +43,14 @@ endif() set(BlockListManaer_project_sources ${BlockListManager_header_files} ${BlockListManager_source_files} + ${BlockListManager_ui_files} ${BlockListManager_ts_files} ) -include_directories(../SlopeCraftL) - +# include_directories(../SlopeCraftL) add_library(BlockListManager STATIC ${BlockListManaer_project_sources}) -target_link_libraries(BlockListManager PUBLIC Qt${QT_VERSION_MAJOR}::Widgets SlopeCraftL) -target_compile_definitions(BlockListManager PRIVATE BlockListManager_LIBRARY) +target_link_libraries(BlockListManager PUBLIC Qt6::Widgets SlopeCraftL) +target_include_directories(BlockListManager INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir}) qt_add_lrelease(BlockListManager TS_FILES ${BlockListManager_ts_files} diff --git a/utilities/BlockListManager/removed/BLM_preset.cpp b/utilities/BlockListManager/removed/BLM_preset.cpp new file mode 100644 index 00000000..78c81d9a --- /dev/null +++ b/utilities/BlockListManager/removed/BLM_preset.cpp @@ -0,0 +1,100 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include "BlockListManager.h" +#include + +using njson = nlohmann::json; + +basecolorOption parse_single(const njson& jo) noexcept(false); + +blockListPreset load_preset(QString filename, QString& err) noexcept { + err.clear(); + + blockListPreset ret; + + try { + QFile file(filename); + file.open(QFile::OpenMode::enum_type::ReadOnly); + auto qba = file.readAll(); + + njson jo = njson::parse(qba.begin(), qba.end(), nullptr, true, true); + + ret.values.resize(jo.size()); + + for (size_t idx = 0; idx < jo.size(); idx++) { + basecolorOption opt = parse_single(jo[idx]); + + if (!ret.values[opt.baseColor].second.isEmpty()) { + err = QObject::tr("基色 %1 的预设被重复定义。一个基色只能被定义一次。") + .arg(int(opt.baseColor)); + return {}; + } + + ret.values[opt.baseColor] = {opt.enabled, opt.blockId}; + } + + } catch (std::exception& e) { + err = QObject::tr("解析预设 json 时发生异常:\"%1\"").arg(e.what()); + return {}; + } + + return ret; +} + +basecolorOption parse_single(const njson& jo) noexcept(false) { + basecolorOption ret; + ret.baseColor = jo.at("baseColor"); + std::string id = jo.at("blockId"); + ret.blockId = QString::fromUtf8(id.data()); + ret.enabled = jo.at("enabled"); + return ret; +} + +QString serialize_preset(const blockListPreset& preset) noexcept { + njson::array_t arr; + arr.resize(preset.values.size()); + + for (size_t idx = 0; idx < preset.values.size(); idx++) { + njson obj; + obj["baseColor"] = idx; + obj["blockId"] = preset.values[idx].second.toUtf8(); + obj["enabled"] = preset.values[idx].first; + + arr[idx] = obj; + } + + std::string str = njson(arr).dump(2); + + return QString::fromUtf8(str); +} + +blockListPreset load_preset(QString filename) noexcept(false) { + QString err; + auto temp = load_preset(filename, err); + + if (!err.isEmpty()) { + throw std::runtime_error{err.toUtf8()}; + } + + return temp; +} \ No newline at end of file diff --git a/utilities/BlockListManager/removed/BlockListManager.cpp b/utilities/BlockListManager/removed/BlockListManager.cpp new file mode 100644 index 00000000..18bb154a --- /dev/null +++ b/utilities/BlockListManager/removed/BlockListManager.cpp @@ -0,0 +1,385 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include "BlockListManager.h" +#include "TokiBaseColor.h" +#include "TokiBlock.h" +#include +#include +#include +#include + +BlockListManager::BlockListManager(QHBoxLayout *_area, QObject *parent) + : QObject(parent) { + isApplyingPreset = false; + area = _area; + qDebug() << ((area == nullptr) ? " 错误!_area 为空指针" : ""); + QGroupBox *qgb = nullptr; + QGridLayout *qgl = nullptr; + TokiBaseColor *tbc = nullptr; + tbcs.clear(); + // qDebug("方块列表管理者开始创建 QGroupBox"); + for (uchar baseColor = 0; baseColor < 64; baseColor++) { + if (baseColorNames[baseColor].isEmpty()) break; + qgb = new QGroupBox(baseColorNames[baseColor]); + // qDebug("create QGroupBox"); + qgl = new QGridLayout; + qgb->setLayout(qgl); + // qDebug("create Layout"); + tbc = new TokiBaseColor(baseColor, qgl); + // qDebug("create TokiBaseColor"); + area->addWidget(qgb); + // qDebug("add QGroupBox to layout"); + tbcs.push_back(tbc); + + connect(this, &BlockListManager::translate, tbc, &TokiBaseColor::translate); + connect(tbc, &TokiBaseColor::userClicked, this, + &BlockListManager::receiveClicked); + } + // qDebug("Manager 构造函数完毕"); +} + +BlockListManager::~BlockListManager() { + for (uchar i = 0; i < tbcs.size(); i++) delete tbcs[i]; +} + +void BlockListManager::setVersion(uchar _ver) { + if (_ver < 12 || _ver > SlopeCraft::SCL_maxAvailableVersion()) return; + TokiBaseColor::mcVer = _ver; + for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->versionCheck(); +} + +bool callback_load_image(const char *filename, uint32_t *dst_row_major) { + QImage img(QString::fromLocal8Bit(filename)); + + if (img.isNull()) { + return false; + } + + QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); + + memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); + return true; +} + +bool BlockListManager::setupFixedBlockList(const QString &filename, + const QString &imgdir) noexcept { + return this->impl_setupBlockList(filename, imgdir, this->BL_fixed); +} +bool BlockListManager::setupCustomBlockList(const QString &filename, + const QString &imgdir) noexcept { + return this->impl_setupBlockList(filename, imgdir, this->BL_custom); +} + +bool BlockListManager::impl_setupBlockList( + const QString &filename, const QString &dirname, + std::unique_ptr + &dst) noexcept { + std::string errmsg; + errmsg.resize(4096); + SlopeCraft::blockListOption opt; + opt.errmsg = errmsg.data(); + opt.errmsg_capacity = errmsg.size(); + size_t msg_len{0}; + opt.errmsg_len_dest = &msg_len; + + auto img_dir_local8bit = dirname.toLocal8Bit(); + opt.image_dir = img_dir_local8bit.data(); + + opt.callback_load_image = callback_load_image; + + SlopeCraft::BlockListInterface *bli = + SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), opt); + + errmsg.resize(msg_len); + + if (!errmsg.empty()) { + if (bli == nullptr) { + QMessageBox::critical(dynamic_cast(this->parent()), + tr("解析方块列表失败"), + QString::fromUtf8(errmsg.data())); + return false; + } else { + QMessageBox::warning(dynamic_cast(this->parent()), + tr("解析方块列表失败"), + QString::fromUtf8(errmsg.data())); + } + } + dst.reset(bli); + + std::vector blockps; + std::vector basecolors; + basecolors.resize(dst->size()); + blockps.resize(dst->size()); + + dst->get_blocks(blockps.data(), basecolors.data(), blockps.size()); + + for (size_t idx = 0; idx < dst->size(); idx++) { + this->tbcs[basecolors[idx]]->addTokiBlock(blockps[idx]); + } + return true; +} + +void BlockListManager::setSelected(uchar baseColor, ushort blockSeq) { + isApplyingPreset = true; + tbcs[baseColor]->setSelected(blockSeq); + isApplyingPreset = false; +} + +void BlockListManager::setEnabled(uchar baseColor, bool isEnable) { + isApplyingPreset = true; + tbcs[baseColor]->checkBox->setChecked(isEnable); + isApplyingPreset = false; +} + +void BlockListManager::receiveClicked() const { + if (isApplyingPreset) return; + emit switchToCustom(); + emit blockListChanged(); +} + +void BlockListManager::setLabelColors(const QRgb *colors) { + for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->makeLabel(colors[i]); +} + +void BlockListManager::getEnableList(bool *dest) const { + for (uchar i = 0; i < tbcs.size(); i++) dest[i] = tbcs[i]->getEnabled(); +} + +void BlockListManager::getSimpleBlockList( + const SlopeCraft::AbstractBlock **SBL) const { + // qDebug("void BlockListManager::getSimpleBlockList(simpleBlock * SBL) + // const"); + + for (uchar i = 0; i < 64; i++) { + SBL[i] = nullptr; + } + for (uchar i = 0; i < tbcs.size(); i++) { + SBL[i] = (tbcs[i]->getTokiBlock()->getSimpleBlock()); + } +} +std::vector +BlockListManager::getSimpleBlockList() const { + std::vector SBL(64); + const SlopeCraft::AbstractBlock *p; + for (uchar i = 0; i < tbcs.size(); i++) { + p = tbcs[i]->getTokiBlock()->getSimpleBlock(); + SBL[i] = p; + } + return SBL; +} +std::vector BlockListManager::getTokiBlockList() const { + std::vector TBL(64); + for (uchar i = 0; i < 64; i++) { + if (i < tbcs.size()) + TBL[i] = tbcs[i]->getTokiBlock(); + else + TBL[i] = nullptr; + } + return TBL; +} + +std::vector BlockListManager::getQRadioButtonList() + const { + std::vector TBL(64); + for (uchar i = 0; i < 64; i++) { + if (i < tbcs.size()) + TBL[i] = tbcs[i]->getTokiBlock()->getTarget(); + else + TBL[i] = nullptr; + } + return TBL; +} + +std::vector BlockListManager::toPreset() const { + std::vector TBL(64); + for (uchar i = 0; i < 64; i++) { + if (i < tbcs.size()) + TBL[i] = tbcs[i]->getSelected(); + else + TBL[i] = 0; + } + return TBL; +} + +bool isValidBlockInfo(const QJsonObject &json) { + return (json.contains("id") && json.contains("nameZH") && + json.contains("nameEN") && json.contains("baseColor")); +} + +void BlockListManager::getTokiBaseColors( + std::vector *dest) const { + dest->clear(); + dest->reserve(tbcs.size()); + for (const auto it : tbcs) { + dest->emplace_back(it); + } +} + +int BlockListManager::getBlockNum() const { + int result = 0; + for (auto it : tbcs) { + result += it->tbs.size(); + } + return result; +} + +void BlockListManager::getBlockPtrs(const SlopeCraft::AbstractBlock **dest, + uint8_t *baseColor) const { + int idx = 0; + for (auto it : tbcs) { + for (auto jt : it->tbs) { + baseColor[idx] = it->baseColor; + dest[idx] = jt->getSimpleBlock(); + idx++; + } + } + dest[idx] = nullptr; +} + +bool BlockListManager::loadPreset(const blockListPreset &preset) { + if (preset.values.size() != this->tbcs.size()) { + QMessageBox::warning(dynamic_cast(this->parent()), + tr("加载预设错误"), + tr("预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符") + .arg(preset.values.size()) + .arg(this->tbcs.size())); + return false; + } + + std::vector blocks_arr; + + for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { + auto tbc = this->tbcs[basecolor]; + const auto &pre = preset.values[basecolor]; + + this->setEnabled(basecolor, pre.first); + + // find block + int matched_block_idx = -1; + blocks_arr.clear(); + tbc->getTokiBlockList(blocks_arr); + for (int bidx = 0; bidx < (int)blocks_arr.size(); bidx++) { + const char *const blkid = blocks_arr[bidx]->getSimpleBlock()->getId(); + if (QString::fromUtf8(blkid) == pre.second) { + matched_block_idx = bidx; + break; + } + } + + if (matched_block_idx < 0) { + QMessageBox::warning( + dynamic_cast(this->parent()), tr("加载预设错误"), + tr("预设中为基色%1指定的方块 id 是\"%2\",没有找到这个方块 id") + .arg(basecolor) + .arg(pre.second)); + return false; + } + + this->setSelected(basecolor, matched_block_idx); + } + + emit blockListChanged(); + + return true; +} + +bool BlockListManager::loadInternalPreset( + const blockListPreset &preset) noexcept { + return this->loadPreset(preset); +} + +blockListPreset BlockListManager::currentPreset() const noexcept { + blockListPreset ret; + ret.values.resize(this->tbcs.size()); + for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { + ret.values[basecolor].first = this->tbcs[basecolor]->getEnabled(); + ret.values[basecolor].second = QString::fromUtf8( + this->tbcs[basecolor]->getTokiBlock()->getSimpleBlock()->getId()); + } + return ret; +} + +const QString BlockListManager::baseColorNames[64] = {"00 None", + "01 Grass", + "02 Sand", + "03 Wool", + "04 Fire", + "05 Ice", + "06 Metal", + "07 Plant", + "08 Snow", + "09 Clay", + "10 Dirt", + "11 Stone", + "12 Water", + "13 Wood", + "14 Quartz", + "15 ColorOrange", + "16 ColorMagenta", + "17 ColorLightBlue", + "18 ColorYellow", + "19 ColorLime", + "20 ColorPink", + "21 ColorGray", + "22 ColorLightGray", + "23 ColorCyan", + "24 ColorPurple", + "25 ColorBlue", + "26 ColorBrown", + "27 ColorGreen", + "28 ColorRed", + "29 ColorBlack", + "30 Gold", + "31 Diamond", + "32 Lapis", + "33 Emerald", + "34 Podzol", + "35 Nether", + "36 TerracottaWhite", + "37 TerracottaOrange", + "38 TerracottaMagenta", + "39 TerracottaLightBlue", + "40 TerracottaYellow", + "41 TerracottaLime", + "42 TerracottaPink", + "43 TerracottaGray", + "44 TerracottaLightGray", + "45 TerracottaCyan", + "46 TerracottaPurple", + "47 TerracottaBlue", + "48 TerracottaBrown", + "49 TerracottaGreen", + "50 TerracottaRed", + "51 TerracottaBlack", + "52 CrimsonNylium", + "53 CrimsonStem", + "54 CrimsonHyphae", + "55 WarpedNylium", + "56 WarpedStem", + "57 WarpedHyphae", + "58 WarpedWartBlock", + "59 Deepslate", + "60 RawIron", + "61 GlowLichen", + "", + ""}; diff --git a/utilities/BlockListManager/removed/BlockListManager.h b/utilities/BlockListManager/removed/BlockListManager.h new file mode 100644 index 00000000..dd066cf2 --- /dev/null +++ b/utilities/BlockListManager/removed/BlockListManager.h @@ -0,0 +1,132 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#ifndef BLOCKLISTMANAGER_H +#define BLOCKLISTMANAGER_H + +#include +#include +#include +#include +#include +#include + +#include "../../SlopeCraftL/SlopeCraftL.h" + +#include "TokiBaseColor.h" +#include "TokiBlock.h" + +#define DispLine qDebug() << "File = " << __FILE__ << " , Line = " << __LINE__; + +struct basecolorOption { + uint8_t baseColor{0xFF}; + bool enabled{false}; + QString blockId{""}; +}; + +struct blockListPreset { + std::vector> values; +}; + +blockListPreset load_preset(QString filename) noexcept(false); +blockListPreset load_preset(QString filename, QString &err) noexcept; + +QString serialize_preset(const blockListPreset &preset) noexcept; + +class BlockListDeleter { + public: + void operator()(SlopeCraft::BlockListInterface *ptr) noexcept { + SlopeCraft::SCL_destroyBlockList(ptr); + } +}; + +class BlockListManager : public QObject { + Q_OBJECT + + public: + explicit BlockListManager(QHBoxLayout *_area, QObject *parent = nullptr); + + ~BlockListManager(); + + bool setupFixedBlockList(const QString &filename, + const QString &imgdir) noexcept; + bool setupCustomBlockList(const QString &filename, + const QString &imgdir) noexcept; + + private: + bool impl_setupBlockList(const QString &filename, const QString &dirname, + std::unique_ptr &dst) noexcept; + + public: + void setSelected(uchar baseColor, ushort blockSeq); + + void setEnabled(uchar baseColor, bool isEnable); + + void setLabelColors(const QRgb *); + + void setVersion(uchar); + + void getEnableList(bool *) const; + void getSimpleBlockList(const SlopeCraft::AbstractBlock **) const; + std::vector getSimpleBlockList() const; + std::vector getTokiBlockList() const; + std::vector getQRadioButtonList() const; + std::vector toPreset() const; + + void getTokiBaseColors(std::vector *) const; + + int getBlockNum() const; + void getBlockPtrs(const SlopeCraft::AbstractBlock **, uint8_t *) const; + + bool loadPreset(const blockListPreset &preset); + + bool loadInternalPreset(const blockListPreset &preset) noexcept; + + blockListPreset currentPreset() const noexcept; + + public slots: + + signals: + void translate(Language); + void switchToCustom() const; + void blockListChanged() const; + + private: + bool isApplyingPreset; + QHBoxLayout *area; + std::vector tbcs; + + std::unique_ptr BL_fixed{ + nullptr}; + std::unique_ptr BL_custom{ + nullptr}; + + static const QString baseColorNames[64]; + + private slots: + void receiveClicked() const; +}; + +bool isValidBlockInfo(const QJsonObject &); + +#endif // BLOCKLISTMANAGER_H diff --git a/utilities/BlockListManager/BlockListManager_en_US.ts b/utilities/BlockListManager/removed/BlockListManager_en_US.ts similarity index 100% rename from utilities/BlockListManager/BlockListManager_en_US.ts rename to utilities/BlockListManager/removed/BlockListManager_en_US.ts diff --git a/utilities/BlockListManager/BlockListManager_global.h b/utilities/BlockListManager/removed/BlockListManager_global.h similarity index 100% rename from utilities/BlockListManager/BlockListManager_global.h rename to utilities/BlockListManager/removed/BlockListManager_global.h diff --git a/utilities/BlockListManager/TokiBaseColor.cpp b/utilities/BlockListManager/removed/TokiBaseColor.cpp similarity index 100% rename from utilities/BlockListManager/TokiBaseColor.cpp rename to utilities/BlockListManager/removed/TokiBaseColor.cpp diff --git a/utilities/BlockListManager/TokiBaseColor.h b/utilities/BlockListManager/removed/TokiBaseColor.h similarity index 100% rename from utilities/BlockListManager/TokiBaseColor.h rename to utilities/BlockListManager/removed/TokiBaseColor.h diff --git a/utilities/BlockListManager/TokiBlock.cpp b/utilities/BlockListManager/removed/TokiBlock.cpp similarity index 100% rename from utilities/BlockListManager/TokiBlock.cpp rename to utilities/BlockListManager/removed/TokiBlock.cpp diff --git a/utilities/BlockListManager/TokiBlock.h b/utilities/BlockListManager/removed/TokiBlock.h similarity index 100% rename from utilities/BlockListManager/TokiBlock.h rename to utilities/BlockListManager/removed/TokiBlock.h From 016b24c13756be22c5449f631911ae2fbf6d23a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 00:41:41 +0800 Subject: [PATCH 0266/1123] add new block list manager --- SlopeCraft/CMakeLists.txt | 3 +- SlopeCraft/SCWind.cpp | 40 +++ SlopeCraft/SCWind.h | 8 +- SlopeCraft/SCWind.ui | 8 +- SlopeCraftL/SlopeCraftL.cpp | 17 ++ SlopeCraftL/SlopeCraftL.h | 3 + utilities/BlockListManager/BLM_preset.cpp | 1 + utilities/BlockListManager/BaseColor.cpp | 174 +++++++++++++ utilities/BlockListManager/BaseColor.h | 51 ++++ utilities/BlockListManager/BaseColorWidget.ui | 56 +++++ utilities/BlockListManager/Block.cpp | 11 + utilities/BlockListManager/Block.h | 21 ++ .../BlockListManager/BlockListManager.cpp | 233 ++++++++++++------ utilities/BlockListManager/BlockListManager.h | 34 ++- 14 files changed, 586 insertions(+), 74 deletions(-) create mode 100644 utilities/BlockListManager/BaseColor.cpp create mode 100644 utilities/BlockListManager/BaseColor.h create mode 100644 utilities/BlockListManager/BaseColorWidget.ui create mode 100644 utilities/BlockListManager/Block.cpp create mode 100644 utilities/BlockListManager/Block.h diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 01929390..a8da4ea4 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -48,7 +48,8 @@ target_link_libraries(SlopeCraft PRIVATE Qt6::Network SlopeCraftL AdaptiveLabel - VersionDialog) + VersionDialog + BlockListManager) target_include_directories(SlopeCraft PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 56cb261b..3c6c9889 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -21,6 +21,22 @@ SCWind::SCWind(QWidget *parent) this->export_pool_model = new PoolModel{this, &this->tasks}; this->ui->lview_pool_export->setModel(this->export_pool_model); this->export_pool_model->set_listview(this->ui->lview_pool_export); + + this->ui->blm->setup_basecolors(this->kernel); + this->ui->blm->set_version_callback( + [this]() { return this->selected_version(); }); + + this->ui->blm->add_blocklist("./Blocks/FixedBlocks.json", + "./Blocks/FixedBlocks"); + this->ui->blm->add_blocklist("./Blocks/CustomBlocks.json", + "./Blocks/CustomBlocks"); + + this->ui->blm->finish_blocklist(); + + for (auto btnp : this->version_buttons()) { + connect(btnp, &QRadioButton::toggled, this, + &SCWind::when_version_buttons_toggled); + } } SCWind::~SCWind() { @@ -104,4 +120,28 @@ void SCWind::when_cvt_pool_selectionChanged() noexcept { this->ui->lb_raw_image->setPixmap( QPixmap::fromImage(this->tasks[idx].original_image)); #warning load converted image here +} + +std::array SCWind::version_buttons() + const noexcept { + return {this->ui->rb_ver12, this->ui->rb_ver13, this->ui->rb_ver14, + this->ui->rb_ver15, this->ui->rb_ver16, this->ui->rb_ver17, + this->ui->rb_ver18, this->ui->rb_ver19, this->ui->rb_ver20}; +} + +SCL_gameVersion SCWind::selected_version() const noexcept { + auto btns = this->version_buttons(); + for (size_t idx = 0; idx < btns.size(); idx++) { + if (btns[idx]->isChecked()) { + return SCL_gameVersion(idx + 12); + } + } + + assert(false); + + return SCL_gameVersion::ANCIENT; +} + +void SCWind::when_version_buttons_toggled() noexcept { + this->ui->blm->when_version_updated(); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index db5d2d01..af56ca78 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -4,7 +4,7 @@ #include #include #include - +#include #include #include "cvt_task.h" @@ -28,6 +28,8 @@ class SCWind : public QMainWindow { void when_cvt_pool_selectionChanged() noexcept; + void when_version_buttons_toggled() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; @@ -35,6 +37,10 @@ class SCWind : public QMainWindow { task_pool_t tasks; CvtPoolModel* cvt_pool_model{nullptr}; PoolModel* export_pool_model{nullptr}; + + std::array version_buttons() const noexcept; + + SCL_gameVersion selected_version() const noexcept; }; #endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index f0556eee..213a9662 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -170,7 +170,7 @@ true - + 0 @@ -1277,6 +1277,12 @@ QListView
AdaptiveListView.h
+ + BlockListManager + QWidget +
BlockListManager.h
+ 1 +
diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index cb297992..89467bda 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -228,4 +228,21 @@ SCL_EXPORT const float *SCL_getBasicColorMapPtrs() { SCL_EXPORT const char *SCL_getSCLVersion() { return TokiSlopeCraft::getSCLVersion(); } + +SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { + if (basecolor <= 51) { + return SCL_gameVersion::ANCIENT; + } + + if (basecolor <= 58) { + return SCL_gameVersion::MC16; + } + + if (basecolor <= 61) { + return SCL_gameVersion::MC17; + } + return SCL_gameVersion::FUTURE; +} + +SCL_EXPORT uint8_t SCL_maxBaseColor() { return 61; } } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index b1dd2ae0..002d38dd 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -325,6 +325,9 @@ SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, // full palette SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); +SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); +SCL_EXPORT uint8_t SCL_maxBaseColor(); + // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); } // namespace SlopeCraft diff --git a/utilities/BlockListManager/BLM_preset.cpp b/utilities/BlockListManager/BLM_preset.cpp index 78c81d9a..c9c70814 100644 --- a/utilities/BlockListManager/BLM_preset.cpp +++ b/utilities/BlockListManager/BLM_preset.cpp @@ -22,6 +22,7 @@ This file is part of SlopeCraft. #include "BlockListManager.h" #include +#include using njson = nlohmann::json; diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp new file mode 100644 index 00000000..193972d7 --- /dev/null +++ b/utilities/BlockListManager/BaseColor.cpp @@ -0,0 +1,174 @@ +#include "BaseColor.h" +#include "ui_BaseColorWidget.h" +#include "BlockListManager.h" + +BaseColorWidget::BaseColorWidget(QWidget* parent, uint8_t _basecolor) + : QGroupBox(parent), ui(new Ui::BaseColorWidget), basecolor(_basecolor) { + this->ui->setupUi(this); +}; +BaseColorWidget::~BaseColorWidget() { delete this->ui; }; + +void BaseColorWidget::set_color(uint32_t color) noexcept { + QPalette pl; + pl.setColor(QPalette::ColorRole::Text, Qt::black); + pl.setColor(QPalette::ColorRole::Window, + QColor(qRed(color), qGreen(color), qBlue(color), + 255 * bool(this->basecolor))); + + this->setPalette(pl); + + if (this->basecolor == 0) { + this->ui->cb_enable->setDisabled(true); + } +} + +constexpr int basecolor_cols = 3; +static_assert(basecolor_cols >= 1); + +void BaseColorWidget::add_block(SlopeCraft::AbstractBlock* ab) noexcept { + BlockWidget* bw = new BlockWidget(this, ab); + + const int idx = this->blocks.size(); + + this->blocks.emplace_back(bw); + constexpr int cols = basecolor_cols; + + const int col = idx % cols; + const int row = idx / cols; + + dynamic_cast(this->ui->layout_blocks)->addWidget(bw, row, col); +} + +void BaseColorWidget::add_placeholders() noexcept { + if (this->blocks.size() <= 0) { + return; + } + + if (this->blocks.size() < basecolor_cols) { + for (int i = this->blocks.size(); i < basecolor_cols; i++) { + QLabel* lb = new QLabel("", this); + // lb->setFrameShape(QLabel::Shape::Box); + dynamic_cast(this->ui->layout_blocks)->addWidget(lb, 0, i); + } + return; + } + + if (this->blocks.size() % basecolor_cols == 0) { + return; + } + /* + const int max_row = this->blocks.size() / basecolor_cols; + + dynamic_cast(this->ui->layout_blocks) + ->addWidget(new QLabel("", this), max_row, basecolor_cols - 1); + */ +} + +constexpr inline bool should_be_disabled( + int, SCL_gameVersion block_ver, int num_blocks, + SCL_gameVersion selected_ver) noexcept { + if (num_blocks <= 1) { + return true; + } + + if (block_ver > selected_ver) { + return true; + } + + return false; +} + +void BaseColorWidget::finish_blocks() noexcept { + this->add_placeholders(); + assert(this->blocks.size() > 0); + + this->select_block(0); + + const SCL_gameVersion v = + reinterpret_cast(this->parent())->version(); + + for (int idx = 0; idx < (int)this->blocks.size(); idx++) { + this->blocks[idx]->setDisabled(should_be_disabled( + idx, + (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(), + this->blocks.size(), v)); + } +} + +void BaseColorWidget::select_block(int idx) noexcept { + assert(idx >= 0); + + assert(idx < (int)this->blocks.size()); + /* + const SCL_gameVersion v = + reinterpret_cast(this->parent())->version(); + + assert(this->blocks[idx]->attachted_block()->getVersion() <= (int)v); + */ + + this->blocks[idx]->setChecked(true); +} + +void BaseColorWidget::when_version_updated(SCL_gameVersion v) noexcept { + const int new_select = this->prefered_block_idx(v); + + this->select_block(new_select); + + for (int idx = 0; idx < int(this->blocks.size()); idx++) { + this->blocks[idx]->setDisabled(should_be_disabled( + idx, + (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(), + this->blocks.size(), v)); + } + + const bool is_version_ok = + SlopeCraft::SCL_basecolor_version(this->basecolor) <= v; + this->ui->cb_enable->setChecked(is_version_ok); + this->ui->cb_enable->setEnabled(is_version_ok); +} + +int BaseColorWidget::selected_idx() const noexcept { + for (int idx = 0; idx < (int)this->blocks.size(); idx++) { + if (this->blocks[idx]->isChecked()) { + return idx; + } + } + assert(false); + return -1; +} + +int BaseColorWidget::prefered_block_idx(int checked_idx, + SCL_gameVersion ver) const noexcept { + std::vector scores; + scores.resize(this->blocks.size()); + assert(checked_idx < (int)scores.size()); + assert(checked_idx >= 0); + + for (int idx = 0; idx < int(scores.size()); idx++) { + int& score = scores[idx]; + score = 0; + + const SCL_gameVersion blk_ver = + (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(); + + if (blk_ver <= ver) { + score = 100; + } else { + score = 50; + } + + if (idx == checked_idx) { + score += 1; + } + } + + int max_idx{0}; + + for (int idx = 0; idx < int(scores.size()); idx++) { + if (scores[idx] > scores[max_idx]) { + max_idx = idx; + } + } + + return max_idx; +} \ No newline at end of file diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h new file mode 100644 index 00000000..8aa3b132 --- /dev/null +++ b/utilities/BlockListManager/BaseColor.h @@ -0,0 +1,51 @@ +#ifndef SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BASECOLOR_H +#define SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BASECOLOR_H + +#include +#include +#include + +class BaseColorWidget; + +namespace Ui { +class BaseColorWidget; +} + +class BaseColorWidget : public QGroupBox { + Q_OBJECT + private: + Ui::BaseColorWidget* ui; + const uint8_t basecolor{255}; + std::vector blocks; + + public: + explicit BaseColorWidget(QWidget* parent, uint8_t _basecolor); + ~BaseColorWidget(); + + void set_color(uint32_t argb32) noexcept; + + void add_block(SlopeCraft::AbstractBlock* ab) noexcept; + + void finish_blocks() noexcept; + + void select_block(int idx) noexcept; + + void when_version_updated(SCL_gameVersion v) noexcept; + + int selected_idx() const noexcept; + + const SlopeCraft::AbstractBlock* selected_block() const noexcept { + return this->blocks[this->selected_idx()]->attachted_block(); + } + + private: + void add_placeholders() noexcept; + + int prefered_block_idx(int checked_idx, SCL_gameVersion ver) const noexcept; + + int prefered_block_idx(SCL_gameVersion ver) const noexcept { + return this->prefered_block_idx(this->selected_idx(), ver); + } +}; + +#endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BASECOLOR_H diff --git a/utilities/BlockListManager/BaseColorWidget.ui b/utilities/BlockListManager/BaseColorWidget.ui new file mode 100644 index 00000000..220da7cc --- /dev/null +++ b/utilities/BlockListManager/BaseColorWidget.ui @@ -0,0 +1,56 @@ + + + BaseColorWidget + + + + 0 + 0 + 400 + 300 + + + + GroupBox + + + + + + 启用 + + + true + + + + + + + + + + + 30 + 16777215 + + + + true + + + QFrame::Box + + + QFrame::Sunken + + + + + + + + + + + diff --git a/utilities/BlockListManager/Block.cpp b/utilities/BlockListManager/Block.cpp new file mode 100644 index 00000000..9d37d921 --- /dev/null +++ b/utilities/BlockListManager/Block.cpp @@ -0,0 +1,11 @@ +#include "Block.h" + +BlockWidget::BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk) + : QRadioButton(parent), block(_blk) { + this->setText(this->block->getNameZH()); + QImage img{this->block->imageCols(), this->block->imageRows(), + QImage::Format_ARGB32}; + this->block->getImage(reinterpret_cast(img.scanLine(0)), true); + + this->setIcon(QIcon{QPixmap::fromImage(img)}); +}; \ No newline at end of file diff --git a/utilities/BlockListManager/Block.h b/utilities/BlockListManager/Block.h new file mode 100644 index 00000000..c04d6d18 --- /dev/null +++ b/utilities/BlockListManager/Block.h @@ -0,0 +1,21 @@ +#ifndef SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCK_H +#define SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCK_H + +#include +#include + +#include + +class BlockWidget : public QRadioButton { + Q_OBJECT + private: + SlopeCraft::AbstractBlock* const block; + + public: + explicit BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk); + ~BlockWidget() = default; + + auto attachted_block() const noexcept { return this->block; } +}; + +#endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCK_H diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 5e03be4f..5599b306 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -1,92 +1,185 @@ #include "BlockListManager.h" #include +#include -std::string_view basecolor_names[] = {"00 None", - "01 Grass", - "02 Sand", - "03 Wool", - "04 Fire", - "05 Ice", - "06 Metal", - "07 Plant", - "08 Snow", - "09 Clay", - "10 Dirt", - "11 Stone", - "12 Water", - "13 Wood", - "14 Quartz", - "15 ColorOrange", - "16 ColorMagenta", - "17 ColorLightBlue", - "18 ColorYellow", - "19 ColorLime", - "20 ColorPink", - "21 ColorGray", - "22 ColorLightGray", - "23 ColorCyan", - "24 ColorPurple", - "25 ColorBlue", - "26 ColorBrown", - "27 ColorGreen", - "28 ColorRed", - "29 ColorBlack", - "30 Gold", - "31 Diamond", - "32 Lapis", - "33 Emerald", - "34 Podzol", - "35 Nether", - "36 TerracottaWhite", - "37 TerracottaOrange", - "38 TerracottaMagenta", - "39 TerracottaLightBlue", - "40 TerracottaYellow", - "41 TerracottaLime", - "42 TerracottaPink", - "43 TerracottaGray", - "44 TerracottaLightGray", - "45 TerracottaCyan", - "46 TerracottaPurple", - "47 TerracottaBlue", - "48 TerracottaBrown", - "49 TerracottaGreen", - "50 TerracottaRed", - "51 TerracottaBlack", - "52 CrimsonNylium", - "53 CrimsonStem", - "54 CrimsonHyphae", - "55 WarpedNylium", - "56 WarpedStem", - "57 WarpedHyphae", - "58 WarpedWartBlock", - "59 Deepslate", - "60 RawIron", - "61 GlowLichen"}; - -BlockListManager::BlockListManager(QWidget* parent) : QWidget(parent) {} +extern std::string_view basecolor_names[64]; + +BlockListManager::BlockListManager(QWidget *parent) : QWidget(parent) {} BlockListManager::~BlockListManager() {} -void BlockListManager::setup_basecolors(SlopeCraft::Kernel* kernel) noexcept { +void BlockListManager::setup_basecolors( + const SlopeCraft::Kernel *kernel) noexcept { for (auto bcp : this->basecolors) { delete bcp; } this->basecolors.clear(); this->basecolors.reserve(64); - constexpr int num_basecolor = - sizeof(basecolor_names) / sizeof(basecolor_names[0]); + const int max_basecolor = SlopeCraft::SCL_maxBaseColor(); uint32_t bc_arr[64]; kernel->getBaseColorInARGB32(bc_arr); - for (int bc = 0; bc < num_basecolor; bc++) { - BaseColorWidget* bcw = new BaseColorWidget(this, bc); + for (int bc = 0; bc <= max_basecolor; bc++) { + BaseColorWidget *bcw = new BaseColorWidget(this, bc); this->layout()->addWidget(bcw); this->basecolors.push_back(bcw); bcw->setTitle(QString::fromUtf8(basecolor_names[bc].data())); bcw->set_color(bc_arr[bc]); } -} \ No newline at end of file +} + +bool callback_load_image(const char *filename, uint32_t *dst_row_major) { + QImage img(QString::fromLocal8Bit(filename)); + + if (img.isNull()) { + return false; + } + + QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); + + memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); + return true; +} + +bool BlockListManager::impl_addblocklist( + const QString &filename, const QString &dirname, + std::unique_ptr + &dst) noexcept { + std::string errmsg; + errmsg.resize(4096); + SlopeCraft::blockListOption opt; + opt.errmsg = errmsg.data(); + opt.errmsg_capacity = errmsg.size(); + size_t msg_len{0}; + opt.errmsg_len_dest = &msg_len; + + auto img_dir_local8bit = dirname.toLocal8Bit(); + opt.image_dir = img_dir_local8bit.data(); + + opt.callback_load_image = callback_load_image; + + SlopeCraft::BlockListInterface *bli = + SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), opt); + + errmsg.resize(msg_len); + + if (!errmsg.empty()) { + if (bli == nullptr) { + QMessageBox::critical(dynamic_cast(this->parent()), + tr("解析方块列表失败"), + QString::fromUtf8(errmsg.data())); + return false; + } else { + QMessageBox::warning(dynamic_cast(this->parent()), + tr("解析方块列表失败"), + QString::fromUtf8(errmsg.data())); + } + } + dst.reset(bli); + + std::vector blockps; + std::vector basecolors; + basecolors.resize(dst->size()); + blockps.resize(dst->size()); + + dst->get_blocks(blockps.data(), basecolors.data(), blockps.size()); + + for (size_t idx = 0; idx < dst->size(); idx++) { + this->basecolors[basecolors[idx]]->add_block(blockps[idx]); + } + + return true; +} + +bool BlockListManager::add_blocklist(QString filename, + QString dirname) noexcept { + std::unique_ptr tmp; + + if (!this->impl_addblocklist(filename, dirname, tmp)) { + return false; + } + + this->blockslists.emplace_back(std::move(tmp)); + + return true; +} + +void BlockListManager::finish_blocklist() noexcept { + for (auto bcw : this->basecolors) { + bcw->finish_blocks(); + } +} + +void BlockListManager::when_version_updated() noexcept { + for (auto bcw : this->basecolors) { + bcw->when_version_updated(this->callback_get_version()); + } +} + +std::string_view basecolor_names[64] = {"00 None", + "01 Grass", + "02 Sand", + "03 Wool", + "04 Fire", + "05 Ice", + "06 Metal", + "07 Plant", + "08 Snow", + "09 Clay", + "10 Dirt", + "11 Stone", + "12 Water", + "13 Wood", + "14 Quartz", + "15 ColorOrange", + "16 ColorMagenta", + "17 ColorLightBlue", + "18 ColorYellow", + "19 ColorLime", + "20 ColorPink", + "21 ColorGray", + "22 ColorLightGray", + "23 ColorCyan", + "24 ColorPurple", + "25 ColorBlue", + "26 ColorBrown", + "27 ColorGreen", + "28 ColorRed", + "29 ColorBlack", + "30 Gold", + "31 Diamond", + "32 Lapis", + "33 Emerald", + "34 Podzol", + "35 Nether", + "36 TerracottaWhite", + "37 TerracottaOrange", + "38 TerracottaMagenta", + "39 TerracottaLightBlue", + "40 TerracottaYellow", + "41 TerracottaLime", + "42 TerracottaPink", + "43 TerracottaGray", + "44 TerracottaLightGray", + "45 TerracottaCyan", + "46 TerracottaPurple", + "47 TerracottaBlue", + "48 TerracottaBrown", + "49 TerracottaGreen", + "50 TerracottaRed", + "51 TerracottaBlack", + "52 CrimsonNylium", + "53 CrimsonStem", + "54 CrimsonHyphae", + "55 WarpedNylium", + "56 WarpedStem", + "57 WarpedHyphae", + "58 WarpedWartBlock", + "59 Deepslate", + "60 RawIron", + "61 GlowLichen", + "Unknown", + "Unknown"}; \ No newline at end of file diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index cd34baf3..7a89caac 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -5,6 +5,8 @@ #include #include #include "BaseColor.h" +#include + struct basecolorOption { uint8_t baseColor{0xFF}; bool enabled{false}; @@ -20,16 +22,46 @@ blockListPreset load_preset(QString filename, QString &err) noexcept; QString serialize_preset(const blockListPreset &preset) noexcept; +class BlockListDeleter { + public: + void operator()(SlopeCraft::BlockListInterface *ptr) noexcept { + SlopeCraft::SCL_destroyBlockList(ptr); + } +}; + class BlockListManager : public QWidget { Q_OBJECT private: std::vector basecolors; + std::vector> + blockslists; + std::function callback_get_version{nullptr}; public: explicit BlockListManager(QWidget *parent = nullptr); ~BlockListManager(); - void setup_basecolors(SlopeCraft::Kernel *kernel) noexcept; + void setup_basecolors(const SlopeCraft::Kernel *kernel) noexcept; + + bool add_blocklist(QString filename, QString dirname) noexcept; + + void finish_blocklist() noexcept; + + void set_version_callback( + const std::function &cb) noexcept { + this->callback_get_version = cb; + } + + SCL_gameVersion version() const noexcept { + return this->callback_get_version(); + } + + void when_version_updated() noexcept; + + private: + bool impl_addblocklist(const QString &filename, const QString &dirname, + std::unique_ptr &dst) noexcept; }; #endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H From 38c00d4ab681dc7c850c6180070733786d3f0a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 15:03:49 +0800 Subject: [PATCH 0267/1123] add more functions to BLM --- SlopeCraft/PoolModel.h | 2 +- SlopeCraft/SCWind.cpp | 222 +++++++++++++++--- SlopeCraft/SCWind.h | 21 ++ SlopeCraft/SCWind.ui | 110 ++++++++- utilities/BlockListManager/BaseColor.cpp | 10 +- utilities/BlockListManager/BaseColor.h | 10 + utilities/BlockListManager/Block.cpp | 12 +- utilities/BlockListManager/Block.h | 2 + .../BlockListManager/BlockListManager.cpp | 19 ++ utilities/BlockListManager/BlockListManager.h | 13 + utilities/SC_GlobalEnums.h | 2 + 11 files changed, 386 insertions(+), 37 deletions(-) diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index 9a6e42ca..db35c959 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -25,7 +25,7 @@ class PoolModel : public QAbstractListModel { QVariant data(const QModelIndex& idx, int role) const override; void refresh() noexcept { - emit dataChanged(this->index(0, 0), this->index(this->pool->size(), 0)); + emit dataChanged(this->index(0, 0), this->index(this->rowCount({}), 0)); } public: diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 3c6c9889..b45cca32 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -2,41 +2,72 @@ #include "ui_SCWind.h" #include #include +#include + // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind), kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); - assert(this->ui->lview_pool_cvt != nullptr); - assert(this->ui->lview_pool_export != nullptr); + { + this->kernel->setWindPtr(this); + this->kernel->setAlgoProgressAdd([](void *, int) {}); + this->kernel->setAlgoProgressRangeSet([](void *, int, int, int) {}); + } + // initialize cvt pool model + { + this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; + this->ui->lview_pool_cvt->setModel(this->cvt_pool_model); + this->cvt_pool_model->set_listview(this->ui->lview_pool_cvt); + connect(this->ui->lview_pool_cvt->selectionModel(), + &QItemSelectionModel::selectionChanged, this, + &SCWind::when_cvt_pool_selectionChanged); - this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; - this->ui->lview_pool_cvt->setModel(this->cvt_pool_model); - this->cvt_pool_model->set_listview(this->ui->lview_pool_cvt); - connect(this->ui->lview_pool_cvt->selectionModel(), - &QItemSelectionModel::selectionChanged, this, - &SCWind::when_cvt_pool_selectionChanged); + this->export_pool_model = new PoolModel{this, &this->tasks}; + this->ui->lview_pool_export->setModel(this->export_pool_model); + this->export_pool_model->set_listview(this->ui->lview_pool_export); - this->export_pool_model = new PoolModel{this, &this->tasks}; - this->ui->lview_pool_export->setModel(this->export_pool_model); - this->export_pool_model->set_listview(this->ui->lview_pool_export); + connect(this, &SCWind::image_changed, this->cvt_pool_model, + &CvtPoolModel::refresh); + connect(this, &SCWind::image_changed, this->export_pool_model, + &PoolModel::refresh); + } - this->ui->blm->setup_basecolors(this->kernel); - this->ui->blm->set_version_callback( - [this]() { return this->selected_version(); }); + // initialize blm + { + this->ui->blm->setup_basecolors(this->kernel); + this->ui->blm->set_version_callback( + [this]() { return this->selected_version(); }); - this->ui->blm->add_blocklist("./Blocks/FixedBlocks.json", - "./Blocks/FixedBlocks"); - this->ui->blm->add_blocklist("./Blocks/CustomBlocks.json", - "./Blocks/CustomBlocks"); + this->ui->blm->add_blocklist("./Blocks/FixedBlocks.json", + "./Blocks/FixedBlocks"); + this->ui->blm->add_blocklist("./Blocks/CustomBlocks.json", + "./Blocks/CustomBlocks"); - this->ui->blm->finish_blocklist(); + this->ui->blm->finish_blocklist(); + + for (auto btnp : this->version_buttons()) { + connect(btnp, &QRadioButton::toggled, this, + &SCWind::when_version_buttons_toggled); + } - for (auto btnp : this->version_buttons()) { - connect(btnp, &QRadioButton::toggled, this, - &SCWind::when_version_buttons_toggled); + for (auto btnp : this->type_buttons()) { + connect(btnp, &QRadioButton::toggled, this, + &SCWind::when_type_buttons_toggled); + } + + connect(this->ui->blm, &BlockListManager::changed, this, + &SCWind::when_blocklist_changed); + } + { + for (QRadioButton *rbp : this->export_type_buttons()) { + connect(rbp, &QRadioButton::clicked, this, + &SCWind::when_export_type_toggled); + } } + + this->when_blocklist_changed(); } SCWind::~SCWind() { @@ -46,7 +77,7 @@ SCWind::~SCWind() { void SCWind::on_pb_add_image_clicked() noexcept { auto files = - QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;;*.jpg"); + QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;*.jpg"); if (files.empty()) { return; @@ -59,12 +90,14 @@ void SCWind::on_pb_add_image_clicked() noexcept { if (!err.isEmpty()) { auto ret = QMessageBox::critical( this, tr("打开图像失败"), - tr("无法打开图像 %1 。\n详细信息: %2").arg(filename).arg(err), + tr("无法打开图像 %1 。常见原因:图像尺寸太大。\n详细信息: %2") + .arg(filename) + .arg(err), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); if (ret == QMessageBox::Ignore) { - return; + continue; } else { abort(); } @@ -72,7 +105,8 @@ void SCWind::on_pb_add_image_clicked() noexcept { this->tasks.emplace_back(task); } - this->cvt_pool_model->refresh(); + + emit this->image_changed(); if (this->ui->lview_pool_cvt->viewMode() == QListView::ViewMode::IconMode) { this->ui->lview_pool_cvt->doItemsLayout(); } @@ -90,7 +124,7 @@ void SCWind::on_pb_remove_image_clicked() noexcept { this->tasks.erase(this->tasks.begin() + idx); } - this->cvt_pool_model->refresh(); + emit this->image_changed(); } void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { @@ -122,11 +156,31 @@ void SCWind::when_cvt_pool_selectionChanged() noexcept { #warning load converted image here } +#define SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST \ + { \ + this->ui->rb_ver12, this->ui->rb_ver13, this->ui->rb_ver14, \ + this->ui->rb_ver15, this->ui->rb_ver16, this->ui->rb_ver17, \ + this->ui->rb_ver18, this->ui->rb_ver19, this->ui->rb_ver20 \ + } + +std::array SCWind::version_buttons() noexcept { + return SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST; +} + std::array SCWind::version_buttons() const noexcept { - return {this->ui->rb_ver12, this->ui->rb_ver13, this->ui->rb_ver14, - this->ui->rb_ver15, this->ui->rb_ver16, this->ui->rb_ver17, - this->ui->rb_ver18, this->ui->rb_ver19, this->ui->rb_ver20}; + return SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST; +} + +#define SC_SLOPECRAFT_PRIVATEMACRO_TYPE_BUTTON_LIST \ + { this->ui->rb_type_3d, this->ui->rb_type_flat, this->ui->rb_type_fileonly } + +std::array SCWind::type_buttons() noexcept { + return SC_SLOPECRAFT_PRIVATEMACRO_TYPE_BUTTON_LIST; +} + +std::array SCWind::type_buttons() const noexcept { + return SC_SLOPECRAFT_PRIVATEMACRO_TYPE_BUTTON_LIST; } SCL_gameVersion SCWind::selected_version() const noexcept { @@ -142,6 +196,114 @@ SCL_gameVersion SCWind::selected_version() const noexcept { return SCL_gameVersion::ANCIENT; } +SCL_mapTypes SCWind::selected_type() const noexcept { + if (this->ui->rb_type_3d->isChecked()) { + return SCL_mapTypes::Slope; + } + + if (this->ui->rb_type_flat->isChecked()) { + return SCL_mapTypes::Flat; + } + + if (this->ui->rb_type_fileonly->isChecked()) { + return SCL_mapTypes::FileOnly; + } + + assert(false); + return {}; +} + void SCWind::when_version_buttons_toggled() noexcept { this->ui->blm->when_version_updated(); + this->when_blocklist_changed(); +} + +void SCWind::when_type_buttons_toggled() noexcept { + this->when_blocklist_changed(); + this->update_button_states(); +} + +void SCWind::when_blocklist_changed() noexcept { this->kernel_set_type(); } + +void SCWind::kernel_set_type() noexcept { + std::vector a; + std::vector b; + + this->ui->blm->get_blocklist(a, b); + + assert(a.size() == b.size()); + if (!this->kernel->setType(this->selected_type(), this->selected_version(), + reinterpret_cast(a.data()), + b.data())) { + QMessageBox::warning(this, tr("设置方块列表失败"), + tr("您设置的方块列表可能存在错误")); + return; + } + int num_colors{0}; + this->kernel->getAvailableColors(nullptr, nullptr, &num_colors); + + this->ui->lb_avaliable_colors->setText( + tr("可用颜色数量:%1").arg(num_colors)); +} + +#define SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS \ + { \ + this->ui->rb_export_lite, this->ui->rb_export_nbt, this->ui->rb_export_WE, \ + this->ui->rb_export_flat_diagram, this->ui->rb_export_fileonly \ + } + +std::array SCWind::export_type_buttons() noexcept { + return SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS; +} +std::array SCWind::export_type_buttons() + const noexcept { + return SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS; +} + +void SCWind::update_button_states() noexcept { + { + const bool disable_3d = (this->selected_type() == SCL_mapTypes::FileOnly); + std::array rb_export_3d_types{this->ui->rb_export_lite, + this->ui->rb_export_nbt, + this->ui->rb_export_WE}; + for (auto rbp : rb_export_3d_types) { + rbp->setDisabled(disable_3d); + } + + std::array pb_export{ + this->ui->pb_export_all, this->ui->pb_build3d, + this->ui->pb_preview_compress_effect, this->ui->pb_preview_materials}; + for (QPushButton *pbp : pb_export) { + pbp->setDisabled(disable_3d); + } + + if (disable_3d) { + this->ui->rb_export_fileonly->setChecked(true); + } + } + { + const bool enable_flatdiagram = + (this->selected_type() == SCL_mapTypes::Flat); + + this->ui->rb_export_flat_diagram->setEnabled(enable_flatdiagram); + } +} + +void SCWind::when_export_type_toggled() noexcept { + const bool page_3d = !this->ui->rb_export_fileonly->isChecked(); + if (page_3d) { + this->ui->sw_export->setCurrentIndex(0); + } else { + this->ui->sw_export->setCurrentIndex(1); + } + + const auto btns = this->export_type_buttons(); + + for (int idx = 0; idx < 4; idx++) { + if (btns[idx]->isChecked()) { + this->ui->tw_export_options->setCurrentIndex(idx); + } + } + + this->update_button_states(); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index af56ca78..2dbd339c 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -29,6 +29,11 @@ class SCWind : public QMainWindow { void when_cvt_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; + void when_type_buttons_toggled() noexcept; + + void when_blocklist_changed() noexcept; + + void when_export_type_toggled() noexcept; private: Ui::SCWind* ui; @@ -38,9 +43,25 @@ class SCWind : public QMainWindow { CvtPoolModel* cvt_pool_model{nullptr}; PoolModel* export_pool_model{nullptr}; + std::array version_buttons() noexcept; std::array version_buttons() const noexcept; + std::array type_buttons() noexcept; + std::array type_buttons() const noexcept; + + std::array export_type_buttons() noexcept; + std::array export_type_buttons() const noexcept; + SCL_gameVersion selected_version() const noexcept; + + SCL_mapTypes selected_type() const noexcept; + + void kernel_set_type() noexcept; + + void update_button_states() noexcept; + + signals: + void image_changed(); }; #endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 213a9662..a88e31e5 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -669,6 +669,9 @@
+ + false + 平面示意图 @@ -698,17 +701,62 @@ 0 - + + + false + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true + + + false + + + QAbstractItemView::InternalMove + + + Qt::CopyAction + + + QAbstractItemView::ExtendedSelection + + + Qt::ElideLeft + + + QListView::Snap + + + QListView::TopToBottom + + + false + + + QListView::Fixed + + + 10 + QListView::IconMode + + 0 + true + + true + - + 项目池 @@ -721,7 +769,7 @@
- + 0 @@ -734,7 +782,7 @@ - + 0 @@ -848,6 +896,9 @@ 0 + + 0 + @@ -858,6 +909,9 @@ 0 + + 0 + @@ -875,6 +929,9 @@ 0 + + 0 +
@@ -885,6 +942,9 @@ 0 + + 0 +

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%0DTHu08 zhD&ClbQ|2n9jSPn%FValP=e$_MF3?qWTGS~$rd_tIGh$yTlvE2)AsMQnmFD*>bV!j zQVr??Sg@5sn61((83M5yI+a{#q!bIPhm(6mRLZ0Ww0JM#ez?Da!2YE)WB!`Lf=_;) zC;okMKUz(g!x=1g;xlvxr(6g)<&7XI;9x2?0-~ZY{`v~^J!|vX@8WX2l^%aTzZAdc z)syg2k&=Mkvb%e#iLn4fM2ml0Bz4`=4LN7aL2Ay7(6*Vo!`%lP_OV|yg))&MVjNAO zUIrN^L=3$-K_)+S%b($&iYwwhL_^u>oZnAQO0#D?R%Dt*Pq2tne?l=s#Dfhh0ePaU zJ?iI?vwDTIUQ#c|LW;@5`UtgP`u&syBbo2x2#>E`nJ%EU z6XL{A8LM<%^ITDyHKg90Owppe0!0lbdJtob3JLYL_sAjU!TYz=)7LGB$|%j|)s$8& z94F;5TSmg>XFOhM!>1I1G+8bL6FwgR&>q2^rIDWXI#5!KCAux;A|X|T zWZkG#xZj!H&2XbkbpJD^$N3dD@N~8ERPJyJE*H5U_vh@BIjSlvUY}$JVF4BK&=8N- zF^12Q4G{=i1RXI0XAl$0DJ@!yHiTN<_2m_+bRyKe6<@VjcFu8(Y>l?a2|1$?L`u=D znz=Nyp3AK_y=0$9u$zjOZ4%x@ih7OU~%)?3eYB9f9$n$xAd8MDe zT7TMfn2i_Lt7r4et66Tl%|Q9g``^4wD{bE%a_>0whjHk;W;R=2&Hmya^>5y^w>PWV zU(R0~deMx*sJZI_D3sK44oj-qCX9C%m$D0gbGwb`F6Z+({Po52tM=u9L*C{6DB0ZH zGQ816_;{`>|4RMsyUrUrow69z61N8=*aQ=xDAsg|FjE#PWw?xVmeXK}g77q7CG5ui z*pJZEE>ds%P5$c3Z^nGJS}oSytXzxv>fCiwCR z7{FixFFt-URrn7_LV$#5U~PCJI*CT(I-`+TXe<-f>dWLajfMb&KzzSgnumC`Zy-V> zYeaB96@(q{N9CWSPPj5kj!@|77+Nc?wX%V&O@YjHXH_h9<%p~k9!@+$36EmtF2>QE z!8X_ciEM)d%!3vZfm|4Nl+0q`DDQtSqm?m^*N~EDi%B<$isFLCcT|r5W?>so%EHNy zmBmFRh~qth$C-9=ksj5H04O3}rVc6oV}C&De~<6>aMC~jJI6oEdwzy$!Mvy0+-uf} zsV@+a;tdj!azR%ugQKe|(d>8G-OH{=Bveu!J%TJkDxun>)TY#ymzujf+cLH}l85)j zs)7W!YF0CBjWo4wE zS{pRrq!iPFRUzt>Q{)s3lwx0t2tr~C_Z6dWVR9ELK79i16_c&kyStQ8X=JgJl3)>E z!q^t_SB7|KM2MThNz3RabPs2%A_3s7!C-hREO!rqphQnM~E|m zQpi|S7pDpZ2ruYHFv@#k3TYiHzV99DB2X*U$*Bi@q8Y~dE8+C?Dvkv!WsIISs$<0* z7k@IMn5;?^UQi3qg&s^E6xou3Xpy1RL=KEmFx+1`9mBgdhgodu5fnDc5k(ZO_TO@DDx+rxGLVB#sR=*UE2d6+Vx8P~j3_g7!9$e2 zK@f#oSNCH))ghGcIZfT&eDp#`KE;(!79@m75T!8Sj7%C+zysh2QlttY3ny2I1UM>Um~bM)ZPKi!W&LS0=Ev)UKa}hPAY26jsjL9Tbe~A^zVJLHgQWbu0;aSe z2qUvbPHNzop>s2fEa6KJAV$cDa6}?<(FzHlvYUnfRVnz4L~SS?t&<_~fEeI{IFv5E zlq4X++@PoXptAw(5Y~x^B)}Vr0~h&KXKNfZ4-wu-dInvMdutX3jyb#Mu|fZ0;XnRl z`QuNozcD{t1O?exgWM8BVJG{F+m~^eCl)BW+EX`m2!~gp81LH6(Ubc9t zlx~RL(!z8_(p5Fo#ViLPZcIEtHk3u%&A_!tyW8F@w)p4c=h5h>aytv3QTEQ!I%#|6 zM+a#6rA1wTeFd)K%;>_<0y7ILLs2>e${~pvw2*-ukqlNC&qV~1fWpR{6-`SHmcr(p zj2G)y*Z7SgZkEfGnr^q{-K`86>|6KlXJ6~+Y`}Nlj^kC#FD^pXmerdfkOFGxoUL;P zrjW)%!}16n7MHhjxntADVcG3(y5|-+I7iA5IzkItc&@!2KJO0OAI-k(m-st>d5d3U z^vi!Sezw~m*v#7b#UaP;V8Mp^;p`CkE$7W_zqqg;{r2z&f9vyA^Y!i9wX~1l#+$`- zS#m|l1m{vBAv)U3eL*h8muju}%b6tcnPQRhT*sN@mZr2Bn&Mz|mTM3LO*j@R?}yq+ z8i%q)Bs>)sC|v+aMJFybu}5#IWY?(du!%7jImirmI6@3`coHdR`^@aY5s^X~a)4wo z3(aVxN958M2#z8~ABmyN4e-oVK+!cLahBCE9_5nnNYCK^KV^g|R}je2XnUkB3GUau zPIkI#JFhqN^3ieaeCGK0<)eE{vEM2b9lgSGLh4L|^+Yy&%)dc6sUncl(+v@-h`>Ch zxc3j;A23X&N4a|<1mF=-m@0rx z(rHmjWg4y};6yq(Jc8BQP@4&W;zO>=TZx#QYI^H`0X--}FI${qQ9bR}jikrO3Nj*v zNkoGN6VI8NAr6foXrxQHNOJe=#du#?mO`yBtM@sjw3`&K(og%x=|HqB98o$AS*|?SV0Pp zTq81}0SLtbB_d2A&S+4Yvy;H;=kpjT@4HQo2&6KKMoHXOcttsNz-u%OPAE7^B17ng zu+Wjrk;Y(Vk)I_a^2GlWNTyWN3EdDQH3xGM8;de3g?<$iVRX6(2#(b5b5Ltd3Qn)0 z(rxV%(ez;*3C?Qt&eCR&SvaE9f(Z&A#xmu==$S|)Y6~=Io5BtVbq}E_Bp3=8IDN`h zh6Jp>GNZ=(o}%u&e@&Pu99mXBEaeMv>>O2rOlS+E#PRinQX~>b1D4Bl+ldg+CuCTe ze>ho^Dr9lGx*lV}EM}ha;R7K0QBf{qw>t!76OLnu_PtHZ6rm|MOErW6&KMm*X%Jau z0HlLiG$E#%cTfQb#33-2i5-k!&yXW;vYz+qps(6=(lkJWp1y~T;G&t0dGsMH1KBsC z<8mI_c(+(Kv*dkBXqm*#;2BPBI!X>~M;WC}(y1#44(gS^D~eXJZt<*(i`XW1#vu^d zhLI6XV(QxY<*e0qY}39^I$I{hVH+Z&`(NCAc^LX@v^jkr`rO&J(l=O{o4b4OL4=FI zRhmY+W$MO$vs2xtS8u%?g9lxr_Y1x|c$=efLN$_lHkubQ;3EU{uWN-ZV9*H)p@2pK zag=i%fiQ}}N9Y0J;9goq7|dV>wh%2Frt#2Njz$J;Tv|Eo{kFGnZf@p^%^~Ogb~g;Y z3ER|ZlWdJKHQjQt9{aqXt+jh*xDZ`8t$9d}#-qt-N7vDlXF==xf!nm)E}rjX*7pN^ z-psFF3`RRF#+%OWmT|j?ZHrxs@x}JD(9MkBewf?m>C6A>&AYGi&3ZPIaV3W&+F{>H zq#4q3b-B8@`sW|Kxb*a5{k&hS@~7X|kABpnz32jVc;cY4DyKgU>)?y<8Kjy=$$7*| zWy!pvEfuZsLYc%n@h*+6^bLl@f#HhMZ(xpqz(XNpkVd>0|1FuEp-3&o7R#E_Ls6|t zF0fL1t68o=1>i^&az_cIl&?t9P%CLj7NkemItL3t7rR#LPTITHI*aJ=^ zcMtRMRy8$E0iy$yP%EC$Vor`CEea@Fd3x#v zUsbSPln9BCuu{$4;T(c8lt^uO28AdAsxoAbbz}`NptQDh0*YIN35wC?=!`#_ zq07@{h^Zi|0_{htpg>qz*!vR5fU>w4Dg${49UvoQ0Gv8XHPgQ!yLAhisIFUdq1L{~|GIf5{M#=ZX*H2p7LWI>3AsbOo9WcQHZouK^x5A&_YcaK8iN0XahKe@5vlNNDc&%1xKU# z1bqzvBbCw!XAB{7U;u;K4*AB}LeeN0GcDYF%!i%zJL^Xu%lgD6AfT%D!@0kuBi;-scPLlFU^iK^%#$DT@xH_s;F$NygPU$o7qPjp`if>Nl_T zgZb?G@>zDxh^`rtw{3oBW&zQrWv7%RiD+ous<~`z-|zODyKNexZ=~^IHk0*UWuKef zmi;gm;Ob~`?34IwD$wyAdndFiNKtUgDp02)inGlqIc%uIniwhQl+nP)$OG9xTQo#; z&1LU5W;RGGl8D>G-Qn(wuP#3N9WoMpelcqrwq27t5fREaBD0HT^wf_j?};=X$KK=ZWDLb_0pu+e6aiD58nO7BHzWl{pihKY2-Qjg&gL-*YO7ZP4tJW zxXRb*D{MEP%{IFazIy!|TclZgw}1AdG@CW+73Rxkxooelb-4;n&)2W6nsnJTyWaP* z=ringyh=^q?H+$Tb0$2&yRapE%~-)&U`1`{Gw}s&!C252;;leAh@cg3IW`;JkNRPlb9= zsm_8=kyJf$!axc&XAcvG2XnXxQWTG$&r1IS-6#%>42K}33VhQHU3(V3yAzu7>zY5m z+lZb@MX`{EVnZ)|5)i$e}cemr{{V>e9J{Yh)qM4m?n7I? zzYZ^aK9w4?TNB^GB}&E$Au?!nB0AMRY~wU9Mx442vH@$#qFlNQQeFDZwzNOgYG_*| zS#ivaw|j#LNJfa&j7S9HfN5GZ&t`l(&XYB*h?vLlVTj27x~3>va=}Y5rPa{e%)J=NdXro7lxncv?&AEB zzPh}8`{vV&^FROj~>) zcEjeiU{TUM*>+dP+cI4RQymQ8t}HY{fr zkBt}LV7Q2>a}Cb5<(~5jIa%od=gthqaD*vKGmwcWC_;fsG@OnL)fSlV1+X&WUbOm$E2ldVMNLVCg$iMcI1YWSkd(UYE=zDMuq3rm z-Fr-BoI>bvL?iWQTTbFM<_zFV0_>&zLXQnIdh&0z+(FGG5-HMB&?#QvM!0P<_2 z7GZv;k-7YKMmttZA6^PS;2q*F6PTpZ1N`i$?Y$CVVI{(f?CfOvsYCOqJhdit3D1lnRKi#~TJz0&cAh zI<+q6U8=P4?!wbIY&rLL9KRmV8TYJuB$OJOTV7j()go3FzrZ3Gt{%9mEv#dZ+VKt` zLdDFECrAfvTy3e>ER_O#v%g+g0! z@wGp0FpD~<&=INOzzIHrIv-X~JN9Ms9TtQiz$uGbqH3URX@nl=5?@F!v~ z(^?}v5F3jpgMW64 z&pga@KF-^d;oL7*k^0rg>MyP?(=T4W{>7KKFRrJzSG!lQr?0N!^47n)=Ji(dY~Rkm z|8M>E-<cBl9;m{qK z!4{EFz1BqJ+OeeNyu97-r&+d6{b{%Pm}kSOU0?6!&zQfz))yb=Kl!%b41-+{ z!@R}3&s2%nQ37Q2b^6uYbfs}S+?3wMoYKmMyf3%V<9lDX&i2)^(pjubr|zeQ4efLs zlVLFQ9*MIdn-x$UOC8q{B_czGC|QMyU`Pe5Q>JQHPMzt!){FokH#k8M@8iEz$L4qG zjMY1jfD|ElNR@NfJQ4xQ3>Ev)lH}^1ZVSk08FSWQ+>(1#cPv9|m;=?Gejwy}%OBQJ zMfCrVn)zQu^WZ~f^hMdMYMiRPhhVXHB?NYF2Xx_Zi;XXc12&>Q%pTAn#yvo{DiN{c z=Y02SDsbG=qmF{F`hv^UpG4^buV%bFNuMhAX31?`N=eDc$Ype zdGu-Dt=Fs5+wGNe?upc|S3`eQ_VcFnc{~fzPv&{vY&In#fV1^_2Mj5>I@WZ1_JJfM zg$d?WQrv2kTEAL>qz<)3cL;8*H&`v8;S~o|DHw!D%++d6x+*Ns2q0{__tf;>L3DY8 zrx}zq3sYze?L)Ivyt|WjR7#0jE6UJ%L{>GPZ6eNn7^#ZPw^n3J&K_i;yi||XqQR*X zY1JDHCQAm0vj^c0cXlv$tFg~9Dp$)?LJzsnD=N1Aq{j9wXE)4rn01%~DZ@iURZ7(0 zkBHkvbJkfzO#(J)=N%Qaa1=5d!cEI4ym=<;3tZcJv<*V?S;$Z^%`I9e7m{AR4mv>T zLoEUR?m%Dvck%|}HKB4g>sV%pgYSTg3D!u?wpywpCup=$OBF$A=NHI#c|AL zd)YpG(z-6-0=wY|%G7(8-rM$*?!tGi+$2|47Q0X``W`hEd z97aPvw$s)7S3p;)%^d|5Y#d9+<#AIaBdjUDf~0Y-{$B=&&MHGyku9jo;%G7!svTaJ z2}$FF)I)d_v`pM)<6kVvs3WO3nif{ndfYeDRF&t~=eH27>t1N@3o!u@y|d0BYR*+X zIfbzYig*RCLK|TSTJ{XQ1rxDJ?2@{qRG({~Z_501)sMfsNjc|l-OexhWV^w$El$_{ zqyF-*ZhrUI{pEl2KYe<2{ku2YA6~wFb$va)x!i4cQ6_ds-}*?u_AB4re(%qnl$oZz zofL+d&+1$pht2KN3>(wr*BAXbCVw&XvwnKDdhri`v3;eJVvmQH-RbMIE`7AQc)J>( zr6(6dvGtq%V3WRh`{Q9Xp1*zZ@~6N0UrvAZx1R3*?iX+W*5~~4_U!Xv_4(O6J-bMs z{puJ0Kb!(kj0{z)q`+Zt<{l_1Fyk4zv`{J}S+u!c!ztiExSYDs>CFPeoos(v8&&a6N3X*Kk zeuL|gXBvi!AAWT+Oh4I9=r_N#!lzHpwdz!yv2ZXZ;P(kxy)H8)KAYxDZBzo2=m-t%}#kxjQj@#PMU4r!hTZ zIU$m<8zLFpqO;PY7$;Mq=AlwGP=F#7X;wW#M!usuP^e^gOm`R^9SE3`lu?$mZj-mQ zBGne*=-o)X!h441U{*conu`$UHvMNIg;WGZB?Zg|6Vo9LxQ?}~Fn|Pa$QD>lvlV6| z+|0=YWo5ygwm-(a9%)JA10@-J0OL#luy6FRv?)E%fsTecTE={J8D&kPKEy@>?{MYb z|NODi;C+V1eKp^|pkw`>h2?-TKFn_G)VKC~s6Z4f`UE*FVv$ou8=K%V?Pu3GA>jW3OkV9TgtV?le1yq~3 zaE`RdR@!v6qHRknwtP|3FFbp$(15tLbhhP1-+Yh;NZpQ*FhV`mS#(6Eit?ib&v{ZiQ&!F_A185K2EdTeJgjXD$gJk&}V-K)!g!0 zNglN!0V;fH!=?rOlN2?D+91mT!6Fzy5ldsXl=`%U11f*1rD%mJQTxZJA%ca3y?a02 zfzMdg455}a*w|-Hd~Ed}9%vWUd>MB$uK?bMkmzp3Tsq9l5C&hv%d~U&(wu&9gMZiV zc63mWKW(8v0NBzdXsU8}X#`h54{c};b@EvflBown@Co~B<#Z!d2p1VJs6Q6-a7juj zu=8+kPcf0A|PMV&8s+@l0&HmW=54O0U5g7Jm$1I z3k=ihm;L2mJN-QyLaY66uKwTk#cuG6lWzCsr#JufcYgaH{NPW1aee+MecqjY3y+@U zZ(ro|vzv8)b-ww@<405JU|whu-V8hih4{krC-EI$ke0KI1K7RDQ?>>I~?fy^v&8YAE^fjlO{mt0_?9J7S*T1u(_q_eB-&k$F z`11CXKln{u{u}#GSN3F|P6F!tPZNHQ9Qu=7qKR;RD z+}IBJ|Li}U`t!>tUySQ#<80bbHmaX?^RPN%mf@gO%pXc2c#w|uO`~l)x^J4N zq7Ix?FY5-n1@Hn$o)XA;9@w1?>w!d`*Z68z@*AArCc7bq{N}gT*MIRl>FQgb48t&v z^FDDJQUN*bZ+EwUbiLBFvwi-><(IENzuA5C_^rC_7-a(i#X>+>gTVv>C3%lT%;WWN za{HYx`sX>e^LC!rGt(9^pA5z9RoU}8@3z?lTW3oLmwnB6 zR3Jl5m=FDd4^Kcfj?@l>*C>F+q={Bhw=`AN zVt{v1kX+0^wWG|Vo;2Q-VBUj=z`Y?OdM66|9f(pzLFl+aU1!{tPR(dCK9(Z7<%nn# z%*r!1?}yv3cDvhKh<)D!R+S!g-tF#IFVuipaw#R!5;}8BMp&12`;oNOYVC7^DC@u^ z460a6SVn>x3xFP$zpcRh=A{;5Nd~Yj>tj=B9*%kwbUZ|YC>dJFOurvwYwmfykuA}tk+r|RTeN{ zvhbF8TsyAU1~PLg%Ui90^f z7!NkmplW!ND3tD$5N?O1e*@hteW4p zBwdFv6El1QGA*mI*Y7>M&Nx^Pm$#iq*r1AkJ=jn|fESp7&5y=WJ$` zIE#gD-rz}5!);lKEg?ohi4;mjmf;zks0?Mqz9a2+y`R?e>d&P7?_K=%lhqGbKx0Or5}sH2?DF-~P_Y_kZ-=|KQ}&({%o59@eqh6z3ErqpZFvXEr|Vb|3rOXZGq* zdUcVm2cMsE{@?%3Z~wP{?-#$ga<|*luA5gEuQ%PZypNN|d$XTSQGWR5C>m5e>$D-%P&3Yo_F!-XLdFW&wKy4^KSNk@Q0VmG5&-vNS+g+E(pM3fHB=+C? zx1aBQGnP3UGEl6BXSPIe5U@FCrD2t^`sx?cAMdYpP)KkYP^vH1Gb}F5cy@eaPGFPsj zD;zVFU0EsxQ{_%drG}%|JF!H*7q@Vit3)nx&FXI`M~S376jv2<$%Z+KdYmQ+n-z=- zgi>8)YgenLg4Eb6kHxnpNXVfS%%V5$slwnPv$j9_L9k#j2d$bb%q!s|#0L`uA1ss~ z`22&|yAL~9ejq&$X~8WWtnby}UU=8ZIQ|b!1C3*W^c|GoozHyZQ~%mNcoeO7UmNTo zszdYrENVR`a|ys%0wo|Mfw{6(}L6xpg-;H*a6>az;dqa&pXl@R3ke+&(1D3i0vuG|evI`jKKoShLshgY2>h@5%i3~4|Kvm1fB|#|F z*NW{zXA5MQnPQo+)F|V&y|6MpRCQRc;|$kE!~AjkN)%Qcpy* zP>@(HSAkQBNRA|RJ4*#N$tL)`Fu8;xb<0H*W;InV01T~w3#X_CG%!T8QDl3QmOUUU zl@<(BF=QgQQ5tSzY09@*(_*ALUfB*UfkT8bBNo=OL>S&p%Uk5{h28SHRl=|@Y0s{< z>Y2iqC_S5z3OqAa&VJ>)QLNEmBm!bsm{{q;Bxr%E8z<wG*I#ZV}Bcw2c<#u!rl@zcbd7n= zZy41bSI_mWFH8b5B7n?dP=ZLa=m{ift+J!<*lp3TR37IrMM8FEBI+qxuxR*3nd-U9#gB^GN;j!d zL3JoyiOvXlC;(q_VeH80$s?!tL9BoDH}2?xUpv4Yx?cfN6@BKA16@?pCcH!{Oc|Du ziux>{lrk*SW@3iIa5`;~Zrvi`@kP()n-?4Z3HI2p|Kg-CBX2gyi0NXz`lZvpd-CY_ z{?cz`U(J*9E)OGD;%cUc{THA8cc&f~zB|*~HQsc1ow{43`Sx~`_OI;Z(Pne9+rQbz zfc4sjxBc{Gw<~4rV@NMzdzr1fvb;ZEKMN)3y!h~>-=FN?ym(A)jppuXQ?Dp!s|MbK@S#5vwi}j~NdDeFTToE_7KfB!j^v&(1JsD1WzZrTW zkD)U5of%>-vr_VR8c%n&um>ZEKUnMeKw)vf!r+JzQ)TeYaN35GCIqna=MiIA?uTw? z{i^~CbQE=ynNP--!}xkw!KSOf`y>4i|7>%fUvKx*?VQ8=V(E4+m;3#0Ki%+pKj~t1 zvYqWSTzp(Oc0k9X%1T3FwdKGls{uXJ><)|m=BiwlS+-eUoSgPQN&}yspRhZPhy<(# zAKY%_eLo|eml!u^DVCsZUT1zfGL!4MVwzy!NqO3S4 ziBgY=kf~S{Dic}Clv)AJO3iA2gMkwF9$#w#-E`@32sUc}7${o$$xAueEEYAD2sjvv zRq0crRI?)`pinMFrMQ>6n1DbOhGb#2O28qK)`DsTXvatkmnVc0xUZhNx%C*Hq z*u)Pz;5{Vy_|Ss*Lt!4t*dJo3RhMQI!T5l(q7LBStE&$!^kWc*{xn)E9cOkO16<$z zYBRLyz>Bbj+EIg$Qi};#lHHbU3@W@LHlvgXo}XPzdmneB8X>sm%vrP(UOioRfY+Hx z#YdqrN~oxXZ&NTVfoLrgM6mD#pjOWgD`Ki)0@kD0 z@cU^S^Ft@Iye8m^gq&2&inAc(>?@NMny5^TU}2Psb`lCBq=_mP0f%9?sIQh( zW`;>&eN&>Vbt#tn)DDB>8Xj1ISJvX7s}B+_oQ!l7R=$Ke(KRZJLp-g8Sb-TjQ&08A zZbr(miD@sN-46Ll)bRl<4(nj$omX{-AH-QesBakOZ_@Vq5>U-1S;W$E5E@VPo&vP)%ux(D_+)A7qRK{UPyzxKILtcG zE3~@32~->MTE%EAO7nXP<*ImDY?5CuwOeqHz7aok41s>%s(Ih2dYSvQH*KYK&;cV% zh8aQdEkPiGw~W1Fk8*=~1*L4RoDdy~E%!#iXr;dO#!?Y@O)(!8$Qq?`fg%7WIe8+K zR63^6Oim(&40b}PV2>p+B}rxJXS8S<$_t}53YS-4Nne+a_Wc7~9uZX!UCrXw@OFzs zBaTTjM`2KhME0+BppEI!G&ydaEDA{@h5{!$U;q-)0TxIFtIT0mKck=Mx9oQEiD^R0 z4M-w@{kX|#mwi7v=5EgYl(UWVv-R}a{RY-`7AwQLOV^filwn__ZA`(SB?*d@hc5m3 z^S?dNyGTCQaTKIesO!?})nFfetWH-ydNp3|xh~tYtCyGKxBcRa^62#9iQ?uDHoS^F zjjMsT-FiUgF30N?GV|py3U6|r(hecfdD3|diY(vayxZMaKg`*O%qK3#^eC=)b@k)@ z#Z~sXJI@@h$MuVTU9g$T_B^BOk-cOTSWJ=kC~lTgTE@Iboqp2ruRF@P-6n^4=L7v_ z*`T=`-eE#6IM?vJ+&;=*ZIDlGzKEMmzJ7lFd#Njr{c1grkGA;9Pv88lfAq)y>mPmj z`Ra5(~6=ivje4}(x2c5NQO*9IW%!a-< z7=o7{eWKs^v(H7_mYwgP?Q=073c1~G$8pSaY@@us{N6ad*yXFUJl%Yk^AuVYa3ojv z7SP~>W0^W-bD&eK5hu`ExWIf$oilGVt~htdRA#_2S{?l;q`3x<2ocpNtXM=%I>JyM zug_nLwr$F*MM0`qc=3%md{`D}N2lVWJkiv|u2q4eJ0o{(h*mTJgSJGaHu_B#vsngn zMZ;FCA#A2iz-*j_0C&O!jIa@y4{aC5LmoMO;OxW@|61uB58W5ZQaXBO-QA(5i8L1A z!$G+L-23^3hoWPR$2V#??jN}xI#`F_fBD#3^zSaEsA{~n_3#|oqd{j=G!LAW z&^YB`7@j|0@3&uVHk-54rzPuld!2JOYM$rqyj^d)l)5ghHQkn2^cUtT(p;iViK4p; zux+j>!a*VmU}CANP+!)TAPkmaAqz9BP9acCRi$c6%t?KLiK<~;s^>P-elVd&4`_yp z`dabH`l8vZR6LZ}0bvo)Y|4fV%@nMf8daza&4@w;5sp=@Du@DxA-8m;rQ_Q|v+pYC zxT{defQ+`_lv`flyKnRaftJWjn7F4ZX4)Mj5~-{hRIGwCXcA}E4t)fUJ2ZD6 zXOHCv2Nxcksp*54{z*NsMk{_5j_i^vCk7Ez_@X|nzwZ*P3>=P9i->vY%;~uDum!Z; z*9+??LZ~jzQ!81#{oO)unsiAO9k`^~30Bkx8A?%mpH+ZHr5e;KtI2kYVu40gpbD2@ z-j2#ZJ}5Jec4YuvP3~Ygu|Hz0001BWNkl14gxy?uJ!z4^=k$?)g@((dB%+0`H4{4f9Y`I}dx>$+c`=5=Q! z3In^|H>nRYKie;%WX+ZtjPU$ZN~M z+IaDxA*s~z>K(L24^88L`ugvEhOa)}{h+`4NvHAYz$dyKwl79qyiC@on<;OGtGWA= zpXT}5`S*Wo{ruNXy}P)$I5|1lY)(#2PEJoxFU}ut;!2yR0SvCU!9N*GG9<%}a-yK& z>nS-&m@G;jOF2=v;iT;Iw^vu&H~Vpx^yuR3(dk-cp39fUx5H|9-1m^t!O^sDz>)TAd;>P|gRakq8nynR)_@P} ze5d5AgW|1@?15CN!H0f@@y;W7OyMxQ`+Q!I-3K_wK|=kf*zoW*Jv86@>hfmSeJl9^dkNbkCC-0zGj5bh|_JkNbGNu@|R zI(S5sQkYyo%ya#b(==I0T;!Qhp&3+QrV2(zr4ZEiTFWgi3M0MtNzGJ?o9gad*oh5G zUL8V9^<3jh*xa)BOE~<2;R91c(G^6k?_#Wpv-GfUJ#BqR!x@d z$)U>L9QIK@nNarBR@xzDmO4SWVh=!Jv1oRy6m0a_S{30HkViRyQr?-(*@&gDryi zzJsN3ka8Xs({1By=l><;gcMRWu~&}qguK(7z+yvU>7kB6NUZKx>$O3JvZ-{Gu_S=h zN|V*78qgFDnn3DNOvM5b#>p$yyf%~#rij|0Z;Xu+Qk|k!!g3>uG7zehv`SLC*UWvl zH%HZ0O79Bt7DC-2Uz7`HgAlqUAm%*{^t%DEJZxYCNzsC-R?mR}>aqrjS(cUd?01oN zN@Jug)7H3GH#f)(lEPqvBYWrCtOAd)8>ZP+kmj#&5hyELZ9LDO!?M|AK6Zq=xx&hn z0x|DWl+zrKuR2gLjf^Q-q$D@El@~L8b-Lzi@;r4fxn;S1e)iGpKldxU@BYe7f6}G0 z_w%7YH(PmJ_}Qg6`1E{b5$w0|<|<;`OSWE>T|`#u_qI+p4>eO{LUEc|^tlkPZ|(p1 zr(gd5@BHyU(|YpL=v*0V5OZ)GFM>XJkrg;C)iHysFi*#3spCS*^`QmyhkagcX>089 zyL}lg6sa|k7NhyU|N6f_8((zWFRyp;vvTn}ai%ic+}%vm3-oKo+vuLKSO3NMSN@~# z{nmf{nH3{1*5*Q&;RP{`rRzA|?7{6!&-psXex~RH`&!{vA5x{ryWqfHJ7<_7rvCD) z_~+BjwC+15lG%}X?+d~Q zin$~bMz90c(5d+a;)K{RuUH1n33Jst!vbW<^HOmYKw5&9>kYYt4(pIucVr3UJ0`-` zsj+2sR4bYfNwn>#yyQ8*Lkf?>(HA8hbk6}QtQN}IOf-nWTCt?seVWh-EU==K%`?1! z3hZb>WV0DI8YlV)g|tnUso9v#3ITW>*%y=#JmB4beRdCcW6}pEtmKDa3=iC2$t*2e z^5qRc(LqS}?w>=W?)}dP-o+9x^x1d-FY=+i_2X>6=DB5^eipzF?Z(w=RZ6+Kx>D&cFRxBcHeH`ALIyK~Ea%wo_coVx=ZY$ohlnWEAZIz3T$(=gx3LfHl7N3Yr>km@z(C4Ld?`?D| z6AF|lxL`%bgW2qWV9So)VkU}NKtXh^dbR@O+J^?h;%yaXf*~bDZG6`EWtlLLhN}Bz z&43`kUf2j3ER>0)a?KW`Ku(|&ZZ?pc8Y}JWPB=`k9r7)(gCd$YfnXQp2 zQ(5}OHRWTel+uxgD%f&WRM45i5e60`12w?eu_omWxm%B&L8=@k}XXs$3sVY&Bp#sg~j3|m5m{W6QC!q#aK-OT|Ts)>bZ5Q1Sys|@4@HUl826$->>0KzP32u`&E+0L^5c`KG2D& z>Yitr0vTym%JNB`Bh8V0l?bYu;nm4lNoxu%mm+LR&1uyN*bp3k`Y)hCZn{Kc0q zx8uk-J?rxNOgQt?mtB0dx=m%@O}JjYn9c4t$} ztND6W##R&ffUNk6%wQl_%@< z>1O=n5304#$7*h_I#_dRgY{Fty`Usj5+ph zb^C8avldGYmh9*2m9Ow+eiMB4?9=ht=l!FPJG|}BPx^9V+x-*~&xf;th8b_KpH8;D znx_8d?N2{>xxLu=(@i?Cnf}zTMkfm*k%{W%E5!zOYSx)L$WW*Z1W@XLxxIsTtw~0O zQp8dCMrp$$w2&#jZz8-aEAOH?nq=^hm|H#QtxmIY)Q-G^#|b>{Ku6W<)dE@uSjb>5 zv<`HE30`19&+sD4V3>_k05h2BBQSz9EmM29QZ?&VOMXi&1o6YnuMcXGA1IW&4^%Zj zq@^yUJYXUmF7Bt!#eTU_5B!vnloan5(2|(OdkbqdtZX?LXckd?f7F1~f&o!69qTvl z`W)qWy}09DS|s=ln6gTlFS5OubsF4cOLM;IQwcB^Pd<3>snfb2Jk2L3Lz&iPwK+ZG z6l0l&fgy!*Bnv8!C9j8JOVhOJx-?B0W~np9_U7{P+2b@-?P!GiY!Wrol7W%aAv0wG zlY!)|_kxj5b{)I}0uI^@b^#L^rb3GvAEkFc0kg7yth73_+rv;lir{mDQK(_ zWSQP&O#msPJ*;-5p47&oA-lp=h-^aAOavpK;>u8A1QA_XfdSOq`&^d^p(s+#%?83N zx3ZphO{&E=QIq~!Q?jI%oEF60D+i=N!;BWkZHJk-AuM;Vdv*iYkFW}!=F%1Q3g2`$ zQ(#|gE8n4;&`;J0) zi+fM8O*73FP<(j6=>s?Ln!9&;t;_A4m&r^t@WtWzbc;8yEw0t4JlBv>nu7yjb?Ou$ z-w0uv+q{kzFcHO~mu~_a?B;#1$&~C^;QPz1Vu4QPSD+9 zYv8hmTh*JJCRAT()RT3n88br)s+6kG03<6Yu{5PDuMRMfdg`mPja`Pn}af0nNY}MUr zwc{|E?}t3)0fk*mE6xLXn)a)7^I86t9ScvsTEETDV|@E@ezYID?Tq!?&IhISsEZff zm_D-M($D8xolTeXb?%2}b4 zcH3+7>;4RYnfrWGN*S$__oukJ9zU_|khZUc?$hqgHobZCE8qLh?(OSxweI|nu=)M+ z_KS4;o$lm{pY2k)ldIPrB;C4`cmRI#p?@-KK+;_=tBRYC6@teOw{x_&ICgYj+Kmndnq6x zL+rN1NMUsb;5@Hc)Y-i6d{1WH7UP)ug3iGN^^{bgEQJBm`HLRc#K+qo{?fDbt<&>Y zWxxCBPjB!DbFq+fBX)oAlk)T1+gDqSd_7(1DzEwrH7Z4R|TN$zu z)fuG&jFLy9omw7P+g~h*y1*{h(nH-`jX#GV;d!x<)p2;0h8pFSQW~@{3lQ|6<#5r( zB&MiN8#-V&@84|4SK1u8k ze!aurlH7Sz`0DV19~IEYAB58V1@r)FK$XAYZyrX9RV>@7vA%Vvp{vRMYo&aHy+>Q#|lo`k{tJ2sk zAOtg*WGxgJwJ#d2OI=In`u)x8UDS-rcqeM^p01%JWiv!%v!wP5g(s0SS!4w)-VK4I zu+Mlpi(_D0u+6b8WiRC5Eg2QjQ)k|+oH+DLAxqtPNCC`?+no#ar8=2!`|hC;&tdU8 z&i?QRXfp?H^w*IE4{VKNbPs8~qR}~;p(mF6nM{T-&}t;k?G6MTY?@JVT= zXR(N>jHa%`iZ-m!oe`%z+u-7YdmC06OVKmF+9+bh4Ijb3)zXU^`$dG**L@B%650kcV(OGF{e%k7$T>0&Z=9NfAz z8E?t%fBUaqrPJMZKFe3<*FPxx8?B$svLAf0-MoH&_T#fNe{r^7uYNMdF2P{t z^o|4FRZk;%+Oki$jYLoVYFd}<+qZAd-u~ndy7=*W^U2jo**<;w^x68&A8z)#{IzF1 zNSl^f?(zBjU;d9Dx-(0Dibj8Guiu?13!;*M@h_sa<6IN+@ZM2Tb+tF1C>?khOWpB zdvyWGEQS03 z$?{F8d-CSVN9#wQPs7DnxZf%D4=)9FjMuGx2KG^UXs{|#sz++M>hKl}Axf=<1FlE4~j~PUGQ=T@c*GjRsH${X{1qJ z=NK>&rbx~Q_B#RaA|sOM3a`(EHhgDi*u z3R@snGGFOEZZiQ}K;lciyCk(L@Ln=x)xy84v0M0mQ4YoT@=Yo*i9c+ zZA$olA(G@Y3t9(rcgmcWx=w)8lObf_;2gfa~z(r$8=s@+$ zoZOWSZYr%T&I__YMX2bvEXhSglX+03QErx>?mT4DEz#61B?O0XzIHuEAuXcT(13x= zlywZy$vwE0^==*633e7a;931%!!D2l}THjIm`+HY%1Ksm}Y~22#4ex;y^HA=}@uMy{joAcaaz#=yg(Fc& z904;Jz>b!Qnq@s|Y~Q3|Wm})L&-2=FLT;>Vn0rPK7^36s4HOcBP4Fycu#45KvJwYj z>&U^v3dgA!loGH|HRGbxB*?0CGS={b>Swz#6*UhcEk!Hz;jF8~kv5vm15n>VJ0!R? zz0QYmM)jcq6AzhDT0|`X&VnyD;I?8_jDT6FlWGCoYuH#lj4L=x-pLH;Vhx1Vv~sy2 zNwYzD0e-L|N9BkDAVpnli&WGQLnKfd@0@KFJIGWT;k8}q%WSs=t1mlxEw=wZ+TQI+ zk|aCt`@VDBBO){F+P9hMo!!L(y9*E^uA)E!Fq%m(e4r68G}DVrrayrHm>%>ZnJy+X zQ4%SGK?ac`ge8C_7TD`tx@V@Zb;-;KcRz;@?va^QT{X+0t=h)gx~qDsDl;P7kDv2> zzmL1ygN^-u(1+d)$(rYBSMaI02!kV<2lvj=!MnA04xJDt#w}w(bWlW&a}atI41$xe zK9}n=*(_<{pVK;9>ilk< z;V&lWn62^1Lo4ll)iVGU0*aC=yDHF>BErsEPeM>SFgm(o>i*|{btSO#WmHNUMYUhi zms;Q#t1d3$q7UR~{ZUx0!X|A_Iqr^KSwfyiIw6=rM##vp^*BN&pcoeF%F?q87#G|Q zJ_X+f*stfm$t5p`<#_(`pMUo9Uw-sOIyzcy;&UV^4);<@b}9W5ixXKaKY4#xU^qU0 zeEhXu%bE18}5q&XjPeCX5+}I(Kv^rOnT(W;y}_p@9^wZDx{Q zqCpBnmXH~V*xI===;+DT;Z?f5Y^>(3Rt)up?bA-r;{pQ`*(UJ~&&$g?`d4M_G^+??9 z@GIOHdEe8?qYG8VC?N==6_QbfF;@|>=JzUx-j4kVzPXs)+=X?#E(QtSIbjfI zktRPP+)6vTm5LDAU4z38#NqVcj8=(Oa~49~6YYR+zbAIp(zSs~>TP{s+9E=YyaNIm z9H7?|p4OzbCSa=L>#B_|E#m`5uOPqbEH3VaUfeS)T5<;*M*-Td570$->%z`DdiVy; zb!?M#TP~zowf0ItP%==cd8>>;7EzZy`vv1DnvB9laow7arW*^BGf|4uCD(I^IbCLm zPm6-vD%aLLwsblKs%0halTX7c_p*v9!GQ=oH znUm`lHhSE`%-g6-v@~TNy||de48<+Gxv)M0RXv>NPM5i5#{}eh^miDc4S{@MFK&Ns z?$lixOY0LUzQn|Q$H%{FhU~p=?skGLRf)diOnX-sl1dyZR=GBET{?qz2ptgJN2>4s`YXwT-{5q>vlb;dpY=d!i=D<4Q#2)vLm#r&f(dx`af6kZ}nt2d-(o?lj|q% zFS>ZNS}m8$uvmq~iLOqhU;3kylQ=|)IrigHUXR5mqr`i?XNDRV8z8WvMimM06|D2J zA{QtNcn1rBSXESc9WSHd;dIB9tWPTD=o0~2$Qt3sf>wm#04Ogle$@)AOrMo~Gm`v0vokCPN|t9&J3x<+oCAV)HNq#vT^ImekXRT6ujEexpVX{ z^QCeWgGf7Zh#kn{4^X+Yq7(#8c2z4tnu5ZjZULq&Dntb6E$t**!CBr4NIFO<4EJ56>w9a=y zaW?NQ(Y~w$?T3H9L9u%W?{$xaqu5u&=uAO&&*zMi6rUZ4*$~AI2xi)Jsa4Ec&nNp- zdBRLcC<&TJX>Yg*hgl=Le48GTg)!B%c zYjKvQ@!=LkU8)QjG)EQ!58oPG-U%?T*C=F#*WJtLD$OCxjPL1)?T`OBcqWL44j`kR$J;JxI=cGBR20ZYyZS+c}{5)>{{fp zqf|<`u!fG+sClO{1Sq8!L|2W7g4ju*vt(7FP({2~3+ksSgt%R3I?}7N@YA#SuTS$Q zVzMmnalD{U;1`Q{`S9UtTJ#UU`S_3i>3_56y9mkSb~%IqfBW`L2yeRd(~K;FE)?3e z`c~6sb9wpS{cqEYx9jI`Hg7g%OjvJo8po0*TO5Zd?>`=&p6Gi=-SP3FW47(~lWC>v z?KZtYx;zf$gYyU9U4Hb-(~rL%zjv+W`03xSO5o~29{TqmABTl6;uawS9Wuw_7n5CX z#_RR=0xP_hR_n*#F+;Pd|_k{>kZ&pIzGj zWDB>ubd0|U_4DEVSxe`cszJH!Xg}EE4TRNBVRQyB!6EcMyeW9&{4^rp_=bBzz zT)n#9Y?HjX);A+A^N8pJ>FY5~{Wjg5!~2A7Qh?W`Qvxe{l7~ zh_u3V zoMnVLNGVimmNXn{^#uib!w}WEL#fius;Z;jIUF$PJ|p6QSlUCqN=IuJ8}@Cu`f(F= zicwtXkWC!SnWz)vh8!6))xdS_k5JOg&`5NLEaqfc5me-^HC|CYnpr(S%WQY=oI)2^ z)d5C&Bj7Q@=4+ z(g8IR);K3g&*C=Ls1ZR4D1n9UQu!OT$?PU9^$&nqRlM#AEi?aHq)y*k?%8aEFyB#Q zi(7qBa-$rWhe`0NbD@ECk#dq2oiz86?(hs5Rii>qO^lc%tSoG_ z8?B5c#rc*rcy>*|NY?KsB;L%2UJ<6XQDKbq1?*VzQtU}cou*#KPBw~> zZ5AntjnLIgZAcph)I!m)acGe~F}f%z6=Ii4aig^YT8wHgP8RKoxq(R}xo6i(9*r(Z zm|QlLYnRb{w31w|L}gAo)Ooo)i~+|Co6s*UIP$&k^L>T&R~?bdU2SQ^3Noxir>Z6g zNsdARt|@Bj-cQaBF%Z2wVU-5|Ut0|d>S&8cHj4hbmg%p`Z90Zpn;lU|DV5N-Im}L=&l2JrO#0a4s z0of%8CI^rP#WGkgSjKD7>z-T|Tex*OO9D2>9*U=pc1OT6B?QOAI6bAuZPrxGHsi%- z-c1t5%d0Pz$BT#MIWimH$}j2LQp)Dd+kf%>i&xj%H|sn}l&+7ep^xaOh&k5{_yeH*M9AH zK8lMk949HS?OB=rY`MAi=`VkrkEY@8tQumhQE2v9z+aFC`o{D|W(Ma0;Q4k3+DyPm z@5tUQI)WM9);yiD`2?iS;gtC2f3bb}Y7Nc(urgmbg2^=Wa`N!?Ds{`ybth+!pBych z$E&A5dTZ0^&EHo#8-SiqW9xfLxu0c4Zw;!HD|Xfc6^xtvSN8p_r4 zt9~25{+-py*U{P4T22d!^VW4U0YGif^LMhX#i-Cfi*I$BBBU!Tv#6w{K zBO$G#cLOR`Ux4BW3033fWwW>XQh!> zO@#-zR%J6x$b|{%0p1f)yaR%`fV~w#EvXsZ13Y;3humF2Pb%{Q+ia{Y5Un0a{6=%+ zOE7u&1-K;S+D)h#0?oV**P`|7)**Y>-dhC5ut!SGySlr}jw9$hF=&|?Tz8&m<6&XP zgTkU=H*WX^4?D`%3ddPv{cZ^2u4i_KNU?+i+!nyeVkJr0w`PazTQA{ zXY`;GV}_fA&iMdPt%h@8Ueg(}cA)Ey?-ZLcfuX|IYWTBP1BV={W)1<{^?J?c%jy!l z`K)pOf7Y9>x-=Oto;nE;tiP-@bY|D2BIJKBK#<8b(B*j^uXcW3$?Q<~j_ z(J2R2yX=sZ=9~?vG>1EK747JN8B#4(OKc88>S|9_fm&ILKa4mIevYl`*y}pr%5Cd3 zH>uw7DuH7qWJ8?_a3BlC+4VZqo`(wPND}J~R|{xIto5`rLnMRAIk_Y+$=xBHp}0)c zjfEA$wQ*aJ+}2gfGLJBuiIA*Yj_lIHe_jD0l&@wl{ECH3*nw9MP$7-aC(T#uZ6&Zk zxssBAWJtuuwU@q=PAOecfdv+Yb&?`1pk~n*sVSaKAzi9_V&E1)y)LNw7i6J{Zf4-~ zoE_O3_KoAhN;9Cf125x#cjR8eC+v2>(B1DO3s<$}q^z4@tSEO4SqV{9QHX%myYDBS zCofUD>?ZJqJnqBO$LD8{PfPdh6TBUU!QHuBV!T2bVLvVF*P_QuFOfjz)w*o9_V2!T^*{d4 zKmIrC(=w%$O3uZNWQ?JYF@EQR&0F~z-r{6+_Q}`2{rthNF$PTdy=#2$VYt?>Z@ORp zKaPI&m&<48+aaEecLDftl!LtG#5Cs8zQx-v> zjtK9|X7H&mDSCeYw-%452PZ2zT`gAHopiG3#-nBK9z8i4dt@mwpB{r(7trr*wtpUM zTP3`O;*c%5h63@zmo=1C;7X^Knq)fRm~bLTSU?KQDp2^=`+hh&;<8wdn1)oQ?Q=aTc4Yrl1u7rA=r2+a<>*OG5UV^SqVG>;5x)g)yQn5f3G8N z*V<98^5ra2OX};eaKdN>HGdf9R{7(*mmbJa`2Yv@Dz+f1Ce9C}xCy-j11u7O5c-Nx zNI>Z-+0#9`6NoS+1ujk{)Z5#l_u%cMfvorFw!__bS32&Rdg|rA75biKzE0Fj>&#fy z!xp!;`zwWjN%aIEsNRqS?6;oT)xL|ysjV_H+|mBrY2e@4XspI)wb9{T18qfj)tv8N zq~X>ZG1s8CHoU!wutW{nWK!*gg>j+XDt5~pGm5!IYNuS9y6Ds``WOb4aD4g@7~j0U z=vQ&k_uGvR!_viJ$(<^(?-xFKF{*U#P6dgAA^_1j6m9gWAiRymZ(PdC7T5{@i_iJ< zb*!-$F%`JfXQ*Cu2c4yf3TshHqqiXNdP5&prQWFB<~4|k1{dMn;+8#vO%BRv^<3d_ z6tDJ2X-ND;2T|0sx+xmQ&R7T&7|q2qtAxWXQ^aq`exx#h1r?Zvn`QJtgvMM+*GlMs z7tR|7I{~V&+(Cge-wS#9eFK_Zh2=mLm>IOLKOX>T7mrfPxm33zb!{4#x}~j-rHnSA zByXsz3DQBLQYq1b0D&cX=~*HyxQlr3j8=*}Q5u)sOY~*K?Xj4RL=j|%0WZMPhJ|(d zRPBDX%`CHDf2W|U2mZDuHx)MkQN6Q(Ht*Viijh(w1VRzlA~Y33E2zkwi7Z{3L{uOd z8sH106~~CFAj3B`xyB@wxHTm0d@~N+La(RXt-399H@y1R)Af7d#m7JV^SsUKn65`s zC$o6G{FPsMTDs2+nnp3e7*%_Q)2WNU|I4pN@20TSMSpx09vtc8W1g;L=r~351^cKN zCu}Z_FGr-IIFd}GcJk=O^&~@tgz)Im=_^?5N(QG*>Qi@eEJ0Ix{5bUe!XBK(51zy) z59Q$*ADo8MqxehbXFt3CPyV0({oh`6r$73GfBb`|znd@DE0G^ArCh8ZKiK|ueD;T* zo&DzO>aUh(`8B9K^vxekGJi4LTppCsG7FCAI|=gbGFk;np;g_pN1`Jm`H%6(QOh8k zB`#O~W@Q&gSog>e|8SB0L4O>;IBh8vMz45|HwdRWFJ22Tg;vU{Y_n+Md2P8WSgWym zLoSp%Lwu&yo!E%8^cFyFiKjA&qJr4i8CEfzxi2jDp(sr|U6lmFi~=j!3LPC|O)*j&==)3qR_-$w?hD$(v+7v?+L9z7-Xdv2)tY!)@MZ49 zQ}?>(8$Uw9Jz8YkEiDjdMG-W7m3uXlQF!1N+vDr|URCq0wa94#=&`EuqSxO4|iz+G4F~4W>0& z0bXhYa>kscI-O`_jrs5sEgc9Myyfgw@ZP&!I)&SW=2I&(Xcq3(WH5u3y++3e05t&O z)~Zd?bFKpy)^V{n1Zg-(WVFgMEA_*v!pyK4*+g|cbUB?v+Xq09l zUTX{}(Z+>s7TET->5+q#X`wV{DQ=m_Bo6+pKbLjjwNcK zEylbYy8uIYwTO!{*|Pt_)7N8J_3`@Ut7zTp2jTSN%PSAz!Glw5lW^gyfK|3>Pz7Ty z#fP|JE@kuihbQG5|LA;A5JBVRx_d6p$uau4e;#{5zpnRo$8p@AM0%dw9TV1Fj_cqW z{J1|-Vq_WLeES=5^LG1(zZ(AQfAWY&SBQ__ygKPOVX=Mt;`QJC>~H?!gYZ%~aBX32 zeOPrHOvG_mc>3hykN#G!Pu?uki>1f}6}uq`n>`p`HE}S6&$s1)+Ts`qSYM-CW1)f$ zFS>Pzwpt&B=Zp2G^HV=sUZM-=9LqAU^7V;rj?1RcYv%Fviyt4YHedTdqFp?QVU^OV zY@?6GUn>-)B~6Hk({sreDqy_2F!%9b9qVHl*6zS&Sy$rj$jLy4Vuzi$-F!9U+UMz` zxVFe1!`rwKQE6(#7MH8!Njmy0ey)BTdb?(MQ_4BtzZC0xo8L^TR@7Rqg5Y7<0mvoC z4#o1!DV6)4YdWGcI%74xIfA1iiKIeRJv5oNW8zd_OARI7jT8oC!0QBwbXK$j;ALoA zEKyU}>I!q5i%U~KHg^-NXNDOplthl;L>AB>ucGbb&P7nXey15s%o|osqj$NmLV+Dx z!&~Y+lfm8H3h0hvVl|g;Wm;YT!7Vt&C4l1Sm<0^5j@H3@n!**n)GP!W4;KM0UQtAw zS%5O{r0qVR=22?1@zr-QHNghwG2=W+F>9+aZ}hOV$YI^MTUS%OThWk9#2irXN}tPM zv#_&@1US7!0I;y{_}<(u?$=K3e~z2cU-xKp?FNKymswRGidL93A|m%3y~7^lmo5;h z>YjG3^im2Cx=t*k<`NdG!&164XGA^i`@WC58jdwAlC9xqDFgHvv=2+hlVNqzFVDK+ zLCB+*OlnBE>w}lcF-kW`>=+hqcH6dGWz+7BGU3>{!fFrM0Z?1=r~_o!8`^IO-ggN- zx0(U7Ha#0_sP8@$s-9UJMhXN)W(r5O$+xuX#+fP#I!)lUjBb(7UfRUg4D~qJI+xZ6 zhIDZ=+AKo4r?A*-xNo4rtsR!yHJ>rG@S7&lSwW84SGLMv+~wKPrQE|Kt3(mbIyKU2 zyT1bU0I#S?Pn>--wT@7ag(b8mPgsfvHzNvyJEuA-Xx)(Zel}At_2C zNAu)fVA+w~3%vMzhaAQz9z6B#?jmAlH!n@{8|urpjJO$uu;h$1Cp^$yLeGtxD1x?# ztx%L|Jb{mHV%)$I=|ZO_0IPOWmAMO3*SN z9Iu|fmqF{c(#tsFB40ch-<+Ksr<9!HnzKMelZt9c<9KTeYe6#--ZkyDmFF(`sff_@ zQ2IzxRZqI(2j_tg9>0B_|M=g2^p}5g?d!Zq)2IHURJPwf?ex)uxI95{Pa9{rKEB*S z-rv4&kN^IE`@6sO(Ejw>&(|lXU-0UDH&O9Q*XNgMH}9LYT;pqSXn}iF4ZWDkBn)Sl zkG>f2`WTOj|L327@y*vS&b$=jboxOrw)Al^T@K@$Wx6_&w2J)xPp+SSzdMRx5qCXzZJ4<&K*lKnQUsHfgOQGZ7#1L#5Q)vWA+p zX=F&TlW?6lZC3rb!n)7Lh*yQH10Vg3$>3LddUckBJ6VXVaBF$of(9p^I0t-?6nRIF zT5li)OyEIOtMv#qH)=NZ?$AO6fNeBVYd%y1+B%(>3JRrwBRml!n8C`ntXq8%7zBcv zy;}$0^>*DcqX?K(&%^u%HGxE(2N$IszT^CI8*zHI@s2osumMjaJOvEzeT6RPPY2y#4;T$)AuMzT)L?rbr zNMN^=+>RHEbDiR2ni4hO4AB4%*=N~_~{=q-{SHs_5eD?pIeJiKOWZ}M3xIgddebS?Q z?zTrc!&p=|;!`(JG#aGf>J(q}n7X%LzxeU*z5f4x@A+R0?UcW4T-Ubxl)AG{DdCg@%YMDVv~||mqMa+%N1SbPn?<1R9lRsM9J{)tRf^Y4oihdL z?C8S!Z>$3XJ+uwJjpA!?AX~=N%-cSU!1M#_NR18O&n0Tds3Cg2I?yU}+V+vZGn=b+ z@8r(MBh$V_!q-T)`-+00<#KqHKsUV`EwFaS=Y-u_Lx0K6;CHp351)|RCr-KDD))n6 zWB-9@O{!BwT}y0AEjS8pTW64orGWGP`Q zL5heOlQD~$1ee}joGzhrF&E8ZfSV3QIv<7>`7l5Hb0TA`b)&gsW?d5yo9d`kn#{uK z5ZIuz=Z(9EyFQ!c4q-Y_sO~gDa5tZkH&xr}<`9Ds+N`Aejls;u1uD9#EqXr_vm zhyVZ}07*naR3H?uo>ePzeOl?xMsv^#W*{l&(GVQ>b4h1oLluI%JIyno#l-LWbzdK4 zAMD+-h2@s!;nuxT`w)%FB>S~kLyZ&n;*+ogLE5Z6P{M@K=>gGE3{-bz5bN6OWFRE5 z*_=6dD}5G1m3ua}aF1E7IBs>k4n0G+dNyCOpj$(XnGy<*?onM0D?tEz!IJq1dBxH* z2YAiLF7zZwjvCJ8lwKzl^pbncJ;#7+wJkiEj}_zLZil2D7rx`w^Eoxhd2ljrQs8#f(%T0(#X5|3pfdvxWy28|Xj!3=41SR9va3Ol(cni6ttR15xl*)Ti_qw0$ zB8!?;bw@_8-38&{Nv3H_-S4Gs@E7AP{5f^?yB)Z8uqJAW@3RW4JLscxW~-C9>ZQ(< zgX79#aId4)D;<;`G4)Ifq$A{o=LqYhx)>*N44jBjk$~JYIK)MX01}KwfwN#m7NJ9` zzb4QH9+V(m#Uo2#Qt^NcnqUKFx8z=X+Yl%qzy$Vi6|koTPaTtCy&2Pj-f?7JzyAE$ zpMCb@&o8epCqDZLHrwq_KYeqtJ+rj@jSr6={CfP(2M@|?S#{@&;cT@?n8sJHuaZ)I zfL{dRpuxN+z=$pCOs4GT<*VS01%@-Khz z>eFYd@c3cq#**|b5)$%sHN71%qGw3#T!%%$n<0-z+YXVo7hK!DFVByHfZKX^2cd`sT8S^Jvn zE$A>v2RMYNVbpcM6u3j@sT`qmL0N7VmChTh*=`)J$N?US0T_Uuh>ieR)PmAc2cB$^ zw-7JlP`J7WlmM66j@PQb#<{MIjXhP&>_%Cbxl=HBUG=OY=V!~Lfxe43+ZD= zW!_zXzT5GdZ_9&01*!8@2y^2Z4r%S@D(9HJhdu|<`OmW{+({2Otg3HmHf}vd@2*ok zFvIx)3FO9K?ZF@8uP>5g z%GQ@$%%+^DDH|n7P%@VsP1KFK`u{XAL`ZPy9A;*iSJ8PE7y-D}lU(F{cv6evCWNwx zmw-~!_=Z}K?yni6U}Ow`nDC74_%j6i3K_K@?tSfY`p=w7C!6qI*#di(Y2J z90cYjEoG%LIht+1Ngb;Db}pR-@cXp6KI>m=V2W9;w|G8~beP#;R_!f(Vf)`HsE}>n zwV&&g#yhHw`N5ctO^5WK8Fp$kEd)rfn8SLMM7xQMR6>Xn5F@yBEr_)&7iY!#RCuo+ z)X;LDS>Zkj2kw?a+09Pm{(-u;RP*YO7MAEf&^z;veoP7U9(l>KWLhBgHU*R;0{Tk1aPY>_%{V(+B`)Fu0pZHg{q&(p?gCwWKrD+33z5{iz$vf~%tY?(*jVv*;s_4z@_I;xSP+xiPOD{)ZiN<@15;#C zq?$Y+NRDDMx=r0?=(d${h0 zF!VXw6)Zj&lMkmW$ksxS*f|WnDle87$#I^K->g3TlVASMucnvZctKfibR2f$b>BIy8M|~@-#l!e*SP;_tvf6{NETC{dBy2eS!QoF47h%+xXzoaCI@} zl24Ap(eXl9%zApcd?imU9F>By-m1E0r%h=c_<%Qm;UE{{mZ1fJAnc7j2bNV;xpO@a zEvJH|l#*+j1VzwQ*O^qQUT~Vb6d;T*#LfmkpR`M9+;Y?FQs*-cc>72!UlD2|t&wB( zQM4L+;4Tu}LApU)OzZiw&T|R%%Bd}pRJZ_LfVxC7(mF`z7T^L=$v4aTdiF(m89o*aR7Y5ljvzubTP9iio)zz2ZUj;NX4e;c=WxPaeKmo$jR+-h8!M_qiHE(^}@u!d0Q40))y3tGKj-8v6dx^F1Bt zcX$0;2Dn?##vNsJ?F8JSdF&DmaW{p-yof-d*#lfOsA$f4+b@>0SzJh(W%B|C=jQTa zowA#cr7T25!q~;W_`;pV#LO&DxonDUVUubU5u=l+EG7*>ZZ21I9&Uv!wvMk*K$k`q zgO*NULJMFZ)N29lp(PiVc0adm-ge*M<{QEzqtQHwEUuifT5S1YLNl-QI?!Fko$O~+jiCylSqJ6!6wotatbTW=HZO(SfqcUp zZcPmEPW+_r>H=*!FS27Qo6g_&wl)!VYYsTyZ}sm20nKG5yeF8mrrXrmXtR3oAPgo5 zk==ltfkIN45Sna*eq(Q=d^PPX?w;6)+Y zNqiKz=*FF)qKGS>pCmb?Em7bb_|~z7O*Ou})Gc5>>C93y*&TRpUoYIY)!rIX`aKi2gOvJe16f@oG$2Ip0y631b{KfJd-+|QC^cUxSCXqZNcC{7G?6KAA~G$(9OmAV zl5F0r>7L;-sVhCRbndo!d->51r;C?%@v6ugBYnzxdTQG)@WI2=hwrV1fBIkk>iZu& z5J7izmPb1pFRuUQV}Ew}{`;Y%@npqse)ELI*4u!SemD+Te3xUmdim;TRdmtg>MgP% z-}3F;tJgw3*T*7Pc4bbsyi7 zdKBo2N+mILnXLRy4{rtCI{qY}s z`frXeZJbixJlopUl`dcT=Cez@9OI_=cfRrD?|$iW}&YqAVWNX=qm)2>93vQ%0L@Ukm02H?hhpq?g z0?**&KGG*>b`*j&>X}m93cWZRopQd0D8y zwR~^pBYO$bQe>-12s5yEzfcl(BSCpz@3jN=ysqx7msJ#Pym8(!N<)wByg)Zhx4U&! zZZ$6Iompe>{GfWCZ&asaj{U%)-@W!2mCd$S&m3VlAGldVCeAHZwX3TK+<*7(uDh=SJ_YGXCyM^#!{obWNCdGVcp$n(cHb z&N~w*Tl!!JlU6UhlTzhL~roh)Vp_ztGk~Ubqc9&o%<5L1Xe%?i#{nWcnK_3fKlKM zlQPMUs<4x|2;CBxV54({jc&z?yL*%L>`DpWJ(zNMvGyXacLt+}l%8F>&|V>J5m14E zg;sC4B0v%ZGPb#ShCswACfESzDNE^=99HyWmbI$56=!nKjuBG8T#+%RbNuN}goN4} z#Vi3lghCp>qKWV;;_dF$g81E^_nQ!Lp9{IecevSr>c(JU??%TiCkb7t&X*b{Dlnk9 znXd%`Rri7zT}<3)3g3opGYPRMTxoPuvWr=eRf@`_VpY+Ih9XUhBtBJMUftu}s&~R2 z;%?@27aDyE?qp%NjHb}M?aDfGd{dsR`enDw@u7Th%}D{|}!2?r)upcsYb3 zES!@~4~4dOEIT(FJ-biV`mc6o=sE|4HKkk#!D9Ts{`ixhJRg7b`S!9{Q5pw2r{U?E z51*{!@%hum>NqJhZzL^-;Llg-ilWor@~w?CeLP{UUbjA*H5qQNq_Mh=Nfyw$kB3E-ra%zs^?#ybtYa3u(bz{ z&Ra_oHAoL_#6Qr2BN82apb!6^wRdZ>B+0Jx*4o=6;#~4pRehbF?wR4t00c+^AVpFa z$^;_?lO82An%?!N^aG?PJ?cqsGMGtblu@K80tAKt3>;XufKr{YVbsX~sl8*4B%D zV=@1wZ=LlC^Fy0>DW*w!<3NWUbH$pfGCllw@<@|RM-h^aV^{vFb>2?zmeYQ-*|&Di zmcFC@TCvgV74vJvkLEnpQFc^6aVIm~*?ETv^E^u$hQYiGWdZcsln(-_r^3Gc?66v` zR;%^>&4u;*t{a_?#{J9QdowdA${cw#%t%5hu)?JjHUMxykG};^uqZ z{7^J&L1Q4Ov;<|>x2L+`^8&l5uUJ{Oq9xbo8;6!fTUHV%7RaKFIF>1NOY8$#g|=3$ ztWCU8H6jwSgJEJI8FR&LP$9Y$L{hzLS)@XEQFZVU$3wQN+`-@chAv@6bRkp|j4BkR z-CqQ){mXSxSbo3aiaqt)sYQPuHFmESE4*T^#`r`d0_|NY8>?6sDd-Z05|V*w3Nawq|v)B!!P0u+<6a*&Fu zPaQ16Iu}V^v7xVQY=ta9sbb)00voT|(1kH%#{$}nCr(hk=Dzx74V_uOO#%%vfe|&a zu9|SAqA1-!7>{CQ2AF9=94K_OPQ?i`cHQPI>=HgpbKoEyq)}yp2XyNlPAGLp6XDZ% z80h>8b=hBU7W|vZwfKe?md8%a!cn4HMhpSqBB!G;x&roFfpt`>EHOa!iC;v(D8i`$ z?4d5u6`T6njdoW1^)ZvMpM@~WXdSB#Qbg$x#$wE7IbpWetF|1ZfgxH0j|(0_VPZr4 zkjq*aVwXF~B2VawN{&1_W4*F3=G)aU%p4CfKHu$j`#f|P=Yz0)cXaLbvRifCs=vEm z{oDV0^X0$i&$hQdoIStK)4UsRH?Swy%<~^TKhKkK z{ffjWUKtP{?~79BWAVUEu8Ki3F<3#S$6CO4eyz;!rLu|LwRU6bbJsC3$jzZjmYI(jJ4q$p^g#0>!vIi|DeHUD*~7u+2p1>0 zJ4_K#O3d?of4?8c@o+dyWB#lC`-eI2_VevszP+Dr@AKXLxF4t87(Xwm{Osk&|LEiN zv5(*HhTCrF*O<$%j$T0|GgtKB0IpfqCCM3@i`ReRAWR$O*TR@JkCMwr2XM9bi+L}@=!2`H!*mLgA!sajw= z={7$f!@xwkB8iD0uo8^*06@8tJsW zXra>_ST6FwpkaY`0m`Sj<<+eY1CZ^N4v0>Q^4CLf+eai=(P1nr1W3&OsU_|i^z&i~*OvtFkSoCGtn zMNhx}Qw~$!*j2ITS=+S_13!Fv^T+3DknhdpWGOPxnC4JSm^L@JySdjR3)vPsjyBw0-Sa(PsBV``_TqtR6spdD5r{|&=g293&_Sy z&*03i2%`1YJdTLSn4!{Q9U>id()HA84K9*vL)}P|j4TKf6eHsrb7f{YJ;m25kwF+~<#glJ31B$SKn z7S@SUOWLEG%(Af)ifS}A z!cmhEN`%$Z;E^o0v_!h&0m%TOsQFyp#ErJMt+jo%<0>mBmpj1bU@LIE)bz1 zhVXUvwbDv3M((EDp&)M)V#B=l!-Y*}me-tn>Qc9CA!PtEYaj_pULQlXYB+GA1L*Ss zwdGY?O$_5~jB$1>05X*s^=b^|ei-KKT)Hpjcama%w?CV2ruF&kFUCGaI-q-e-hb!A z?O%NVlX&m!$@hQpzpPj1Wgb~xuGjqhmY;t8^FPV!ukJp1@#Qm1GV6!cJ8SPZ<8?Q3 z>e-!toKuQ^-eSKgXUu)EL-NQ`x_*`Om~&naE95|lDK=(C)3S_|k_#YTKbj7^&X6oZ zv%43?e%x*571FL>4>9(Z-W$ernXbp-%NL(L{U`tQpZ@Mg|D<&9touRh&F41!GGjku zLrlah5W2_;fAm7yjNPs;x9gkk7tj8a`Cq;}$Lm&88ie7JO3+hOh@m zQ?AU1vH#_VoIg5y|5+!!hnZNj~@M^)}}W zCDP|PcWLNSceTA!u*i%nGUe>!n5Qw{<#8(5XWkyli`{&^iZAE$D&pI+{! z>-}^$#$k>e8fO+LGpXyay6Df&`pwqQR=;?%9k$!Y|LuG8haYazeD<<0E5D0aYmQpa z0D=`Z7)B+DG*lE@1xHemE3Ch&bgWceFLo&^B-9iM?4;@!+|+ae$&nqAYN1K2vJC88 zgP~*eREN6AmO2GnlnLH~ieg3!MPZ}%)rRz>qxwv!oLljg2tyaUo z0KvQ+z*^!RWmR@w`Gjw0nt4l;&6}D-?rwG4JuzBDL^q@|&()@8?p39pb9QdJZYX8k z9}cBE_nywqHQelh_R4^-=B*uvewBB-cqWW3L~xP+AA@sL zga8UqBEpe{CwB(3Kq^+cy8ls-iXAn_?YfC$utL4H<+age?Z$2zibWy8083f^mQYOf=c_iI6_Uw- z@cF2Ph?Ajzr(x za~Gwolf?4&^@=!bka(GnvNVBSV1Z5vWp|e}2WS|FRp8Oa^L8fBfBEi^Ho>Pi`Q^=5 z^WzQv-j5!=ceeT2&woBnU*>VPxa+#I_e*2iZr5kb9;NR~PjtB5q`uqC!;l~OaI@dv z#PmT2=Dg2^MCtsD=kqwu=rW58Q??k3)3km%WkzxLEn*P1o>tS8&-2&Gg`r0f#g%$r zZO_h`xsHeey&UhS7rUF=_}Q4_;>rB1bZ76Zubx~VhNpM?aX){V&Yx)=J%a6b6Ptk` z?k~r~{c5<4rzw8_onIeb{Q2YZX-Pk3S$*sKJNRAgWEE1dOj8rr`2)Ja4Cw3U#eVqb zU;STqKe-<-!PIF!++vzKZR3;8$RG7~=l(~3cEjg~&73zEcb`Xhv-2|NNBwZQT_=R1 zOEh`;;B2*(=G{1yvf8Y&xx(i(npsLKFa?aB=$(6)@@_6MPqO49?a_qMh7J|!G?!|1)xP6BNb%8P#ci~ z6w%H?bzOa6SV(Qq18}bBEvkTp%ypL9aLa8cCBabT+#i!jt=4<0Ov zOtylKboZgZy1aPYM+bZ1-P%%$DN44!8yuGBkhJRiVbv#ND0jWPbvf6;#2kTAe@Ug5 ze?~SjdsNaCkM}@(QEGEC15uP+QK3mh;W7clF+FmrZ1jc<_s)IER3}dOcL}9xB4ji| zRKOipEChBHfkTjCv=EUxs4Nn@PRp=2W^2NfRwp##Op3V;L=+6M852DSha`* zyY}2eOLBb`v@GpRJ%Cmu*lhQv+J?6zgs)al?+IP&#DmXqvD|(2QdHuAOJ~3 zK~#ekrBRlWE$XdN!=q%j%x?TOY56zh7xmn%W!`U~u~Nlt14_)G87GF|4M7yb36$gb z1G|Gseok14|3AeJJ!_s|fu~-U-vgeD#~k=V33=^h#*QJsjL_s z^_^}vBy2rzx_N8kiu+D`M{&Df+zU}F>7_T37W)^L&K-^#vSS3WnlRdu2t@r=8h6}9 zx9;OnyE#wVcZ#vh>;1l)r^9)7eZG3UdDQLFY9D@ccW=|Pum0+%UH@pFbhf!X8?K1M zJ-3(V_p7n%ro(zYfB%E?56-p&?CNU$+0}kHn?n$M3@^Pw1Q-*@4|dw0v!hhLD9^AmQ2V&MZMJLdgnR z^0Z17V*k+K1ecLu9P2;&k~BhckQXUK3K>cgo$i4R1R)_@N>EL%HpCX;U{%d^fY(MP zH~_TT$P81siXo^FRAs>dQC1*B_1B(yvE!%-o*$^h2wE%&u(c>GgvbnKKv3{#5^6%? zsAXt0WQGyZQow4hE*VT=f(xl;oiMwY>aJa-3&%F%@wR`kH7|{)%H>1rz^aKIteC!8 zJs&4*i%xyWooEj}+C(>rwG~%O7AvTj)nn#styJ4Bk`|1O@dORFEZDZ>)hvmR z;cBsmtv^>q=?v&W*4I|V&kjrS;}3X&8BgTVyp92 z-fMrqyWicD@2pmR*L&J4rR0`?91$U!FZyOrjpESQiSe0HlVkU>zgCc0A@UL#KJeE$_S5u?tCq zN_BK7wTn$ng zv9CaV7M@TzUIS`IoUYmrrPUiMqx2@)!<+64YwZdE3R8GUrRJ8aMm5!wUFAlFSn5*` zs!qlNFmhg^W*5zl5iVE>3WWh6weMAkj8`?>54Wd%J1wUsM4B1J>Z4e$^Yn^e6zx6e zimRTDmFP)P)z^%000o7XL)o;L!f;p5&omlS`&xm;;kaWSjgtW8R%%W_7yuQx!Prpoq z!??aY!+l!iF(Z2B21 zr*{z;=W@AP0XA&U`}K#z+2eG+-Cp#YC+}~+zn;%N{yL|d*~YXQyL3&zZxzf#ePE&y z4y=iSc~|E7_HcH1N{xr%!*!y~Z!jO%zM5b{V$0AWWZm3yR#C*tssuo;O1C*+;1s&K zJ=`3oyZyv_$JL7+hA-}JcXuy-@bNp}d;hT?_BT8AxL3jqe)|08*{*!?;(j*^Y4~i{ z{dBVL-XP1bZ@4?`_q#k!<>$9~n(|>k=VFR(nq$A44~O}uK0JQ%j`fdi*rv^8y4<3U7ClgFQ{?Q^#}@C;-dgf6cW*q zMi|0?HA?+C4qDX;gMhr*(ZUr(u_#0^l%Zg${m)QP4R~C&2S?;f@Ob!d04yyf@)6o4 z))Ksyn-wXghX&Zmf|0S7jvxPW@u*d4V*r7eZ3gR1`tE!dGf zom~D`xp!Uf^Bm4Zcc_fx{;D3BZNM`knyj-7!hLFJ}1l*$3GwOU|!#WLc zHvR`CPVtyC0?NoD)=^&ZIy8tfk~COA4jQetimUlg52p|wTl%IGt!GQ~Jf4#3F}(`y zgXD;)MN>3Ao|TrxSYwS8>`plh3O}U>#7QCekmh(oqS@8VdXg%e450FLM-DlAGUo7}>e6NT57vNZs610YWI zE>}K!{9+Co#i}kskty3T9jWg*lazF@rVmv~1=K6|+PJ(WQ1Evc&65xl&@+v0tH| zxfuG*fHg!y)N3kq3OJbwFz zZi-3tBJ-4nt~VUIc^tr1k&zwybK&l5{_8)Cm(LD)JUm}tJ^yO@{OOnX^EmA;|K9gj z-+dQ9y5NiabQ)K^C#X;6E*i8Rx|e&hvrZZ??GH~)Q@`1Sz3iqB=KIM#!5>e?NmGn- zR^0x)-%a!NH1B3zUqAo)+4cSXK{NmSi^s|P>zn;y(v-P7gmEz6ynA&smbja}Tfg(Y z@BjGYAFduhdenP*bXK~4wK{*CHdn*hm8~{Yfv;BkT*kD0KHGIJb7BtMSUH$?4P67O z1zwr};pO?B`|Xpdf7<*1`r&WaKy_w5aQ#H-T0Nu-5ragFjOZK}Ji_O_YY zdbrB*?|%8kAO6|Tur!KP(OWk4mH=lpSfBBW@AryGX@*I!O`nkkZ1cDuebZ|_ae(>M?^WXT*zq2~K zoW!)gD0J(&-r#m@r#l5AqZH(TSaGXWnF}#$(@|Eq_ga`5!Z8b_MtYU?m8upYB*~A4 z<7FshgeRDw0_66Bm_R5&4X_XxQZwz<$$MJ-@jb0nN&wZ-I%*)2;<7mb!k`2>K?RMy z=A%1eiKVD|sy6W>WKpb+WPv~g+x^u*RII9vw(*5nPej!x*O#c#3+*w%3Kzv15VQ;h zt$;xjF`YCrPM44w%{?89c6nJhXtg7>BnCzMeqS1QP6pr$>cGFXq7%C&=mHBQSk+i( zv)3L>tB=D@*>lI;|8TNSo<9E8q<~W>U>l>tWKBfr^>h@ArqaY#(860tqW(a;33*hFK&Gaoh3aFi%jMp00JV#2I^tUr$B zAlU>E-|}ovp6p2n8Zt+LnX6P^b5(o>5!Inf1kHtH0uVzzt=34ffUs!kC|g>vAYR7oflI-BcM#n7z8wT8ClzTq-US~}1+1S;&>bKUn;vwCW7 zZ>yjQCNUy*um^_DLq=`8Z`uT^DvtRpwHj}UQG=B_!30pqnVupD-&95o!xa{p*1JNI zt56`aE1Y4f2=K}iFV+-s2`Ke}1C!SrOBF=I(t$Vz5iX^(Y7WJmd0IdpKTln%4d!~M z91G}pbqPL!Sb6ovnzaS6&c_OhRGc8fTrrnoNQT0`^_EQ5Ms>SwEFPmg;dsSqi=ueRD4|*fWvbLdqO^lhojLh&m@voKj{15f zDl1nuZ6HDsRHTJ&;bGkvX5pH`?q2fdmu}t#_lkse`wWnWPz29A~%Q|U& zwmM(0kU5U?`Y-{vFK_a{{nM}i_;Y-|KRmsCVdnYed_T?yk^R}-i2W4jXOGvb?T@t^ z27UPGEG2H%T|cC*v(>u4%a1?(;`uM0@80|5y?^?9|M}V3#d_6`yL)cG%d{GmZVqu9 zoWmwpWZe2{EVzl1`yPFopc&TnEvob=f~@@=C$aP1!dLxSxA~sqYPJ4yWQ<9?sbcO=gA2r58=^#J;11nCtPlj*vul^*Cy* z)ArP)4Zv;X(>s}JWz%v}dvqlbxrj73x5}u|5H!jFhkC(T93*31hsuQ4Ts_o;U>E`x zq73R7J+V@Da%EM+riJ%hEqO?-tZbpX4|EshDylAk5Orc|z+9*IO@_#_ba4bLO{c+t zAIoSo-@Rp^(27|h0IR`3#VmvjHeX$Ev{%}cw$PL2SDMl|m9&J(z$}<4OVxy$TlBBX zYF{XtC-_xz{z*U7np{K-qAXe6aS{`Dvgx-z^NISo#wWMfmsjfMR_I5Yx*iG7GC;*@ z&H2Ve(^8za&w<$X8LkJ)}qlW$;HBx zq;}iZXzg|=sEt@>$;-J|21xsF;UDYG(ZMGd?kUiqu!S-ijp54+Y_ypOz#Iu8Re~aH zgCbguODQm+;pLW-XVWe(w75ttSVEHP>A)HpBh}=>sC-#isGvFZ5MY5ttHoHv#l2el zpAXGuKN+3GgT;)?#Ojnwg|b(B+AfR0On0u@u3rt1AQ7y(ll+1FWT|24=AFQ(bZ+Ls?)~ z@9{9z{yG6U6%V~&J04IZA!m}XFf&+@%}a|s6bv{R&XQ0%xI}|8*faG^D|IV&TUvHw zu|kZ}ff!+vqg0db8%A=@x216KEhQYafy4wPvNx_AJ#a2)2dAbJ)qPSSojZ^L78lpSiBT zzWM5&=XuKK%D3|wVsrk^2bb{Q{jb0O+rRx^L_Zf>t@B6v{NKF%_y1eB|Lg`fO}IF_ zT&)V2i_wfPU*7!I$NHV$c=GW(+-OXz?J%!y{^I_6KW)nA+q3ERx&Hkh?*HHy=PxYX z85aqu7 zZ0(lD&uB37DS;H@`d+Yn`tAlJ$9Efa~0{a}^nNkXuB~FF8h^6|MTkH{l z)Buz?AA78BpOw4v^!nH0FP~g=KV5&)74i*u{hhB8uo5mJZ{x7hIABUqF8QS^oTblY zK<=X?6{kMXizoje_>X=RmL8Sl=Vdx8Wv?OT{eIq_?-Bjgzq)&N*q325Y{fAJSn`NG zch14Oq3^8s*+02>=VG;5onKsatHBaC=bMz$i}yaVuE#LMu!+?gs}JuN|$ZM-FidB70_EM$nNL`POBTOLB4kRUro_^DL3@fD)V!PZk|_+A)sK_{w7-#p_-!d13p29C z47cuYG|92Mt3v1ml6~KsF``5SWJF47l_V><6ji68q{^*JM)iHp6UkDl()R(-djb)B zwLi{8s~&Zi6@yDf1gt}-f-+EobSM|13hlqiKQ0k(td}0*oxz9P_NoPSq4_53wbni8 zn1dqeNfgyt>m1jUds#FF(as6W5v*aOWxikpRjkgd+qt%NT7BUH(+F5_hN{CY>U=C% zQ+%|ff$M?j&WHEDGDD)h)UuPr9j_UiGLk!cC?rb7n5&**85Mp8E1FHcP---HL(wbK z5|s&7Ma!v#;~~<1zAW{zY#6YP)oAzbXq`b8CQllyJZf^%{i@5HgS6u&z`48TtB{y!@GRB znf1xzx$M3=++4pi{@(WfJ5Qhfa)%MaeR=tnO<#TQqt$Kqou^N4wwvKMi}ld&p6JEz{O0>l zR*(9#i=Tb*^}qOk{^;(meD}$(|3`oOohiro$AACRFaPXfyUK^#-Szn4yX#><(f*zE z{?~j~#ypjGa{s;CNCiG=x_j5Ai2Zz+(rPq2I40K^Q=f;vg9@e+EC!>IPLyc+C)vXH zB}}-xx*ziS<^A>bs{0o|_^qq%<#(>X{z-cLCQ;%Q@%+2_^H0iWAC)iPEzh>P zf4(+X>B`)fsmlk%h%zC{i_4FT{?K0x!>~F#-)t|t^>(%14%@R~SiSprJM`wauwwvd1Kk<-tn|UX{ zSK0yhfvMndj+ciV5vx_7%P5uJ`@?v<;#K95Gd1RXrBiKc%vPw>P6sMyZt?x9dcxbO zgRT40M1bwYOq$WN+=<>r$H>)v~~9U!#68+WsDkg!ky5t3`X${RLcRMGPRAG8r-e zhpz5E%49Liv^s*gcdL$_A{MY13QbaqrR`Zwd~CG5Dp05mX=+I}20R+b&A?(IdCg~t zLa1%MqQun7=x-Fz^<$J$E9MLqt4(oKqa?oJun!`!JnU}|ai0w@+oqj*XqIQstpGbF zIMvBm6K5i|@-|G6(Pd86j))T;s+Uk>a3Fk%@u)9X4lNNQ$7&J_`x~*0_1SbdN(FP> z{9esf;1n%zr5W?v6~%z1Honizr%=(~d}Sj%?h~_KKclo!Lin*UUqfXe(_+TbtA`ay z9pVI<2*6^=dW<;uyykF-b+;=Y-0%PO<@SD+-pgf*oZTJBxlB3FPhZ?y`rL~4*DH@l zQ6}O*^BDW>5aaZ9-(P(6o!@{xJIv_)ogB|dmQp}-@8B5A+;7h5AyYw-!QHb0-kDi} z(v)L4bgH^z0672>WXf#^_%t@AT zRyaZJepHoIlS~u}iP4>euIFP~x3Pv?7eMf_!8a*P5e} zokbP}E!9*)6wrC3LLxk!_F0eDOZrA7QqS~#d|U0=qE%bgoJ5OantPSdI$gArqg{i(HMzJm1AerJ&1^;z;k{9;zYVN8u7o@D3OBKqo zq@BH6jXhFt^MFILgJI87EL>R6c`vo2ok9{#0+{DByc*HBtlPDWE|f2r%L3r+@O+;x zXTQwuHjgT0L_hi2yZHPUN>^o!!w0{(`t5h;Ke(KJ_T~BC8}D}8ay@kOb$|JbGJO8! zPdBU8Fgz-o{;SRTPw_i*=tpPMV2?Hb&Y%AISD*S{UR=KSC!da=Kbyb2>7L$yo;^*j z>znzrzkH_qm;LbM%X>Y0c{il)$=M?-H@eB2?dAFhy#FQcpRM1yxcvCzdG*y_9rlkS z(%irQ!qeCI-ZOl6%!d!~+2!T^lP#{tyR*j^=(fMS8(-e{U#1cLS#S5l#p?4-{$hQ0 zyYr#jKCK{|^zf#5aD#yhh^%)%F-(Dm^vX)rSmWnof3wBK*o{{o{MO4ae~|y`_gA0v z{XEHQN1$T79gS1Vup2|9v)`Tm_ zxZVepl?+(1Q6DUrz*)E}wx&8A7mi~;RqCgusWkudb8;4p>uQ`7iPmN1@!Vcb9$}K z#CEW(iW)2t=rq#m0Cw@~1eQ?{8*jTZP_0I|5=M^Ad{8M5$9_FlIUlil4|p{qeKTzH zn_oGV+u9Nlb7WDqvw>cDMp`sC?K(frR8ylLM6F%g)V$HAqiKTinnaQ&sE$h5IS=Cvxh70Ts7Q?)ets;26d zSe@fr;Oiz5cd3RIy5Oi3QqLwZART;w0F@i2@O3K?nh>lFpE|`9v%+kS#hy zOZK5HSPfg+-_=69WcLM6TYX1ny+BE;SaX;>7z>6qP+1}<)xrGW zb!%~sB%!>-Jk|bZjZG;_{<%Rl6_lX};3868O&u^PskIJPsAPMeq0umjvzUQh)0BgH zXb%u5>9s4L6<3nNovpbcawg_L1`f**u{6PqSVcL9(_8o0R9SVfQ- zHNb^N(o!ZAu+;D!lc6W`yJRM3aHdU$gD{quh-*d=A!cwEa%r4MHS25bFrh4n)8tS* zFf>3=?pVe(Cm*Z0JNdG)>12ZuHh~V<7%nWGfg6^!X@K06P>f+Q3nj`Nk)cxYa}iOZ zTACISQL%^k_S1aXw%SvGDWR?{!ZbXdxyo{c66wj3rDQC(-%aTZ-F1#pyrm}W81sB_ zb>3w&Kz%=GI9qo%gmQVje*VGqhgWe(`DS~4_{pb#@PGWn+ceuk@Ohy0U2d2w#*$B*BA|Izv5{_-#E z&NuJ8e0uxEi%)ms(5G&_UUw-y8$bHv&+eb!?LPZ@e>3hT-R!0^XMKggdfZ=`U;et* zKHKf!lldDhqQ4@+_YL1aM~4Hp``yL=gVM^9gttdxmuAA3S)1ik7B;BP zpIOJhRz(pzA)t{Mkq_nva1USH?!a-44^J)pQ>|~*62e>PeC2>G zeOM{s2;8d6^~3+N>N8c}lvYE(2^uk*0OW?2L!n;h*8PY5ij&=6e7%_d)&VWsOH@xK zwToHjlS*JvNwtk910tP3A5VggdBQ(Al>|(wJEiO$-{j=(uL02(poI91Us&v=-|RHA z+D^aGX}0txBa}Rjx^e?bQv#_0kY4NdYcUX*tOY!_!Y&*~G#SjSo~ZWoT|@vdOCVr< za=NEsSPw&23Te6Phi-kQah~q?v{Fim*pG4Dm)m)s+fH0&R|KpY%jxQw-HcEbzdD<= zyv>@uJHEtrdJ<5!Z}5*zkcMx^ft7r0|I|2`W#pY-xnho=yPqnfV>!U|OV7UITtK4D z7RqV;eT>UiQ$DJd(F%f5`^%LU5>39`gi8+vQ=Pf^A_Zx0u9~XN=m0VCAO4MYuQuT9?8hfL71+xf5O=rQWeY3tA-p+icCMU7QrBF3ZR%j*< zQ*EMm1>WGha==Qdv%6KyFqVj7T@hz`CPTQjMP9W;AU^PIPF9d3(QgfUC3y=%$rVK` zTw5tn3Cm=r6<`)3j>?6F+4Eq+Xm3@eFD}PnTpJCZ!fVG1=&Bb!OGc&0gSx)VJ!eOz zwP&E}gpXzi{S_!4S6>~gAd6Q3zJUy_@U z#YC4%y{F7&u(nmvUfo^zO6Vt1mkZ0W&?9Ttq3X3twGfl+c#tKt5KCe*^kB&Ry?KVQ zSeM;rl!=(2iSfew5GQC758@=wLI``ytgUBSCS@o<*s|hP1^EI=Y`b1vNfyQefJF55 zDYSV@1MwR%ga&f!xHO!DXR?)Yf`I6dJ!WWD%!(2@M?`CHi&==MK!68@-|_PY4dpQ) zsMhaHl}NMqZH7}woO<^}cXt!|tMztuhKzBx-d3C8gUhq;UG(q&{O-?D_ER~GxEo{r zBRGUkuZ9zPbOw-%Z{P zKV1LucmMRZ6#dVC{Ph3)$+N%QWxe-(eehoCR%d5t+tvEfS$=1AzVfs6ul?H1*`sT7 z|9@F~w;#*4?9A)?#+d7}_l_Nrk$Ljm>Rx4+tE(H?>b8svu-vk6qizWr1QPIoc;^p5 zg1>@)f)|8%LH$G{Hy2|gEJMpSWxL9CId!gi@)oy!S!>QQco=i7y(2Q>luwJS)HzXc zA~JTaz1Ey#j`4lJuZ4`a6^qBw^k2>!jQnW3*yy-8{fm>Yf22=-mJhu@O}vEn9Ijb=b~^{mzR!a+pZw zVK2#?OLeme4K+ZGE@~!}dibI{sO~N4hK$;uiL_3dAAbAb?;v69W%qda9H;;Txp}DhonMyf}0G#6* zx=t)7)|cr~WT5*rrUyJoP4zFFQxj`lVFZv>DBHFB=spN{;7+(#$%R8Xoik_7RjrgQ*7N9AWw_C|zld5E|a<4HdrM9`h zAm*)4&L0T!klJ2QB7hVBZm%vbfu0}V`GHp7{=fBS!Wn2S$r-o>}Vu{$ekcZZv zB2zR`#JTY(>6(9QD#b%4DhqB5jSxr?DUr&k^j4rHc`WEQ$`WIG+9;h1nvPL<{;N5DA65}jMG zZsucGMlD;E9c>T`;axGW89zz^-Ql^|1EUKCe3Cl3c+C$=sqx9EDk5s4suW1x3o|rB zia@~}K$qTQFHLxe%#%&n!Y$P;1(>peG?#m7PuFY0@EHY=9RoMs#?#i~*qW-OB< zw1S*(x7kQG(3+z_k{+Nik{Q~FszAL-RFy`wQ>q~?(n|3*nx&O)EzmlpDr31n|*qG{`Ph0FxvB%{G&hFJn5f;^5|^w zl}B%BvDcsd^U#fKb>vyE_^|!zA8~@RN)_>=F*XFCP?-XO-EDYQMEv^;gklU2* zrq~}B&|k7M{rGC}lP(YK?(e?3I0d%4ec7e+*XubYB=jCrejz$3jmlct&Dhtf8kYD5ORWHkIe@#Vp)0;ZXNZm|gHks+TOL^4kFOq&JoL(#ej>6|8`dU58(QPqR-jIQa*D|wL!V$(w_qj2 zfW+(uiOSL9xE^@Z;GYI9AWtw2R3WyB15D$=GVQloIR^((MCGySOJ{s(96YAYaxa97 zGnQEvNnQc(#exsPyh=ydKUV-z~n zQ(>udok*I#bA-5)#51oQbICOAly|SK!SB^Z*TUKkb$3*gHbrwt3Bh9EC+n?-`G%M~ zlz|S3nN^Ij>ft6Gn;l(_JHeIu5(mE;m3*KSSFjf;r6vMZrW+&%XYh$y@Ffc9hdR)- zLpR(Bqlwx~FJZ;eN$r@1T=v#QuGc&|A5zz*(EYp6JT?_L%hYKpiv=t1kiMM*cuWeY&LU_)amlt9@#;RIf*DkZxJd1+Lj`Oo4b>BuXfl`~gQr0- zz_V)Pq8HE&qhk+jfE_V9E*P3KFG7o@%wqqjZ3WJhQ@VQCEu zSnFf5B4vaZVWDU9eX;E3#UwHXhf>Ss;^xLY9l&!bZ&uH7BL*ol$`lt-QPNwCy|Ptx zPleR3U$m`=6ui}ym9tqbus$8fbKAeQYF5@mBk)H%~r&O)E{G-#X!M{@U5s9((7*q8s`ir;nP8t4HPX<%%SINoBWcG-JGY zJ)ZBz*8|l=7t6kF)6ZVM{6GHqqi;T4fBP#>-(9ucaNYVS)}voE{qpUr{J8URq2Kz} z*W_y_A725bWY0TA0h%5l#=LJlw_<{kT-{lnzPNza2Rmm-LP?U^B%Z=i(XiG`N1gy{ zK$O3bFhAfCtreV-9o*eAJVBCc#&`^|@u|p@_L z>B;Odcc5_#u6r-NDstk&VHJszQ|&EQjiGf<=}p{k=|AHCZRFq=#Dwj4_q{-;c6GIg z25f^#?=5_9$-|Ge@pk~)j{6k|b1cXk8|pl=@z}5+kPvz~Y9AMs;wqfaH1IqhpfL#( zkJ{Tcl!M|?^{KWY&?J=Vq3cq0FQ<#u=}EtEUR-YmG#$`7w6M@=#Y-v3*-C~L6*Ntg zQd^vw!)L@?yx1r-jqsuAp^Z66MnULGLnR@#Hm%t6dMa=pbm(?(y=X@rV%`d0keMLH zqk>y&(m@3OO)_hZF}5=jNnujNy#UO|OZu%Ac4WhdQ{72wm1?Q@#8$8=G^9=#XEl+= zsk)wjYQSN<1(q53*YPAqfZT7+Pv8v&!{ikvH*FuV*kIr-a=* zoQqtCkD=+9{tc+8LqG{JM`Ygt@DwRfk(y|n3cga0g<4tKMXDye9IoN<^-RIsWu2PM z`)9-pILt!}Bt@8v-V{h|qVSd_Lp#FNcTf<;nd#x(c3OdtN1VLl&FmBqXQCuBHptPv zz^|tijX38F;>F;CSBtj#xFwWGwPP9D{Wr#0eATJ}85m<*6^xEdER4tR_*ZX#w4= zRDN^FprcVC*>9aUICTN&G5jMOQj^wIC>=df=*WOcqsj%g?YJG&=Vt|!a^(YF%3uE3 z-~8WyxZ4U|<-fkZ+P%0MF9+}2=GVV|^3`|kTdR`~ug^A{>qnYS(w-&XyxiPelpD&{ zk~OJa_uYCpTP)AdJ6A4G&+M~TpS^gNnDWp)zbKm#eT#L2=ervpFR?hkzVzoWpEs*q zmaA`k`?r55ef+5BN`}0@?gb|&%l+sjZ(5#p*0ft&?kr!T+j@2r(#*zEL`4%Dw@#@n zKI1OmETF$6rf_q%dw-`ZU;OZ$^ABD4Eyx9-iaiDa@y35BbDD;DoLo{VVi7`q;jC6My zotcu|M_2}(lBGg60*#w$FOVZ2=s?H(J$^f;fHG)}J`sgCC=C(xj6S0BSfmP?4^1Gc z+;~WIpkZLOx=yl|x@}hYZJ6Fz;btL+RzoB_2r1%PFQ5k>eV*AK8i=Hk=AI`wcbU8& zwJ>$gqUQi4#~3z)PG*LX+nXrjO%tI&1N3GFS1F0;L^`k+^a(8>;KJWz$q~R_j-BXr zxM#$Tvj78qa36qCv=9))pf36*(K+_{?{%x`5F6KnbRfI$97%lXe7w7bz*I2#1BH0# zQt4)(c$m{TX?>@Xp0kq08fckC-g0-(d6 z53_>XpW)GP{8lGBTO6qgnmI!!B`il`&^m#MZwV@e3B?Je7q8l<<1~%hw-%UNDtUB= z1Pn_<&RB$tlhxzXlMc8V2U{*yz?k>eF0|NyLJ>)g_HDC1Jy|TC>_-|?6(9;B%*OqY z)h$gDj(81${SvE%z8zl#65ax^;=vt*2kxyV6}{Q%vEy!;KZv!OnY$J16}6XRnn=Sv zxfQxgjAf&`bT_1XL4ia?yAuLxiBY1HDG}2|CUj2W49v4&D54E#sgK3Idw?rb0HnyA zskq4qnf_ud*O%--Po6(0KoN=BuMv0mqO?lbGKfb#iaR5@$z&t7KT|RLRYy!oletih z0@P4zS_Na9)v;S8heKsn+7VvYdgKty!How^xv@5UoVRpPBvFh8c!m{3=#iL+mpa@l z!Vyl92o&Kv<1!-GO;9Kq?k+~`<<_BTE?-Z4-#}C(F$G&{fMv7mIS43nusqtZRhP_q z?6sL#w`lk#+lZ`n{OHICEgD98F)*cm0l2Q=>wN4_yVv&_t9RduB zq`krr^ZV_| zle2ZdzWLGe*&l8%KY#ROyv^$n#*!aV#?YV}g&oNZN82&qrPT6^5B3i%bBl|` zMT>U#@%LZ+>^xmJyVp1Jwe|J-gg%9_v!S+z1PJ()OpfGOWP`bfU9NEMKGv#^2zS%C z+rNnfaQ6i9T&PA@N$N>P@uD;fCJl}75~&sfzzPf?qamU;p&GIS!b}!Ori}Cq8aRj- zaIE24E&yFQ(G@0P{oU&m4V&mFN6KO_A=S_jjiYrYxWc>2ucL&DBhX9kg&}M;owCHD zhEB&#D2mfdXrRn1|DDvTosQ9MJxG&vt{7jXjT|c~545pcNg@$66mIntJi8*Ov3!%> zyUy&Q{ainZ!A%j@iA_WVD+PSSEMQA()myN2OOc`%ZpkB)bY0ISML*cwOUz>708U3{ za7%3ITagWHFLcOevg_rLUlIY+V3l*=nBqL8Vm~Oon3V^!M6i761gS%zd2Amn4@x>i zOCEKP9K^G=MAT~Cs(+l^=%lU1f$N7!O;^>RhbD5pnH+Q6CkZH+?(~n38p(cdYuVA< zTX@}(Jg2DAjr(v8Z1JfH~oS=f@Z?xwfsLS7-+HSJ%-zT<#K`;x|<_rrbDeC4fmCz7i znWAqTld2Y(p~R@Pyx=qtOwIh-7!*??u+o^Y>QnU$Czvg0B$XW;CnZ2#B&0=07J+{S zm+pfyD9|R@st7#*P@YA^oj|66rWAK~aeWA|oTF-~Fp>HWDM+oOy3kWqO|?;TX0Xz& zz{}L0hD<4LQDQ2p(Yy3<)@Q6!=GE$Fc{+gcAoU^HWT6!X^DUa9>J%L{#=EskBu)`g zQOzO6fjbLfDkcJ8IJ(+)^l+|NMj8 zIWIE+fb)Xl$OZ#5V2;sYz^4_K;ua?>uTzV$>a%UuqlXOox@oLbc&bwAnu>m`njogu5a&0k#u`(o%5rV9*XCtf=@Hy*fzGfS9UQ zpC4)@QBK4p6b#Uc)X7E?sCsgmvS|Xq3Z7<3^dcw%62)sB(T2)7VkQI{at@+%CL#e1 z&=}NRJab|($kEC}mqKgiG*DM_7W2`V9cnfMfwGzVga>6h9w*Ly@EnA|N`sg>IN)fh zxG1v-)ZI3(HXr_Q{NPVENNFp+E9TqPll_TrR*$c6zBw=N|A+tHzx%E4|HkK+Xnj{c z*z8}GC+&E3@v02@vhb=&(k@?I51Sio3(su(RP?cot9-RAJ#0H%-(c9SpMLta{r>Ck z_GLp}F4&!(EYWat^9jUJ%67ciJznzBx_P%l zL0Y0U^o))pPM`|VJh|87wjYWoo2>ld;w0Iw(wigz0ID7K12Fc&rfD45<#AiG7z|b! z-jy*LyrEP(lqOEEK0>&OIK{{;lEKKyGx$i)v^man3OSNDC>(z5X$cBaU~V{Ziz5g_ zg4Rq=?lOxD!XrHAaXA>_EJw51`mr7f^Ma>QO;Z}rw1{Y}l54{ARJ~NwjB?qkLg3@6J>WkevvrY0iH#*_d z1f|G9=ipUKCjgp~vXNF7kIQNYNe$xwSI@^r0mpe;s{4(=nQTsHn@c6l5%!+ix_%8!*rVghv{B59s z*~ZEx1SwD_J=5s(b0nSu740P1PcA}n9Cv%E?w(mPV2NyrQwkH+Z&>jy4F73hGdmq_ zD`z;daOR`aIO$+M0)y)a*&7DKkg=y{`VccG(FAI7X6wTH zBit$naN}qkbjad8ac@g*OK!%Y%|o&b%g@s_Dvh*=O~YbRvyzPUghFFH8Q%C#z(h%q zL~WEwRKY>qS&vm@s+=#NNaHZ(X!kH~0+PO)f(E4C>v6IBeGUntF*`*=Ss-wPkOu4qM~tJEz@#)$!&2 zDNoXqbG(}t&t!S^Ev(o0?0Ux^|KfVT-?x3UzWThp_{r|<$%}r0XP1BH$+}H1_REi( zW%~Jtd9i)(ukg98-@0s@ra!sqbt%@J_Mlx~KK}3*pMCt33+-F);=R~@`txT$-hMly zd%eHD%KOFnqs`|$v(4kzfBeCRpWCt@nVvm+e%7wf*}T5IY)_VFm;2`BCUsb%(=OfY z&{MjE3x^~cp$;J$VnJAe>D{tezpzx^b=K^K21~h-%RYCet6hf=_o{{8ZC_kV`&0d9 zRB>>@2sfA?4VM#kP38}FUsfTFhVU5*>2CD_!1c{E;N39c52m}nbRg;zX zYSNc-ZzQ$a0fKN?zRLq|u>)Zq@tPFv$zX7UdkU~0OYIg_D#w(b;ldbS)(&E8s%{Br zP8(63PWb)X}R4&YsM<^na!WEfag*sqPDBCqpMTh)4iSJTbL5wE7f=d zFzE+v?yVQ=cM9ccglgqpYDXOqAN!i?KV_=Gqm@|o{RdF8-I5cJd0!9A<~9b0tm*qU z*{k>8eVi!p&y?+AvGC%ywbZq+ai4el{lLZxSR4f|#Q>*E8Ev!y%;P?nG0y?UsIhvi z>SH?;lYU@u&{<+wT=lNh$;Ya94pRSWz1W939|3Ta3Jsk`Ja)uo@G_0-ZK)-xd)gZvh!`L>t$HiVJ!%16@#S?gE7}O% z!|Eq6aEQAv*Ky9=S!Z=;TRiyn0#5@znYcp1f2wLrA`~zYnc~q1s|RSA==$|MR6ngp z61!5JPT|*$pWss5%sk*SsyRbU+zA(&)_J(WHF{*?<}?ZYg?loqf=-KWLv=(w1Y9*U zlG;#XxFry!h_n#m#?z2hHr~9p#pO<}UvFj41i9Mptm&DDSG%pEy?l8yerJ8rE4AB? zMM!OWo}UjV{*}#@e0BNRwcYIAeer@ne0KSXj5q7+@2&CG^SyuLli@pGr9!%G z)2`2-F4H=7C#f`J5?`-n4eQTFCQi%;%k>};qY>fMPyO;*=LI&2Cjbfr=muRHFdDul z+i|~;n~%rqOLpfdpDb5r?{rM%kw)^6n<6Vr=?cF0>Lb}TZ>Rn4YWrs|dA(cgb|`s! zF?cR{zaKZdal6Z#UEb}7aV*2;^wsMNPpMm;Zb#pnb^UqMzfXVJ_KW4|+h2LQK6&(b z@&2#g=*gAHZqwG5cyPKaZ zn$+C*%a1>63<*iK8HW7i9>8O+d9`k=#(bnL_>%mF@7^S z!eAL%D)CBJt+FX%(n?{DhN$c91C6H<4@p%YsB<3dnAXQPLIzyKy^@=}&TDJWvT7T| zrx$4eb=qDQ%J3VhqY0fi9AJ3<>gHv1pYU20%sdJIX78HZKmG9dpPK^7y{o~c4FA7G zcNr}4bv0fpw22^TK_2&74;&Rc&@XH=`&0~ANK7ZylLVr4s*LAVC%^-@y07&)yubC` z-x_Z4myUi)Dfh2$NqwdnV$N%%K$J`jNfp&Sfyy@|9DjQ;^c!@D!wLM&dycp40(IfP zC5fI3YtILFV6_QHH+L@3O(>k8@q|`VGHe3Vg5<^J^R{if#Ue>lKsQ1}MAY_uk5q8d zx2wgXZFP5bGwzKYVYc6m`+ez`;>J>nnQBdxGk4F~DW;SpDa=a6Ai-OVFttM+cx=82 zF-o31dVosZOlJdGz3DmE(EQR_&ku2tQSW#ML}u%$=SU9(O$ZZDL8pt9i^&T(*U(Wd z!$6@MMF6wnl!soXPTv{lHks~4welu&rxvV1iJN}3#VRdLt)8nNVlrPoteN(Dx5;$8 zf&YB9XS~|*J!lvLkF8!=KX7H46^A&C zy=uBiSWZbYv;M0Ng{9Ow%cke_mPYnKX{hu~KRP}Fkhmcza0){-Ooc3bN*jR|>JU?4 zN8ey)a&2V;ZsB7b_XI7g&82FSt*+Xy77}Qu&e6FvF3CK>*Vl}ILM<+Cjm263OS^iS zk+|&@Ug9(m*-T?i2&yx{K79I9kvz1)er7iV!P4o4yt6d6C))c)Y#`oZu1-oM=~ zPq$-fmupF~UK9sXrzSO$>9dTh#Op2`B3>LduQg1ieK-i`doo5gc*J#A@P4`e2l>Ol zH~eJGyGOgekdm>a&VEEe-J$74(#I`>I=RzcfSGQ-q)DSi(- z7y*xp`jkwlIjt=LA_D`U@O@>RfnFI9UL&bdJR(Z!{##QLrh-^}G7;WmF7#Q3;YY3L z~;AQJ}mDFPuIu$HVUV}&T??_=^N*Yxrv@6*Z#Ut%$({p7sitzm4`mvh$Oxwdi=qT>_HA$jekd9uXJOT z@m3F<7TC0=I1bfcjO~apsv(42Q#j}0oZG*HWbxDfv8ovzT%dJ zpe_(&xnC^lQvl5@-l+Wf2WAW6T6>f}2{uRoO)P;DYmnESg)V_@3YZ^h=29&O(U!iY z6e^+XkA!Qlh>DOm*reYGN!etgt1n|JppQh22w98!T#8WvsO;isL~7OHIE~QA%BCn4 zl-5=2t=jgmRBia&0y{w=`YGz%W*V0Ojt*Ay-nr)iAYCD?gcBe&3sTTRC_hc_At zL#l@2CewjLA2^{(NmMw@h|o-{Hv)NK=_IXM^xnryA`ENZ!OWLx6c>vFIG>#^{e^m z*@n1w3^o)S*q+z{ZF$hz$(QEZrjno~BpE_t<>hhy?5EwyA~n8Ro;CZgce1{0H&@rE zdHXBZ|9c#335!rmr33bQZ*TRFus(P7S9tt-dp73g(b?0p$4se7P1kjcwqN#(Rli(z zUDvdqr?&mI?|uKB@4T}gv*aWRyZ!DX_SsN&Foh9AaYNxrcP$|a;9)NB;zWB8q1Lfg zOtrR<4D`A`Yd2?naU-w9nk=0WHf(*w;Lg--_P*VhN9Si}scT1rp1kgtS1ry9kbJ+y zVs~(1C9;FGU~+T`lc&&W)ehk@d%Gg4aT+!fr9vWVFrgjbXZP=?<&M^IE~anw7WqpH z=!7zD-@#cbLOm1%Q=+I-%tB}EQ93J_+#9Ea2CU>+5pHm+so^D}umeFhNT0Y==;BCe(Cv0=?Hn!vv}$-Zj9h zVeTHT@a?YiQ4-btpSRmR=EGsG-2KW);4ilz6$in?k@@m)ikje-b*~EH)8q@E2dhWF z&d<-?Sq#H4#HJZig2ig}{Q2{;%j59v&1N&mz7gr#evoYvO;GN-?RI~&8TP}NJsDFe z#f_?JBvVts&2DGT_{}LnY<|0L8S@UMnZ@>5Uw>7?PS5Ey*AN_hV_&M%{6&W?zxC)( zGh>@fssMZ%Wh0410Te#1xg%93@>`BH5vNdZ2xZl!h-<5pu_(7{+ z>FEZd3+XiKv_?GC07{rf=MDt|mJ%PtIHL|_bk4kyJL>29&hW6R9zPd*RVN{0qD3`w zqynw&cg~hkOYO$nla~5b+axn0=azZ-0h=+$8tu*_X9g=T#pVF}nQBbBf+HYq;-ITU zD|50#&oKcwR%dxQ9X%6dG`+$@6W7f!MeQ6tq&^qWQ8?BKhR<_ECpA?bws;kFSQOSb zn#o{wmxw1U6j0h+pKVMwVRMW?1f*BlBWKk_RYJ$4#ek8_AcfDD6o(d1X34a1Hf92z z?YgSCk9$lY=A>t1y}7(1Q$i0s+~VgS$nNUVagUl_V3phGn6&;;L2Kl&F?%LxPE!R~ zAhGFOsb_FU-;)EZ1}k_(8leR`%0j#sX$4BWm6=#tN9$A}&CR@2^J1;@f}c>$vLaS0 zt1g?C0yA;RK{g}%E`MX;L-#Dby1x0#A75?UiY^zY;|qwKtxnIrB5v11+ns#o-S>X) zAO7xd{L1j^U;Nb%|JT*}tzpQQHzS*F`S{#?bnMzrzS3>Ky0l*m7cZ|i4FT%QoBcqZ zZGX|X`>(Y2?QfptyL=add+B?AdqsKmIOCx3O>L=d1lMo;RPL zzy4rz#j{hhKHeG&egh{bn671i^LZI}CE>}F^YYrBeB+&e@*n^E-C`jkk{XCmQ_?22 zNww`jiV8y zIN(_{V$CWrK}sbfn2?d{S$iK+MNxBT3;l}c+-XqGrIeMR zuqh?N+6$$~Jfsd)pVeds_rNDc7`X5NlMCn*DcpzRjWPx z=iFoZZ)fn{AwTsC-uL{#M54(~)+#ww*B}72lRHEWfyr|>0g{N^TR`&xv*7X9-!>86 zsh{RbV(uK@!cAoJduu{JI&BmMA~f4 zSj;5taz-a?x!Vjb$OhHqX!paWxb~})wk%sR3TP35iMA?DQ%I2{Qv3Bd9CIrq_1M53 z5+9dfL#r{;tLd@V*6S154YT~I^a4ft!4C0Yg zN>$82N}xO#p=5lh^X-v_Q7fq!oco&tjk`yMdd}r>zKOHYBnF`T!jrDfUQ8B+CGiAP zpmB}A9RR9f%3ufC*3b*`Js z(aqnL2jo&sI&N%pYCMD)H{MFAq>~vLgHX1LS!fEu8drvwXo=OiDS-({JSM_Y}e_xAK@536KA2J$NILerc{ZB$ovhUx+iU^g*V zXZcaqB#7tVi zrGVxrAo)HeqAAvX*8^4zffeH@bZ-f3 z>$zrJG^c8*xOYBw$j!L<_!1vJPs?_=ZkK=br_Wz}e0envUt8lJ{pMF_&pwl<%hUb& zJ8RnTSob#_AK#d7U#R_}>wVm`zj*%YxBlrj{`3FzA3ytpzmXrFug}>%YSYHrzI}Aw zTlQfvV*Js^SU(=$ZBsL*<;sfV{Hf%l_ZbZUT(IsIvLK_?aN$jSe$lm zf9t)nY&Tn&pa_Q40@&{{-i(9iMcZi-&kS!;Otj0vH~{&w!4QV5Fh@)*liJ(6&%VF; z@yW%$z1h)*wEM9wZ}yvuVVAqp?D}mpF=ThKqsk<=SQHwPsfvAd4HER z6K0kjxs-xzrJ!JIUDKdAa@(h6@5H46z?NB4nluIuh`9|YttgH#VBw(#FzTTTuc3{N zh-`r=R!rTH(!N`_XT2{?PTW37X*F2x_Jf!%&594h#pmtWSdu?#H{VTpJGSe=A-ox| zUj>A?_8p>pnE{{$b4II3@FQS!2t?>~Nwcs`D<9%`Q1%7;<6!p##2j}-hI~_udb^Wd zK@L^nHU;>F(9~H|NoF2gQ$lCr?kuorzcHvxoXv0yRRDjs48ScK6P#VzW4Myw4mUgW zVzhR~Zq?AySr4{m1TYjL(=5D+bq>Z7Il)u^(x(NrhFdryO?^hxhepMwcGUfa>C}Io z!5ZI!SJ~{fv? zs>V%O+}wRPrhfIfNyBbfA!Rn%C67KrbR2V+7LvMB+NNEsPfy3OL&;*%KBkT4Z7Yj~ zE|!{FbAn^c^W$ZU!0c|3TRWO{#2|Bj5^sj3$0H@Y6;=4RT%i4nIHKn)a6l-iIFU! zUxk!u$Eie-D2|(3S11Y;cho>YuLY@3aQ}R4Ui8CQsx;G*T(4;LERQn#mnYhrJAu~P z@PUdIHHaAnG;c7@t#xtc*c;p(I;GggdC8AWfz^Lj^RNtnOYUuz|5G41Y2-Mj+<3!iMv%p=8U}P<$t5|IwZc6Q0PgJJ4|0G2XPLmj| z@YSNH*K0?w^YGO8$nHtne{D|cDOL6wS+JxsDjZP^}hZLDO_wy`*biho5gYHC; zs^@lMCv^`FlZ|>!lyK43u>@9*6QDIT9&;ZzGuUV-1$FG60Us-0+%1x2s*TAaEyd%= zmrQ5^xMWm!zez2f<6RpcX!VE=gQx6?(zeX>jpQx!&98m>7cs6=%gx}!&Gv_X^_M^T z`9*&I(ewA-Zl3f?N0YMc6El!%j@?ody?f?EXnTWm0sK|#$9`|X1{#2U+Me% zpFjENf4cc!etPw1|8u{2`QhvH3|?&pY4Wp=HsYlh&->j^U%m5-PpQ#RF*4y9s_GwS%qP`tZmi>EgpN}p-{@Djlmfa_tP2aRo+3sQPVp%cnw!OG1 zn1rj;(Pg|Tu+sKzJc$LKV%>;Fp?o=s-HGu=kkmE76NTj@U%h|x>8r8zo87f67h@_} zFZ22`55{rf8}o`yI_5XO&Z+Iz)NB>&KTRfW+Sa}An!1CS2gWPd4qI%sS$MLs_gpY`Dk)jR zg|8u}UIyTVT=uIbEzh!z%dy|=U(3+HGc>P9Y-N|1jr8f!Sc8;HU2$rMW2oI=ajEVM z2MSO;Vr-FWE4s=agd$T9GIlii!uMrs<-XXDyG|x||Kg2Sw5ALOnBOoV=HDr?CzNO)9*6c!joeEZP8 zKj!N0hp53c9FuV6(hIp;`D5D|FaFV1&%0VdEh$3%2} zk52ZMo2Kczr4KhLC6SbK_G%tdhv(wOj3TLRn3P^mo8h(sK#_<)eDg9gxXyme7Y}W# z8*jhy{Qn7w90l~Uq0hen03ZNKL_t&mMje5b^8|mYp3MoHkc~b>|IuRamtcaDbeYPP zuoZhvXXOJM$&p6F+(4multOxZMm$`fT5iRqMkFA{!K@axLIVRo>JN`{no1FI!qw0S zlR?eHFY8|1)ncF)jn@NB0yTUve%m-3!UzhhId2U$Ad>|g=sChsBQDG z_uCQ=d`q{hx1V+jpgE1YCQh=~(OpO9Ekj^zZ#i5q&ota$rR-92i7e{tAz=%=hmd1U43PG<)CorJMEq zN$~23M-_ zq`0fY>d8_b=%fm)f%kw4Ol;I*?%Qww^?!fU?5^Zx87?`}@!ohbY|2@C^3CnjZ~dG9 z#ebC_b!CBn?bDyX_-Fr3+RC?1e`2pc$^7ovzPnzGdU2IkyXNF-{rdEy7ngdb|L_NI z{oc1U_w?Y*(t+zCML5Q$Z<**xK5_ z>s)+idDMlj&)fahhs(3KK3njuj8d3`L?sc&7b9snAS$ssk!V{2=-3Ro5GsO_Bdrxd zucg$5NhuTw?)Yhfg#kP4ZWE9E+oOx1gS*$jo5_Zv%KMu#(tERh)9NxS$}5Tj|0FQ=WLW{w}^P5 z%Q$tcyq=1K)m>Av4G3xV1ksrqx<}&J+SnFlxHScZI;sysqoJUXg$#1&K~PyL_<4>e zv}1k1q^6q%&<{y35?FE0$B14JX}fdUdgnG@n!sFh2f9l29?*!KYr?!+A2bRWAA%e_ z^g`>+#GqoAh_q#RDlIbl;*WPRfTw_ z82W~^y-H%_NUUP_jfke}76o6yQEt-#%|^c$kfKwVyNjEdO_Hqn{hbm*<_W;0Nby;9 z6DrT9KC2{zM%IiGn;`>;3Z}k~GBsS=5Vxh;-^{lS(q1ho`@4&rO$V^5!4e?3$u#Q; zvvU}k6J6orAicG5GCv;)`rR}4aYq%4K_|@=fMj`7zY&s^JM6jmPurA9s<~(pV*_jI z-`7GpT3j;JtcIYDvoM}49*M92A8T*YWLc7(hkfT9_j~UfV$8_O${M;xbT?)+27(|6 z1EG}+qDdz0$b~kNX~CVA+UtL4A(P2OlbK{9Hl!KM2!WyqVQ4fO-RP;h=Blh5B4c>N z9o)~+!u<{}B3@P($*{Dtmz6If?z@BgIp6sP0ipIvmaUoq1X#-Ii^R5zf}~2jh&$({ zA7FsvM6r-;!WrlTQ^p0svOV}5vm~MC5IJbZr-?Q(vKpdE2m~W05;Ior1dz0dw3gLx zn$hUpwINZcsY)7`-IQZ$s2QACh=@tj*shR7yfsoVgp#?5ieoj7tr;8}6B8GJi&hd; z5eO~NrMSd26OjIlX@*C#XjN_;D`UcpF%g={Iv~`z$J{wX+!;gv=QV(g2HWk+j2H37v5VY6u-6FcjzmMu#ZiVdI~v zYmP53x%J`>p3d(T^Y-08`I~@eYdt(~U-kUz>7vt?s-inNDZ9<1U!K4IZucZ^dA@#s z_Sv5(G=gax&?7p=h|AXKC+H1cK*exBDRam^>(| z(PBj>Yr3c<;U;5n9|9Sg0)eQCe4s3ZK)!9O^~RNzY%NmzqYJL23lQ$&<>&J9TY^>F zbWnJoXaLU0RE6g)Nyo~w7F8s5r^2%pwgntPxZjQ}BUzoxD_|;L7(KeEwF4CmEv$8IDIYvW|BIN1C*Cf1iPfwRu?dIvRpYz6f-yX@vV*M}v?0X-_ zS8DmSnaF{3bx~_ac2pFR7F;oS3DaODp^~99CXi5)@3RBgGIhI%8QHpF#IA7y_{v1# zNii)WyhB7W=S>ZfIhaIH0LQdKb4bm$3K`gljLE#qu-^H5gMdG}@K;BLE zbGk;XtYb=xDJypARIUh(bKolGHKpHhFw)a2-*`3rKW|xo0 zEK(nKMhN|I6}_FVGMkzE%8=$@Keuc5ypOYcqdvYfIs9j_iMfrGkBK{DXgzWNb$z|= zx-J#X13Sgc4i4wek%*KPFBUjFT5hjIy8sk1#tw0_S{ZKuIOk?uG}|U|D@25-U|9gc zd+!{p-gE?hqHq3f-U1(v-e6APs; ze5dXiW)_e~LP1TF2SGYTI{Gf}7SNagsN+}YA`zHP;vldC0QD(YGWXdT?=c9|)B|e} z`Ff=^qZguN?VPv~WK%)LxIOoByixUxi8-1~YUmeJdRk3x@B}Bs0?X?~K`I7`QKDtJ zSt14q42;xz8O$tEp@xX68~1#i*xOAfSKhh2y7g)j8r+w%k9F<`)9{f8V09j}U{cbJ8dCWs&02)P7Q>RSP&`u)nbAf9_rkt%&5QrjK6pC!d zB&k-JwzfZ;1h@=YK1~Lv4~+~`yYP(^!uy%gOhEot1EI|4(=aX?5 zSIp*gjOB%78B#jmKKWWgqC#gWD zE)W`r#33>=E?xDp;TY@S;PE84R(>sitAYGgxnSKE4=4S%$G*a>JRk8~$LnFEWu| zydz9^&B^b@orI8mW%Oue(7##toDLh@7R`ELJ{h5D8dXhkrn}Sgy6rZliz1#Vh*MD4 zCn1yfF2BvJuIsuDE{PV>L*ktC)V3Q{B^qhj*l{b|*GYU?W3v0MEQYh2-+M!jHb!^q z-KSA?QV1ePeNxZs8jJ|X2aiCvig=>l>79`cbaFI`1)kWknHj;Q(Nw<_#evn6XK!P# zI-Qd3OBm|YD8W5#BNw2(4OxiYXzN$No_j1eRfi&J4WFG{{L*)b9;W;XsM)iiDwp!lXgh@vOqk(!@r0 z8!Da1-(@Ga5uh&Gvrg!GHeW-QLAgew#h&0>tPQ`Jr=$;qEL-#sMirs zhnr*P#%{Wj3EY7iyh*elR<1(YnYK)X%PAiU6{@T>5W3Xg94rl}lHI`ws*x z-9tB99#wx`ecse$WxYJ{?nJt3yRANMU;eu1<-xpb2_*MVPdcS%8$CR%+UEo-mc`;w zFpt&+E4W-hg48fpO0Jvf1p_#23k3quFp7lG1Ch{;e)BudRFwrXxa?#MujCTUqVtmB z+?-0d5@bhPJ^ZwucXAclEjebhs+4G}P5m^+g582b7UPS-f_6Pm0$MFXxV&JE`Ml6R9F@{8iC5v8#CTdhy`Q9pk#ujmh%7@kP}c+Qx)P z2+7R-srhYCZLI_;vCBlGexqXyLX6b8wS)+Zu$Vmcdwa)rh{B$n|8(Zjr;T!-`b1DQ z<$mQ!=Dum#&?S@2?2L@j+92eoHIqRy^VnK%X?P!#RZh>6+UuKcU@{RBqXOoLJwbpX zdGiR3V~VsL>;@wa>uR}&vlw}&3>#!K0hGMD9jG%z&1990OS%@$qUq$lMDXK8x)<2I zP;3X{uU0_AZq$|8K{YikY7THljwqGOz6XZV@R@rL5HW{-OoV<|9PU3cVjq3O=B*|=V{*LY%P)~e?cZ}~QmQTP)EKTfevfbkNM(KIupZ2L= zskax>9$XzR6{%KLrK;Y05s5LT)G+|jF3ps{!me(v*PG`}Tb2SCn7Jql=Uk^`W=+%7 zO<2z7eZqWp&WiwLK$^cXZZ;cLyR+io*9`EN*&f-AB+Oi4+)B5Z*sBefd8#V7(U9zL zu=1Us3rCu0LnqL+-XPng7X=T#2iXTTNuwI0an4J-^ovx=WWRUN?Q(|41#6%0?8MIn zW@Do)2sYT`sevqos7D$oKuG-)Ki}DfH<61uWiO=ugOcr9vd~XV8-$coWjpBnz>}!^t=cB}sB9D8>q!m0 zvrg>-49YMdfsWDgFw6`^3<3ru8U<5}Y-&zf1qzFyU)*VI$^k&!9YZG~ z4PEXym_>vn`+R5t14TycrI`sJ=|Z+Q!jvUUh^C3DIg|_3Z+?WE!tfVORC00{gyBrc zvc+tX*y%J{O>2fmMg@Hm)uy9rCCA%pI>2PZK@{-S5NPUS%2L_ds79j*a;6FrV$bCA zXEifppT(N}tSMiME`n1=E3twjBM5`2P>l))fn;P14gy}^f}xSQoX=;onJh~Ujo8XpPQig`HrpO->RGWU=l8#Jt;*No75@0y z(~th5KwDmQPa5&Ez@tZx>h)&Z(pHYD(<81=eT(~xgDubCiHgnfQFl@;>h6~b=SAgDEVP2H@JG$P)d%|i)6KK1jmX8-ra9kgEDpBC zd@cTY7p}KproxE>f|`%LA0=Fp?&s^Putcdh1VR7;nNp6Z*&Sa1z#@PQ-cZ3xHE-n2 z$k6sORAO}{bI@|#Y@V;Lmp(*j9W>~CQ9Qf6cyjst&GMaUq0M@0ojHgJi8Cq4shEEN zcSy=di)Ghzmz(Xnd(wrrvZA+cG3|4b(g;F(!u`Nr0KgF_%LTiWDGc0Adi^^jnFuglQ+zcuIZCb>6;)nZaUK5DHKU zcmorPym^>pH?h&+e;14VGW<>NUS6C~G%!;%Frb2HFvFZV?bHF36gz3SHvo3Sr1Yj6 z#0#ltU-}h#PMz+?cm)P0_k5#7tS>mD&eNT1pyc)B)p0dWRYBMZ#QAdD!C-o4jT;8) z>QK54j^o+N+jw$CvJdp_vTtA1p(%d}72zg$xug6WXDE9_iqjf;`g5jo)?2l;7(_{k zgq@@UeKwn=x_QJ|P=FWfTtF$<4q`d!6xZ(@tw|iX`1_0zY*%+4-kQcKptH9@L|> zlQrG@L-$kl{vomPMGjQC{nRJ2M|u+Eg`ECmC18_sS}o@%CyY5E1Z2}_R+?r|Mau3U z5oSy|#ClTs*(AT}#@SBzbT7wXN*ZP}v1GB3fDK9W^5plKDw;?tJxRnYruyH8(mV%O z=5do{yT-9lPDp_EcaIK`?*w>`6EO#-d8)gOKHZpLXkN(jqzoi%Y???6F(#FY4Z@LR zyO!?v#F@C^^F-s7)f?>RjNezDGJ&2=n1q=@gy3_55(%k{PP1A!z#)8-QJ5-!B{m?^ zP|F%7a+a}}-qW~x%Sl3x$Pol!A_gQRt_YO!U9CM^!!rLBk)YO-FCC>_m=hI;D08NH zA0u+lKImYKoWUJ4qbZur3?*|xQ~_nuGUfpD_Qs4Q{nwX{jfq6T%G42RLWGtK0X!^d zHVEr`FjbTEBszxArN4#V_cX2d+6P6Ic62Ea;J7WII4{ve==Gx8ZerYuHqKQwWLeC9 z^Bwv1H=1JPOqaY?tSy;o-1kwJ4A&jRZX^=Ow=IlDT+oh z`P8tfS4)003fuT<>`r05MLKFJl4-61QBfMwW8X16;1x>hm2I`Tc(OYG^zyRuq@w(R+}~&UAM1%e!czT$@a608EDCVTRA@~T&Qgr zr$~SQt63+#2Bwe4%l46u6VIf8m85f~IZy?>+)CN$rnIfQp3PS$N3}FxEb03Clap{% z5GziCA&9TLxZ1Xt-WKbQpR~=nzi#Lvz^j;d(4%ri7U#f$mw-TM+p?7qF4kw5#fmQr zvY?6m(7MdvP0B5u$ZA_o^0kCX=h`~EH%!^IBO1*}sY76~R57Q{LWsy2G2j5vOvf5j ziQK!$r_&WY-8K>?qFGcUjs_zO$=Vq(Lf8XAI|G?{f(J@N0i@L?MT_$U8%pC~#ofMp zZHOU6*pC~P`c&y12B zu<8L12<@zsWGOm$G)2fWx&A#ZWkQJE($4McY*gvaf8$#VbPjpp!Iy9vyavbqZdVQ4 z=buM+`#@7~n{v~xj&Wz9_N83sTW_E{#fU@{DFWiSpa|z22^%0nsx)jcltaNyHJahs zv#X{)^sZutbHy;Hh%uIBiQv1gW9G7y^>s*v12Z!dGdbtVvP{0zHz4Oe&cdd|YwX%A zd}-rBy)VNK5x6gfBTXm=6Fbsg9eAsHHoB8WLNe`SCS`WKd*|;o4v;@hoN+|h`f5c- z>G3#T=@UnX28iy@Z ztf_HOA_A43?!1|&>h)>o937|4I}&1!?SoRvShqAZ*M2ur0*bqZDM3dyx>B-KB%^#X z^+pX%dkfYgRnJCZ@Clbn{&6}sgt?F!pI}au$2NIUCzlmPNS`Y$j)|9Vdp921zad$E z3QUZI$Qya^3E+w5gp%NCVl0qUxsw9AUvP^)EEqMRGX%A*#fI3imBtmbPq-IxnnWof zq(2H{O9$`rpu>2SQW=1zqK>d}FoCeCUxUJi581!uiU`CDp8xRU$JSnc^Mro>%s=0* z9)Izyra9J%4+-Z~>UQzc`I}MBSFN@7Qq}#zFW>*hOOCdi?JEAluaw#zw$1u2e`TLs zJw9K2=O_Bz59%+9m$vJxw_ex7gZOL{m3?(GCwKaXZPJ}IGhcl3AN}rc|KtC{DpA0dpaS<5onaGj715w$6POiVwlru*2KsDTb7UB=DMr28 z%H`#VOwx;Vr_Fmpr&>@(u$ba0#X{LQ-?r*%a7o(6dC@$4`A~vIS`;(Wf?Rx=7IpAH zegDJ1{61f-)@wBtzYW&5F|@I3+wf%1a25ui7f;I&8WEn@5kob^opE8*e>( zxFixK-w8K{qF)daBch+PS<>Pr2dTvLAc7LgUcfN2IA|=U9VkVAXFJGLiDq-H3`}K7S{&WvW{_JQv_PS47k6A#`cv};`#KxWi%M!?3Pr{Id|s; z+ZT0c*`{qu7@#S_ddr+nUtB1^m!Op2sAYC$o%JW~=;&y*UDb8nbzNQyvj-uWK~)peBQs)oxMqWq@J=rJ%|h_5^Du2H z2EZOSSdJgc;VN>9mvfpoM3v>g5c4*@S_VA!oGs?ui?1YsJ*mUGNM?xGJ|ClbXHWr9B znJQw$2}T0+U?)U7Gpqq0DMSTS2ukA$D1gG?6hTt{6d6ThL_WQx-3#RPgNimLV48AGFgd z(jH`JrbGq@ID<3z-ZoALGIQTSWl)M$Nh1&-WN6cxLnswu2-2VYRO9kq1bQD=()arc zgB+*=7mR{%MqtgD8BeD0jyTVsc&9p7M2jGnbQ87&ilo762X7peqFHIgupywdzxSX7 ziy($5-7b{Z001BWNklT7lbKQ#o42oj@>175IXbquDK_u5+xCkefBe6__xaW8 z`e`uSfBVs?hxQ{`sSeRjAum{^{?( z>7|7h?UqTj-afMOrE_=kda>FPJ$%6T-;ggh+q!8eI$al+HOk6|&_PW^3>sAtxGocY zCWxt^6H`JY(^^hbzCA;s%FyJy`_4L11&mD@A%`qL&zjFTr!+@GaL6g#GkdbQVp(ms zvWfHA!XF&G{Jc1>E~JF=yqZ;|5i4YIbyfb0Kl-=-^S76AcC1GS&8$)>7pF%D)qzti zPudetu9&xr#R=&>+sxm7xAA?3vw;nQBpA&iX6m_N&eG6{$iT5<@3`eRXiS?cSaJ9lig- zCw5#m`dWMbz16+%{P4Tyr7z04T!w{mD~L0R@fp79%5OYumP@ToU@fBwSV(`HrKuN9 zrh;avL8X50lUvB>7^}*eoR>;N&c5Bb^GSC)!n*m|`Fh{%P^hD%JvNwQ$3 zYFTfMoF06?htp7+5g?YSy#pIKCC(05d)Dm`BBqes_&O5pEllqi`_qtUOFi7uj{@@~ z&3eo2IN^~qO|&-v5-#vnfPfb==I)q?mS#faj6J~-31Dh!=#5@smI9t~tsK+jwuf3` zA2h>bbk{&zP6hYA?VauzzvoY!Jg&@`xK}Ri%VgP!^4FY(1ne5%88B& zsA^FZKKR7tVBT?3G*i=%m?5c>P7iv|BCs0>^p3m5e$xGo8hQ_4f5*6L%H&txO@^C5 zr+4=!b~o`O&GBvWl^@{3PZb;5V|x~J@Cp%Ww84=>CO5$3-b*^BlxCEqODTn9@2EwH zlUH$?kq_@w&cPo>lpJtV5=2IjG67>^Pm`7cOSv#ZIt=@}s4wUR+c(pN0Cv)^Fi8MH zLNXM8Ad5txY;vZ_)<0*Y=28!-SYgU;rdcG8Kro_Ug9U0YydW4s;yCgfk^Wner_@(G zw?znf!SXCdC1_@-A}WP5h~iq64W_xzQ%Rv7A_fPxjA?QoQJL+QZqc%!;{s_@SI*95 zIhyu#XQP~XLp@U5EBOpYA@49Y3^ax)`ss*_?bb$egEhFXU`@2H{^PTzC|z_;d%U00 zcqeJSlfbNJ$1*bhK~9m4W;kC9q8EWS`wD1hBrz8UB`^nOKmp8?qDs}GMvF#JF%Y4v zhTeW?R6q!>Lok7m6kZao83bybBm;6NsYX^yWG#_0NsW^!b;2)&C=QRMA;P3T;jjMm zFMi|4|L@C>pMH4sKy~%t^1ELU|M~xS{cqi29gj}F@vFc8PygB3TgS_*>!a`fuiyXP z|4}VIY3d92q^(Zop_Fs1FEzH^;$BlZKJ>HWu!3B;>kqEAUB^}Uo0XfDGhjLM+&0fw zjCB*>z*u*B@!CUw{MOOwd+SG=fSO7iJzKX&RL5r1`jZM|>uz?qI68Z!a!&+o<;lk5 zTxOj};R`kt06BOnSXGD-weU_D2iscA#DcTVSu5zAMuwhr@4-w=#gt+cQ!yjpR6k)$ z4|)&;wjAA4tm<@Y69OUjRt< zpW=706fa9FIUGeR_5R^mxM+Xy?te17oc;c@5B~o1KkgoXe|tS|-GLSxs*CpenG~ld z2lq>+GVm6$DIx2}4+>W<3ahYgI}aZ{)T7H2q|s?Oi&inL!~OaOP)|9?aOMC%8;}cV z(;jxQ2|F@1gvp*Pd2F-v6+*uGvmM9WWPlqfGXw}gYig7G?^ zeLu2!^by$!-i|OB;yB^osieC-BQ3kFH>2e9Jr#POA1Im@VrEK|EK?Px49kr0o%+~r zx`OOO+vVUV-x@dE%ro2Hy<0@jmKH z4~LB+dzcWVyGC|Puc=+k@DI)`-q~C1i)2i;PB-JGX+K!bcl$}J(w*epc3(YBysPUU zRFE#Fy_Z*Pr=AvtE6Zi$394P!b<9qf5!D%;9vscw@xkKH-gtBI+_tRZ3)9rtB=h#z+d%Df|p;QS?IvKj%*bF0&)CNd40_gMUhM%R`r)gL+ zvX7=R5#?y397&!K>z&U_lfosvhlhDqg7#^L(Pa~||IIQmeWJj*fXK4>eB7;tp?{!B zFQF!BOqChQeJR$E-pQ28wR+Ne^Egf^V~Uk=ASCm-#0FQ1nQFg7D7Q&2t7(s92qE@} zi|!H?qK(IwEqnUc1HB>riG5JQ4W2{#-8B&b&cMKEW(*uDm?;@AXhfrE6aaerQA%#i zv)<&SD`~P~*f=Dys7Apo7@|=iP6hEW6w%4{lQxn}i`OAW!~k^8n;B{Lsm?JD1O_QA zFexmWF^LB=VViuxk_a?mh71!(vs1hd>Htq;P>}BL3l@epjD9`mSBd<7*cDNUAE%&fnITuC|+X_Y2kf zKjjar4}K{1XP-a+$%UJp@RH{(8$eWGd5YOd_gpvim6bCMPp^M^eA3M0yeO(}j)OUU zV|h87T^!C1(24i2JZs$fdh?^_s{<^qW~(26d-eE}$3Oh>lcqT={9?PkEVoz1;o+mr z(TWZnuDrbS@u$^~u77eqzvr76Kl<#$|NY;5?O^*GFB`L6xzpp-=R(G$4w2BYb+BL- z?=`Dk4SoJ9Zpm`ef4k!DV4b=eq!%1xG_yqZn?>7rH3wi;5kX9~it)8TRoku|JJ=~9 zMjyIv8yCg58omGO*}Y$REk17E#H=-ALlprPZ7@t&pF^D4FKb-8Zni4VkLXE>d#me{ z>-EvAFaOzhKKk|_{os@K@^^~Q|GS@$*R=ii~x&kvFYh||z4-D6SltA^FrAwMbq_MczA zHh=Z(<%P7g>1I(5%^#~&oj4~NlvsNvRZDIq0$>wg7nnc zeqmBfMADA$tR_L0nPAB&WiVKE{Y-8c+ots}CD#g3k3DC^(G@obw!=QCKxY=nLhk;_ z2om;j#l!$L%DE`HyrY_LtBc1`?Jn3!Q?dIkO@+JTEC7KqjTAA7Dw0YxWFxu2;OzM#I*XaB{QRAR1P33P6 z5=yqJG^ADZ)Kld<@s(2C4opsn02$ipq;JCEb}xWM_jNp9>BQL!xxcsNgS>Z?&-;EI z?T%@aI_doUqNiJoK6I)INC*KyQI+$#pUq}nw?)@D$>9!W7DCu=x0~&ng+u5>(#Fgp zQkFAu=A7Tf>_;Dr+a!}70liyfId~*vH*N7N23_Gx?elicq$ll8W)cyzn3={M1bRHG zoLe?F1A{3?)<5Kd+u*_(r_X<%^Or|d*`+8Y9@!lL>V&KP!jCT6GcO?<~>lSe=TE}IxdDUz505f&3<%z1GkFenb1PTFbMh839z7Ci`_NDKif z%NlA}@A@$h9HZd{j~fyJn8h?NBTh=bY!Qt$aa6RVDX^e7dxw_{)3PSTVsr*mIFcPI zf1ZkFhvSUOn@QGiAmth{=Y5nkU%)2c%=uq^gi5lzA^`+elEMT6_Rh??_ClgLDxGlU z18KL_P`AEuhz1f87GFXHXq96u3mGtDGeFq-TzfJ&vqIU!$kdF2<{dS8mPZ=}VSB^X zm}1IXHZZXgB9XFi&oLby7RrXfJNNDImxf#o)Dav3g%?zfa?ne%2Xj4wwskCu;&@hZ zTe|1f$?E8|dU9{`w^!eO^7Q$~tIKDzV)@Otzw!C!@5j0=#aWE8-Y!dd_YL>3qj|M; zF*L`=r)TBYsP1gF?V5H=AFYq1mf054p(yC_mfyRaebz2sU(kB?#y|h7)q78#s#c|5 z-E-H!{VT6tUmsm>%YXe>Uwr?I4_&#Lb(OiZkK607xdLrmedo_V|I2@K@9pa0-+#EA z@g*J3<2J>XyEHSf2#o}*i*oYt+TdInwVx{jG%)t^R`O*aJ|`-!JARk(B;*XlRtk++=cG&`ucU22k2th1XJSXye(_q1jik%#lyLhOu4Yb zbvcung|cjv8$ir^?<)j)k&WrFflg3B`)V7ank787&vHtPDS-~0SEA8dW#3P??B$=u zH7TqXw0B}3Y*>zL2UFX#v9-9HiW%(g&lP1)RQ2d@H^O-X`gF(VV&*|PO(VdT($gjg z-%WRiuUMr_Y}xW8Iq&-sBQbh+Z^rJ|%e{WJ}Yb!Y1rPrbCLU=aF~7 zW0!H~{5>MI+9;dfqZcl!$~ySVY7*Vje>HRP);B zoYUBD>n27+&6oh2WuZ*52GLJm0@ZF*SW9Wr-*y{E*{Cfc{0P}GRlKy znRX-`(+|wq?;~khXt2oe`<@GEAEuNYj*;!05_>q21Dq^wGa6W%~vTYg+`wn8( z60qg}rf+kKV5q?@&<$iA0-HJ`Z;3FMj0a#E9n16%Pt&{vL?|JqR4```@*JI= zkSzm%hGD&K*yoFM@1O--e90^fT&6Z}438kO}Q)DqN$h8d;D>kZn;{rHX zu(KRByi-G`$%$INNuoh5Jz{3unwn8GjX7oqN(@VhcXx>qvsZ|bnGl<#VMWFe53lLc5OZuvt0U%qo8U-uzW+j?vzW z*FWHSvw3`8%_zW~%uhYf+Af|f{M&Dz1gA565w|Gbx<5ZTdHR=s_xYz+jjNX3?69oW ztP*Cfy*M#npgt^J=(e+JS%vmk!%O!Lm%KjU^Iv;|%JL}q<&X;Z>Y`<=)=?^ z)@&z{pnqVgsw$W=$kY)-MM2Drc~Q+=MFAX%3}R#f7NW5r6U1m(x(ReHhJ(cQ!lmM| zp(kgZT5`O8_{k;=#*(lbB7cU>oX7IRP zx3zIc)E1~`^TjroamqO=90Yb)`MRlGT`lSKRSMUe^QUb5>YHyApXgb2+Pe8H&ZO;J zgj0kzGE+?jp*n&W2T#mEv{5{LyD*xnzWOqHzir%}ZBhCvx#t_^iZ>NlJP;nzi{3T) z_E($~fGNq#Ubz42#13L=KGE%&B!`;`&D5`-H+|XiwzN;HCU%1>oA(9qp5x^7I3xu! zG4=aPmiyT7*PQ(IRcmJuO(-|We+|RG8bAY0e8;wU=iGi-f{Ot%0W;HNTBh(hf${+R zZo))<_ae~x@0ka(himfULY#hvLU7+3sNX4jJ)DRruv{+tEDh?7IGCA9 z;0h7%MP$>|_0`I>D>wxdn6d&1oib*WrT4xRmKYJErSOz4px(Co3tZcU*g^Cn-aXNt z$Ny(JZ$AstZv*vshn?B+t>11#fk^0c`-Y$FB8_r~i52k>*+jG>w!^JQEL|fVC;4NVQ-9TIO=bAv9gUe6Cf^{U>(2X9? zM$N#u^k*n~{{|p^Un1zU9EOi+gWoo3e|6$5J#Mx$W670}fi0&tG7u#<4@yuSG5@yL z?+<3ixnWSfyYIEg%n6;>NdN)&b#qpAn)OI0v1N4G0Z#KTDqu25Ty*@f^N23lVh|kB z08m8@4qOn;AT9;65X{Kb2scMJX)cr^LP8%-Ka}Y_ZJ>I+X6G^_%!cF%tbiC|;kb*1 zFd;Azd6IH5;Eb>F?AY*G&H)R#!}p#fU?i z!k7SZ|D}f~=T*I}we_Wx3(s+@N8(oHk7`~1q&xZZzj}85$q(K-zWgtL@0I(f&9lwR z=hsiWj@ZTX^GEfgHJ40+cvY>hFJG6l#p$aDWhwVh=y*X_jgKb*>MINF6$4F>m*!6N zFzC#>=YRN(gR{fqf@ofz%KYfyq~z|gNTjl%rNeO%w_NMC!|JLyD9dFl6>IB`7QxRQ zLhI*SbVQO*F_?{$9lb|4p+t@gVkAccb?L5c=*BEG#+ZyyF)?K_Gw)?UixRaX!A5mm z!)h;%k|BFv@yz{f?q`GjaC%yUjc!gf3=aV_yH^vMCcp}=N(Ul375w__I(6aS4Zpc?C@Smo)y92@d<>G zn2N%%7*&Ia99+c*uUAh#xc|R=d`(x6Yj(N{M^C@_^N+%3s|~eoxot|7rLW+n5!ey` z*kZM6?I5stO{Vm;7a5H=Sh+ORUM~Xp#z|cpKZSTd|>1A526^MJDFYSGl zb+@+BJ^ON)26;|BH}>pnGLDQfZP?~_jyHk%o=SgRCbP@2hR#W)diUq*kS$X=n?qZ= z9YasH&8>pjAeH_~U$WzJGZxd6e5wp`Wy<0X&OPCI?*R_dzBw)Wvq?Tpu5S+?nC)|8 z9s?GXcIu^l6dm`~q4@ter1GC7zWc@1^N`$_szXkh-UJb8RD){b^`?6$nb4(FM(3P} zh<73$5O(k^k(2_ZN}HL*QBk>{KuE9j{|lELI-s$ASrBi(tK3}WU)ia6-+x;_Clj~zP4$)8Acw3j05U8^z!f4a~MF_@9! z510^hJ{EbR66An_^C}D?jd$KLWc{Rdm}#U)OQM_EpT;>q#w`CX>N_L_%8JR@2q7YH zS9Dse+hychyN*STC~T;{Y}!1xhYkRC494s(fp1guj-1Q82P#qv1fAR747aRTJ(N*)Z zz46+;!{eFTP~jKz*BE;$bt<5Cepnr>pDsU-9htX=O|@-A zwSa0}Q|KyRl+Vil`)~aJ^SAGvU$^b)QFZo;*OHt){MNxMu`7-atNE;Aw=8E|lu@YI zTy7V%T`rUAJp^^+$`aOnNwsh@g7<|r!*p1XpEcQ8m@@!jJ3gV)psw!4b&Cyl7WuEb zkHX5g4T*CQ@SX3UMVfwuVLuuu;-ecE0l@5q8>HoA&2gje_DpogBxB0hO{Qy)D`lp0 zs2RSx3&)6h^>WV}OjX(i=G=};#?L?%?p=M8_&Iqr4a}3|i)Wnprg(wOyHAY(_gi$I zb$<7^IOctjzI_Sw_cIo7dyT9o+}~TIjyo%hY1uTqW)|Yq87HGzFmniPTFa7vV<==} zjGLwl7P_vB!OCi;erBPI7LbxPnai>?%)Iv?1(aDqk%&c7^{k-4Ina6M=hIyk=*VQ) zZ5X~ZN`CJ|Yu~6yU)1jGoLd7CT%SHMM56Ti0J@X%K@&pmRD-~7-*NJ;0n6CoNnb&x zHZ&DCQ)h{34ZSytd4L;tThdndxQ_H$;|4aY9sKhlZHEq@N&HsM}QphZk~_25srbH%SusMsS z8nXgpNR~-MIs>|0V4HeS$BWCDxFzw8i4YN%IfIwbr-dc^p=L;yN(|<7-3=-AQ!~_I zL#Ht(jz9oK&Pqf_AVVd7D89`QtY?YPp8d5CUr4tZTmJ2Z^!R&=l-6FB zet8Ojq7yX42DBGn==XmTuQq=DM2Wkg=(ZfU+ctc9(SCf<{JVpblHK9Kf%AnsnCrp( zmw)HC7WYoJn>fK#Y-rn(W0DOS0h|S+*{4<@gXyV3ZSM#Y4Cx1>F-N#r95xk#B$$UN z-?T9@NQi{U8GJ9IY718q3Lr3VfGtA_5^*RWG{wr_s}`|1@7fQpF5W$nKX`X}-2!SQ zeXR5P_!l46+wFS&`26~UXJ7ZTWn|u3h|brsS#P_xGg_=0T3^*)EVi?{Spz7`a(-N_ z<7dUsv5rCYYIa;Te&v&C7M73Pam(XY>Drz~}puHZ9X5{D~az1r}ytiuof z0_&#rblR**Eo?RtZNUz0kQfgZi|;?DfA!~o_vq!f|H*&<-xfcAxY}YF;0|zLXf^K+ zvCF2V5tz}-p+OttTtpPDu`}Br7(FSQXy?(EJqu{uWjN5S|35^L@pO*bPZVhviM*?x z8T%!j+!(r78^(8*H2WUkYWR#3YT`s)IR2Wn`>gl43UCX;&J4MycF+szgp{w8$l?hk zO4O0Wf6y0JbYC(FpD5L2iecZ#E3m=!b@a!upMk16LEJJfs@b}*jj>Ip!ptm*^)R}JA$F_&n z!!H~$>>d4o3Fl_~i>GlHpI)gj!5XLEG5uUjqYuCYeZejA_YSx|AnS&)nxtW-!(-1eV#!~DXJT*`YM6`?zvGWD5R`q+|KX~+{C~NOaF=DhcF9%#*Tle{94eg?G^Zeps z+gvF&N3+v6-gx!wq#mMsCOR-8l;E)yV#}x0GKZTJO*|PFno;JD-1S%pOw;X=2!E<( zAaHLI#oP;@2w)TfGIItd_!K{30C4P4t#xtz+_e`b>p-o>hT8C*Ke_(or(u1Br4QFq ze%!tE510JA@AzWzsn&RQ-dV%#($`jZ92XDHF6zh2dlsC1aj|jEadikEQ7N}?q2ukQ zKvCU)<9@ekH?#_V{qFHmV_pkxYBI#Awa9ff*Mh3DkQ46~YTm5imR!AD2;^0Rup`gv zUF43tmOJNb2MB|yWvwaH)_T{GFWZ`7l#-W_rigjsQS91*_1fyJ#h<_l1T$l~dp}A@ z^8h>#1#VfEH{PFl(wM_c2!=wO`VvKPc(6PTg;?bqhv?WVYKFSxqhbRBm19$cMX>(- z=_h~uGsKUnwQ;@iKvaOfW*zZ*s578fl8DWEtUt% zUpfm65P&!m_-XDTrjWM)g4?%b0`TMvw~D@Utu@R)VQsvdC`14o&0{= zYWtOW;4H;S9%qj*(yfZ_t~#eL%eenNM6@@F5O=T7ZXe*~$9&u!_=l%H$0H)Y&!@S# zi|SxzVb6Zr$0X#ig=`*5;K3yWN!UDawZ9re;m+8|0SKdA1|arCG6UEb>@w6by+c6$ zk*>E5LGQwmZFb|ndUdQxGE7dO{dJf7Qt{b;Accc|21>@R-10>Q^lb_UM(@ADbe3X_ zef4ZHng}xk0##Wo7AGes>*veWHLHdYqM3Q`#UX5C+cs^talVN$ipXr{H=7nvVuBg5 zsRodW7^UFmvER+Mwl@mOv2eugVFYj!KgGW{GQD@Ca@YB^yF?q7?J)WFk(gP+5^VG| z$N|)0a;0|y(FSVD@c*Yok!hW3cibog4$UvTJ%{>|w3i$6?#Y}GMqqiMABT>CvK`U{ za_WC95Aih&8iO|T8@OlQ^O&G9oh=NwluAEEOYWpSs2ul4JrC)3Io#V|KqEU#&yD=8 z+tV%yVL)?t3+ql(@U-~!5z|sQ+Ctd?nbY(<-`&9UG3;ihiouPhpDZO$XAp=(cFIjh zHDo3DlCGs9GBYcXqYV>3ArnTYg=rj6ZS)Zm2C=+hq%)i< z)YK_dks>DxUxZ0uY{dwKTCo8R99N~xIDU=wV{cNi633QTMN@g6Z(!z?vGEUtZ|vpI)h=ELgh>a<$Zdb9AQd+t7a zSnIcb>-U4z17q5e?yfa=*QOF{JET@=lXPvOWKcjLjT`00^G6ju9vLaha-)u+r)NMX zajL3keAhd+bhYv^R1#C$NRl=giD~u9%XbogSlC1YVGINTArcq>f6`Rf!8Jr+02q!I z^Kbs~SM-hf2d=dC!8pX(SKq2W_j0@UcmLL3`t^@3EAR?q2RnbDmp}LN3nhI;j;Ccg z&2u0;ScSzZVJfWVjhP|Ru|kG4$#ajPrL1+u9+ZH_x}?b9ipsC5)GXVQC0;6@YH`oh z>&AvU`eo)RjjaGAFbIMWg$dCR?D$d0!yj zoT+Y|EvqEy)2lvr3U^e8&U~kvYy_t?6@l;ZMSVZPM+56Ve72V=qi5H}I{#3GPMqNF zQEo4Aya`C?e9u^4d}aFdkb0e!u}^=C-fYR8vuy!W_rdL3N)lPi#T06w89I%;(=qdV|P-8!?AA)NMp&lY-Wb z=D9T%V^l!c+1)_`zBNkHS_f?ty9w=_iBS+q-!=u-x|O}8*I}iQe!^1^BGvOC8+}|1 zjy+wBc-kg*Qj6(kn0dU+_a;bvTTube#MA3l{bU4v^ESbg&c7}&?U}bd-2rl@qG#UD zrS9j1J?dpck1pCS2WZWsE3I37?i7qYNgVJA6e*QQ$ad==bgCM%(Z%ed&vcf$bAH00 zF+J1*XTYpLOL#PU{#a!iun_Tw_-{>>3IieN1`|0895a#vTFy9INK6-l!3% zEUVhft-ZVN5K1eRVjD825_V0kM27 z3@H#|M*->#!;(VmARFp!25JcbPzZ(0*)zZxSVX-N&|8>~;S;y(7he6w;q)FhS4;`0 z4OPBWvs}#F707Ow-J`F8s@@FpRMbvyk696a<`dy(V7y`ZeFgN3a0TGfl@Ca*4-@@_B7WS-@3O0m*2h z*$1!GcWogW?tb#4Pks8+H>7C6PWL!MTmc$p189H#^}Eg%DcrLr5v5sxcxGk~Bf;AU;MPB?+v;Xl?T4eF!1O*tHT? z&we($`SFh*f92bLfA;M7v#-4Rt!I9+_&M@dcd8=aI|e~$ZL)}tD4=K}gHSrCD-i*g zaR|T$YJ6(O32(UUay}l7zqBZSD?O~ncW%mp;6P@V3_`MC>M)(k65VbUtYQ#qgM`40 zh)&6-N~fqYsiMi9cV(7>FMV9B?v7{d93YQIlcLO~2JK8T6K=~>p?T=BZ5@mQAc%L) zBu7S2*Y!ptkTD`C1^~iB0Sq*Z07gX!paed#0yxqM~Kc>zfV^A+tep? zBUOoynB;ZuD|)u8)7Aq$8{_vP!TiWRukd8#SOgy_nLctbJ`xvr)F)P?&ocn}$-iPA zKZf$Sv3-IBhrB!SgHt5CHynCId*NNT$(?_9T5IB+8Ge0YK-^2M>rXMSb)UbbqaT zb_kYt82?Aq*}1o}blT|i1me?)t#_Y((nfX=;k=DbcLH@FD{MMqa3d%8_K86~2|N)J zVW--ln-&P{x-mr*MM*b*6A|2$#7^0+h)4v+oeiMR?Dp(nBZEzNu0ufd+)36!Pkp^B z=B(K}o+d~s0HYEB1KO12;8wWxRUO~GvS>UkL2Io&1srMEhh1O`ya%TY1UN}uF~-dk z>cCVvQ-C_xX15+8)lPNWFmH}DU9RdsUyUx)Weuymsl-qo#%SV+R5+fT$24pkNiHMo4wbt6M zk)4Qs^n>HQ=broV`r1{zdieDC$6x)Xz5WrCLsJ1TM1kOwqGHFqQOF8t>QsAV!h+c% zsK5l_Lv-inl~hK}iUZ(fTal~5WLKW4ioFF_0EY?%AG=HobQ3Rk45C40Ow5`@R3aqO zuq(if#84V2(OV1oPN7q`>nClBv#JU+ibaxWY@Cipqi-yZ4p5_GHGl{q)Il?L7E{;K z4@Qv@X>C(~rfF~89*rk~)EVa9X{!wnJd%3fFT((=I50r$?@AkXop%%PoE#9)Pqig{ zw;1qa1Kh2@hKf}T1rWFOxlc$9hEX_rKNpAT+YSB#L%*+{E1eUqZBvXfWm#sK0{{^v zLRC#kf%A~E$|usOl=+lmOl4MTRME9}cZ{)Vnv{~YHYz_t_B~rJe>4bkp@nz zq2-f4Qvbk+PjT1->YXO~z1}`P2H*Yu18AamxXdH==Z|cB?^u%S)ti*w`^2*ydnbR^ zlPPzuXRePUF4FtlH~RmbuQT##BBXDtqG8*E9A~j_gML*1dmXR$KrScTN7?*-#$$DJ zrs`>Z<;g})c-o)3kyq&~95*T)r!6>;-rm6sXLOO@elnv1Gp4SJ+p*2gXo}JKEmjpl ziMW&g>9l5zF@UCLdeiCHYsg~*?aBIPhMR;zboum{VJs3%Jk9~!h^*>4^$t$F{>6?qn47p zZ_V$-`(JtO;LW9kY)6W`)leadqO0nZK!IO9Qsd(M;qt+1HIF(Am$NKygA0;ce|)@Z z0GxAq9Fqzvf`CC{G#1GqQc4ml1MZtV`?Zhz6#LhSbSt!fBa)l-)!lP2j4CLrtT7PyyIuf=Wi}|cc}o^ zz#em%k1Dz<AZ?3Yx+Lj-S{h>z0kJjnKmKSuBG6Pc#9d_;y4L5L00rB<%--}HE%<%i{ z)!!Nz(BPH^y0eKzB03S&5|J#k-7ynFiZOQSzN(^e$m8A1SEhUJ+u!9@V&-g8Wd;e_ zbx9jzj4^qhPpA3uQi*`5YcA~M@W45Hst1DFNi}RN>-r9O9W!84?!ZGEraKwnO0VW68X-mg50CGT$zX#8`CrQ2YN;h6Oh=3rS7Pny{B0!QZYC>WpKBHo` zY0Y3FVutw0K6#oDQb%V(g|mI3C$fnh;hr{5>U{^B)ALd}8*(8rC}|T~PY_H@DLF7Z z<+LbLnTTDE0P3NIhKgBqhF6^ra(6k|7|AOj;kq?@O~PI8eQ%?btfwb(w`dGONMhKb z%~#FpfqCk9E}y(wKKJaU+a@gUMyq^nT7J#`^wGi6?%Ah4c9USt<#=TD>-XMzoA(CaWWS@$NyAe{1`{_?zFGjVqHghJ+owNISo{vhl zcsY;jrdM3YxLx3jnO}o1gi6Q^Y=Ie|T}#vI#-y$Lo-UlOp(LF&BqW8b?NVA@^O_<^ z$3AZjoawblvNo!MOk&M`xu7<8O-oHHP2Kn!%#MhlABblyWTi3kcAvewp|d4NhnuuP+}U_v%UQTzn?$`m!yvkq2>PN7KCWO7n@v!GYxSh;$Ew^x9)%Zyn=My)+vkoSz=OW|2aX>tU`w@p{#shD3 z6LqaW@3e_w!_v_+p3gX3SpMDIZI8{(Ns0VP0blR;a8 z9ZG?Zg3x^k2c22P&`C_3DL8bxq^c*#bZ>W$2*5dh%PE}$PjaF)cq0gWCWXRrVUwyvcS8T+4yW#yNV!DbaK3)`_AA z_Umo}5o!Vr0EP^c%f0eSTQ=%4lx8`<^RPYSA}?39zwsY_@?ZVspEl#Q;Z7%$@~zK( zk-qqp%dq12IbR3wQ=TKDX)x_$v&TLW(h8?_*I#-gOSP6QD&y6mJedR;eI z|JlQum8*b2W*q<>NXW`jd1Y@;EARVgyY>Oqn6ik|VtJ;v0uA zefLU)=SQRWO-4DSSHFD!ckj*eAOFN;yt~6_Kj8n`a`j8a!L8=bGhdG*G(dK;YyX8! zZ+`m6%AbFMAs0{;Km;UX%sOEhi&sKqQj`cP2wl7C2Np&NLPwS*kO-a z*YXQzaKSFR6-kIj6^vmb6w#C<4B`={F|InBB_iq&XaI;2h}K6* zcg^)@N>oiJ2L~b|!CKP}FLq+}J}(~jxhliB)OcR=?(Clj2CN9@$;4}4j=n%}qZclC zju4CkCpr$?SeYMrL>sPN(lZ#me$N}t6ZVIO)OY<(UvHz?+@(x{YbLM)s3z&mH&7I$vvFRtw-M4h*lgIALCgyYmIm@i^^yH44FiTCkO15vL5391qUWYSx-= zYgfZH8~Tig+erkuA#$9_v=tFG2})vQ08(-hT}p?BbGP>Aql~hG3njkud*6C>VdtUN z%7e*{V>5F3gYUe&Y!lbB%X{Pe>i(^VOOMVLrKZrTTGpJ?l+-#Cz0bmfa2%FZkeDnP zO@v}Ba|&doT(}MI|I99=3Keub6F}4HG;^0DLU!}Y|zp$s++>ciJDM)B<+W@*0rYy>xm5Ti3-!eW37MvKA{5qxSX^v4q+YI(>0JH zOYeNFo&BudR+PTPqi5fE^8Wnp!xr3(J#m{{ahr!;AWEgo+xAvPNQ_nLB=Iia+V-RMzyHUp|mK{*$ZGwsq2qsW@hN*pHxrU1O<_pPmV)H zTnoH(VYCk9f^Tb{45pgDi-r2g%G1Yv9?BM;W2eCItA=jUm%1B?-><{`MUtdg4#dKm>-!beu6F zR#GG)!j9p!ei;!_Ig6o@D(G1b*4cz`6PanJ;J>lUIxE+Rr{`AhdJz@a^x(@GTjK~A zJlHlenKGBBE|o7le+{n`Tpd($oR#Q+!t!|59PO5s6H>i`r>X?HG2iTjec{n8dLyQz zZ&QO;1tb#npu$8cB`*?za_iV+O-jj4rdKB;!^${fE#CG*|ypZdh>KSqwN4=@_s3-x*+}`c| zq73{-k6)-s&fp?v189Eq0jYjZrLKXK9PvDab1Hg3gOCQnwKDQr+EY(-Dd`c-r0ziN zLz=md8;$zd<qMQ1thGiAB7(7iYOOUU8N(;yA*j3&6$jN*pyBM)I>9F8glM}t7?Yk3 z4&sT!EySJ$7UlF?&>3x1XTTW9k|9iWvx@UOs|PRF)$RH5&4;UMG&W?iqxqTZT>ZiK#-u|Ta2Z>`*8V9)4sVF9aQBa zc}iMMc4+U$zAJDgCUev2wSdOtMs<~uZPWaCSpzGZGKjEYZ&5HHhH*YEjf3j2jOpeC z4(f3LV1P(~1`@=eOIM6`S9a4_so3Q-C;-qpN-2p76EbdE(E(7_0-B1zsDh*@0O%SP zJipfw0Dw1|0M;}S5Y=_&s5Xc5_EO!ig9L2`@$yvMrFx%_4*0$k&JW;Kr8}ADaE9 z3dD9j?WIf47y*zV7!bs@zidJzum-FlT7fW-fwbYplL#bPw(3gDhCrhzf?7cEHK5fK zMc#E?1yB(-&Hi|9&!lx={YYh!-a8^}-$zp~wPV=+PXjBHojm9xo!RgNqcQ9QPV8{_MX-e1}si_^C07*naQ~(h| z0_Q*zFhdgoAll6Mm?Xhy#Myif<9wx(QYu{`fXA`%1}8p45R0NBY)n#Kg_z|T_|*7T zQ1i0zBBI7vSgoLN=Z`uBRS^-=qypnnwphf@wuFrU2vG6(fUjqt5qiAdvwbqua|ZM7 zWJ3JeL+6Ye7WF=`wq@R_?J>gf({T9^_Pu=jMtb%>Elltw(W<)oW>wy~{Q$`Z6#8k@-~s~6T~;9CuX!~hwfQKU3A7%WBt3}PyU#BszhHS!j~ zo-1~BT$`3It#D_w_h<3e^3wRa%%8q;?S0Q(TfO<+1otDDktyDcJEfmXlDbR@Dz=42 zUu)w6cq>0TzPU>Et@PBrJQ^=gfQBm#|2ywwc})=d?RGkfGKu!r~H!*5RE22cgmM#!L! zyO;LsW60h@FJm{ZL%X_S30`~}KkRN3K(3=8h7|nC-@k%M;B2d0-~&Ae?i_2 zRrg;^4(YsN{>GiF6JvkOu6n{PKDW8B9M|;OU4)? z$g<+$gX77lU@Df2MoiZF#&BV+b9ErdqY$yJ>;g5fl)+ zyfH~YM4Q_fO-is@NlLo2W4(vqlQA@OXQeI4oeynOw`2p68psuJ20NdB`RX^{OjAD& zdbReGCgn#f4)EG)_JupI+_tHXrB#2_3ev1u#>r28=IMX=XLdD<{iL3XYeHXM&1-Z=nJ2IF9qRe3%ekDKuh>?Tb&r%L15 za@H&s;_MioHTvAjRXbN_%=e1%1a4O#4@_Q+d0LxN6cMA%0E~e)`Zgk>X^)#=B4)^t zBt{<)2!L%dwkF?$oUAb+pKXO7yd;LF1R;}q|r^P|G%4mlPLSz&8bAw)2q zvSdKeOzo;_eG`t3=5ZxFb-^p5kuXt8#7t=vlZh2UW1Vb|%B5SHw>__&N}OdJ<-Pzv zb-5#_dL`R`{)r4AKrfPXxXlg zt>4?*z4K;sHz>?D?uJBdx{G!sy)14Ixx@p>jC6-i||K6tpmbY)ar znJ+9^V=SQ}6N?A{5K)W~5vSAX{Mayq2zK&2Yry%`zevw($Zl)j*jhk2SRG=hBK+Xz zju*Nh`yK%g{l2;-&ic^Gz`(8ziWpP0*0Kdps*E9p=wq1|zQxY)$7Xq+!U6=FoFPF736L2HzK@=n@9Q8OicFM|8b&c-4CD%Xuin1? ze|`CKE@BniW-L+L;PX);TzWdpN*AnADvFU$ag`pv|3@zUOaJ<_Q-yhZjT3-}(t;vX z2?E3MssYG{t(Sr8f_Y79^HvKC7Gx&K!``xj5s8^T~5}p9-tyI7IV>1;370@#_9` zvJ0UN_wTM6U}d%$AjBls5L=0DW6ET+V6$EX z3x}@v@3nX0UA`)(pg=)NHWY{jTad;{G9=8-nY(xDul&xRy5r`@p1<*_55Mns|Mbgm zeD&eoH*eki>_@JB=*IN&bxYPZhu6RS=WaaDzxzirUyhxB|IO>G@629=eCJpH6%Nr! z%n;dTYOu&aEMU0U0JPVCV5o}MmSTjVTv!@fx*dE&+qsauX9gwjRSK}JmA9Sw^PVBl zh}#)wTzA`?(nCd4N>M~Q4WkojXCg>RMWiSSNxWJ{rjZJT5P+rAC-3|Vvn=Z>z(tWQ z=A96d7(+x5qr`|E1M+R`=O=D5_})y=ZH@DA#bGW=azOpy|NB`iT+A?E}y9h_4$yMi2f{=zJ zxw8#I+f-y&&>kEwLWHj`?*5H`=imC#AK8xtRomp&A%TE2ZEKxF#2`Y3vy4N6rfzbZ zdmlxEwd?~MOV(i10QFcG4)5BQK@SXRSQ88-Ww0__ehAzMKEi-}r-9|L4zs;l;oGD_4(W6`hHBw!3$^YU1JH z;o{)oOvhh8Ja{vRaXW=Lj#5fAF{dPSZ4~V1Sef3@9db#@Za3bnE!&s7)=pW3S%wayeIDwgL(2v8BS4 zkX>!?(&1uj2=wrScG&yP$jB1vRV6y2MAlld(3)t(fB~ChT7~=HdIMj(H+kt+`r0>c z9Uqx_b&1Vqe&MG+`3p~10;z&a>Dj;X>>L(H0h5(|565ogzd_;4`yU>^5Bn;Pq&kq0}$23Y&KA_&gV-Xy)mY)>ku+y#*MVb*|@PD%Cd~83{rXT zo5r(ovKB@FB8V{p5Hlhv5_E1$CmsEGMlkpXy+821*o_!rJCHkV$%1uT zNNTUKj)EZ&)EJwh%nEB+U|a$)NJ1h6$z${m+)sXD=QAJro4@`We{)#_Lww`K7ys)u=UESX~UdEKlaGDs)8#M!;``sfKOVz$QjkJyfdDc?;0z)p zfgq3sfFLIrLB4nZSz!R#7>qG_-=v87I1kM*gh{uS$PIgcV^keTqba1w=xthzlI%d! zI!ZLbSf)VU@B1_j^+K`C3l}*+Mm*Xrwal(ZfhH6Y6^R`qLOh7g#8W<7uH5vC+ zmTHJDu_FZLu@A*}-hl}W?*M52Oo$1JNuY>xMScGT+b zVTCW>K7KF{=q74QWZUMHYw^l#c3ifvw0X&6GWgtQ-XC(H zdf2|PwSKjMCBMrpdW6>UY+}R2UYV2yTN~p}3v+EKmbOhh`Gl|1AuQjz_40Mu`)i;4 z;8&WEMp={K@TlTcPW;iLx-)4TG#TWX6NLmz9{HOebP0S2ASh^5qlRcuO{#;-E)?OT z!SZJpi$HG+7u{N*_8xH{hTi|S_Te8MM10uy{eOcB$HrK9?d^o99qhymh#gdnF-8D3 zh7%b8*x4P|OJ2+Z8!&3RrU?;=Fjm%(O+5mA*u*^+4^KpSS+y?cN7t#2;phec^K zXJbePO-iclLI^<2E{lLcbUc~vU%K+Kk6+6iq==|6F1fYE{Rj7u8>XEfiv6T^5DkD}J?8Z@W&Rwui@UG?*_*5BXy;*t zbtFWDuikm(=wKnv6qCGsMgt-4 z?VD0l@@;6nkTsWcE6s7HnHE!td2G|vW(Rlu|MFk{Pk-;TuRiy&=M7edQ6pkVHdUM} z{N>A#U4H$x|Hr@gV0nLmPy!cii-)lu*<6ak6h*N#?%Mv({pw$S<{1b9BvUZKf-?cC zN<$V7!o3}O>S6&M*v@{t3@gTwWs`FzLPV4pT9a0-N@h#}zOCBDVi#Oq?8Gd|A$;g+ z`S56U%g3~=v8{7k=D>zqU{HzD9%`;^92dN|3)m>d2xy5R8WV(pkzIlDVgtva;%9y9 zqR*gY@NqQo0n3&WiT-)Ar6!MUQ7bQ0M(W}-oA)X{F1R24Ri9=`O)U;54e{Upakgh zvM5J4KYcX@CCu|Y|FIwc=wJPn=byfLZMj-t8i@1{oIgW>p1yVDR6+zsWXFcUigDr~ zNUotJNscQfHD>O)QH@auy+vjQ74Yg^TA2tbt;$d^laEOejA0O90FxkYDWU3n83(3S z4-g4FVgR9n%s6}A-G|uFuFb_}-rN^?5ElEhcvKcfM)3OWFTDB2H(&APWO6^_8^7?& zzb-F5Q$M&=%;#k)kLUXNf3}NUMf=w5md~b(?D8R0GRcWuM48KMTJndl+6nJIO@u#=tQfxKnfqMnJM&#d#6NQBIeUBuVEdf*Ck`v?z? zIHcUDk(3x=Vn(JF3r<|Yj-n-HT`f@)_&T=OIu+w{PAIv9IZF-~F0I6x3Ga`<1QFDMtAybJ0ftfP~gfA>>FzRQZuR zUX;srzN-fmpK@4;f~HQ{3`M_}7;rcje4sut40Yzvf&0Kv9jt-p@4(mg6#6cf11;ML zXSRljU-Wf`j@x_4f!-o{T#?qk3B-WR)>;v1nx<(Q=UkpUV@&6e5`e3!s+&dTcF6=0 zGaZehw4HNGmSxszN~sO4_r7iYVo^<}<191Y0}(k##6U!Hs^NtjfnG%X|6F(K59EBf zz->w2qjBi_+^mEYpbf#0%L{-OjknL=d;!gaYBh5z6`^iEvU545Bp{r*Xe5GlZtT5C-YVL<4Xf6pu_iB9 zZ8e+S`{O^n7XudA{?YB*|Kg9o^7PYx@6&(D9VZ;h`QFy}51m%K34MqlCKb>C%u#j~ zqN2#LYRV#8am3{UxG>%tH^)M>1Y4kRo21Rk%E4k8GYTfpB#0Uk1KtNzXaS7a3%&n_ z`~-=a8G$0m(XyEzEtdy(Rui0qEpe(eiu9d_@oOu&3VdmKe~OnbwTqZxr2TvIti4kF z*suL-mwxv@p1<;-3I4%b4|ZWU#pyirCYz5(&#s`TVb91S!-CNP8DL56@;a9v%TjJ} zW$CDmMXgV<){HSPZcCd-Q@C<|_<)?bbnVhVc`4?1mW%3OG#UHG##9K=qFU~%fSGwN zm;RdUaI~pSOP6Whj$GSJcSf}-qQ;iMV036wz(B#USU?WI37BC78C>u@844uzy`G{H z2pZBur(tBSr_pW(lq}}#5mEz-;&k&PsZ0(ikEKVERN_(h*Dyd4~=A6WSzIcI-Z z)JWc|aoZvSJxu*TwsfFcB330zJ_(ZbA&p!vO6`1EUe0#Mld^O^04j?$KBmyY`5%@NV#LPkpBqE(nJrka| zPksLrcd!#u?|$AR{0_sMTKc+u2RG*pJYaNSclKaont}2VICMU5kCVNzQ&}5utp8d= zZh$$99>Br!`2OC$Mts9cGcHhsmWzr|t#PW@CIL9y&nSV0I{Fw98544=K^M&2be#YU zbu(90lC&ZZ1c(^5B}0~4q$)2E1p(Pu&=f1sHc}$sk-OTod)N047l+S$@<+b*(rf?u z-~aFa>;K{3%lF58un3WCHcA2_U=5%|Lh$?=1*%8bL65pzN^D6rOs1omAlOEC?Cya8gPjVj@*U$LMQ~_4 zRpA2GakKC+ghLd`&1E%Z0Cr1FIjK?hUM&*}KuRE}#M+siM46~UtihB}I=*&wZ^HL$ zJ}UP2%Es=cJB1#Ax$?n)jgF5BDUSD!8D7}mKYVz2=}NH|0#3u?{=&b$AM4jk<9E%? zM$P^txAj;oYUpS$n%wj911p;$QaMII=I02$X&$rWBafS|0<8A8;=8J6IowpH9Q z28cC3D3TawK#yH(y(P$;WC{@T)B*fY$WgdQ=w7$fG~A~*EF#7ji7AEX@=O?-)&o;D zc9)hajFa2`*^#{TrSJUn??{7h{>F!&J-UAL^S}T5xBm3ym3`j_{_S79{uDOL=IN2Y zIs4kDaCW@-lk7!X!hO0l`tmmy|KnHr$N$ZrsP}SI2z3>nlgTd^2D#GBvf)h6EFvB1 zkh(2|wU?4H?0nG+mLI)nbyM6Da!i01djGu@LfQ_(-RB1)eX@x?3l;gj3G{#HInW*N zSyd4U@l*?AJRX;2DIy{uqD0tvsfa+9Wm%RX#1una*Qk^kNtlc+nV{=C6p6;r?(TTi zz*$R&E_N}-G>zZHF{kPqB03a7{9!?SaZ9p3IFQ5iULnChcp31cf9?h>k$|C)fO42u zaQFU0iIS5GVWkKlQA89HlL~eTo~o*XcILeRNtF-)Rf&KB*PJLoQ58|q2&XK6>V6@j zL38>BQN-E3?pZ#zD$$$FS0~Zi{O5!pK0lW{EI$LOd zPsTH_3Lyb8umzeZCj_SuG?AziWCaYsp-eK>k%eYNDXT4IIiUkl zB4TSIfY(^`Y^{9_rdP97lO4f-hJ@GgpI*E zEE}~;kYFM1POqiIwmhbN^W0^5qgfhIgBql{ZgyoguV;z5c<}J(wMA8wOtyUerNlgW zIL{B86r-2`nZh_ooRk&`*%(Dh5tMRk$T);4=sN398~=1g7_n-IMh&4YkeRa)IE-!F zQa8H7g*Sf_09yut7$c*}Gp7Ld!O?V7to-3U@2;D@hp*jz`FGy9HjV%I|9)|K^#-jD z-d~pH>g4^Ox_sj~Ko7e!xOVHlJy@i6WyLzEp)JO>JpJ@jm#^fr99V$MG9nOw_0SI7 zhX*6C`raU{_`}`Hcj4#t_U7}jObE9`(H#DL-Qbn8 zoE}?ykXzbl-m86s23jG>;HJreBe$i*fVcI;o(vu6+JkUCClxTKh_Ld_{xq*DsFur& z9C}p{0u@c52~h~Ji%Jj`QAuQN#*EmRb^~-$Hftv}08~w?NzY{bCvzSV1w{}*BB@#w z1{KtVAfTE;ZijHfkInpNY>SR;s<2TzQY<%_uRb~M?)QpVKQF>`1z zEn+$jK_3zZo8==6+*Z&63A-Si9kjTfn2g1HxR0r)M+s&9= zP^#J%#5F;T7$pnjm@;A$gId>ao-h%uqh|n!%}5g(c8r!GjyTH`7;y8gA#HfE`}3yD z+!zias;WVZQQ7U(knHu{X|}7+IDd`Pb(bb|++Lqm@)MV@e)QVa&nZoFkaH8ZgknMYnUGdck?bg;O|&zWsYZM%N95NI;+fDwj)&V#@H+_@9aICoB#H|_=g|5?bprRz?FvM&)8FHvLFj z;vhn{b`SwF2Ae@^V3xzN1x}DVn9dia9AAMdYpI2@sgTr7+^BAB=BsSgO5NNENkM%Z zA*NL+zFk2BSFBt4?I27JAw`VX2(cxX6R?2#w%REZtczn&fDp)n3IJyjz~*2bUz(Pa ztJ7WH#qntB-OjWCIGVaV8(+;r;5TLg#Ezam_79xfozEpy&B#t-%5%(C$Ma)*VEhC0 z`FLl9V(+ZlH(x(6qbt+043Io}vLqtWMgdFdt)1sTG`Y#8R^<-g*mbnkCBV!3 z%@N1Y7MX9=Xg*4|1q5VUj8%!jCIPmVD1jzW1t0-c!315Mgqo}X4CrhyP_@Y#^(wg` z^4n>WmMsM|*dI_LKuki+HZv(k@Q5MGI9sjYso+Lr$G2zuhX>c7p15#?*N$hivB_>s z%Y8}37(gKBlC?s~05guBK*d;q@kkoA9uN!z#)JWo0X1co>i1}W=D|&e7rQ?XMxZZT zlwvywYu{zk1sjtM9|+yj`-f6iE>@i22QGjfj2sXU5Xvc!q64I3^u&M(JKOCf35XFP z#>iR+UxmQ2#Sm+Y8dW*BAe2&6MQg3Kw!7d)3vbOm?Shz2+~bj*rSmA<8nC{l>);Q` zb%t`Cha%JORjH1*rF*^km+oXr01CiFlWEyTKme-Y@U_=swG&00dPLP)V$ynji*~#D-uwlPDVE z-gGpt8}aVa&Xw=Jdgs6TZ~o!m{X4&Q{VKGJ1PYQ;N=$}DWng7spwnc}D-b#&Mu-M- z54%T|^|j|npc9NP`Y{pAmv;^yei5onjm!6seQl8QXzv9LFMM$CBeto%*_}#ZDQThD z*jT)9Z3Uo7X-iZAXE6{PPR0Ef9wEzGh07*naR9=$&h&<&ndB`6~Vn0Ss zG-S(;t(KN$N+KyXA_xKm3ROULw>|eXU$dLF@^GpEkm99u$a@VysXgwfx~J;i?|f%} zd#^qB+-uF5?su|U9P`48->Pd<4$%~H-Sp_{lq}luwMvWoCwY5zZ8)uAxVK$bCRyL4LWue}2aEz%xO)ck&$edGHy;v%elaS{S z1=cu58pMz(U2)>z>J;XoV!krkx=~)1!^7or-j#Kp&%35yG=jaYPGq2*D}3@)%t}?J z$@JbRmu0(j_wVi3pSq$3%rI;?Mq)AqsxaQxjax39 zDkOEbF&yn$y2@HMto@*bOmKy_-BQ*Gplho_=WS8YXxuE9^T&ZgAKw6dpHZvtoAsrh z7t{Yf1+vY6^`<$~L>mJ14WF;*`Gf*uUDqQLW9?LL3_FMYw}#*QH^03+I;qJn4~}-M zsR|qWRwXMynk7X;k`pOIC9TVEa*~{qfJiArb5dhzofZ9#q|Bov>30DxJuZnPfKtjz zaE6Sr0E3K(=GyHiZU@OjgtBKHq}ATuxN`aTKL6!^{42k7<5~$#mQXm86-mWy$UL3b z{0f%q1O`gNs0(|qyyoAzgAFHA$`A%KoZ;gK%l_e=XRr13a5`Bmfn+@^ zVvJeE&*$O(y`y2p!w|Ex1Dn|C(JQmlSz49u^S&k3pZ%F1{pj<1ue^NwE*`Yk&yggdppv*o}= zdRqofZ4Sv7Kk>6a?HXd6U4hPDA;ZQPYrV17T2Iz6v$s$g3}<6}jBIMRd!rHy6Y##Y zO=mSjok4;jMiw8Dbow(A3%ha`7*is{uWnGlkex@L1Ys)iK7elx(jsqBKDj{(Zr zMRFIrAiZDA_vRanO>;3XHibhjy2$dJa=yn_R;#+M zjdkxR7*v(fD8>r2WwNf2W@OWnq8Pw9;|<55&mjzbmxdl~+ZILPy<0z2W8fT|bNVh- z_Z{T-*%q=FoMX4)KzzS)py{0MljwW`6VA&p<${fD*8RiG%*Yw4%FNzlblBlp$w(<8O!?Os;ZKe@;j4j zT}QYc@FK#zK8|K4OJtZVGaoNjE|`=sw1XS@%3&3jMNuG3LtIao1c>(>fUHWy7ux@4 zwVX4l5ke|pD)rr|-@o0s^bm6&a~a9!GUb})(d4oUqo@f4W8Dz3%*>;vu8vx`d=6RQDNzL8YPQP}9rYSA4+p4$yY}eOy6wZX>PWok%oNSt!!N^S9$c*a6tXp2G ze)L!W{?ngC2Yl_=?BZaTtJ(#}uadU0k zpDg@n(iL{+BcG}U(;K8r#)7gjjx$(d<_+;MZyw;zWua1Rs={$zK<#~Eh|f#M`mFeQ z;SBeNjP-dLplq1)eQpLTXXZfj1@|Z}c7TdNzccfgnT;_q4qX>ktCe%k7f!^8B4@FN zhJM+tPW!focxzF36A@Ke)esqG${A@GmdozsWSNnPXzfQRqB&CtSgls;T#k1{NBPr0PA{y_gK~oaux`bg@R?5 zQd}Wi~!z#+VV*^_fnb z9MznU4tAn;L06=6LRfOURhHL5hl9;BIL62om0^t`C=gGIzBYv+$-d8q9TJD6rP{vS z>~ozJH%!4IP}S1HN7l9*AtIeZrb6QsotLGpj$DzeQE{^x zOSx^yJvbRUn%cUsVzx?t<=fLgqc9odm9+nnw)pYqZ(`BxU<>ViP|uijgNw9XmNkXG zM3K`x4C(@<-mYRsu-?~0ENy!?vU&HjEILl%02l2sBH@A2O;@r3nT~ZN&kwn#yB$W&?FvJ`ClhB7FKA)eu!iGC4rT6Lco{xdl zc{SGadf)R&am?@2__QiN$iRJXH$6J@HFTlsNe{nv`9Vx5EGxrE%B#Zqs-7&DOOV;#9YujEaz>2FT5Akc zQP=e_460BiW~d^iH6drtoRG3<)!Sb%K!3;xLL2IU(uP&rn_9V^xk1_xNa+Q~J=qlR zo!3ki0<2_+B4-vh>Qy`~?#*mo1zC{}t|^l8$kct`F$txh$V^HMLjuXl8fc%{IWm9{ z95ZKRLCR_z?XsWeyil2Bifvc|mqTP{YssB+ePM{C@?7K`)VP!alh^{1RbiN1mKakh zMwC`r0@N8UBr@mW()8r!^=h>g5;Bf7!V+X4wdb=!p7nh5W5oYX;994tjLi^BKN6!$ zsmV-Td2KqSCT!thF6?w_+z=0z>1e3Uij6rjr9*0V3bD{Fom{i(3B7fZ3kVdpeTl#=suhUyDFYo zYn>QzXk*f<9`#Z$p+1&PsNLeZ>A0Px!41BtysWyF{>f?iw_n8luldjBtGQa4d^gap zO(SLp)h6%nxxN>P?9{5M6Sl!YwmTU?##<#xK)dK-vDKw3QhJG(+!oSy6L(w5mlPtZ zlTiyuX#;{Oc#5INYRI;%w#u?#H)NHfpfHTmx`*_;=Z_L{1~5{CK>&aZ1Le6fOdIDM zoMEh>s54@exl3HyB1q0rDi_3Na1QW_!WMnV;>=NdqbzpCad)G9``+oVzVM>yR=-gc zyehSa5tMx+9E84Yt7*pWtO&cQ92IVha~m-))ehZAtE99raDpw6WS}wxxC{`! zYSMm0RaJR!+m)ois<0MWAtK(wiEl4;Rgu!cWHy?TzTcLlKIWeM~4yq;$dk_U?i~kCjA7l_XW&0LO3>CK;U^ ztKRMGG##9}-sH(rYtVcs?#$%vg*s=%77|>Sf)U(fb2FATurj0OoEF+u%#X}aEqTG( z@>@hh&G0sHTqYb3tHWU#;f+;_nUGX7$gC?d*3CI5l42CH29T6O&M3=jh!F-kN*b~i z@3Q8htc&d>6(vgQdks;OK~VH8oVhem$tkBKq;MqO41#d`b?g{7K`EW@66`5k_MB~^ z`K^=T-rz?@irk-6p*517$q6vl*`jcDl0M0h#dKMSOzCUl%BeL2xK~b6fA~XawCFNS z&2YXCxiq#Z>}e9~lXnt=X!h2{vP>p7VjjBQT0?nQ8OyUaG-T?nk*n~~3`TR8oUJc` z$F^m}a@QA2U&f;8GGahwsWi0;`d+NzCqeQ_d(!?xGteJ?to+@Zj5WMy+g1cQ=a{oG zkF2Sfxn07!Y#1pfRbvc0MqoBZC8wA|Srm2S*_3Rw>v}<%b2i4T5pzl^LNUholJV5q64g|0*P3eiH)#|s)kf6 z)`=Oi_O@RGue<=a-F2>#sLo+%leHHff7Ysh--Y#wfFe0(jbJ5U zXWw`H8w#+5(|7`%fgBz=d7xf-a)&r z>*ByBu?0D0n?sSC(DqDfO){QfQE*g%jO~N((R8p@oa4+$Kl*g_%yzP|S0@1lsz62! zTMbX`RsBFsWd>ruJDz%>Rof3mlSo5CXme&JU#l&{KsAgpRU1*j6{Z+DNQ{=zf5<~< zGKdJQE*o-eOb-lTFtq2wl({G^IWBUCZZ()*`WC>+X?rIZSMMF}Z}W-2Hu%_Y*`+J? zx_hH>VAb|lfVDwS?i2)?4 z4rCxX9f4Mq2g5!S3bO?OER!ZCVtg(QLuTv(AsrpgCtPV-QIo zQix=Q3bW>XofBlP(zwoQiT=%P-iD3+-oS81xiO`rwJKOcw zyFe#*Ua&x8w`~CJg~1QB6Wi?Wice%M%xpH)N6oA1Z5;hhKK@$)OFEX7D=Mn zu(b|mkQ7%{**MDH7)1hWT{~kk$GJyl_%NJu!Qz%M4J?z37zS8dLmERRAxpHBNkeTb z10a(GHrWhAOo*aNxpS!;QJMSIQG3+7ZB@NmHyH?BPLX(ACB#+gf&~mUg6Cv4Ny}R&a_QcMpqqZ&S5Z(A<07QtOZzA zSF6moTNKnZ&Hn!WJL~Zi;`vGY57Zbc;I)5HRz)5TUUPbabOK!} z1*Ij}!K^4wpo+ELhNVYfS``=|f*iqMWG29Rn}UQ0$wg%VoIqp01PE!hwblOT|HX?h z{m9d!;-JrC)JY zC`Nu+*!_pca_x#NQa5XxV#39!9ZnXIWnL6cPem$c(iYp@Vx}kw+|=H4?my%U>LAEa zV{67(fG$(EuA0;auN@tP+xv;{lTCg95aqVJ*KPgckN(_$`l+V)@%gFy$gNka{q|}d z(yiC32xkr?Bj=bKga2?PD4T|~>O%tZ1C4z3NbNz@J#!v-)w3GLZc z5JI+)_EDvWtl3wr3o4}RKrzIXSLB?DoFyz~Lu?~w0w^a5L+ky)bI*S4%Cjd}p44_p zO=j&@v##8#ExDuxOeBCTzyt#jgIKc?)U5HUWHP$8cw48OG)>VobxdoKX{3}K^F>#k zq?GC1_U=wtlX$}x0Kt*e1=kgm%hM|QN$DIX6^dFrDg_mx7+0_jGYv5W=W0hrz#-wB zgdivd7>L+0*ng+Jq=-KKx7sMNN{au(8XF`$u~s&pq>W zeP#FNC;0di{d|AhX2XbWtXF;Uhvl7ztK&DneV^jPE|r(lew7aVGS>OTR-+J)l9kER zO?3rxMIIywn+7RS>{3d(;DQ;}8c!DaNsN5bp0pg(WA%vX2hbGCB z_M}}z6DWfo6%i_+;5Cvq0kQ%HP!eS8875~=CTFlJ1W;PDlUNHpTQX#{U<-vp9a6Pi zEQdCEQ?RmOs)}M-pIq9lFu#@hXR?z5c6nkPO?SrAHm^vQN(2xyy<;S_&NC)aCgODg zBPlei0*tmhdFGj&(b&WYB3;kZ81qFJKfM<{W376r3ZSxGRW^o@Bs=PMx6SpdV{O_x zb$;Ti(xT)byT?8BBszy7cGf1gxu+ZpnV8s!)3Au;_PN|=U0GO=7+1nX-2U3Z;j3?N zx#n089?WT8^fK6Qz4q3nuz=Q?)j$m?7^)eX*9p)>c^HN)!DLkuK(=?LIqAvCjBT-d zWqZ80Jzp%oap&PH4@z;h8Ct4*A2N41%Ej#MMSEMuGtPB5%;x%d`NEZ=)_BVC*kFd<0VAYR{)17NQ z0-zlnhoQRj8g+-mTc3aJ;o+@?EkFL5YOjcJ#uhhL%YmG|I!NC^HTGSvrYT@FDvl2i4i4Wm{9IA^ z)nXZPU~a4}07Jw%>sq70nsR%0VhoJIY9(u}I%amxrIgm$&v;jeV_mEC1Wi9_=ieS1 z1VZIeY6cSt5oi|V#L&V}%p9F3xRj|iYJf}xFknEW%1Qtsz$t446DUKC%fT(6Xwq`IywkU{mmSH^EzIpTJ>07C0Z zps@?5o*aexfBD@@4_RWd?*}chS)pU4#6os%e%`#3yXNwWFM_XO> ztW2(S+{Q?i6N^a$%>}C#-VYs;z%sG%B2QxEllG*2-~sewd8+qtJn!q~Hv@(#E0U-; zP#}tCs6*JAOuK*}5RI0hiIEIVVrJv(>qEHT)RTFarL>7%L5M?Jm34|ek&>a~)8om` z$S^{{FenjOYpq2HD2k$~Cn=(;Fbwb>F(Jn6y*Vq8>3KUIeHZPmXIf63#b|EGfSzR# zu;G3|uv!0{-x0r_F@81_a6Tuwb3M!Ri@tXcIfR_6jxn()!{Wq_t#eoI{vqxk`|%FC z9mIRS>2Kfrk-H}!D=JBR&s9irI-X+h^4NN7t+mGG?wQf(Uz+%PNOz3gN;o!q59Z(e zOcy3xaE!gRakhB*+Ks0kyn1qJZ`%wS&CQ<>wY@6Yqom=mzIO_$e&gGL}v(o%7)Ho(o?EX4t?t> zZ5JQ?(p%R*|403JsamNgmL+$Khco)kuO9#ADeK|zbVI4tnl|M6F!-Eq^Q z;H`zVW%0Du0Nio@reJye|*hprmFt(!Ir`o_bzPqnvC)dr;ZQ@Pyk%%a*qjsAspvFhDX6+<1G)o?f9r9Kv2 zxO4w7bE!cb#VD;dudy1NwsUt>qVDIdxwIFbh3`i%?BdU=yg0#h?{e%;M}CrKqm$y4 zYGW{~3f7MHY*hxRP|T&Z<)fM4pg@}ecDkW}JfD#>CmR|)(1vl(=>T>^Vi24GWgvrc zVzsLpW4Nm)@b}X0&Qpi?X7uH^zFg8LUbtN57Ib>LVrTdEA878()zPGDc25@J`fzaf zi^p`+FIV?QwDqz%SuSG6H^px-&~;n3`e>%fVHkI zjg?f9l@wqB=a^%rVUWz0B?unOy4P;+gW?M}K2=lYeK$6)M%^vi`KptQq|3{f52nQe z29O*OY{u+_SBvGeYz(RORaM^n`j_c{ef^cxA52H?BA$i8ymmoU5HPBnTeoig+OOUE>2A42Hftnt#eMjgH+e2ANlN!t*aOTZTqg2$2yg3 z{k5SF5=4Mpaw5aV*({`_Nu>{cDO4%Ss*SL>XuM4*|7 zsY!)Z>rrHpbtxnn2=q*%;evth#qODDi!T9e078Pg!q`rop`7uRufM$iCtshk zsrr7BmZ;*ks#SEaxjNr7CyK3Of>IYkcb}ZcszQ!=A!Vfu^Bx! zXgJ$)^GS}{_uq*UHe!-C9iMvf<8Z@`$7VYZqZaEe9FRb&psaRS8Fn$}EXkIRiUMvM z#TDyxH0eiM1n!C^_=Z+t)~C5DG+!5L6)h3s&`SXT%UMM9dy;v5nE|a z7mNE3kFP%Gp8Lep7Pp8ryA@lbtynTpCZ}M@Dvo^W9_4Q^OkT6;N+6KrqN?9|u>YI? z@?ZS)&;1Y2UbCy2kl~!wZ0N|f>3YYEB#4<(rWo=t3^_+*`0c)HbI^D)wMd2!a_+0j z6vgED*ckxH4y;k!3OV5PDCE+A&)bs?ZzyV7=ZP7>f?Upi7zASTU=)Tyrf)QQz$b9O z5=TrzfFfIiNmK1^jfaezgLc(kTaR`dsmwOI<22;K*UiX;)e4;08nDr1gxOVPgw1v; z@SH~^#@GO`qUabg=dvh<+=1bkN>^l0k#7&ON;cbSWy_|tu6D(0$T#|lq@iaf*2q*8 z1v3*6)W?iovKYg@2PuQiJMzHyQ4apA$M=h+PA7^j63Cn zKAY`SmA$#@ufBwxr`~vYAZE7r^t00|TdR>fZX<7xntC$XE)Or44xl*_c_p*Z}(B=cMQZb{%}67+>1ZI-WjYR`VY?2AVdv=zNC& zerG4m%Ww> zWhQGMEgSewk*x2}KyNxAHr_~|(*WAks`|Wute%q<_L)E&=LFEtDbVZ2mZX-Im>__V z0mH`N`WakJ8Wf^Ab)A_n(MDf-u1fM=qC^l>vmgt>`%1d0aRYc*6WV17pjgdaq1&E| z#>YW=)nx3zlv$!e_O4I1E|v4eK^TTnvu&vE`pQyQ6itXRran^;C50h!3?V45CDBz_ zjX*$x7|Wtq^_@Uh1N9+tQHY+&c z?=J#tS&@pBsVmvj+|H{pwU7?l(c=yEcZgbkpYd}xGfG*>0L;c4RAeTMinQkeLc~HG zEM)^jETAaLs;nZApcG19k1ERpZAWTI2MS`xZ;XG8Ypo*6Q6UcxW{Z0^&1yFwbtwOw$2Ob{A!}8-+Hy{5o(2(Wr1T!_auf<>L8KZ}zv!3!YHK;?(^(a}sNOlICChv< z+O~$xqA5EQPPr${OIOW?(XDXh^`iyC z9M)YmG1{8RkxI=*eW6!(Fa7w7e~n+{;h?r#(d)rhC@($#6CbV31a1Pee01)iN+J-z zk`ekJPA-^< z*Y^oQf8YT057rOwbl>`KV+@c|N+DZv>rFXHmL#Sw>QNQbFc_=WDWo4a+pC}u zhIzg`Y1@{FhGAIe*coGp9wmxA#>y%pYq5dH|NLRpq|W$-vlbFL zw*W-va-FmO!#v)_Wk8t)usQf{hA769v4(7cq!7ap){urW^-%U!D@YY%m!gnX9s}`e zo$Ta{C6e}VI5|8ThRI?UwWwm`5Oq}OxHh?8q+E(J!QQ*~ut^g~6l(2o#VkVQ9+nl`B_F!Hcf9Y*U7U(uU7{)A2w+CRSJgA)#Hg z$43W(I>k5)0N5o;s-HJ%EA5=9%6aynWMNhIquNX46=^-4%0Zn8u8_Nxc8LsMQg&a*^vD2s|y=R`x> z!H}^eGBFG(#inUW zt^}}CFklB1*^jxl1E-Y6T&?n{Wo$otqkQqB2kjiQIeq=xTL<%5Q4Va3^Oh_@W$qW_``hvXKfhl`}YCPiIK(kV4&9kI>y)sII4VM4QW6>r7~X-*W>{z3>Th zZVc!-rG%aJwsHnFcjnKZ)BWT#Izl%rHrn(9%Q-zqoXrq0L4jysgatqxYc zfS@7St+KD@^+=8Dtc|_`Stu>x2C?c`C@+u+qC|q=(sFp}TK)Ww9SKME8hRtW*JX4$ zJGA3+eCzGIg}?TZkJksQ@v1!@PiLbEnsIq>f0nZIwh;s36q2wiK}m&`*D`8rD{q2Y z(9rjz@t7S%!QO@e!W#pf&BrHYMa&oivRMZQ0%feObY){r zxzr+xH=Q*B80wI|BS5|LXWsPaL`Ved9d{J;X-FDKqjJ=Baxmpg37P^Bkt;5fic^9! znuIAAEXnFh>I!j>`-oMC!Y(7d{6)I^$Ip)UG#;}oNih%h{yZIrluS7!o^DUCTvuO& zzE2jK)Mpiwdd?KH*?a!^larI~XfbvG+4&*OjoZJSR;!h1OaUcG*Hb2KSEr#1%4xDw zIW6CQ_4eCeI#Azu!v)w8$l4 z%lX8~vr6Q=K_`G@VJ^zX3#C&u7VQkSL2RK>mu(;Oe91K<>@?zskbnia+VIRkEus#V1p#`&cpoEL!J6o}-r#343jj%lNxKNFa47~$lC1KD{MC!Kj6 zIg`;;k_;BjStMmp=($@!Rii?LL?%`9$)~T~G}m221x=$2aIx?c$)qTpDVPhyH{$9j z3k(1oRGP;7U-w?*5bi{omfb(`%~Qwx{yZtYJ|mRZ@XKLC8>Mg*QBOZCRGekjzmKGeq$S z{r{!M?Zyk9NHoS}%@)pKYisN3<-NGgPmeQHPQwE$8gN%Z~Sz=6Lj4@C` zrW{F=MQ*~%T32xClgYtv2`=B6jlOxb9~N~TOc}B*_J`&xcTd0e;PjNZQKMCL{rXl6 zdD#xRw}VKJ`PHiRQk%V}UijQE{?6}y{?6CGI7S%IkL&UFRvL{v=xVfGT2iBuz}4#* zv*oeR9J)L#+Xx+9-MIu*B)v17QNFzj6gpRXH-ZnKfE17t`i#DhBr<8ruHS54Y#b-g z?L_O0e_yJy4gzbPVZ8dMZ-4c7zcir+-CXy^>iz8QeS2l};$MGh@UdMj@BjX{tu@A=D2kl3h^!-#$h(4B1BLXhzKM{iXD)}f=WSKyCek5SlaJT6R#r}5eAFG~MluO7!?KwULs@3zO7pQ0JP_#;bjO({aw8ITBvw^fK%7CF$f{WURewIegXQN7Ca&{Oe85Gwm6+F9z1x^ z&hIadM`l!d6&KNoxp(Luh$EYZIdWr1%(Uoc=5(YdMNtpc()RT`(T3hF)uOy%4ijg| zN!5@Ff@q(IHg+~fn_z^+F{v7WL`)zXMZJ<{z!=Lc%%q0ktg*J6yU{+44y!4bMq7O2 zjn(lV9DZr*T4j2qgRw8ilV^{Hok){vR5wH4b5N7voWS;j4n$hmd3UO9*X-2QQ=hyW zzxe8Y`}D}0aZ`)dzL<`h%H;9hC8RL4^C-p)Da;nmIltp`;lxNElHsyq7lsx&8S9$D zbKO{@t0nTPt;BGoAZn|kE}bN|?DZ^QcUB4((Pj&|Uaa~h3dd~iDo3>_9cKH>Z++>t zr|QdBQ+#my;6Yv*%P;)cM?doqKaD9~efz|I{lrXH`Su^({_?LI@8-VX823K?(?9u> z&knEMedDX&@>i}_mu@tp?b%y6-hvG(STS>5)nrTpQ>LMV!>SlJb=hP#Sr7x%zygWC z#|a4l^ZmLN-@L&`x&a!*o8L>7=G;yNcyl-RI}ttZspDk$G*yQLXT z)gR}60IYS?cgvVM;y8q52p!2*8j@tP)+!(YNn;3o-}l2XsMa}SZ4w-V646=r|K~jm z*WaJTaPS#SaNZPHobkMp<}>X zKqyV>k{!n&O((e=AKp)V+`Gw`dc%FTljN@lvkH2j-}~)>d#KxKJ8f;SLgE9$ic zvPd1t)ZA+FHPs>6Ftlvu@WSI%9CPOn%5qn7>2hk?I(Mx%g#(9ac z%qL@D`}IREWBbL|&3s;68SRFzE_yK!R(|)X=kGlGj6QF#Ub!*5_wb9q^V_AxRvqT) zl;Sn08(0YH~aasi+9fi5TuWi z=+{FslPaY{yyv@;>YuNv3-iA_*K9Adtbd9i>+@jF;RT1_y67B z8?D%BHW`(e>f{#x(|@=B`Iq1N!mIPr9RHp4>>s>x>pycTKAioZzZELC{gdv?)5|v> zuJR(8$pE=Axz^gv z*Ps4&RjiIImPm@CDT|Rrg^nyaijf4i69jO8Bu{zBgOSI)L^pB#6~2GRb*9N-h1nw{%d!)nmP0E-6~a)^;K~z=YrY~2j`x9&fe==do^Q@ zHRhOo-K2M}&pYiwpE84fLv;h5Iw8Bmo~G}KXzwfaYR-rB&+d`f59r^_i?MxQb!K5@njM#dr6ti+qMlMAG+F(0D5eS{K=G89Ogq#;iM@Q_5v4d-l! z&|yNx%7)pQ(sF4H5kiX52cm4llz6+IDT5d^0J-SvASuh(m{>RU!e2EZ0oeGMhOHeX z6j~++W=auEtNCa(XPeJ*Giux9_%L*PVO_gYw(%r^M3ahuqX^i*7`E0*f+{6N67cS1 zvcBu~UI%BcSYVyXfh!) zwrExyib$kcX1o^-5nwM_0mcJLX|V!@|71;evH$-QmF9Df9h| zha^s9c2aihs$JH0d}WN?tkze)eRzKQPiS(N_1A9g|HAP>jPZ@C{fkcDX#C6J;oYN? zXATe4H{~E(9?rDngWD%^H0Vc!X}|SZZs-Vacg{>df{$(p;Qn>9SGy^u|7r8a($jdH zb}@@TBaO~e2hh6%fE&_4DUY03}jYO)14FP;xF;-jW=o2`NEAY+Y`c*osmTh?2Z}?nocu9`NJn86ZQw2>RXt zy5~ZZdTwl~=ZMgr_t6~_X4i(7dY**rIx^nbo}LZ$GCwefgDo}i4VtSRH9&_yz> z69a8jJxtEbj*yt5ByMxVWV@Vvo+TNXQIP>^;I4_~FFk9B49{Q&wlFq$Fd=p=s=en% zgArwshxyp<56qrN^>*jIb2){MGp;tV@$>7&xq`>;*cC=y%&1gUwEYxM$l9bzBw!=X zxx5$zK@{FrZc~oBqn3AHEo|k~FxT56=gH1i&9iSkhOMvGre1FbK{o3}RWH8#o!8!4 zth1Bpy^Mx=vC?k2noGC-)2e!1>@*oWc5GZU+>Hiwe6VtC)<~S9?5HulLjyf-j7vrh z_STy_ul}%Hon84&yXoB9$!cty>SB2n{N^ONk;w?gxpB!OcI-l%Au79)Wk!)=oF=gs z*InDXVkCUj*dtq%XPSt1v#li?jGka4w0x$8k2BH zV(iak!=v8*$4UgzcWQ@<5-UNDAWhX-m$L+^*QTC>D`Y-gXI48K*mTjV6G278;cSTc zm%FeeWMyL0guBNNc=p`+pIy?O!GHD-e`C0&GB#=p`NZsK*~CO` zQ^mHjkeR#VNQapo4&BknO)@dD(a^3B4}IvOC2_UMJZ(dckIPF=$WoO7dI_6D(UPHa!$wJYhiKa<@TK<{`i-%JwQO#$ei zmD1s+Y+n06x2I%R{(4D4Y+t*m-rCK+E#m%Z_8<`fnI}cUphU)43c)LKbpVklBtRsU zqallB>n78YA=<3ZlHJRO)_b41!de?cH@{vj*B7&ywI*xo;C*BwW6ZWBq0O8nTi0z} zx5Ht%twp7}HMY}TfcP&V_WRQ{`W}(=l_H=op?^bmc+wll_8f=1fbTBp2=zKy+F5G5 zcM|8W&%2|<>n;GD2vANyM=&WXQj^=c9l)ppN>ETBz2@3jzE+iy$wTV$z-Y5VJGQ}& zbEX{KDNzCe3=n~hH3xvzYAFPA#8&oSIQfVF)qhgBeRu`4@RDzr&I(Oyy4G9?pw&aaV}kTg)_#r5>fH|{o9CvM%OU~hFUD}0yE=Hc{O zm+SBcwOpLF$5bTFY+j&EoV?idc1Ne0U7dtI4_`I=zwpxDFaJ{g?9r>!!Jx4F?r_xo z2_b*sr58W`?W?`R_$KD3+)M%+L!?PkU~=0NGG`ct3qEL)BwmrMLjuLO{53$XV} z2xgl=7-QP3+xdJADkLG#4I85%QPCiZ6l3x}#P}qa=*eO$vTFj+`^ahf%bX4Bn>2GX zCm6dbsHNTm`eu^Ac1cR&4QY<0r-o8)=t!||Wv^Y+B?1~L0ZA!SH<5Me7H&+)94LSc zwT)B{q&j0oZY1GMwC%cNDh*OgLNd7_lZ_Wokh>uWU_fRM#8ebUMO9kgInm-EM?vTW zEDT0ktn0?|7)Ff>lFyFiZ~eXJkYy<2>bsq`%SEHF-|x;}iwtICR23u)5vXBmLuXxC z7Q@a%)P=2!1%$-j$ht9EQ(%n-$xxf2BQ(ubv3YbKBinAWv@DIC9*pdus7GaB`?$N{ zrpsK}X}pg0CtjG{``dTY8nRtO1hCM6d52InqoRzvjt+MOS}R6F2m>x$T(;MDwy!y#Gh%7j^5}w2taTZD`h|^P}0&XGJ$C8YfGVvB__J;q#Nf z_gkk0E?PZK-7h};lgZ;RkEbJKx9tnVaQ3Fm-}=OO{~`>GAyTNdY>d(q1h_rYN-4!i z);e3bsIKk&#ns|!MURYMHtFyn9=SRS$HeOenJiwfm;0p#lC+##firYo2o1}Fa_mpJ z)=}CFtStsSY?}pTHZMl3n&mR|8rCZ+^ZjVoi`ulYC?J4XOQe9=b<*{-Bbavhyly*B z5ecL)s;tCJFL&oAc~|>nZJkfP_15XvE<^b@eyeyTJAUxi$LE)yJvoWx#$SKcc&*RR zzkIHfFa3N&Tn4e3+04S?8C)F{>I3WGkN*6%OLUiWnws&&66l)o;IM8G1w!ZyRFM){ zgBrClmf&Kb;Gtp-Be$>`08of*oMkqWWJQ3!J|XhtQbr!E@Hs9Ecry74BuES-5f33P zlpK@qEwShatm%d**1kj@(GA%r-PlP;zmw;u4xqW$0o#pT+!Of9Uo&HE+uznl`T@S4 z3)XJivK?600X6^tAOJ~3K~%t0p#l+*0*VBXg2`;Nn1ud8>3IrL-JcWStMu9LlO?0WV?)DKH4{po+67$O`M0x|(k zn#|03AfQ%E$EF1mtvlN#W&$OoF5>_Vh~Abu4nX$Re03ydwKs1E2dLz@RoIPr)xxf3&?H|4QNK+(Zph5~#R@SYW zBS~lNuqXyyKoG+TV2G-@At1E^5mXpmLKlF>}WGu3-@j<%^%Qdaf zAKpb+dtQ%*XO_qF^?VJ#KRt}`T)ZZqP-r>rlO1i;ETmujkJBCc8hIVOSjA3VJK z_Fvd#htv8yZ~f@N?tlM^@1LJst`774jSmqirI>6R^IV9XVGceSc0`fMS(8OIF(x82 z%_hgA$??dCc7xWi=9Vl4y*n8Uif+&NJl1(;ks^XeX^#CNq(kem4wCZLi~@7bzOYt| z2J0iI7PT)a1>$irtDH4O1``6B01IY9+otGDuXSVR27E&mKzGJRNyM12Enp;SMVZA4 zaTS>(cx7@k9$VIB-DH!=@P{kx$#~3HheelUuC33?>1F%I|NQXiS$BI~4hAuj4LpY2 z8$8Z%w<;ULN(QaZrmj9T5go)8b&D8bEr^iC{m15GfOtV2O~a^6FcZ2_awc>qinWGn;L zG;QN@L(G7%P;N>@gBU;xjqsVVW?W2=HTAk_m$|!>b8xE7`)9L4lY#+q&Shm014N!2 z771(Lf;+pebw)Xmj8a5M2%g#|r7k@;`vGn>`Oz@rfv)(wZ(Wu1^+7Tg{w7^7ej7^o72n~-#eyUVVYW>HO0Cad${{jloDBMSV#f2)-Wi`tSX&fTrM}AD3x*=WNkA$nkAQkxM797T7n2*5Ce*QXl(}Nlv3Tau9zgPxA)nW z=~h)q5RulS^Ff3OCZ$BI0uUpF)#>VD zvKUIrs!Lz6+|CXcSH;!an*s*FILrHIAV8ewUO(Usk9(5o2p6HUbKVSZ%U5FB&UJ% zL27)`m=#7-p(ct&ocujDy*#)xRtXowTDPioLY znUz_XykkYK8Gza$3Q|H8$(^%|5FlJwP_JK}2DYYF* zSADZwce+XJnApM;60;JNg;Wv5Dvt_iwI&@Q`Fg+uqo}nKS7eIo^D3nK(TCtx8mBhn zAT5)|5Djtb>+y(Bjx%fKgmc1kDJhhQVXa9?*6TGh#(PDAw;9?ND$EAkeG2_Sur{UzMAGh;wu0c!zJw}CSWFqS28OrUm7L}ZOdh?tD#rYm6HCd?Ms z=Q@1c6?f)bgN(HtG{qz^*|wlJ8xHG0x7%Wx#W^yVCZQ;xtK66Lfqk`WgKQZCRu&DB zb47_5)vQ6bK-;x&F>eWZW(R|hKQk>O#}%7%8gt~S58;BUX3vh(xO`DuomWMPTgkgJ zg-Ht9O{1w=YqrK9aci;12>`*XA6Q`zpB1fB*UkqrTxvdIQXk9AX@o>Imb`)uOdZG9 zcC&}$lj`#?3f(__z&way9=Sl7eLD^Ff#=b;UVT_M^v!aWhnUgIa_1q14l`GB){3o! z>$)DH7%r#xS`)L({>8s;ZvWB0`qu3EwS5#R*>3nKrAL}FV-5!QuMpfSjDs6YO5?0k z70PN;@8!-~OPsG8>e_CW4^ED9_068YeD?M$$H(3C?i^Ah<*@nQMY}$ojHibiEe~Xz zoHW*tmKi1^?Z8+8$N|-|(~*TAk@o{(GTtBx$Q4zS*2#xKez97?*vw?yz$6HxBg3?F zKJL<7_Oz$pEs@%B|JOfX@Kr z45WAW8tc`_$Ld&^i5v;@Pa!(*+sh;ss4;|zras=Qt0U^69+^P z7zyYEokEMdS@{wp6aHH4e6njg{^Vr;4or(S#dM$DuM-0XFbaxH5u|`*lMzz~*%Fm1;^wvB2-S2k>Hl!g53nic?v}6;*6J{GghLUv&ly#WS z=LhGTy}EfgrNO|UG+ovW3-j^kZ#NgMUso%PJD`gSAI}1dW;Ny3VzleEOC||zi#9<5 z*)&j_TgJwbkZTD-P)o)k5sX8_^W&4FrNQF+CO@TLe)jgqpYb|>e3Wu+n_N?7y9Rt~ z-L0-gf-eU{_$kGicGno!*<@`3+q5?-Ve9pJJg9HId=c$vafadP!{cX62U4);lQg#^ zDXAn8ls3<~G|AMG5r|y~2R>dH-m@`p9%a%D*>+{IiuqZ?&zRy5-dde^qvOGC4&Dc8 zg1g@6tLJY_Gyb*B1X*UHcP?O5g!U2SgjC2;CtM4dT?f&Ctm()RXU3U=DKi>1`PgAR z%r?^12o-~Y|xg>t;C{!aSl-yN@X@A`+2R*Ps3ud6qzg?sTAcyBOSw+GUWCX}T^ zEsKyOMS)mVBp?ckO_~;?y^kH79hP7F{jd7L@R?_RzO2(K?}=BR_EGy&KFimhe*b-Q ze)cI7E&LG}(9diLAR5$;bnIrYW>bnkeIcTE84cf_-kfhJ-o62WZs z&_tq|V)PwV zWkhLvG|kM;Wlh~#lcxkpTiL)ijZr>wMEtl0x^E@Coi&2{`8w~m9o+HW<%5~RzCiY; z@mGFt+xjL2?qr&GeO~U@|9#y*Qcq3)PM=y2lSmU9Ma+=x`z(t9sV?(82WMCxp?eO_ zV{mBOXMx!hOlkn;C%{CN!XC&26|{v2p%gO+lw}-0xE;b!hFUtv4x!q-L8ake-wsm)OOOZ8U}rC;E~FR+ zAnx`NR|uhXXmdE#7?vx9l^;)IFlnm{Q#MvWT~s!-C=Luj4ufpE-tgQ%w)1+gwU5h% zcJ56-UN_F#s(&DFgk-agn{S+0f__O5Vi^TjXdSNLo?;`^sBzm?84 zy%vo^i5wWraAXu;`PAobrO6!YC8h%|+hsKvT5m%GX`wlFb!=9{>=uBKXpp(Y z0)@o1twIT9h0P!_w1Dpn0yB9?Qt^~%m;ZXd`L!Du^;?+KZHG5nfCUDKgo@F+YT3lf z#d?&CJLF;I{AGP!FMO8dfS8U4wm4iJj~*knC(B6~96r9N|HTjL_SSENTL*=~xNB%~ zNyEKnkk=uFmL5y*|4nEc;N@4<75*fot2%)R0wQ-S|%0V_5Pv_S)Gf0>XrAWS$ z6sfL#UAMufEOUlg6U|n$=@~igWFS&sAinG8Kb17% zJ&0%Ld+7&E>4Uo{Q9nQCzJ&nNE)8za@xRl?4mVTd+XJ~MD_G%33)?Yu2+{B>p*eHq zLJ@@PCd_SF>$v0*?8{lGK z+N9Pnfo$?i3(kwt=RS4s!Jp5YrWGY7kP3kziD8|X>0qo8RimmTM#cLKMxSK;(~oug zPMb5N7!4^Kf(U}eBw;Ts-r7Hu;GjT*g9f+a_0hfN6ZeYib>4+6jfn=MS)80-t{yer zt)u4UvusLsI@3+Ifrv5M6y$>@Wrzs7c)ASN3so|)g@TfU~M)n+hx0EIw$zxYP< zX|vgQAIsr@^CCIUi;^cV8QL^crg2 zo*gmg>qu2O+#lq}Ca%l++S^gZIFX?b@TTli(#nq9 z0L5O+j(%?XU`hAqo0*Ni6)1^JvYjp#PZy`{+!uBM8b-hU<)$>p zeUm9wp6>g4+Sl%O-jFmxZ^p!8w|(%XAd(& zxhS&`y{~Jw0^Sx_fr7k`8QZQ)XJ;3~F&D)l^1@^W5RnL>Cl(uQVwAdS35Ezz-mWaF zB)VmtRi1c%K@x~bl_07gIIDpthxFmT>xhGJDCdb64^&`iYn$nc}BjdHLsTe}XPz4!? z0a=g%7z$9cHA@Fsz<|Y&fD~!)-!Jh82C(@crD!;zHyUT zlH3_OwzT=+=T^q#9!X?xv;5@iufKHq^?`V~E^v2=TvpvmGnpLjBjZW}997p}iI6wn zv_E)lQ=UJbyt23Vf|J_cO?EUYiqh6~rEb!QRNcl5YQ$`>%sr~N3tf-XMV`jKI9l1o z@cs~c8fA46>}h;M7Aw14e9zdtbcV&K0x2a)YKUEyw`OHy2tK=?m8+v!{>&$eXI{Mj z_~M1^>bE}k;-_zwX8qV9YF3`r#T#!g{>{Vl&;9LBmcyXD9%Yo1<~nIs*|#o#hrgTi z@wq#`=WGjvqd|#Pt+qq(s2kT+!?4Jz2L+K*bD2*P3o{sGp|z$~eIwoJm2_U5X4)z- zLYo2`c%<@XD!}yy&^vxVNMs-afiRHfC}v2r+Oc5APxw?Nge&vpA z*0CT>2(W#9vY$2{d)iWjzPU7dL-*-Bux=_j{>GTsr<~+>Q|=bL^FI9~l>L9dXMgrI z53sv^^>!7Q=;z zbZ^+z|GSddFHa5*$+odoBGM#et%?c)5sO4kVL`&vaqYz_ zn}{e7pi@ES^e?@1wyu;4!0s5&964<*@JIyAg1u^e=kaS_Jpa0ix8zS{E#lr-@b5it zzVhAC$*{gX8g*H-SX>-QI>nvGcfJs&!+0{g<%Zr`Dn?_Ux#wQ=Eu|Xyj!L3gYqJhb zjz;r#U9GR*o?|W7ZowD~ijd;;V0`f0vE(UK*PZy`%&pd&3EGd{jy#yY`DXX{F~!E5 z9J6Vi_u4ep4s&T4jc?iugK!p)&lauiaL zUr$D}HDV%?z%Xui&EKf5MxnYiscOa<%+NpX>;VSPcg>1VFN*uuHovuQ%caMFF)`J+ zSizr9D@V3U?O5z+8OMz}cp&CY3v|&KL&PBRPX;g{;H?hBqm%io53j!Uy<2BzdoSJf z3_ozTL$AOdPhA83lo{y0c6hz-b2CzkzJAHn({8W#dwJ@GS8j&6*PEKbJ*7K+``Pr| zmv=JIyMa+ZzcK9z?38u^@!iZc=@TJ^0Hn+SG{)#MGS)In@=8id5K;}~I}qG(Fc}RU z)HZb$qUMFF!Wb80XAA&oyA4RTMIl6z3KJ2rq$J))!;Z+Lq%n%>6Uip=&O$RkA$@*V zqR=z>Z`Zg={oYq!X$R1RBvTF>xNSG)oM>xu@nrha6AVq*o&BA68U@|}6xIx9a}A5^>h;sQQVBDQ{2)Kf zr_P4|YrUw~*S{Z%{Im%+AlY&4n>(}PfBPRCe&(600!|PWW`N=X4(M7GHQK=kKR1hT z5#0z&%I8*$4J+q;L6b)=4rSA$i}& zI9^_AtbE;eT^J0zMb&jQ6SAXWyJGWL&8Kg@c<;IAn!}UFKlg=iz4Y?47wP3ceslBv zAD*Xmk(rbIoc*NBTrwgMAH6aS27@AZ8QUz+i&D~{^an4jUi`Ef+1a1};in#d(zzj?h_xs_lZy3xqWL&)5+}4d{z(t$1ktH z`S7i@Ka}gK8HL-={TFHYtmT-K$zLg#dv)#x#4)Dz#d?*b6JKjnW#CoR3lTlq`}i|2 z4L8z^hjU9@0a3aPQMIopdv?G1dU#6<9<7#F?)YeLGHlbZ%xWsk;Y!xc|EIkmUXbkFA4-fkPc2i&fsSm_72ceh6sP*H(OA|gPDl$nh& zL=lrn3LF%nQZbS+eQfB$eiwK2xJZi~@0#tpzA6Jp1NB%$jfAR!>eD8d97V?^M+ z7mZuQtg0eU%%cHS5!n?;yr&=DpCorv_H)v&|98Y%J5LyxKJX(*&q{|MB3b#s`|HlY ztmkvl56A8T$~z0vNx!7bzKlqgc>~XyCp}&@czpFAEJ7W-pBt5<-+%Rg{l9!A-nGsEI4VzLA&S(&HjjlZ|+LTzdGZ+obuE@{3Wf=yY=2>jVo9<4lCw63clK;GA z8y}y?a(`(Kt}#PK>%g&<&h8x%jnFKH`v>FwjE%jjfAnXViNpvJDp70gWqdI3F$}Ma zD>pH&^)tWtqhJ1wAI8aM_S|R#H#T2+{rtOM?dF5wd?f7;%NIE|(hMh)5MyW)F%^Sy zFen_@vdJq~?0;e;&||A z?KteER_;G+|M=^t!@UQGx5{7nn|OYh&t}iQPCoD2Gmu^Q+LJPkD)!DKj6tdOoHLM4N0B1swn zN!Gf&m<$eLloT1nK~g7)Sp`zUX#$A{V2nvHK@k<%d*ME0`#}|{a{>}pFexCcASeLq zhX9CG0U>$fm8U7WV*7Sf2w;7;_@OhTP>Cv@p-H!QB$lk#g18e7#yE#fTlsde}2swie>AoI01;+>yFoOu1pbBP$#Ipo1XerN-I6!T2cr1Gn)o`N|`}s0! zef4-HU;LgtwkuQs#FD}pWZk-GXj-EfqzRw`s>qy4Oe&8z9&(e*|p)UVF|(LY*Wr{o|-9`@UdymE_s zlASAc%0*=+8rs_>UoX}axXi?uwaYY225-#U%kwyGhWTmy~)IF>kEG#YO2 z)sN$7jqZ3kTpmpi@2sk9wJNCkjyq1CogBabLktwC;7xI@K+HDu9@o!=kTd{bdl>3( z_<55bEP4OcH-1oYi(mg$EOwrZX-~k^KN)M+d->T^u#k^T%K2%LQNM_)Z#=Tgk2&_t zG3)JH+>;^h&A7*#>HpmfwCTs(GoI?_-F3pF+LM9qYhx!pOA+>#DD3=T`i{l&wt%2+ zf2Nv5B&8?SgjJD}#w1WNoaKe=?MU7)hakXy_IB^<{SZYUOtW(FHOkKgELb-oHu-jwvZZLNu_}0yum8_(%WS*K(INZRNcu5$`=z zWAvI@6_FT{4;p-mUL_$(kq_&|>EUQN%`=gv7U^OaeH>5(U`UCGRGthuNG!wI<$NM} zVfKjKDlDPr`{T&*2!LfUGcy@xW(LG%7o6s$rNZQBuCr2xV{`g=`7nxeuB{s+vBntU zQ5l?btcIC&n?0!Sd}Na4_r8U9bR^7%nVBpRiBWYvd8w+E)Yba!%Vjn!KK{w$y`hMz zsud=J%64k=MS-DurzwjGrl<&)bAIrBe>MzN(1G-!I_?yg{B!+dYO*CccU+;)erl($Z@sSLR& ziqkWvh#K@_QC~cItVo-6txT>gOeRs=e2{yg`Me{H@^V&|%36xG*PFUpJX~%bh0SO( zy0t2wvB$6Q-4~{l&wk=@bGLo%`R0whdsNWyJ9u-IDr*kdO_Od~ZCehv(-h$UkGVH# z(j>dG!|uIr@ZlR{$hk7BP=&%gb+>wenoWY;G*S{JO3S8p(ncHo0d4dnXp)R8Em|_k zWG2Z>Mx&9mW>Y-^APAr_G=M5pp{g<~rJ+IU}pELmo ziL|nLu1BL$p+Re83IUzh3XMddka05#=g#*R7bod2El&eacrHyr@YIE#{Ql!zyDa?G zHfFre;a~+<4rD7AokvLO>N=(5TeQaoYC|(vd#=Y;YVbZ?-+DYLpaK>Ew`av9aDZhn z+Lhzllp6~|W?Vgge&_=bA1#XCzxnzdU3~kF{?<=m9CodPQL5Kiyjn(iU=Y=-wz0b` zslZTQx65KKd0@cDr3HWBuytAff2Nfm>^?Wt)nw>KXy6Hk79NJ^hZctoEiUZWLiI*u zGqVVGItoqz$jpq0%p4;mPKvt9CrC*M5Fry-S!<0Zphg=U&uuG+%&4qE#S*JJ0z!yt zsZN{@T5BK$9U4ItO)FqTsfYwk=t=_#5k)}_NQ}UM90N+yAOsNN=oAhL3IL+&AeX1A zYi$M)q%)jKNC`nfXG@ZhMF1#)kSZ^}o%7eHQxL%$o=7||g50A7F-kVXY? z?-zH!`+xi|h~ar7n3i zx%F@U_~Y+=tDa5^#tf7wz!cMFL(GA4RG@@9X*G!e3IpO*9Xp@~07@CHwbrP}Y#1|z znL$=b7k0A_>0~iO6%#N6vj~X-WEK<<5r>FO6M=C|0qV7#@)U31xmmC8S)(iGC{zX$ zG$PF+%ZhmnF1Okmt!LAa$E;j==H#f85D;o+N+}Z^Ni$MhAtMSB5GVrE`DhCqDdh=H zER-(XKU$^zy+V=NE?&1YX4W~yl(%img1hsXF#g~}FjkrnleB;oSsPBxev>)UXd!7w)SmM8c-C$RGUNH zrn)9}^I56qqm2$V02b5zZ~v2{@0nTEV(kIcwKvCtbj&`p>NH$k&W{()_I@JFoKlh} z=UFfbmOPhULr|!cLGmfYx{jyTLmd$B0#-%(4`LI+D+LfQUC8lil_e5vHKd$g(|pPZ zP|O2-Bgm-z4mWh1+936*E#*IW>olJhVuph1#ceZ^Fueq9iF=&1KM7#E<7}H?^C3tBPkzvxc z!G6PoyH8*H3}f7TkN)X$P5_3!-=Xc<_g?6dnE2rk`f~1n=;wJ@H|Z}T?AOi?+quF( zTe{xA@AZuaJX2I7DrN=*W>$(sI331C9SblL)zj!&POvD+SW|Ih?{n&&-ju-a%u1xn%R(X*ErASKr2 zppMdS1J@UPLj#%SUUB#No{I4zhmDtV|LLr6brO#Ab*OjYmrs;*bzzviI9cjX~VvGt&BtgtY1ce1shoKQsfae*ycC%X7NJ(i; z%7BmtP$Xw%gIyb*KJnq+@@v1n^@o4>g{|_y`^JuLv^B8fEUUWD;Cbjg2?#_PX+24c zcNA|Rj3H}atNoj4W5OX8v{3Z$$AVWk^PVu=*oggO+ULtZ(V4_dv0Bk zafOUYRNcDAaj{vOd80*7a>*nL83h?Y7TOd8D?W^8BiOQm__{R%U`(j_x}E8 z#4l5$v`^qq0xa6f`NP_6_@|g1sGC=+YVVj^qhQ1c4K+>XvB1(~$A(g_V8)=U))@ty zZ#El$SQEif#EmDMXCKd|^@`|hE$=T(Fi?UzkK{Y%+%(0<)El~3MZ9e++=ug0H z0~6Tr(Zl*L-=*Wv{oTFKzxCDhlV6|d*Wa9NjjOHu-%Fur)nR?(^BIPuVh+W!Kz)Tv zn@wE^F;><-cYf$Q!26u=yZ0Ww^V56ri`U=2Ir6*mv!<4IC&FbV?e)Ev!CBk?o&fY^ zF|xz@TYo;rFd&HVile7-7_c6Gp97hAxtw4c>Xl;h<+R(Szu12QMkT4ThN5;HJDVnI@fnmHooq&Wlu2{yxcBCGWRBz3E$0z_e} zXjE9O(7G5xP?%C+PGZOafCYnI0EE0CGb9iZVn!6!+le_b04YKU3@J&Bu{5hwHn>yq zAa;M0HX@<`F%lvYkRX8IMiqF5HxU#G5g`aI^x3e%C+WwC5JSU&9FdU}g8{aP1Q7Zo zkq0r;(jz_!0|#n<1na3kAOi?@(;ik_SJ=5q&j(%*L4VOX``qQ4 zS-gNSpn=5T9kZd>gi6?Ohcy#2q!cwNM9lMCn3F_iloUijB#H>ciZPHDt1J?+XJF1z zi=s}*k=L=p=Val*VS7DP~jh^RVgRhdH!tQ2|*Z2~YQ z8toEi2{?fWA_E}sS^smkqHN?^*aT|~Y$MPy-TV3D$&Nc*EkV)ttdzui>vXVc8&`*5 zSE;@-s;rp6bv`cGDz|E`9mgh8^vSdH|!+;h>TMuT}wYAx}EXvXt5(eM+=>2P} zzuY~+#`C&*Tz&M5DyCi5I}R&jD1b1KQpiG3fEd4tUYvIcAfgscU9EyxgGRA3hR7@r z4pdqKEimrslm*lXwW%E*SL9TiY<0B4ihsey!FuC3ivk+Rpb?D*wPRZrlZf<-7XA3z z8~?%Y&2HX#@Xq_c^_@R@WU;7->i3DPEBmdHuzUbI2s>e&-6P)5uqUv&vurH6<9e8AaNr5AS z@AFl+&p-_~URHY!^`E{Z8@S=Mrt*UI`ja#Ia7oWg1C*}m`P{;FFN zW&r_+)FqiPv%)SeA~7=~LuAq*fPygw$g;FqSHcNExkgvvB+Dm(8BO6fsY8$ebP^HN;N=Q{jxYrTArOJcz|48ZD1jtGBvB@iafDu*6u02)&=Zh5M==0M z>QtQCF?Il;Pyj(o(Xm6oK*9)s0tB%jCy+#v0E=|LBmtP>D4+?b0}unSWFZ+P!n&sl zp!aC05BLt-arV~=_MAwhC#?0F{!n zLd?@)L(CoC;UI{@sv%i$7C~_m#?VBZ0SJHs#mGt&qX2*b+yl(YD-+1KO#r9sn9tpW za%3wkB7_12A_B;O96P@6lVBm2~PNWg+Vuo6gJ z^AXS)AFKe#k4yuUK&4n59^?J++UBD#esQksv^X?A#c8gicS-b4=?>Z59u;k*8-?*? zDlzRi-GA?g%b)+bEbA1q=pk#D+wsAaR#aLZjd!QI7?tDsY&@M9V>l*XH@;93!&i~+UO zTMQOBL1HQ8`9;Hh^Wlk|(I~*?z2#4T{^KKryjXnk`b(?)zLghKk&K0rcRi%wYh!KQdaFnG*q= z>Yf2vM5mOPPZbWrn3AxhL;~cUOIa4H%DLJDOeK{-wX_M7AO|3()aHh*^7ZDi3Ix$= zgp^o8QZaJy>~V|tqK{_7920N^iNKyYkUP#HDqw{YRS}BaQF$e1bB>d4JdUo1;=0pQ zpMaShr+$rl>UqD<*P5rHk{%oexEb-Zh)@Kc)apsN<}*FaZKhAt z%<%H-JRK0joInA_1W`mI1Q$3a%h9C3%m_?GnpqPgAfaN8A{c~4xHr9HVB|di3leY6c8jJg$5Ep5)lN2$chY+5K&5s z2xE+7khD!~K(rCV2~q@R(SnQs3?d?gzx(KWk%p@Wyfv@MQM=#pJDfn~%a`RAx0+AGWnN zyI4dJ1sBQ(&$S#3fCxz>a!L#goji!fVFZC}$|B_f6`NUY!ZGf2FXaOMJ{?DW8_{$* zHt2(Y=Bfv ztCeu{uFJ1DdKxdu^`ig!a!KtoP@BuIwtWVFe&9}}SL!qLyMMAqZ7Pl}LLl-i0eIVD%D9O! zR%|4{D)Ue2$yLyw6-g|C#j&(3P9TWzcD+xWkfTbiVvp=p3Lq&_LP;P2#S;XD5g{s+ zhVOKXAW}j~grG@~gdhJ&ttM-IZJE91N4NFlS~l9w%A(l}vmNX$p6g?Rdnk)vxj63` z01X49%li@*)kPPMvmVaad!GWmE+xf>rMnS29`TQU@QZ)? zKeoxEu{#2*FMlci-M_P4$W$bC#%%%urxti%)aOX+Z+`p3KlkO;-m@lt3t9?B48{wjsf)UQ>Z%mDf?4%Egt_ z(~?=3g}drt5nutq|NP{Cnr+q)>dmMbU*9>v&;RAa;+yaN^qa?jbN#j3HaDSOWQwrZ z{o&)VQ4{mpTlwTR=F`36R@f@cja$q24>oC<`xsT$wqzl=8)iD5z*eDC1yF!e7L0~0 zrG$|YKnW_+v+X=LQBg5nZ{@Xl@aW^c4$c)M$QUZy>NtQr}XrnN))=Cj1 ztvNFSCQHErXl4PjsPfRDskXdcY;7&R@jK?mqWIGje5cm$eb5@iN@w$#-JOM!n_Qs> z)9P~c_6MU-OiVkwWB0QU50-i&v#L5N|4z1(j`y3)*z0b!Y^0gs7Sj@00H0!@&- z3nCF2LpkDTG|Gtg%=VSc9FEWxS6oq0v9qtjM>i)^2P{v5Z}2=&X&_L3)c_iM1Yoxt zrt;x`%A2>F$HJ?Vc=djWTjk+<*LO!k6!G{9_N_v@K zdbLG_y}0ES7ZDC^9~jD@Us5sO;QOb`asL>ab8=b1E;3L9-BI; zeGlBza%te!j0fB9XinS#xsXJJh;#@#Qz$`#=LA}zbh27O!B&N_uGZP#zcsGocMnD% z|IXijO*@#Gb(b_j1jZ+RU{$3+QL~OH(o@9%-R=Hx%VpNEQF(#_q zAudwtZg{<1uRi(~GnZP=Cgm(QlpKUci`T#!B;u}*L0O}$se=ocFw2Cn7M*2-#NM>l zScNDY153~Z0L&bn5fSM^Es!Nf1^}g$K=EY7y|4gtPql^gIk2B;g*%@OIq&7q^usf2 zKF#p~jvg>EizG?HoD>nEjRCdFm>C(BQ3S{wH6jtIEY|MYzxcOJ zFd_1S7FWLg=lgHJHv7!&N~%gEl2Rb4bDQH7Fg%3xmA#L};XE0D47SEL`V-($aE$_y zgu+lDNQ%r5ks?PxAR}=7_YaiUQ_;0^?^MNS)p${2!K5qPNcZIwOY41GPg%ClX zihO6B!=xZu?b<^%-&b)PkE_62h8s>vp;tsPdNid5qf&+pm>89&#EF&GR%5}9`S=*c zTUXT&K78=iuYCX0*Z1{UbMc0X2g`&eu9f4(Z~oW#+h6}DD-9cfFQ0boZdxvC2&df`&vYMWwS;}i zokOd|haR<`{a-vQeC7gVqXw1do6MreY29`rjV^Usk^d_{Pogcfau1{>3-< z{-vLt{G|0cislP}NmaQN-n5&ib950{fUO!efjf=O7*2WC1l{8~z|Q~)Kg z2m}xXQFX_m^!#P3=Xq^{&3L>>4gRZpa zypk8qp9Ai5Xl>*`DT_Q^lls!v(FfqvC5e?}Xfz@YbM3%^+TuPuIdoj7Uf|nU};+)lTwO|w#JawN-0zX02$<` z{!Pp=MipZR-Y;-5f=I@wJhuRJxL7aSILh>FT<&gNpNw(>;OH4bNhGL{^avnCj+_Y8 zSOEZNO~#lQ<7TrG5o@h?zI#TZj+o;Z6Env)DFc&<%F9_B**n#`qs7T_JpQM4vZH4= z?f4cH*Mpt6sFP?K9YsM-B1oDnljevahJrA%AR@5=AOZ#<5*5W=WUXF$H2G3(J;T%g z{3)Q>CCPVs!WJ?9%mL?i~$+KfgvYKO+yd|rkl&jJ*^5fMtHI`?#B6fk9Z2-!+( zP0AtZ&LonEy7wY@>H*vdVfpM}|NQ7cfbmJ@C7-d&pC>y)v7(tkQ^cu|aVDEc> z^2cBJ2mj4@T9{aX0E1-%4q=moW0C2tA}f{+9Xwuc7MsV*VzZF>b;&)CAlo&w9WhXN zxp`Y(o2*+%0ycYLC{j8_NJ6BHXiWsEZR-&5|NTJ>YzdNaCtr_8 z$&-#Ojc!~`b|-;P-bXY}3J>G0Yx8>j_{mE=n{b4|m`p^BG3NuM+e>T2whmO{?&RwJ z9{=p8t4H^al5VH@SR<9D5GrkE5=@sdVWFc6>vmnRk0ukF8&p1qNyh;Y zyu|Oh@3|K2au;oxJ$!qzy06CEPS$3VN~X&Jh`sGRn0dXNqzW0D|R58c|5Z0JHeyQ|tf)5|JWR6uGqqk<@snX_|GlUN4&cCd{X^?d`3}WGBc2 zrA%G7p=~l-0#S&l6oPkkU8j_?EbCG>thHH|0mbvh@-!z|L_{*n#vmFXqkyuMOx=f{)jQ9F52+f z2?SpRp!+8vxggTuCkjP+?qEnTw12*&di|M^#=Sn-@^U8o6KohRYOF7Qbzm@}6fl64 zBXq4_Kl=F?7L`&+f*p(&AUUm@KsskWI*$%{IuHXc0%#&SHT^vWUQcc>GNCv`BO-_) zz`BW5?IW0#;)tja2qJI-A|oQs#1NM)ub5h^CIBY61RO}&vsUe#fKL;P&RUK-xO_fW zo!w~n``NP~TQrUxfl8ziWm1~9Y4(5ky*Iveyk)OS01Ti|NFgVW&MR{?D*Sk^W}E@$ zM)~$w-#k__O11?TLCBUVEgc5Lx{_IqivW>joTZh9RrGI7kKTIy{tflzwTcRpsls}5 zZ0$6^F#?-Cp-fK;e$VbaZvZu+&CNEUfEbrrC+m!+q?Le#ltM_HoK6sZQ#Xl-kccrd zM`jKZCgaK9L%WLyb|gQW{nmHh{BOUHZ{MnZ_WJ#APVfKpasBws&#Eu{#!MbRZsaj* zyQ)P$dATSTep=@);^uQ{^E_*kB$X>D#yZn~{j=4_#}0CR@93DcBQUEf+L_C2Y?g54 z+Sp{c*lUA0R8x&)Ox8fQb}*4sfXq)%C#>L$=Wyb8QN#K4CqwC{O@y8&Sm)w^~juO0_;R^J$Q^B4dm(Mj5RkXstUc4$r#AODs>9X&{P1`(ne6P~?oK(IO}zK6ZG&qNM3KqL(puZ8HHb(l zMMQ1ep1+0DY&j9Dl_=6;0J&|~Ze4>SA`PrFg|kn+;hY;)P33&>AIJ4^I{A@LW;y+O zIhl@TTccv^P3Z)klLnwp0fC87DN!iQK{$pG5hu?bZ#=NL@Vp0gFZ!30v7ZIF0|9!U zLJ01v}DTXf|7hC|-#*ST6X(Up_9K1iV#HhCcjR6md0Ifm-ops*^ zSFY5@nTLf>jq(TzMTB(k`f_%}$s!&5LejC>XYGT)C<=uU6e7kLwJ1f%ijt(#z?Fn` zQ{9DqnO?10uN%me28$}7V!K?l&GE9SeNxle6elC9H@I1`s`i@%9&%%+S^`TPOGB%J zCZBPZiI5LeCD27V-TBniUA4$rj@ITuT)m+*&Y;jooAo>yykMYxE?J_?#wLY`%H&nG zZdUt;C-rD+hZ?5|Qc5Dp0vp9zh0>OaW-nKSVBsu-MXDTI$p~r&P%vH$$tNLKMm;kheuLzD)P7y$62!KC_&_>Ch%Wo znlBu*y^w)^#mQ%Y+?{KXKjT`shKm4P= zdN+sV9SZLrO>mMEQN7?l{n>JReRAdM^lP8F1`5LLU_72~sp8|7F&_m6iZE^ijI?-cXpa_QOx1`&zG7?W9RM+_;Y z5JKd{%pgdSkz<6EA~SOc0THdWN-06n2AP>zVr-M^jsPn8=98(hDl;*)o7HMrH`ZEXjM5lFXxg>|(^_jpR7!P_y8AB?V$#NF zBGM{D)$NHbxWOcTJWFai)$ zNGX6sLeZ#{!WjAa0J?W#rB8C^BEJN1pV1!lX{med_R=TX$UVUUy^PT?ruoGZrsueJ zFa#70Ix8)WlwTgF{fFB#<++pQFaZ(@3Ij3$cm4U)E$$SXJ}byOF=GDkAi-~_7*ZP?r#406L@9!E?*2zNmQ{PW%z>tfky%3PwQVy!Mnoh8 zAUI9hmM2?&q4SKR3zLo;%SfS4J7-FjL%$&5mCR*HEVa&s<#q3*v=X?PGTRwGmr8m$6|8fEe7e57;Z zQ=>9bm5u-|Y16XE$!oJ_I?aFnVE~0vC0xql++F-%@`|MeFZc)D zVNB{eB6LRj@Ue!OL;@v|K81V#F#Gu%__(22-QLwaJASAAtM^y`I=!vh`pVG{H{%<# zFMM@1o1ENj{@E`=ynFb!ZY;ib$G~hkR_(S?kNio2MVXH!LSDgCTu|Bh4*Zmie<2X* zn`bsCxAIALef!;;>h7wkgVQx{EJVJXguE9ekPQQl18q^^!-xa%js~vMP~Gg z+UI;~mBAf)Xz<6-YS3XDp`k^Dg8}+rCOciq2}!R+XW;!1^l6~eFaXrAbsHAh-Ip;v zG|5KJ{mA$fC7()znS>F+U8LM0y z?`7?Z&B5Y>qvP?Un9Yl8*LSDW5@$HVylEQmy;7<}(w+7+rFf2>yC?0s$ZEBmOeTnm zlp&%JLI@!#p5@AW=c+a!18E^r^I|+7ecc`|*3IGa<8^z|KD=A&E26iVitLTAYpqEc zCKZxOK|D)J$=K(2gI>wa%g*FFqUii}vplDRb?SqGOz=xKkk112-uZ_H?TlY0VS1K_ zPDxU9g`kMquWGlc=cqw9ohh_PI<-0I0s#@}^iPZ|Abh%x3jgw6TAnB>E`%SRsS#Qq z5STfImP8_vX`K4gzj*(LKOC)AtG128kP>o&7}+^rg?F-1zFJ=~c5E$kLeQXf);CXe z9a12P;28s*M1;CDO#uWU0Rl!*Ad<9KK$ygeu+dQ>rlc73nr#i#qJU-vfdDgPfxGv< zKg%4T%8S`}OhuNi$mq>akL_`4RTIHUsHs_VyMg=f_$GTZzL(-O7;7f5$+ucP%genR zpMQKD1NvnEXQfZW)6&Ye(C1H(V5Oh>{dht{I#GSn~OB5CXBBeki z_z+`c<`#vBwALb+I4Ck5q4@ZCb%uHa5h$f5BMT#Ybv_AUw`%I+<>KSLgU5@_jaxUb zUAs0PDW#~c>kbKb{UgT2(Wh|wraLc=?i|;Pv%n}y05X$jN-53879Z|Wakl!Adtf5DdzZP_HF#K zD(O=f4m|&3kKG&h6?yb@^j=N#^CcWE{&3Yue{0CIDxkv&^S`Up6lF?(*peA!}r_#r<8498BI&}?Spl;^5ePocM8~UuHP6IZuViIp-LDf8CW+eY~eT3-bpsy5o?!Uc-le(qqir>{1nUD<0kt%*^fN-cK@ zL&$P&hTZj_a|fPIt9@$w4T=;AiWpQGp%GG`xlL6Lxk1T@C8j7wWm^(XM3aDK$`Es) zQY#@_in2-Pskstf#3AiA6>1h1zmJlU?x%XZ^00Ge4t_kHUQj2iMXrA)0nOB@VpPBk#%d+5o-rTIe-2Iz1p_eleBVDIC`%kc%r zp-F^&4D?XVYyU=W;8A#Q1T>vL!MXBN&gd>-)hU>z18Ag~TZKj`C5f3qYb#*dHmc1@ zo|ltiI>|@Ng*!Ujc-Lr^JMbbMAt-!SYAp!bCFfj>QES~*6B=V|R(Nqr8EY*7oa!r3 zBO+^~lp+w|L_|gtq!>c*xX`6FMvZ6^t=&6Z-TU!-#e0u$&-|S`cXoGoopV)Hb;Mpu zsmSwAY~5+2wbsTMt+f=YENloITkcBpk%IukD5I7+APHd<7Ec(J=CzdKl9HrAN}|_i zvp2V9#+XMBKMJ_FJo;$=@no&8)7D%0&YO06MO~?xK*ypOj zLyHJWo>K?euXXPGUKlnm`T%qiZ>{!ildLl32$W7fk_M@G-ObfHnU4Nb_#!DM8N(HcW^DJ3FM019VSyFqM30jEmo zDS;NyXAqOl95_0F%%|Gy3vBc+wbQACLl;$;C@4V^PRTT}NyZo?AN-Bb+>X_Jy|Bl} zcD1DS;ppTz+dI1Xjq${&w&9k?Wgde|2aw2YMq4AXDR1#Qlru6%r1u@)JKDQ>?Q8RV zdc3R;!{N@=J74<3O*lIKpTGN~-MqTGn{Um{X0up3_l5D5*Rrb$JO+DaDZ&>wvWd*Fy3)OmTHGdHd6OVo|09bWLls(R^#`8W~$sT2rdD zOgOwg9ltioy*p`R^|N(``?r2@_tCrW-XBeFEvnm<3VC*{LWazM41`^I$Eha!Y(ahc zqyaS7CM%E>FtI4g3es5!jNxvwVi8i75}B$fF=sK`N#~p7Pl^ zA8p9b0&DpdIkn3H(A`J5a+tFv@Q@fW90J^w2;Y8MpzEfkldaClZ^c|=#B8QLKa!P0V?Y@MgfD5LAPT{q1*sFUMXSOe$=5{4Zn`|z(so^(;Q8(x{B+^-6C8PF z$-?*yIn;O5Nd4T_bFSZOvq;aUB09y-bMDiKuTE$>t2vtLQGwv1QL-hShhevVP#ql$)d_gIEq358Bj}9W?OGBAfKU*)gM=&$U}V{}1roBXwIBem+@rkA4RpDH zDaP1sK@)?BFl~(53JJYWf-_M@be%*B)YjT4oKn(SF)&L~48V$rVvI?oJGV(G0H}a~ zhysEsbfunz#LVJSwks%pW6HZ>j}0PR%F3^9Fx$ zdu@zb=*dH84xJ@v@~RytcZ~WGUBk7zIX$^EA-|{&Njw)d&kq*9iAVq8m*$^&W3ECh zdAXtBG%KY{6ig^43xpUrqy{N+i-=T~i|SYvYF^GyBA1&0rnKAnl-B#ZlV%i0Vt;W% zhpINyyj+xb-rM=ist6{nSSAHnV)Fb!s!dzQA5@Vy+TiRX2@$)+HX z2Y`9_!{*1goBN|y{msGpE3aoaChfQ03ID^t_~~S}b4%afv|FqBPAt=E+k7_r{JL=; zj;7N``yt?R`dR_J-J}hj;I_Nd-l!b{yBtAK$BP$CDkq>T>I`xvKOMw5W6O2vdW3mJ(XMXc=;{{E@+jlQCm z!HFq6jM3}^*3aS-Ib(=n7*gvcdiax^puQYoT@rKL_jx6kl|VD>q-AJeit3Ya4BWu< z5oEnC96XRAhJi(dJUr$8MVk+V4r6q6QvhPDfsnlSsDfrt3PC6(Rt&-_I2|Rkpt}M= z2FDCBCV}L=Pf?7eQCa4>U9ReKToS7Fx(Xp#t3{-)tC1abuhV;9*Y&xKB!n=V%>bZ- z)Sa$FsgC=33QBh6fJIScS!Rp@Aw*=BvMkH8%!-}G^7#IPyYIgDqZ>D_z5SUtcXzjE z)1CeM_q*vpX-%O0#-)^OmN}Q0Ntg(&F~(TZrbNt&qUgTv{M)lEODS=}4*dgw_dbLW zV~jCo20(~Z7)`L8jwUl%E?wi=+p9m0n=!DIWLuz%&}O2%s22D{1VAiu zj#3J3I6(qoK~RKbKr2MV;GTt~Pr>3Redf76?E;Xc=jc720k5B6JO9#R*=MfLpTM=_ zxz~K=I*CP+fcIoG#lp!O38sV0(3uYlp7m{b+ROPO&HUo(EqM}X3>Qor&Y8L6 z4tDQ%zVZ6dCSW8)WMXXP=|FAgL*C7m1V|APElN@3QennM^=}xh4rk$EH3|vQt4~9! zNZdU8eDAHdZoGJt%Guxil%EaM1mGZ@qYLOEs_OCQ-VA5?*`fKfegCt`G>)aFZAy@2Ts{f(o33B;799Y=t*QyzKW8ZJ zs*TN^*)KM;fzr3E{HTJnOy+Z;-ldcO1%wn{xG%0?7A~inub%hTt0;Pk$ReQv0*KJC zo+{%FsNmbmYzV+9h8O`rFrFy@kP5n(l4X!20LTfEc)r!TK+pU|mFkrVE-RecZ3xu&qbz7baNK001BWNkluH2Sa> zJ^UN^K&RFIRqK^z*4_E7+<{U1&vX4HArOMlS_7mQBZMG`K(?qQAxma#DiyGUU{hr8 zJz#^RLh>;}T~;AQWb6-zot~Oh2X#FQQ3fZFID{k;2t@CF+rD$2SvGgZ0DzW|CZZNY zxA%MR+XuIJx<%VDMnv|$X$eK|eeg+Zol-KHyw%<64{TYMRaO1%kAJ4Me&v-{Zr$0~ z+}unt93LN2Y&HhDk{Dxj(kiKiFu;PD6NL~w3Mk8xh*C-^B}8lmCqfAC-MK84L-6gt zv{t911DhME1S3d8gFNdE@t#JrIZQt9Du&^UC!6&`IWN*A77DJJP(~03^cEX<6m%{^NR8I z#epf;jZATci9erzwA7i4tQar_5gUVnLj$@Ct;)2;(&z5K?dFh~&b=(=q6xgb6e zmuB?2T6S403P8lm&~_oZSp0l`H^M{=b0NVJCZ1zxAw;_myd2hrt*7<1H&+IQY@`+v z1x2MO1UOB+k#5wJiJ$dOr~a_oKebV2`cY%+u0ESOaEu|DL@4WVO5EKl-ulnRfAK#S zr$1FG)T+>0zSgb&=ytmC(w*Z{o=qH8^46}pVd~H7vz|(_V;bNPqR0xOe#ErV$sXJq zRK!>*jb{+k(cx4mHm~nNN+_zxfB^EKnuQq>@U}PJ%s}zEgIN&Q2eP z>8TYUi%euAl1~Z0yX7`IB{Uv|25D<&ROdD$HYYBk0?}n2o|faEeC!X;_Pdg{Z@LYw zZx4$i7sjfJ&9k!8!3|Jj$PHwgfLUlnXdro|(zFJOQlc^jNK0ullPjrr;;Bzmrl^$1 z-8|enuXzxRC^8;L1J5Y z=~9A_UW`4155Zt!-ne=1;nVt0KAcT|=XLwr-x<9B`CzL1-SXD(?Oq+ePS|_UwR^v7 z^2spi@e#iJLCOW6VHLQj8Dio~qkGY_v2NlWo=2;;F-hl#Z_8PpyR%NW*1LmxG!^g! z%WdxybuJ2MOP1TKnD~W`<%%{JmYTDdt5~pRWq6gJu2KdA(W=S`trr2p{gq9YN-Wq zPYSqsr#m@wfp+cvVY26w0JKb(?bUOa%qfg%b<$Iqz$#37hdH>#>-Mu>;-08`| zq?~2OfU2hw z!8UAoX+*IyvA)skT8u0-2HiKC(%^C9^@e@6@ml1p1F6XKBnJ{+Yx;YmhRK6T z9+jve9lPd~rA$6Ef>0q*6qJw{8MH8+VrHz)w9Wgrrl~d#RRg}cw2~kLq7WbiB=#1p zk-8Dy3ul0g4`RQ$J(_KX@$bEHd;42=PwUCq{&)uINa8Km{O1 zMJP%sm(k3U>+_n@zIAQR)?|{7sC3kyNnjbagd8KB0X#O^W&M=(Ay6TE><`$Tka1J1 zw;%sNJ{j$9n1A~H=H~tE=l>`C%O9C{f9t#YrL9dw6XhoZI#63DQ1}E&L5vr(0WB!u z^=RiGN~+cB(rWUGPldK&9_fB>|!0}~|x1ePf!0FY9$ zl^|&{{9tn)5twS>9IHu^^#^#HMK|ah4flfQa%ukC8k@A(OST zs+#fm43O{NzkC1w{kPxy;O)0Rc<_*#<@4x7=3cMYiceZCdbWGhT0nW z+P&hzEi;)lWB6ecx}%f9(ZihzZkzr~-R*mw{zjc;Oq5cf7&t|NpoJ6yTzj6MtL!t) z>p}|+bQ}KxE0X-qvvT-(xx(@mc}YGf){`m$t^m+-^@M&+W=e~1uXytTfcHUQq$E&5 z<@~s+OiV?$2%Z2KkQShMiL+?Cq-YW1JrB=b?&-XyZ||Bhb-4|cuQ;o~bFB8V3E%=i zU&7Y&-6LMPhnH;iuEKACc`pI^IyFs{U4w?mbT(f8)*p5E_6`n@KYIF6kh(Jc;g;Fj z9m00^{bwVTHgMj!5)y#tH1$YL-F)WLVUT4h?FbzKA3-?A7^Y=IUKoqaO$ha*Q}Jdj zK(UibDydjm6@iU5nazs4QAb7^pjv627X%MXuyoyXYg=$;z5I6dr*N5jK-ns27N-H)-Qc zO`er5e7h_*6h6zD~ z;cg|K^y&Y)EB+vv%^;_mg`l=FcE#<4_zQp_UAw`)1fVaK^4DA6S4wfxG;*=4-OG6V z_ubjDNHG!#wuco<>)($jTbGWRnO{cXaE9+{(S8d?cx>~4pC%)AT z^jB1RXyvUtP>ESm5|L&I8aN9f81w=K5pV=4GKA3w1 zP$`w=7JvYZbAh3Cu%4TH=v<6OqZr9(3m{@jLP~4(cfR#4Ddp+u>E{nW`{gfwwK?2) z^UXKE`R4D2bn0Ava(YcxMQ z*`nz5b>2;!H<2nwF@ZH<`C7X0j#zG*xg=i}a9xt$`2b#48sPGE!fi+0mqqNZcF(xp z;B#eQ5b+Ah2VMI*N-B;~2q7eti5u2U080`mw%Z1V*0-(&oT)w1g$ct&=qAo{H`^jZ zTW7d_*fK0jFP3E+i~FDd2^VVV1qFW5tvLU9H2*Lc@(&#9y?>+>Huf23lHDF~P$ikTAcPx9~jF2;lrGszllHMTVJaa_7grRaqaS`-a%px98H z#oA=rs6qi6)33xQ2^+y00mLbBiY9}*_Xems!+rDl!AWjYE_|iM zp;qsl;;1qmyZ6j)&Whb2&1P_&#-DWXEbEqR1^G)1^n$@!>G!;533bf{Y!w6AsVz&` za)&RS{`|LTyqk$y)PtUQlA1sH>!*MIL9Ajiv?dO|S$E!?8hAKTgS$sxzrAs!Vpc!d#UYCnPbKJPBp*m-#*E8B(ncSASGnXBRaO}^<^=ZX+ zTuFzBJ$_vc z+-eC&3!Ud`QDR^sW~6zF7_mr#fZJIsK_buS5DNs3G(*m#@0GsJI;6EtfuaCw^90U2 zh>^-^I8&22h}Pofw$T&O)Jlr1*J}e+=52y4+byNs-rk0Dljay>2%*j2w$?i5TK}mQ zwzhJPl!6d~ImL*G7(z%XG4sij(O@trtnuDUp|*xS0H~@;iI`{k@c!D1ER-ut$5v7H(gPFM>x)|%phN=jvU z)`y6b$)v8U7@8PdFO!|_K-!`Stt6Q#|R?W%TXgq2DpPxO1 z!Is{7K@9Ixc0-ySn+-B)lWVT{tXF#fS0v8M0Qy?={QQ)6<>?Htuq0o+I4>mjEw<)!jSX>oAT5Aq1(5=1#gO@? z5iXw9@)S3>)ghSUy_>*U=4u{Dp+oG&ly3}z>NHZYfmv{|@l!97=i>C=d?T-{n6~bkB^QfA;msKkBICiXR{f&>66nL)lXh{u}fKJ z&{3YG4+%Rtp^d&0O01{n_y`NWYVB*`gPSw6cf&$ zuq$@NgR_qx#{I+e$`pD|z>$JRLsmh5X@Xw%g5Wh5+LdlgxNZ~A_3wMoLk8MCKAOG% z_AlJ0yG0ff)hhn$S$c2lTjBS=yA?})^f`DCqtDIgz|#I7zApaJH#87k`0L^&+SV2vTY)-yxy4B17zzmnyZ^!zZ(0wRj#+b;pnK;+BQwo2A#~?rvR9_D2k?OLI?oR^3VX#KE`{mlrqM&qU4snmP+S&URN&0 zm=d?>S)jOg_dWoG=v($WQA{ahxkd~KWjUL8f)`)9d+YA4k3M8GE4^v=)TeDn3! zUVmwGYXAUM>41}z+WWc%>n*TuF}n9&X{oenKc3R^T*Z+^IjYO5swRRo5p)VubUIQ% znPTJkY*tn^A#+EHo>oTUnK`MG3CF6QvV`uS$alAu*h&B13r}W#_H6S0r$?VWDf<&~ zQ}$oT`ZtDKHK44OAPb{dECaZUniybG8Yc~|HOsk*Nm*cz?auK?K88h8>uk_ zn7ZcfR{zECe(z&{^pn5-QNqxMqyQk!jW~#zQ7|whO2mXz3t1|jHloz+OE8fk&eqJ z2VM7qdocC=5!Zd?Eb4AZo8vG%ln2Ak1%TrVR|HrgVM=SdC9K^|zhdEZG%b|5&3Z5B zDQgmgP?@K*pvR?p^LMiszczgLPwzkd@!jt3OL9_;{_1Ddtv|q5gxh^84tw3=;h_6- z1d^{i4G|y$0459-crT>{D^e7fn0Wk>h4~8@EIjAY@mvrh03saS7`q?cFaAY;>zhwU z*-U-j_gO1=s1=fmp=b&geZ`yDxDBw zb9X}sIy&Ch291?M$`lz9gO7+f9BdK0EHgwTC1#mzz2usvi7}1G!yKlU>6G(sX;gkRAPyWi9-nakWZ@ux&m+rpi z31_pXJLT-u$4PF4MD|VS2)(}4v>BK?@ckQsD^Nm~r zUYJQUGYGo&8bcI|$zyTx(|PLK7hIWq8KAGK=u%480%!%`KuZ-jusNJi?A?poZw%;*)EsUjRJs-fLt2+9imhKi}XX5+Deqme^TX zWe7wmgiK4hhJ0=f$wVZDA>u?Nq-97c21a7Zks~E$U=T=@m{S5qiHuB0i6gT}!0n%c zua6uT=|g9>*=L*n$fG;!bRY0XfB4t`RnYb8d()e5z3|zy&u^9E-OSc5n?kH6oNsP~ zOigRA)u5AGM_y4qsrnsb2MQ^s7#Xy|4g)le>8I4pTo?uVY&0{*bUGbAJ2{dykd&mM zskid@pyy4tsTsPd=UvZtP|D!@RSJ!bn$2odIOqowVCOGR1Zm zIC-jlelUXlkH^1y@_8>FH?*0$0=OwA?t$INLAnf$8pG*Oiex2=oyeiGkfZ8<^3mks zucEY3AQw;=<+&SXc6MaVkc)kfwU52L%ZZcYCR!(iwU}aYQt`M$@2lw)MRfWXpB~@( zRHJ|V55NDy@BBMkP(6c`AZ}31L+)j=(&aiER3U`ScRD?TTcH~y3ET8i0EUMB@RXz9 zI7-~TbdmFdgmE7e$&MOMa*aW4P}6XUT;bpjXc|t zg@#8sGmpmkYfmPRMs;yB`=fs-ZkM;F|2zKIpP0w``>?ldA5Sx`j=t7E(ja^T2&&!k z0Rq~{0BI@6i7%~l5!EVShkS`rYX2;?G(IE^dlf$Is~e?kFq)LId{?-?d2?ERqj~|v zLF2Y|Pt1n&PZV9S{>$0vZL`IqG57rArPimC0U6{uj1&x&vNF^I2udg?I+CNLCJ3ui zGcRfZQfjMG5)r341F-~DERmRFQY@5GAxYPpkn8V+=AV81-|o8U`0z#=#xw5y!ggII zN0XmWxvpR{LYInibnHN8^vovv!f&o>*iCIDT*P_9b4U4{3=DuRZt zMT(1!(3ShuDu!N)wJJQgu4~5%&HbvK(5ekgTC+J)tQo<*Qj)adfaB%YUmTsfXhK?o z1z-FY*E51&Q4-a%1T+Z6?5;subUVn13BlI702|#{aa6-9wFk*n>UHYWI7HM@7%c?8;UV% zB{M4#kqacEm|Tp$C8T4F)9G|NozBbg9NXSLrIh!+6)49TGg~Mnq%;6Ln@!q(0YH`& zEzeyPMN9RyPw5Tww|?uTot>=@KY0A3AN|Eoeui(n`O-JP_4Q(79}SF0*<^x7=AFVI zG^dl1BVmk*F_zT~0E!|LLNra2XWe#UjWM2=+5rHvPRep)OgGCiW-iNeGMPB%5I_o% z=XtBNjxjcMjflh|r6kZ7dGF@Uz1^J~Aw<`NAO7^`qoW@mra}&1$acT3`}g|A4yta| zRe>lvPf;1P0<~ZPA)4$Y1%ojI>PS>50%OfkMby_Ww-?vpWq^C-`oHv_h5H9y2&@rS z1fyKuF@E_5as@b8_Jo1w$+8=PwBf{*tQJRZqG#wPIgF-s46|KU#_i7a`P$?7Jv4rM1K)Qu5wKD*O4VdHT-r@$^x%x4F@KaAQNDQqT9kto8Ku!tX)cxATb4)x$sv% zefZI*4<*znvW-q>x8L2{*sykI|Mc|3zkYHwe)smyMp0mvtD-Az-s}wq-Q#EC(Wp8) zsK-+`9v@E6YARz-m<=U=$J{uxZp=PJw_!zpps_<9Ya*5~V~oU&2`VIzk`*8$7@4$| z002Ju+M&@JOrec$d`c;L-(aJZLX=7=Vm_cclSPq10iZm0wUtTSIpbO!kW@l@d+n4tB9yT^co-$Iff)PC>`XG8d{8+w3JDh)?_GG;*fP+ z3+%y(2wrBy{ldyV(btaO`Of&WLmG;1vpMk{f9S$#qjlpBREej172o!CpP#v@txtN> z{oeQmP_MkCe)4lMeiSGB&31~Z3(2X*>D+{QQGGGk=9ZePDy#SvOLm-M3BIeqoAmO1=j*`v+5*Hga9gfKmCVZ` zx5?FYl7nXd<){C*nA}U*&}RJ&H)z;yHlG~jn~6Gs2~tGDl!6n?mrEN<5;$6}Z`1iD zy6St8UwpwW_g*h4?*8t#xUSzh!H4-d001BWNkl9%p9Ai655{F05q^OC2pN};gU#}{&y?dIhL_xw+lB3~*|eTn@d%%dKz!4vCg zP1cU+T)Ds}hD4l@7=#2yB91H)Ct`|;i2zVSQiw*ftb$C*4LZtz4P;YF+=N`Kl+;BA zTS~2o2N4xT(RSd)7`2hUaUlff>Yd%K+qX9+6JO5Cn1qz*J)fRT2AyFH0p_v0WUP`3 z8do-TY#ljT(LxKFg%B-K-KG+@zvOu?gs>)WB_a#$a;vc}itcPSTWGIaS81hGU7zIn z;MG_69^AkEbpP~&4?g_czj^nEfBuu-`-3;`-@kwN&Ta4g<3~@Qd^XB-KIm_h)e!(_ zqdJ`&kd(p@T%>Y3Wvz89`DjHQ)>@^MP$`5EV&$f@_WWoISy9~TZnsC&66z@hDP@+~ zm_&P+?QX$)ueCNN`{VE3J~}(vpNuBq7iIcv@@#YFw__TpJO99Bna=Yhp-!O*J}?l1 zY8oR|t_?&Q|Gf^Mj=9?lDRB8vXd8e#iz%PSUMsn zI3>|x-7Px1MSt7aZ9grAV>#G}@~%|Dy4)qMu4hpSj3G@->`c!Nu}%Q=ED!Cd!2l%pkddj z!fq)mKpfTb^W)~}xG7!omC`b8W#K7xSPCnk0%($O2o*pbL}w|oo0e?FR!J{b;ghtc zo72kVvyeNZv=_ohp7*A!5mk%JnT4RE zLQCALNRNQfF&gh7c9QQ7dqY)j9p?Y4^TrSE{k{mGMR;{4_nTBGlzui4F;CMXH5(cF za; zxGk;MbG3|{ugrB{i3WF-O`cj4m_FyPvXDY8BoCKjCfBvA6KhHrR!Tnjs*q;>`-LC>6%6-Ejr%G9{bl~*R|1LDGKF^eGNmsDzQ3kB!Ix@G|Bl)n7Q~#G69_~?f=G-+ zA|#6Q6_c5W+Nk3sAdAD;E1XlJ5Jr1<6kShXH*g(-YT4Wrx#eG(z#7{$l_R1^D$i3Q zjA07Pt>nkZUpi=y?a^X=n9#QkT_f`8oYZ1j7B*S_}R*4EZ^ zQoi%{?7d(9e0T4ImtVbc_uk&E7q;svd6%|t++3XSrfHg{k`@Z!JGR+`iDHPD zD5iQIRX892N?B|3JRgnEoO9lL?|qE1HScrIYT0+bK1ctu*UhCufOJwRCA4KR$f?`DpAu`SFJ#>&V`=*}0eR+||YQ6m$~+!d^x8QV-~J4D_l2%;%<) ztq~0%Lt>U5g-4Mz6|RY8m{n(ox|<*A?Vo#XkDUGNct$nnjUeC1PA;>(p4rTRMbn@< zRPs?%>msAXRq3i}1wckiW0aKAi?rwgSd@B%5dAJe0wfR$o0RcsUC$g^>q{`&DAY`; zO34F5Zmc%CTMHosbW-Y5gjoZ#GL#%BpsWPzfz0NCsw(0KjwZd48!AGp+>0aZNv6UXv&>O+O&$NG|Yc z21RU|+4QJ7Zj3-jQ!89Qr=7RxmG2GDetN4uvS)St=-<%k*|+)8fB5fz{njf0=~Kk~ zNWK*8ZOKLk(5NLF2wnxAN^zdPgnV9Cq18USiNqIcaOZO8^ZTuCqQ$)g2|ysWOFp$odhUAz zd_J!4*YHp5XD`xcWwI`aSrR9r*N~_?DzIqCRFKzD)R5PtJ&Q`X1PrK@G*VdN);}I( zI8tU1GVlp01j0!rG7lXk?W~`8Bt1b6AVfV~m>8{6!LrRkw8s zRNDQhTwM3n4;q3w#3rEy#{B z_WS*g$)%J{(@dw+dQ!K7q2Sv+0ZS=UN_AbgRJ75#f-Eb9GC(vd3ibMH_j*WxZ<2E z%X0puux>wj+xzI6Se0oa-E4NIwKm3d`gzM$&qXh>9l|Um8>^JU7Jv6Qx0q;jT#;`I zYhJ#y_u4&nu0EQc9gPki9=`wN=}*s|-iF>Q`PR$*-rhv_gd{+lxN#{ZY^y9vrFg9_ z0xoE?3mDDJFb{CKYSoNO&4>%Lwl*0auCvdBrJjMcZ1SFq1jh(01rrlv0!ri?K~bS5 z0n7q{5mC&c^QCg_#d?9)>_b~s&+{Pod3yMYbMv(W@OcJ$q1@{O&Jx?F5^cZRkrtEOb+Jd+?s2fnZQg-pFz=$*Y`-tT@q z9{uoFpH1j>U?otaNC3pd-Z67(s9G3Gwp4Trri+p@rHtfEN035L5HSKn$10)(6iAX# zn1f6RL=LPcj!4O9D>#!7oSj%Z8#iY}2}>4Q32U5EQzOXapGMM5W>(1{3N(QJ<~zro zqtQ#AJKZeHWv8o#!+bDQTFY78trI4fNI(u?QEC>o$LY+=oRySP>P6855fQ{j!cq#Y z1+c{%ufuo#aWn%x9?x8tn9<)QXlMr43hl4e?IM@8#NK2|YOvSAQTn2`m@;3OyC zt&nD{?iGMD;Vi_N&C4{sdGL03|I;_#y#LK_(EfgT_fTB#WYGxVex_&_ypqTCq^AlyHb8`gv*5ov1=W76K1&@~x*I=i^TssTB-A zRIt%K5mo5+cTkI&4+%g?)rh4i^`#ZFJw1{^01BYisz+3XZoOfio%9X=$$z^2 zixQ7!K3z8n^;gQZ^0Hj2_Q%dI2J&{$#gQYlZPNr zX5xmV`_0*Flnn((kvVdP1A7%%G|Fqv_?#_ZfOL*aXu&!owv8Bb#$<)h;wtU$c>~F1 z`N0=3&}%loO0i}^eFe0Wi^>LEVoV4Z;bWJ?5(Mkvs8#;ZVom!Gac!E<7fC_ZWxioO zP1u^bH%MPXxL;X9)s>9mCE{uob3oS%I@eWXtj$2L($Gle#3WcCf&>=C$Rr|(#4-T_ zGKwTHO5p%yCWg6x_mfZm^#n$6_jXrq6lM_ADK*H+WIvWfIIy2t; zx^f}9ZnsE@vb+e<&88(D)X{Nc&LJ9Jp6qL;n&$3pZ$ZLu6gX&Ouc z8;`Y0W}$7k>>WXuBuSUG&d*U0Hn)Rr-c|pE+Oev)^*oa!T8#t%5VXo;W-YdPpSXbEBB|<&+3_woD`|xylXt95oKkB zW>g-I{jJ>ILKp){9prz^~=>>RUHnJS_hEkMMtZxBI_|-`?VEn{d);W{fk0 zD3Xv6S@|eg$a4kseC#i5)K+d7R+X>`mwCIz7%gpA15l(*ar*nG@7$dH9CHj!9>ZXG zGWuVP`N7}cd9iq9C*0{M-|&YG-@j0jTq2=SFc5%he*y@=1SFYSA?)Sm4V-B#x&Ydi zX)l8+hbqqy(hP1|Zc_>7Hy|P=?3SN55$Ygj$(+@2G)?13F7k(X=dd|yX4s>BRnBCu zdp8RRt|#2^ta=V3z(X0nN+b_;EZvrvNqyRNyf&>(lQnsabe*KH;*=t>xy~y7i{ow z?Zm+q8_QLU>57fng2BB?f$%j+lUGtFe;r176&_nRAVyq{Gg}B_#JY_8x{_x6Y9u$S zeCy>hGG2O3wMcYZ4xn$1;Z{f{t`9By|4ReSBzga$$gfpn1bK?Z^Jh%zOv>so7>B8LzGAcUxtGRjVA%B{d7C0Er-Nd)O! zJs$7dymSBF%bVMq&z>AiXR{bcY0mR3MsDiJB!Z72p0yxS2oYm!nx^e%DmqyUZqDT< ze2$xgQo>qoZ8ys@t#!-nP9`&I^RWeMBeN_kiUI(lXq_~eBLHDxvpmm~Qj_B{k+X&T z#v3>9+}nKTohKi@cl6_N8k%Esniw7O0qfw{gCvQm-+*Q%L` z&iM>p>ULk6$gaX}x>RzZ-?WJkP*4IX+EfkzN|XY^Jh+>g=iD;`bGl~Be9k>Ddp|F^ z%U$~L%K&=$=kgTu#hSnQ2I-On{JMEyg^wOwc8|uTo2Lla(V%nTW?`0u9i{ZcUq1Pl zUEefbH8FI$Gb{iRK_uPbt~sLsbwG;0`Y1YXl0B)1r$@3d6WY3^BM4|K&cFmhpy1XN z;mTpQ486@efaFrDW6XeZt+iGPA*O^Vq=d*EW3)tC8KJ>DQbrn`0db0$P)I2{9rec6 z5D~qLvsp7fsrR3Z!(l^pN;WAOtw>&xQ$7F$b%TmX z2q0)?6N;yG!D=eO^~#KciTwCs=3%H$!&NRmNlsSveikto5rq1bXUC#?Vk9(gUT;o2oy)-Uew zfBWohiw8-VNhMBC{e*W;WroP!9c@E)EIWq@hf!^B(0@m4WzbU2&r zleSs{2LNKB>Xd5m%u%IFM(=!~bzWtcu!@1c0MN@kbmECfM#N-vyyu&{S!y!z=;ZhZ zGg+rPe>C~yje{G%V;&XF0Srm)*g7sxM;AMG)B;Em5`yAZ%asJoC0`d93jq;{!DSm# zMhMjmC;@_Z0AdKP@m>H5Bn=FZKqe3j$gp*g5oByPqP<%|n#52hNP_F}h{yTy?1Kq> z%H|2*-P7(&pPZV#U9tIekb||IG>I|qgRk>u0z&5!D7fgf03jo$NHUz--eD)JI$6?V zQB`@ArM91zrPbn0s2ZRkjZ!4gz)EvY)Y{-f1dhxJH~}+);)~kICF^MTjcgO2Zz5bb zv128Zx}H7UDqA|itDeZ$9)es`g0hP7mAIx>o3B-D$_-jSGqqocDA zZX7($k{o$F9zRJGbfa{qTiB-U@JlH!tSzK$i_zHr`TtV)W=)c%$#s~!f6HBB%f0sM zu3l%uOhYpq03rpFfQg_aie@qjCQ+t8pg*Dq{sEaDs0Ya;Gsz@M6pf?+f`o}A2+UwG zO9LEC&-7Z=)m6D?M#Npd#ohIAqq4H9E4q=R9+N4o9x5XeYCQVNn{V8?yLWPWuy|B_?>j&JD^(pC3&oGZk7c`)1j9UCK$V^)#6- za&qm7w+Klwq$wNcOTTTHSv46zL{k*gda~oa|Lwg`P8RWJk3M?)!8`B$**|a1-O2U0 zHg{g-jmf&rqt8aDT<+PtKw6+r6R_kNJ0!fUs(vB)diiD7cjVRuzJOlRThTzCJWu03 z{rX7@Ql3?A$Y-BHm(SJ}guVJHxsHLpgquJAYVZ^?gI)&EYHABJl-^*@a!TdIyUE$| z{4j0ZD(Bi99pyfPtG#Xe{$!quwreFpRg5N+LMW#kqZ(HN1|&g3LPZ3kA%I4V7S9zD zLvx$uBndDXv^E(v$bc%G$W&QUR7M1FpdJ(?#)y@OiGZS70@N|N^Yhep;U1lGNv)Lz zpe;2Nn2>?BGR|vnrHh!eNu5eS$Hp2yaq0{f#(Qsk3Ze{SatW(Q37s{j7G-f(oKw#+ zcHTNe)>^BIIR~%?$+A%9ESjv*atu0>re6jD2{nU?B{7ge6p6?RO3i%;S)oDa6)Cca zqM~VVxq;aMC4ml%pb^D+!jY59jo^WYhQTTM#f%zUNy2eeif@z;X9pkiqj%5fh}`(x z%=WErIRC*{e$z>_d&oQOV#N2~vdw?}mTr7&$M0TC)man!aYff%kbK(q+a9#&m$mrN z$H2fv*#ip(>ojxq^quM@mt?wPavLCA_-|aINUOAu>R4O{CcyZty7ADMe|5h95Awm+ z&g_Uvw_EpQ%QLn`_6B-+Hu&)321vt=TCAd|3LpUr$VvkZxbnFfQa=GtaU*mDVOf`P z;&7q$oc0Pob#yc+2U%4VRUHr_Vt-y3L}$EH&&)mai4p*gCvEF2+_11XJ>smW@Zq4{jj}-{kGN8=kh#k zbmOAmgwyu$W}il5^5DP_Pymnw9A%i77F7WiQ~_mFd7?Gd)gF7gOL47~ZViCDuu*${ zi13RE@?c#iI1NiCA3-dx_V~Kf#RoERxhikpI?X{)2H!8}Z-76H!%`l~Q85 zh|8E4Fgii%+x$3|g+IFHwkFrnFH*b6ld3cUc4pHUTlIPHkBc!1bKiE8$!LCZW&j;R zzifaj%tb+9ltOzdMRV&`d3=~2KVES1*RI{TwufXCEml<`GN3;6(swb&$dXifXJ_*Q zPp^7u0LEa~b;JIB8djk8e^0+#?XWmIU8ea@;T?6`{7;0m_?+@NXG9!Iven`b8c&UG#Fa@ z0%J@eq!@B9kwt_MC~`jtyPW|bDn#=9?6hrrSGt*>9d`<1Ur+lJGV#r^yL+k-!U z@Jam}rrawgubc6!!Edw{Q^8PZeUeyuw8=oqg2vRS&PsV+S6c$Xa7n2XG6DN{S?8kVug^0vw6c zg_3tSsK<~RKOR+f(N1^XJ&V!VPtMPyP~l1}v~?60i;?ptrKan>bsnwhq1vtoTgDWF z_gf&wdxDwnDoW$DWT!SpHSoDmGV8iY&dRW%8#szyr4V9f|51&hx0 zS#3pKhz}k-c13wOD_rXU2-K=NQqKkS+E-jgaYzNGP=UH4_?nkRg!bNcf6>u`4&@ zM4X)aWoc|_`;lVqd*;TtO46hPsKSR+se0tzjWTQ?5EctkEMsxBcXab~F+L5Cabtlx zJ~_Hw+&O0tc&gSar~)AoiDF7t^b^OGbuO8duq}jZbSc}W@xE@=KFOYv9za102hHlb z{rouny1x>daN9*#CC9v*)j@%Q&$|7kAjRu+Dy8lGqMRuyv(4zqxU96*4~NNWc^19+h? z*~7mJgxgfS2?zRl|QOxKt0SV!V}zN z=@>&YU9{3b67<%T%NXqW-MaYc8?gUs{_6KC_^B0X@4!g3RtC*F$x*V^MqAOwjOsH` z&L=ZlMtUQN?%aGmYl znxEGf`+R4XPt)W8!wdm@`d2>X;-XIq68-s&?*Aer^m;})gNP6^C}t(n6529_<@pSW zJ!GP6u{9bH5`p;e7(hT1NmdQW5hST{=}&WxntOwhBm#FT!Jr;StBS0msv?k>W6U{c z$Q%?i5*yQZId?rEGrAIhumD9M6jEVi#=a8(NGTaZ18kj6r`B4DQkLanv0%^obZ`n| zALh&Dbh7>0t2;+W&0-$Nc<+6T@#Oft@3Syg{P$dGN9rm_i~NVvwQos?d9S`aNtgA`p?HC}y+SXf*QP4<=%&ipYa0Z_a$d$9rFnCsm9wh9n{>4T^AE z6xH_jW>Hk2#3`fD=4_*WV|3@{-S0p6@&57mPY-^-oW8kn?Uy$vuf={VJnMLV$D|K@PWH#)s;juGm;^Y#(ml zdUWTT?Rd8lC2E|p0HBhTF9IzQ0CqBEQl;!77lKQ{06=6}pNUG*3$KHP&y&$m-HTBO`=wx^qV2J-k%=V$HV@nPG5**FWMKltg{hwt1! z|IR{xdLvA=9jej`)UA0Kx&4<7E`Uw&y+zVUMC zuZ6j@EudeNN2FxLSawFd%?`kULbhi@$)FlR8^E+im$p!QGD9IFWCLj|dUT2=PzgQL zAUn${8C67O<)QZC{quv_t3Lpp=DVA5KIK$_5uu#)t>*Nb@PGWx<=gS_`ibKaCCB5l z`|#fM<~#Mhqp^}QP+dt97lUshjjks3ylU%BuExBskJQF1{@E)=d4EA2{H7-rgktLA|APXne zjED_yWEr?yWfdK!RgF!e5izS{%R$oFGUuEF_nvcEO(!));g}#XCt)WRfI|MdU*(wi@T>)-j(YcE|RP5bvB9e#4e zQK%;892u7(6WXFErsG*r6kR;eIk#=wv~f6E=bTj>4sQ@l53wvmj0K>?n2BgKD!nfU zuRs8B)(dMILIKb?=jwV)XqVk`vFN%sv~9;(y)VnMF3a*i`o>#*>UxdK(C?rA>rWp3 z>u^3InWWc$Q=u;F>$cqPY}MpNFTGOUTr}jBoMhk#l)(#*6${jTylk`jgzpj5s{!cG zlO8>1@m7mtNfC5J(CdLp93{+L&y+v-L zl91!<2*9z)RHB-#M~x4Ys=iiGq`b@|Vq7L`T-Eh`w`{vUFe{5~yKL&ZS8OGk95ka~ zxtv`?KWeF*fB73Y+X`EEKbhQIY~B)AaX(=}uW*Kcx@K2f0psv;*y3 z{${bfdE`&AYP?;0nQ=>lksz`n=F$YRn8uh(vmMfSqnqD>WVR+eb2l7=y z?*W~3G8*BTizh;<1s53=frm3+RdCh2OKSj=i5;N?p#zv4cuU4-^sM-kJ1_mp=?{PX z==iA3KXZB0=dGa2dGXR&{@P(XgCz2y*l0?UUoP zN00VDc>lh2W;8AkC8m~ORM)ll-r2&t(ijtC?7G(ZmD}BbO0BhnBziKfpEyQy%JE`! zZvfxp@pwEQ6VYfia?bUAKjg6uSav|+1Au<~usu0CTr>x!fQ{K!J=*-rmtMPj^WOcl zKku8xzx?Ol`Cd7G?bUlXVexg9i@>h|kQ3hKLXhBHF?abTttbbx{;mQ543Q zB9BqEvV465-+ZZDH2KlvljFnt-+S-==~9>edU@@ue)n}6?FCnLTI6vz;5b%M1Vu$$ z0ye;_F+O?DkZursU&eW#T^Z}=2TVM3;zWU}?14Q7T^<$9;n<{v-JmFjAxsSLVx|z3 zpJ3BfMBD%b>4}_+^r^mzE=CWZUIlUWD}zz?g(2OA5?ti6R`>VI8s1g? zxdnoQL>!T5C3-^w6+}ebKRCuJo}4Uur@h*cuxmr;y2 zX@IauI>>23k=$8UyulG_NGDG7cPPrNE}iwAffT$DypcGY zJRE0ybhK=m#bVL-fd#BB$$BijNu6+F5X2(i`r6r>f4$kfcPRejTP2tpXr{5m9`H1% zbipQJFn~ma6KW~6!mGzkc}V*&U^_a&h_*pGn_gl%M24fF-Qjh<*PA{M$Xyz1(Ik3y)*Xo<-QyF>!TU$ zZ2O&Sqd(;SA3o0C;n#28{MP(ezxC5^Kl;y47kmA|J6l^1ruZRLO(f_&LVEEs7fZ^V zjDRa4RlsGonyq}Cj^bz>r&hELtxvq$_e-e9llqgkr8AfwH13D}WHQ>3CB#MipHGdq zGA_7w-PkrG*Nt3sB)^8qIh~X;EAj+lo%)GjZT(*Qf%Dg*-8uBGFJ~AaC+U43senuN z%umE(YbBt*k53kvtg6*G!iXT|I2T8@JKK$!)Su6jpri`Y`L)-UlWkS@k{oDXPT#2F=R1|}Ps0qNTkjH+jItcSK00MLZPO%W@ zL5(7HCWr{AWn@tqd<79vH&GE)F{?6Q5{LTNQ_xTnI(jzs>~WfsHzbNh7jtyPAT<$zd6~| ztOk&CI5~Pa8c(-2MzuGO56%w`9s%HNHu2sgYFT+}QFQ9gOjTn7mvrQ%W)93qpDT?!((zESf=TGM~?_wW>NW)1lAKxw0(FvL4>)(AFok zecuo7Vwjlhn)4VV>_9yoJ6m;q><%NMxq0p8-8<#iUpl&faQNWlok#8a2k&nLx@Bjt z?~JaW+-u*BD^63}bdf({sM5djh=)W#Lj zd7Mjd;$fvo9#~%`1yWE^5LFg{nqFlbxtuyZUw28(3U*Co(QZ|7670Y32_)fBN<%MQI+tWgH%n@JZkOq_SB6my2OUzyK~Js7e!Hy z>ZWOcR(0klj}8IATI-y#);e#7Le5*Gs+osjel;s^Jy1d=Bs9aJif9)@2qE{33Z-|} zAgYLHWD&`2Y=nVTLP&rJ#(M9)^C{&E*_A*hw8jvT7Nt$-vA`19<}T&vNh1~i=GXtT zZewrM9ZkM_Fzsc^B8x8AWj!rL#Jcgw&jyK}s*=IN*-RthBrUe%8;5s(^^@6kY@zBS zi;!?BbC*(vm`mH1bGT#gk_Wol(h@+@LlY87IASY8wR(#g$VdR71A<>dpCzB&Ki=E>-8H}C5z(AYAY z)Rw>%+9~fhrdw*yiHz2Tjxth8_No0G;ZqE)x&q3GaLMQKGa`}K-{1`h2{<4DazUsU zFrxK*4nUPDw*aA=Jnrr;C%a?wuw9zzajfUvVK=ceU-EM1ru*y+nVPC1d2=$ZC@vgyeYZ7CADT{F z-_MSl844LN|1x`iqiqtpA12q@XW<;;XWA?Sg(m0Qzc?<17L%a?iL7^q+D4Lw$~W zUj5cO3CDVSmvzSDYbcf`sTI8wQ@tVkByowaC5OGhTg{wxR|EkNC* zcHY|DOW_qzoOQ!Y-T*SXt{dz!G;3YgP1B^1&BSo#zVDl+0a0(gH@2Cdi%3;~^ON1} zu~I{12ulQ;voN!BrYQWu!J%l(IkQA0D9ds>s}VN`MtO)z8GNG$05ss>m3y(S8W)H# z|=jX>3a8#64J&7^qB*Rp(HNKqGs(N;I zHq1T_o_zyqH^$V}#2Pn& zoVU5`Px?jIEc=ECi@Gk<8JpwwZuRBeTVFOX@6-Dqo_z4p+voc~387dXyn<%SR4>`_ zJuY{9yV25!DUbUOR>^*fddYSGbd6~EYRPJ-FTVI@qneU2rZBdp*lX7TGkP~vmru@k z1E|O=X~`vzkt=b%&&>{B@XxSj{P#JrwLbHc3aWTXU_Hn|{(>$X@TA^*`XnhKp=yLo zNW*(4qPd;1DVaK>{a!)$X69CH_v-TgPm0siQ}3*R21~{mMTjx9Ofg0PvDOmdP}Cvm z_Q-qhoh3v>S&b_=W0{9bs|?BwUzHQ%sxr5IPyj>~1ra@-H%I5o!M$;nvuywj5z)o1 z<*CDoDv%5V0E^o7N@TU?8Xkir?S=Bz(`d-34>xOdp7h}G3@mNmJfzME?QkOpO&wW!$prp4{ z%Pi_430^fFMaH8ACTW^N4Ec3~%-1=bejZcgR>i`P?P3ploWCIBh z(@;L)g>9uMAOJs;l&~r)KI_DO@zb?>pO42)F(G1E&Kl%F6`)6riKt750 z-aB7@8F92TD!m$a26*W36W}UW^nr2b88_5vIyw(kZLY^Yt?nbJVg$@ke&@32MKz;D zMAgb*Wfcw6@6VkP;FEqs^vHSe7IPil5;8tL!{zC9N!Ac&j`syDk^?MMNEMQjsM)V% zyLzyT@4RPjw4t1`i;xe<$yt$thYh=Q20Chkn&o z;Lme7dMUa4=ejanxiDDsxyWa_<>)j1B%eCi%YkC@-0gMst*|bV{pZ#|KVQvUQ3D-R zK@cP<_K1_1O%U)?Ga7BN3UkUiWbQM^tXV|H<1sV$F~`7(MU`0yMWtl`5XPJp6$sHN zXa=>Aa}Kdjk@L!Ao&W&B7G|)IPKK0fbk>DHkCuAgMRT0S-jzhiJg#$$Z2}Gh&b3q+b2QjDw0wnpcJEXE@d>}3O^}Kv0N^lmA?rih?tUEtjaJGa#rF48e zUn~}7<-GSrQH;jr>H~(X3W#(eX&3|;gH9vHVR~srKM(2-V@%r~hN97Gh}dre>fOlgXO6tk+PklH>Z5i8PjYfJi-Z~fA*ef!tm|KRbD-u~(D z{Ij<=rtjZ-`PNsy{OYT(yzeJ1V3jMG}(IH9d8c$Z2)l2Id2d>Gk0-lFOjg{hg&;}!*>cB%I zeCnd03Rez1T8m|kMegF*jVcEX=b+3i1=U1Bl|U5{3?QK3&_%;R0^;$iU(OD{9LMzZ9}3_g(GWx$Tsu@1 zM1f>Tjp4yRPz3;-V?qv`KR%v!p?kCsJ0z)BfLd!K*3vZ0tb|D< zi>9p1T*#sQ0Msr0EN_10bmJR)o%IoRAHH|};~zKnpz&i7 z^;Oy_H&sm6b50s1i$;a0fE(3DCSOu24R*wk6NJ{KgY#+(N}$*p0uYc$DZ_aeYYYa! z5TJ~Cd8dE$djIfxJi~Eu3+pqS{BA|x(*#kFwZ}+Mu6FfGrF4v&u(nyT$`NY3c;+N3(Mub*I6eCW9!fzy;szkcP8l?{NohV#FL zAO0QqvpF4gR6eZE8x#0F{Z9QQ+PZtw@U9jW*;94%sbM-Y-ByBXA9>;PhBb3}000Oy zMDxI4vZK0{a|UFznGB#qG()oabQDv}3*`l5a6L$nn4x5NYOl7cMxK!OFaCgYssTvR zkny4fY5*OZ;$Hv#?M37Je%qgI#bS$XjMj7eqeIDG(MGqOTJN~t9nRtmjy7W9h(`D6*pIMm)T%Pm! ztmU!)FS`Jr%RuXTEeokiPL>i_NSTrnm9_*I`V>RX%anW8Y&|$c(^Mg6iIRI2mZ3F? z3WzL@3|T6SamE;9lqIFm6B&bKkxNz8EU*Hj=t@TlEHQJAg{|D!w_S0Va_-`yiATrF zjmnIC$Wp}=Vjn~@B2K4M=Zvc4oKs3MClRq|t+gp~O38aqXckS=_g#!4qFCA3Et+`~ zLfE{qGutezwWlXt-vwjbbh=R#6;f}EF@^v%=XBx0Y^WZ%B7K9SLKYzcvnzC zm!V8uJ8SJAeZI&w6p^E&P~Qn`odWs5s)hNmVs} z>3XrZarfTqzy9Mt`{BR&!ymu>_PcL={q$pS?i0!U&uM?k$Ymb zrd`)97K_DV!OWn}dtX&WSrx{h^L8|<>blC@bIyb2LI(uWnA4DJrT~Ds z2qx#`i##qMNm`sQGGkfR^QJkU_kC-~xU!~=&CQ+HH#c6{`}Q}#)pK{;oqcrhN8Kll zJuSSsH=5i&eCcmp1c0x|U3s2T{fjuythcp&@zAXYkf?>K4~#6%IgbQfW}D!NJN4k_ z`ee#aKAng11@`iu==-12&x0b!Jj+1i>5JHSa;peUPSw+AbgVq{rjX_|pstf>K z*Ma1^F3Z9{wV-~YbsM1L@MK*&KoeNNmSWs_my%>pJ_`#x^>7%>+E<3?Ia^qb^BRLh z77;g+=>$Ot#YSUKirv$_Hx91-a?_kIXMHz$G}=6wf*z_i61zIa(`ZepVvX@-St9wQ zow2aP=B$e`^e%D|*JuswgSr~$K8~=jIQzLxV5so5DKW%OJc3csP=u4&`OkI_|MbTE ziM3I{^ozYie(8G;cXd9Wu`bHvHa{41 zQTUH)pnUy~-#obfa=&}izE?&}z!0UIMKi*!3B25en`|9G$|1qAfLWR(WoD(=x(vi1 z&Y_FX1~8$*u%}mj#Y@IVpW)5=8TY%LAN`||-1p5(+hv;A54wKmA5FJ@FHFm7-{API z9H=_`sZREHw&U1AN5$b>onRlfK3R-Qz?n-thbW-sn)NSOXTat$j5{Ru*qZX#@7&{) zjg8&E_ebad)BJk>YyW}MZnk*%%8uQN^iTQpl=3KI%iG<{f07*naR2>^UJ$Dc0uKxsXY&ctX$RaMQR$vM>JXlr`yqYoc=q|?I>HfGz~*Y;3D<1zL~Sk9)K z?|tyeg9jhwoSieyTWg7#jX{H0mZi0}szy~+4Fh?j(Zm=PNip>UM>v?r8Do5*Rpp5| z#BSh&bCSOAeL>ba)ge1@rI7#tLc3i07{U8-UDt!gLqvQz6OsM>{YQ@;G4sm2+52l- z5BxXEH(&o+-|_yz{2%_~f3>}REEm_2Ik(eU+J~|m%{VShZn?Au9`-_H(5|v-37JqWs7a1RWC#Zt zNJ3IjRih3B2D?Tws3?(hHc9x200S?P!78R7VA(h@ike z3kv~RRAnY0Aj7=M700KzOA&_bKSMf%g9-wgVNFEI(XcE8h=x>^Q31iA0Yqg60E^@A;-4uy2OZBWFfSRx@4PZL{u6}5>*lzogUNi zWPEz_ui?$#TzXiZ|MTl7e|#%-pA=(6gkjte!5BnU<^(bVVr!Gyr8B;u-lSNna}JoZ z$PkMrpoE~tYKOs>77%kz%3{zWku|0V_SUnTcUsKO;M&bM-`o6FIY0SN&i?=&9JtdD zaC#TQe3n~VVYAq1$Dxj?Me$ly3p&efU~fPaj(@Tlan!I ziU4TY({jloX+ppirLF`xxbw>Ej}PVGJMCz+pYLQhKT6Ge?RAygKn>dlXoIDPXA|r` zM=M!)*LKNeu$6Dh3@m%GJWn`a;Yi*Nt-(e|(ZmmmCnfZHEA`J37X=`^o0@P(+6xgY1D;=T^q)@hIl~@%6T=ivApIhfvJ8m}4ICL(w~3UAg%?zk2`2 zH%?DZsL5kGsb6L5qpurZFMZwlI+Zn8r-fZDiU5g%C=OzeIJo5~S>zm@p~AT3(c#i| zn(j`^^}?|K)GK@A22( z`%dmA;0wn#AybG_W3dFrB2P*P4U7`x8>hE>cu?y6#nkn|N38rf9lfd z^@Cdv=ai?D5Nwt7clW;i_wM`+5W3!;Jl<#lnsTveylIR)M;4?0JQ9xe(a=|>vOk+x zc^)s}RmIfug&faS0V@(d_iFl?$^}{@>7grXwRJ7iET6k>&%7kQcu`iA%0*NUUXVrl zg)z`;Xt}Gk0Q6FJg9@r50I8sJ##QPrH&VDd2d zJY1yZWwAMDO&l=Bm=kA0J0LbhgNVLx16i9`nAukzv2VNiV$mQ64`yRr9xhq3Qegow z#u!=+A;-=m=bWYQdjJvU7~>En*oCDCm8D0-uIrknDGKfT9&xd=RV)?_;i4>kRaS>b z=f_9;U7Msq)wXW;BbVM}Bulv3kl+XZBmerua@ZP&84`WQ`kTawd zhG>-wowOk;i*lG#OeuA37#Qvl;y}rV5ZksJgcBmt_K$}4^k_7C64~vls_OgY-qxnS zQ4tpBi}wCUkKcXwgMadmfArpaU%7MV=#4k7@9tK!k>x<`JfA;0>w3uClhLB2?VWL1 zdTSW~ntu4Ka!P6N-x%J`sGeQg!Ahu^vxszU7yA7eA9h_gbW;gUQM!qr3Jd#D6fJT!yKU`|A^CW!O}Poi9QxVtDS zU|{!I)S!rvLIfSYJD9YfimGN|QQ|=xf})5#bO{l;?UQ7T2*QQh+WNwetSPYvByir1 z$ayr1QPd*nIm8*oGCh!!?}7)L9;)FpDL{qD03awMASw?@kZ1%b!*Dui)+Yv#eH)B1 z)_7X^1rM1=T38|?0whCZ)mvu_0*I0R+{tVi3Wl>XjOCqw_q~6R4}WmdM9*!d-3WRl zRiv1?kLe{XjL@kU!9duVVp&)z7{8YNAwZJRY213WnDuiHo<}A!0z=|ewlM)v>8e9TuJNNTwna=XjM%p5 z0&cRMf^L8&fGEmf1DL3k)d1VF&4uaFu?^XP8H39ug`JbPEtFj}p{TohoGhIyaB8=3 z^tdjSbC&zyBjDFSCcpLL|8qy*^@|hQCut9CY{TYO98Id=crwz`I1>w<16P0^kOCD; z(}12RRZubbq@fEPiNRECL?nP_d;k6V&wha1m384C<2L>j$fzr_E!cW?9$ZP*eYp8X zHYWI@^L1O+eNks$fHAIeq9_224tkT&F*v~NwdlZfCLX&~c<025)|Hv)bb?h)vn|Rp z#Pr0h0HW1s2}fVM|Iuw*>@6OQQ&#egK0@90AiXnT3_uKidF}XdaeB-V4zEFJuIUKg zoyR{3m8MCRXIfy4y;R`JLLq^K4pW9iUl0)~SF~5V`X7*0jjtd889-185odqxPA+`; zQ8BH?;nWp9#{PEf-;-msM{0``$bbd0>)ket0lE|T|HI?T>-PT@BmM;)zy5+}C%)kK zbxByEpNV7bRkd!qW<{>r+J>iHvY~y8A|L`qX?-t1PJo(r*>NU8WUHV>;mfiNAuN~6 zrs;>FG%`>7Zi8lEc96~OJxU!s96Z6A>of_dd8CTO$Y`fUR{%B$S z399RMy%yeukR+xU00lU829lDCfqk)}Q3nLPXp-tMYy^GZhY%2L&beutm#Vwx=ZocX zN$Bgbnavz%dG1nK)H~bvilP|&F|4&Bz|0{onR$?Kc<*<1w^lM@v$B640O+7Uz8D){ zNur5z&YXparkmrz{vyWMw%zIJS=+YEth%xWhD2l2s%Cam9r;5%Nh&U|5 zylq1t2h}?w4nEnUj0C=LRaH6b&(F_KPfrKel&!6;(P)H-zx69S0=x*#{llZ5zW2fV z4}Ls9sR?K4rEfaBTe;WB+=${MHp!lwD*E=CXrFSc5WTYooCJyq!Kc-3zTC`G#Z|)D z^XCCOA;aExG>Xw51bZSl2Exq{lLmoI7SLM(%AzT9EPFv<5M=-$9AJ}ynD2-PC?f)r zq9zvpf2e!2U%k>S&1H;(l&qMk=Ve7L&kkMBP`I+m30mi@$N4l)-G zjozBFfTRcrgaHxJ5Rz6RlCu{AO+ca}Q;HBezvfM0c#P#X#+cHKRT+_@L@X(!1d@y* zMPL*l;@SM_r2Pbo{ZDWFN9Xa=H$VL!cJAK^33KWZmU?_J6&}I+^*r=;=Th9kbsfc0O$k&N|#_UF2D2McYpuE zyEe(r&D|R}7Y`=sQCkhBJGDDoQh-drm=m)jda(yyMAIo1Nr2)~`>|{7m0E;P0!tLi zWSIwrrl9E_sL(!Ks}_g-e5vnm0ba^1AKJWfL~GII*)+QvneO17s1g{%Q~; z0B0FA0Pp|?RKZb0SwXoiW!R*X^Ez#JcdB(R1EPrHfFUYCb+N6b-hS{iAxgRorU*sD zOyz*<|wyl%G$svshQoY`{*L@;De zpB}X8P-?eedA-1HHoI-B#4) zr&f0ML*Of`E3y9|G^aZR5`iFF1c;LUH5)#IFZOhbjDKbrvEm3IkJ|fc^@*E)^f>RF zCp%L$=5pwJJ0Hs24ax^#NOtNmgkdo0=gETOa`ZB-9WN^lbUoa2; zW$Ax>(N6!1Ia5%6@hUEyhA&q@|Em7e7o>K`7m;H=3!@c5X5kFXP-;M8fs~_Lt(PhE zrL8m+L+Hn0yPP@3m~tQ-6B{mI(PO*xc{jSMC&Msw&IjjHOvV&;H3uT36wK*GHx3k#0c4KF^FYex56A?R;v&5KF%fsNDbEI-rRb^?bsu(XV z=j@zIark_m#%Qr1A_Q}hi5n#)j&U3@lt+(_N1d8;R!S8`F`F%nF$ikxnvXhlw1{}` z`=Kq%qA2Vb%vThJEo=zkXm_`5+ikbmZkDT+HbzyIdh4w#mtMbm=ab{RA3yow_a6W3 z-SgL9J9_7x8&|I%?p?Qo+paffF$PkFNaY9ORH7PU@O|e}O2aS=!@$f$L}

@@ -895,6 +955,9 @@ 0 + + 0 + @@ -905,6 +968,9 @@ 0 + + 0 + @@ -939,6 +1005,15 @@ 间距: + + 1 + + + 65536 + + + 16 + @@ -946,6 +1021,9 @@ 垂直分割线 + + true + @@ -956,6 +1034,15 @@ 间距: + + 1 + + + 65536 + + + 16 + @@ -963,6 +1050,9 @@ 水平分割线 + + true + @@ -993,6 +1083,9 @@ 有损压缩 + + true + @@ -1100,6 +1193,15 @@ 搭桥间隔: + + 1 + + + 4096 + + + 5 + diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index 193972d7..279fdfbf 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -37,6 +37,8 @@ void BaseColorWidget::add_block(SlopeCraft::AbstractBlock* ab) noexcept { const int row = idx / cols; dynamic_cast(this->ui->layout_blocks)->addWidget(bw, row, col); + + connect(bw, &QRadioButton::toggled, this, &BaseColorWidget::changed); } void BaseColorWidget::add_placeholders() noexcept { @@ -120,7 +122,9 @@ void BaseColorWidget::when_version_updated(SCL_gameVersion v) noexcept { (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(), this->blocks.size(), v)); } - + if (this->basecolor == 0) { // basecolor 0 (air) must be selected + return; + } const bool is_version_ok = SlopeCraft::SCL_basecolor_version(this->basecolor) <= v; this->ui->cb_enable->setChecked(is_version_ok); @@ -171,4 +175,8 @@ int BaseColorWidget::prefered_block_idx(int checked_idx, } return max_idx; +} + +bool BaseColorWidget::is_enabled() const noexcept { + return this->ui->cb_enable->isChecked(); } \ No newline at end of file diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index 8aa3b132..e21c2552 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -34,10 +34,20 @@ class BaseColorWidget : public QGroupBox { int selected_idx() const noexcept; + bool is_enabled() const noexcept; + const SlopeCraft::AbstractBlock* selected_block() const noexcept { return this->blocks[this->selected_idx()]->attachted_block(); } + void update_lang(SCL_language lang) noexcept { + for (auto bw : this->blocks) { + bw->update_lang(lang); + } + } + signals: + void changed(); + private: void add_placeholders() noexcept; diff --git a/utilities/BlockListManager/Block.cpp b/utilities/BlockListManager/Block.cpp index 9d37d921..aad96056 100644 --- a/utilities/BlockListManager/Block.cpp +++ b/utilities/BlockListManager/Block.cpp @@ -8,4 +8,14 @@ BlockWidget::BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk) this->block->getImage(reinterpret_cast(img.scanLine(0)), true); this->setIcon(QIcon{QPixmap::fromImage(img)}); -}; \ No newline at end of file +}; +void BlockWidget::update_lang(SCL_language lang) noexcept { + switch (lang) { + case SCL_language::Chinese: + this->setText(QString::fromUtf8(this->block->getNameZH())); + break; + case SCL_language::English: + this->setText(QString::fromUtf8(this->block->getNameEN())); + break; + } +} \ No newline at end of file diff --git a/utilities/BlockListManager/Block.h b/utilities/BlockListManager/Block.h index c04d6d18..3935d4d6 100644 --- a/utilities/BlockListManager/Block.h +++ b/utilities/BlockListManager/Block.h @@ -16,6 +16,8 @@ class BlockWidget : public QRadioButton { ~BlockWidget() = default; auto attachted_block() const noexcept { return this->block; } + + void update_lang(SCL_language lang) noexcept; }; #endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCK_H diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 5599b306..4656523f 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -28,6 +28,8 @@ void BlockListManager::setup_basecolors( bcw->setTitle(QString::fromUtf8(basecolor_names[bc].data())); bcw->set_color(bc_arr[bc]); + + connect(bcw, &BaseColorWidget::changed, [this]() { emit this->changed(); }); } } @@ -119,6 +121,23 @@ void BlockListManager::when_version_updated() noexcept { } } +void BlockListManager::get_blocklist( + std::vector &enable_list, + std::vector &block_list) const noexcept { + enable_list.resize(64); + block_list.resize(64); + + for (int bc = 0; bc < (int)this->basecolors.size(); bc++) { + enable_list[bc] = this->basecolors[bc]->is_enabled(); + block_list[bc] = this->basecolors[bc]->selected_block(); + } + + for (int bc = (int)this->basecolors.size(); bc < 64; bc++) { + enable_list[bc] = 0; + block_list[bc] = nullptr; + } +} + std::string_view basecolor_names[64] = {"00 None", "01 Grass", "02 Sand", diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 7a89caac..3b1073fb 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -58,6 +58,19 @@ class BlockListManager : public QWidget { void when_version_updated() noexcept; + void when_lang_updated(SCL_language lang) noexcept { + for (auto bcw : this->basecolors) { + bcw->update_lang(lang); + } + } + + void get_blocklist(std::vector &enable_list, + std::vector &block_list) + const noexcept; + + signals: + void changed(); + private: bool impl_addblocklist(const QString &filename, const QString &dirname, std::unique_ptr Date: Sun, 7 May 2023 15:51:20 +0800 Subject: [PATCH 0268/1123] load and apply preset --- SlopeCraft/SCWind.cpp | 56 ++++++++++++++++++- SlopeCraft/SCWind.h | 8 ++- SlopeCraft/SCWind.ui | 8 +-- utilities/BlockListManager/BaseColor.cpp | 17 +++++- utilities/BlockListManager/BaseColor.h | 8 ++- .../BlockListManager/BlockListManager.cpp | 46 +++++++++++++++ utilities/BlockListManager/BlockListManager.h | 2 + 7 files changed, 134 insertions(+), 11 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index b45cca32..69c3fe8f 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -66,6 +66,30 @@ SCWind::SCWind(QWidget *parent) &SCWind::when_export_type_toggled); } } + { + for (QRadioButton *rbp : this->preset_buttons_no_custom()) { + connect(rbp, &QRadioButton::clicked, this, &SCWind::when_preset_clicked); + } + } + + { + try { + this->default_presets[0] = + load_preset("./Blocks/Presets/vanilla.sc_preset_json"); + this->default_presets[1] = + load_preset("./Blocks/Presets/cheap.sc_preset_json"); + this->default_presets[2] = + load_preset("./Blocks/Presets/elegant.sc_preset_json"); + this->default_presets[3] = + load_preset("./Blocks/Presets/shiny.sc_preset_json"); + } catch (std::exception &e) { + QMessageBox::critical(this, tr("加载默认预设失败"), + tr("一个或多个内置的预设不能被解析。SlopeCraft " + "可能已经损坏,请重新安装。\n具体报错信息:\n%1") + .arg(e.what())); + abort(); + } + } this->when_blocklist_changed(); } @@ -223,7 +247,11 @@ void SCWind::when_type_buttons_toggled() noexcept { this->update_button_states(); } -void SCWind::when_blocklist_changed() noexcept { this->kernel_set_type(); } +void SCWind::when_blocklist_changed() noexcept { + this->kernel_set_type(); + this->ui->rb_preset_custom->setChecked(true); + // this->ui->rb_preset_ +} void SCWind::kernel_set_type() noexcept { std::vector a; @@ -260,6 +288,11 @@ std::array SCWind::export_type_buttons() return SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS; } +std::array SCWind::preset_buttons_no_custom() noexcept { + return {this->ui->rb_preset_vanilla, this->ui->rb_preset_cheap, + this->ui->rb_preset_elegant, this->ui->rb_preset_shiny}; +} + void SCWind::update_button_states() noexcept { { const bool disable_3d = (this->selected_type() == SCL_mapTypes::FileOnly); @@ -289,6 +322,27 @@ void SCWind::update_button_states() noexcept { } } +void SCWind::when_preset_clicked() noexcept { + int final_idx = -1; + + for (int idx = 0; idx < (int)this->preset_buttons_no_custom().size(); idx++) { + if (this->preset_buttons_no_custom()[idx]->isChecked()) { + final_idx = idx; + break; + } + } + + assert(final_idx >= 0); + + if (!this->ui->blm->loadPreset(this->default_presets[final_idx])) { + return; + } + + this->preset_buttons_no_custom()[final_idx]->setChecked(true); + +#warning apply preset here +} + void SCWind::when_export_type_toggled() noexcept { const bool page_3d = !this->ui->rb_export_fileonly->isChecked(); if (page_3d) { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 2dbd339c..1a14e756 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "cvt_task.h" #include "PoolModel.h" @@ -30,9 +31,8 @@ class SCWind : public QMainWindow { void when_version_buttons_toggled() noexcept; void when_type_buttons_toggled() noexcept; - void when_blocklist_changed() noexcept; - + void when_preset_clicked() noexcept; void when_export_type_toggled() noexcept; private: @@ -43,6 +43,8 @@ class SCWind : public QMainWindow { CvtPoolModel* cvt_pool_model{nullptr}; PoolModel* export_pool_model{nullptr}; + std::array default_presets; + std::array version_buttons() noexcept; std::array version_buttons() const noexcept; @@ -52,6 +54,8 @@ class SCWind : public QMainWindow { std::array export_type_buttons() noexcept; std::array export_type_buttons() const noexcept; + std::array preset_buttons_no_custom() noexcept; + SCL_gameVersion selected_version() const noexcept; SCL_mapTypes selected_type() const noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index a88e31e5..f87e4f24 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -236,14 +236,14 @@ - + Cheap - + Elegant @@ -253,14 +253,14 @@ - + Shiny - + Custom diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index 279fdfbf..d0f3f715 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -84,7 +84,7 @@ void BaseColorWidget::finish_blocks() noexcept { this->add_placeholders(); assert(this->blocks.size() > 0); - this->select_block(0); + this->select_block_direct(0); const SCL_gameVersion v = reinterpret_cast(this->parent())->version(); @@ -97,7 +97,7 @@ void BaseColorWidget::finish_blocks() noexcept { } } -void BaseColorWidget::select_block(int idx) noexcept { +void BaseColorWidget::select_block_direct(int idx) noexcept { assert(idx >= 0); assert(idx < (int)this->blocks.size()); @@ -111,10 +111,17 @@ void BaseColorWidget::select_block(int idx) noexcept { this->blocks[idx]->setChecked(true); } +void BaseColorWidget::select_block_soft(int idx) noexcept { + const int new_select = this->prefered_block_idx( + idx, dynamic_cast(this->parent())->version()); + + this->select_block_direct(new_select); +} + void BaseColorWidget::when_version_updated(SCL_gameVersion v) noexcept { const int new_select = this->prefered_block_idx(v); - this->select_block(new_select); + this->select_block_direct(new_select); for (int idx = 0; idx < int(this->blocks.size()); idx++) { this->blocks[idx]->setDisabled(should_be_disabled( @@ -179,4 +186,8 @@ int BaseColorWidget::prefered_block_idx(int checked_idx, bool BaseColorWidget::is_enabled() const noexcept { return this->ui->cb_enable->isChecked(); +} + +void BaseColorWidget::set_enabled(bool enabled) noexcept { + this->ui->cb_enable->setEnabled(enabled); } \ No newline at end of file diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index e21c2552..bd52b905 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -28,7 +28,7 @@ class BaseColorWidget : public QGroupBox { void finish_blocks() noexcept; - void select_block(int idx) noexcept; + void select_block_soft(int idx) noexcept; void when_version_updated(SCL_gameVersion v) noexcept; @@ -45,12 +45,18 @@ class BaseColorWidget : public QGroupBox { bw->update_lang(lang); } } + + void set_enabled(bool enabled) noexcept; + + inline auto& block_widgets() noexcept { return this->blocks; } signals: void changed(); private: void add_placeholders() noexcept; + void select_block_direct(int idx) noexcept; + int prefered_block_idx(int checked_idx, SCL_gameVersion ver) const noexcept; int prefered_block_idx(SCL_gameVersion ver) const noexcept { diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 4656523f..11b9e1d8 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -138,6 +138,52 @@ void BlockListManager::get_blocklist( } } +bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { + if (preset.values.size() != this->basecolors.size()) { + QMessageBox::warning(dynamic_cast(this->parent()), + tr("加载预设错误"), + tr("预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符") + .arg(preset.values.size()) + .arg(this->basecolors.size())); + return false; + } + + for (int bc = 0; bc < (int)preset.values.size(); bc++) { + auto &bcw = this->basecolors[bc]; + + bcw->set_enabled(preset.values[bc].first); + + auto &bws = bcw->block_widgets(); + int matched_idx = -1; + for (int idx = 0; idx < (int)bws.size(); idx++) { + if (QString::fromLatin1(bws[idx]->attachted_block()->getId()) == + preset.values[bc].second) { + matched_idx = idx; + break; + } + } + + if (matched_idx < 0) { + auto ret = QMessageBox::warning( + dynamic_cast(this->parent()), tr("加载预设错误"), + tr("预设中为基色%1指定的方块 id 是\"%2\",没有找到这个方块 id") + .arg(bc) + .arg(preset.values[bc].second), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, + QMessageBox::StandardButton::Close}); + if (ret == QMessageBox::StandardButton::Close) { + abort(); + return false; + } + continue; + } + } + + emit this->changed(); + + return true; +} + std::string_view basecolor_names[64] = {"00 None", "01 Grass", "02 Sand", diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 3b1073fb..3cc59302 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -68,6 +68,8 @@ class BlockListManager : public QWidget { std::vector &block_list) const noexcept; + bool loadPreset(const blockListPreset &preset) noexcept; + signals: void changed(); From fb8e134dd97d502f9c111be9aafb42c7137e5030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 16:03:25 +0800 Subject: [PATCH 0269/1123] load preset from external files --- SlopeCraft/SCWind.cpp | 25 +++++++++++++++++++++--- SlopeCraft/SCWind.h | 3 ++- utilities/BlockListManager/BaseColor.cpp | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 69c3fe8f..78785412 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -91,7 +91,7 @@ SCWind::SCWind(QWidget *parent) } } - this->when_blocklist_changed(); + { this->when_preset_clicked(); } } SCWind::~SCWind() { @@ -339,8 +339,6 @@ void SCWind::when_preset_clicked() noexcept { } this->preset_buttons_no_custom()[final_idx]->setChecked(true); - -#warning apply preset here } void SCWind::when_export_type_toggled() noexcept { @@ -360,4 +358,25 @@ void SCWind::when_export_type_toggled() noexcept { } this->update_button_states(); +} + +void SCWind::on_pb_load_preset_clicked() noexcept { + static QString prev_dir{""}; + QString file = QFileDialog::getOpenFileName(this, tr("选择预设文件"), + prev_dir, "*.sc_preset_json"); + + if (file.isEmpty()) { + return; + } + + prev_dir = QFileInfo{file}.dir().canonicalPath(); + QString err; + blockListPreset preset = load_preset(file, err); + if (!err.isEmpty()) { + QMessageBox::warning(this, tr("解析预设文件失败"), + tr("预设文件%1存在错误:%2").arg(file).arg(err)); + return; + } + + this->ui->blm->loadPreset(preset); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 1a14e756..f13caa9c 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -27,8 +27,9 @@ class SCWind : public QMainWindow { void on_pb_remove_image_clicked() noexcept; void on_cb_lv_cvt_icon_mode_clicked() noexcept; - void when_cvt_pool_selectionChanged() noexcept; + void on_pb_load_preset_clicked() noexcept; + void when_cvt_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; void when_type_buttons_toggled() noexcept; void when_blocklist_changed() noexcept; diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index d0f3f715..ac26683f 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -189,5 +189,5 @@ bool BaseColorWidget::is_enabled() const noexcept { } void BaseColorWidget::set_enabled(bool enabled) noexcept { - this->ui->cb_enable->setEnabled(enabled); + this->ui->cb_enable->setChecked(enabled); } \ No newline at end of file From f29abec81d96ffeade7b7a11f64d6647d2c257b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 16:04:40 +0800 Subject: [PATCH 0270/1123] disable water by default --- SlopeCraft/others/presets/cheap.sc_preset_json | 2 +- SlopeCraft/others/presets/elegant.sc_preset_json | 2 +- SlopeCraft/others/presets/shiny.sc_preset_json | 2 +- SlopeCraft/others/presets/vanilla.sc_preset_json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SlopeCraft/others/presets/cheap.sc_preset_json b/SlopeCraft/others/presets/cheap.sc_preset_json index 78b510c7..0994ce0a 100644 --- a/SlopeCraft/others/presets/cheap.sc_preset_json +++ b/SlopeCraft/others/presets/cheap.sc_preset_json @@ -62,7 +62,7 @@ { "baseColor": 12, "blockId": "minecraft:water[level=0]", - "enabled": true + "enabled": false }, { "baseColor": 13, diff --git a/SlopeCraft/others/presets/elegant.sc_preset_json b/SlopeCraft/others/presets/elegant.sc_preset_json index 60bb60d0..035af21a 100644 --- a/SlopeCraft/others/presets/elegant.sc_preset_json +++ b/SlopeCraft/others/presets/elegant.sc_preset_json @@ -62,7 +62,7 @@ { "baseColor": 12, "blockId": "minecraft:water[level=0]", - "enabled": true + "enabled": false }, { "baseColor": 13, diff --git a/SlopeCraft/others/presets/shiny.sc_preset_json b/SlopeCraft/others/presets/shiny.sc_preset_json index a7ad88ce..4ee55292 100644 --- a/SlopeCraft/others/presets/shiny.sc_preset_json +++ b/SlopeCraft/others/presets/shiny.sc_preset_json @@ -62,7 +62,7 @@ { "baseColor": 12, "blockId": "minecraft:water[level=0]", - "enabled": true + "enabled": false }, { "baseColor": 13, diff --git a/SlopeCraft/others/presets/vanilla.sc_preset_json b/SlopeCraft/others/presets/vanilla.sc_preset_json index c516508d..b1ef6ff3 100644 --- a/SlopeCraft/others/presets/vanilla.sc_preset_json +++ b/SlopeCraft/others/presets/vanilla.sc_preset_json @@ -62,7 +62,7 @@ { "baseColor": 12, "blockId": "minecraft:water[level=0]", - "enabled": true + "enabled": false }, { "baseColor": 13, From 3e8cc8ef98f6123b6686735b7cc9492bb33a19f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 16:15:30 +0800 Subject: [PATCH 0271/1123] save preset --- SlopeCraft/SCWind.cpp | 31 +++++++++++++++++++ SlopeCraft/SCWind.h | 1 + .../BlockListManager/BlockListManager.cpp | 11 +++++++ utilities/BlockListManager/BlockListManager.h | 2 ++ 4 files changed, 45 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 78785412..19be4481 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -379,4 +379,35 @@ void SCWind::on_pb_load_preset_clicked() noexcept { } this->ui->blm->loadPreset(preset); +} + +void SCWind::on_pb_save_preset_clicked() noexcept { + static QString prev_dir{""}; + QString file = QFileDialog::getSaveFileName(this, tr("保存当前预设"), + prev_dir, "*.sc_preset_json"); + + if (file.isEmpty()) { + return; + } + + prev_dir = QFileInfo{file}.dir().canonicalPath(); + + blockListPreset preset = this->ui->blm->to_preset(); + { + QString str = serialize_preset(preset); + + QFile qf{file}; + qf.open(QFile::OpenMode{QIODevice::WriteOnly | QIODevice::Text}); + + if (!qf.isOpen()) { + QMessageBox::warning(this, tr("保存预设文件失败"), + tr("无法生成预设文件%1 ,错误信息:%2") + .arg(file) + .arg(qf.errorString())); + return; + } + + qf.write(str.toUtf8()); + qf.close(); + } } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index f13caa9c..f7259593 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -28,6 +28,7 @@ class SCWind : public QMainWindow { void on_cb_lv_cvt_icon_mode_clicked() noexcept; void on_pb_load_preset_clicked() noexcept; + void on_pb_save_preset_clicked() noexcept; void when_cvt_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 11b9e1d8..3e88cfde 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -184,6 +184,17 @@ bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { return true; } +blockListPreset BlockListManager::to_preset() const noexcept { + blockListPreset ret; + ret.values.resize(this->basecolors.size()); + for (size_t basecolor = 0; basecolor < this->basecolors.size(); basecolor++) { + ret.values[basecolor].first = this->basecolors[basecolor]->is_enabled(); + ret.values[basecolor].second = QString::fromUtf8( + this->basecolors[basecolor]->selected_block()->getId()); + } + return ret; +} + std::string_view basecolor_names[64] = {"00 None", "01 Grass", "02 Sand", diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 3cc59302..5c201ed4 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -70,6 +70,8 @@ class BlockListManager : public QWidget { bool loadPreset(const blockListPreset &preset) noexcept; + blockListPreset to_preset() const noexcept; + signals: void changed(); From 7fbae16c2826bccd6740b6ca9383e9a92b7392ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 18:48:20 +0800 Subject: [PATCH 0272/1123] fix preset applying --- SlopeCraft/SCWind.cpp | 53 ++++ SlopeCraft/SCWind.h | 6 + SlopeCraft/SCWind.ui | 238 +++++++++--------- utilities/BlockListManager/BaseColor.cpp | 19 ++ utilities/BlockListManager/BaseColor.h | 6 + .../BlockListManager/BlockListManager.cpp | 4 +- utilities/BlockListManager/BlockListManager.h | 6 + 7 files changed, 219 insertions(+), 113 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 19be4481..22238e3d 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -335,6 +335,7 @@ void SCWind::when_preset_clicked() noexcept { assert(final_idx >= 0); if (!this->ui->blm->loadPreset(this->default_presets[final_idx])) { + QMessageBox::warning(this, tr("应用预设失败"), ""); return; } @@ -410,4 +411,56 @@ void SCWind::on_pb_save_preset_clicked() noexcept { qf.write(str.toUtf8()); qf.close(); } +} + +inline int impl_select_blk_by_id( + const std::vector &blks, + std::string_view keyword) noexcept { + int result = -1; + for (int idx = 0; idx < int(blks.size()); idx++) { + std::string_view id{blks[idx]->getId()}; + const auto find = id.find(keyword); + + if (find != std::string_view::npos) { + result = idx; + break; + } + } + + return result; +} + +void SCWind::on_pb_prefer_concrete_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "concrete"); + }); +} + +void SCWind::on_pb_prefer_wool_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "wool"); + }); +} + +void SCWind::on_pb_prefer_glass_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "stained_glass"); + }); +} + +void SCWind::on_pb_prefer_planks_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "planks"); + }); +} + +void SCWind::on_pb_prefer_logs_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "log"); + }); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index f7259593..63ebc992 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -30,6 +30,12 @@ class SCWind : public QMainWindow { void on_pb_load_preset_clicked() noexcept; void on_pb_save_preset_clicked() noexcept; + void on_pb_prefer_concrete_clicked() noexcept; + void on_pb_prefer_wool_clicked() noexcept; + void on_pb_prefer_glass_clicked() noexcept; + void on_pb_prefer_planks_clicked() noexcept; + void on_pb_prefer_logs_clicked() noexcept; + void when_cvt_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; void when_type_buttons_toggled() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index f87e4f24..03fca5b5 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -25,6 +25,94 @@ 地图画配置 + + + + 方块列表预设 + + + + + + 加载预设 + + + + + + + 保存当前预设 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 可用方块数量: + + + + + + + 0 + + + + + Vanilla + + + + + + + Cheap + + + + + + + Elegant + + + true + + + + + + + Shiny + + + + + + + Custom + + + + + + + + @@ -165,140 +253,66 @@ - - - - true - - - - - 0 - 0 - 753 - 539 - - - - - - - - - - 方块列表预设 - - - - - - 加载预设 - - - - - - - 保存当前预设 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 可用方块数量: - - - - - - - 0 - - - - - Vanilla - - - - - - - Cheap - - - - - - - Elegant - - - true - - - - - - - Shiny - - - - - - - Custom - - - - - - - - - + 0 - + + + + 优先彩色玻璃 + + + + 优先混凝土 - + 优先羊毛 - - + + - 优先彩色玻璃 + 优先木板 + + + + + + + 优先原木 + + + + true + + + + + 0 + 0 + 753 + 539 + + + + + + diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index ac26683f..a5b54d1a 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -5,6 +5,9 @@ BaseColorWidget::BaseColorWidget(QWidget* parent, uint8_t _basecolor) : QGroupBox(parent), ui(new Ui::BaseColorWidget), basecolor(_basecolor) { this->ui->setupUi(this); + + connect(this->ui->cb_enable, &QCheckBox::toggled, this, + &BaseColorWidget::changed); }; BaseColorWidget::~BaseColorWidget() { delete this->ui; }; @@ -190,4 +193,20 @@ bool BaseColorWidget::is_enabled() const noexcept { void BaseColorWidget::set_enabled(bool enabled) noexcept { this->ui->cb_enable->setChecked(enabled); +} + +void BaseColorWidget::select_by_callback(const select_callback_t& fun) { + std::vector blks; + blks.reserve(this->blocks.size()); + for (auto bw : this->blocks) { + blks.emplace_back(bw->attachted_block()); + } + + const int output = fun(blks); + + if (output < 0 || output >= (int)this->blocks.size()) { + return; + } + + this->select_block_soft(output); } \ No newline at end of file diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index bd52b905..d91d5500 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -11,6 +11,9 @@ namespace Ui { class BaseColorWidget; } +using select_callback_t = std::function& blks)>; + class BaseColorWidget : public QGroupBox { Q_OBJECT private: @@ -49,6 +52,9 @@ class BaseColorWidget : public QGroupBox { void set_enabled(bool enabled) noexcept; inline auto& block_widgets() noexcept { return this->blocks; } + + void select_by_callback(const select_callback_t& fun); + signals: void changed(); diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 3e88cfde..d818b17e 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -177,9 +177,11 @@ bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { } continue; } + + bcw->select_block_soft(matched_idx); } - emit this->changed(); + // emit this->changed(); return true; } diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 5c201ed4..51904c1f 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -64,6 +64,12 @@ class BlockListManager : public QWidget { } } + void select_block_by_callback(const select_callback_t &fun) noexcept { + for (auto bcw : this->basecolors) { + bcw->select_by_callback(fun); + } + } + void get_blocklist(std::vector &enable_list, std::vector &block_list) const noexcept; From 636308979e96f96a000492272b75d2f7626c6673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 18:49:37 +0800 Subject: [PATCH 0273/1123] try to fix macos-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 49f849e2..2238c9a2 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -34,7 +34,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/gcc-12 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/12.2.0/bin/g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build From a8259437396b43ed9a48886e57ab5587034dbf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 7 May 2023 20:53:37 +0800 Subject: [PATCH 0274/1123] write cache after convertion --- SlopeCraft/SCWind.cpp | 204 ++++++++++++++++++++-- SlopeCraft/SCWind.h | 31 ++++ SlopeCraft/SCWind.ui | 5 +- SlopeCraft/cvt_task.h | 24 +++ SlopeCraftL/SlopeCraftL.h | 18 +- SlopeCraftL/TokiSlopeCraft.cpp | 15 +- SlopeCraftL/TokiSlopeCraft.h | 19 +- SlopeCraftL/TokiSlopeCraft_cache.cpp | 60 ++++++- cmake/configure_bxzstr.cmake | 20 --- utilities/MapImageCvter/CMakeLists.txt | 6 +- utilities/MapImageCvter/MapImageCvter.cpp | 4 +- 11 files changed, 346 insertions(+), 60 deletions(-) delete mode 100644 cmake/configure_bxzstr.cmake diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 22238e3d..4f7c0f51 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) @@ -11,9 +12,17 @@ SCWind::SCWind(QWidget *parent) kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); { + const auto pid = QApplication::applicationPid(); + + const QString sys_cache_dir = QDir::tempPath(); + const QString cache_dir = + QStringLiteral("%1/SlopeCraft/pid=%2").arg(sys_cache_dir).arg(pid); + + this->kernel->setCacheDir(cache_dir.toLocal8Bit()); + this->kernel->setWindPtr(this); - this->kernel->setAlgoProgressAdd([](void *, int) {}); - this->kernel->setAlgoProgressRangeSet([](void *, int, int, int) {}); + // this->kernel->setAlgoProgressAdd([](void *, int) {}); + // this->kernel->setAlgoProgressRangeSet([](void *, int, int, int) {}); } // initialize cvt pool model { @@ -91,11 +100,22 @@ SCWind::SCWind(QWidget *parent) } } - { this->when_preset_clicked(); } + this->when_preset_clicked(); } SCWind::~SCWind() { delete this->ui; + + { + const char *cd = this->kernel->cacheDir(); + if (cd != nullptr) { + QDir cache_dir{QString::fromLocal8Bit(cd)}; + if (cache_dir.exists()) { + cache_dir.removeRecursively(); + } + } + } + SlopeCraft::SCL_destroyKernel(this->kernel); } @@ -165,19 +185,9 @@ void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { } void SCWind::when_cvt_pool_selectionChanged() noexcept { - auto sel = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + const auto selected_idx = this->selected_cvt_task_idx(); - if (sel.size() <= 0) { - this->ui->lb_raw_image->setPixmap({}); - this->ui->lb_cvted_image->setPixmap({}); - return; - } - - const int idx = sel.front().row(); - - this->ui->lb_raw_image->setPixmap( - QPixmap::fromImage(this->tasks[idx].original_image)); -#warning load converted image here + this->refresh_current_cvt_display(selected_idx); } #define SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST \ @@ -237,6 +247,43 @@ SCL_mapTypes SCWind::selected_type() const noexcept { return {}; } +std::optional SCWind::selected_cvt_task_idx() const noexcept { + auto sel = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + if (sel.size() <= 0) { + return std::nullopt; + } + + return sel.front().row(); +} + +SCL_convertAlgo SCWind::selected_algo() const noexcept { + if (this->ui->rb_algo_RGB->isChecked()) { + return SCL_convertAlgo::RGB; + } + if (this->ui->rb_algo_RGB_plus->isChecked()) { + return SCL_convertAlgo::RGB_Better; + } + if (this->ui->rb_algo_Lab94->isChecked()) { + return SCL_convertAlgo::Lab94; + } + if (this->ui->rb_algo_Lab00->isChecked()) { + return SCL_convertAlgo::Lab00; + } + if (this->ui->rb_algo_XYZ->isChecked()) { + return SCL_convertAlgo::XYZ; + } + if (this->ui->rb_algo_GACvter->isChecked()) { + return SCL_convertAlgo::gaCvter; + } + + assert(false); + return {}; +} + +bool SCWind::is_dither_selected() const noexcept { + return this->ui->cb_algo_dither->isChecked(); +} + void SCWind::when_version_buttons_toggled() noexcept { this->ui->blm->when_version_updated(); this->when_blocklist_changed(); @@ -293,6 +340,21 @@ std::array SCWind::preset_buttons_no_custom() noexcept { this->ui->rb_preset_elegant, this->ui->rb_preset_shiny}; } +#define SC_SLOPECRAFT_PRIVATEMARCO_ALGO_BUTTONS \ + { \ + this->ui->rb_algo_RGB, this->ui->rb_algo_RGB_plus, \ + this->ui->rb_algo_Lab94, this->ui->rb_algo_Lab00, \ + this->ui->rb_algo_XYZ, this->ui->rb_algo_GACvter \ + } + +std::array SCWind::algo_buttons() const noexcept { + return SC_SLOPECRAFT_PRIVATEMARCO_ALGO_BUTTONS; +} + +std::array SCWind::algo_buttons() noexcept { + return SC_SLOPECRAFT_PRIVATEMARCO_ALGO_BUTTONS; +} + void SCWind::update_button_states() noexcept { { const bool disable_3d = (this->selected_type() == SCL_mapTypes::FileOnly); @@ -463,4 +525,116 @@ void SCWind::on_pb_prefer_logs_clicked() noexcept { [](const std::vector &blks) -> int { return impl_select_blk_by_id(blks, "log"); }); +} + +void SCWind::kernel_set_image(int idx) noexcept { + assert(idx >= 0); + assert(idx < (int)this->tasks.size()); + + if (this->kernel->queryStep() < SCL_step::wait4Image) { + this->kernel_set_type(); + } + + const QImage &raw = this->tasks[idx].original_image; + this->kernel->setRawImage((const uint32_t *)raw.scanLine(0), raw.height(), + raw.width(), false); +} + +void SCWind::kernel_convert_image() noexcept { + assert(this->kernel->queryStep() >= SCL_step::convertionReady); + + if (!this->kernel->convert(this->selected_algo(), + this->is_dither_selected())) { + QMessageBox::warning(this, tr("转化图像失败"), tr("")); + + return; + } +} + +void SCWind::kernel_make_cache() noexcept { + std::string err; + err.resize(4096); + SlopeCraft::StringDeliver sd{err.data(), err.size()}; + + if (!this->kernel->saveCache(sd)) { + QString qerr = QString::fromUtf8(sd.data); + QMessageBox::warning(this, tr("缓存失败"), + tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); + } +} + +bool SCWind::kernel_check_colorset_hash() noexcept { + return this->kernel->check_colorset_hash(); +} + +void SCWind::on_pb_cvt_current_clicked() noexcept { + const auto sel = this->selected_cvt_task_idx(); + + if (!sel.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + + this->kernel_set_image(sel.value()); + this->kernel_convert_image(); + this->tasks[sel.value()].set_converted(); + + this->kernel_make_cache(); + this->refresh_current_cvt_display(sel.value(), true); +} + +QImage SCWind::get_converted_image_from_kernel() const noexcept { + assert(this->kernel->queryStep() >= SCL_step::converted); + + const int rows = this->kernel->getImageRows(); + const int cols = this->kernel->getImageCols(); + + QImage img{cols, rows, QImage::Format_ARGB32}; + + this->kernel->getConvertedImage(nullptr, nullptr, (uint32_t *)img.scanLine(0), + false); + + return img; +} + +void SCWind::refresh_current_cvt_display( + std::optional selected_idx, + bool is_image_coneverted_in_kernel) noexcept { + if (!selected_idx.has_value()) { + this->ui->lb_raw_image->setPixmap({}); + this->ui->lb_cvted_image->setPixmap({}); + return; + } + + const int idx = selected_idx.value(); + + this->ui->lb_raw_image->setPixmap( + QPixmap::fromImage(this->tasks[idx].original_image)); + + if (is_image_coneverted_in_kernel) { + assert(this->kernel->queryStep() >= SCL_step::converted); + + this->ui->lb_cvted_image->setPixmap( + QPixmap::fromImage(this->get_converted_image_from_kernel())); + return; + } + + if (!this->tasks[idx].is_converted) { + this->ui->lb_cvted_image->setPixmap({}); + return; + } + + if (!kernel_check_colorset_hash()) { + this->mark_all_task_unconverted(); + this->image_changed(); + return; + } +#warning try to load cache here +} + +void SCWind::mark_all_task_unconverted() noexcept { + for (auto &task : this->tasks) { + task.set_unconverted(); + } } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 63ebc992..b627d471 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -43,6 +43,8 @@ class SCWind : public QMainWindow { void when_preset_clicked() noexcept; void when_export_type_toggled() noexcept; + void on_pb_cvt_current_clicked() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; @@ -64,14 +66,43 @@ class SCWind : public QMainWindow { std::array preset_buttons_no_custom() noexcept; + std::array algo_buttons() const noexcept; + std::array algo_buttons() noexcept; + SCL_gameVersion selected_version() const noexcept; SCL_mapTypes selected_type() const noexcept; + std::optional selected_cvt_task_idx() const noexcept; + + SCL_convertAlgo selected_algo() const noexcept; + bool is_dither_selected() const noexcept; + void kernel_set_type() noexcept; void update_button_states() noexcept; + void kernel_set_image(int idx) noexcept; + void kernel_convert_image() noexcept; + + void kernel_make_cache() noexcept; + + bool kernel_check_colorset_hash() noexcept; + + void refresh_current_cvt_display(std::optional idx, + bool is_image_coneverted_in_kernel) noexcept; + QImage get_converted_image_from_kernel() const noexcept; + + void refresh_current_cvt_display(std::optional idx) noexcept { + this->refresh_current_cvt_display(idx, false); + } + + void refresh_current_cvt_display() noexcept { + this->refresh_current_cvt_display(this->selected_cvt_task_idx()); + } + + void mark_all_task_unconverted() noexcept; + signals: void image_changed(); }; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 03fca5b5..c7019b0c 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 0 + 1 @@ -470,6 +470,9 @@ RGB+ + + true + diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 686186a3..9c3b3039 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -14,6 +14,30 @@ struct cvt_task { bool is_exported{false}; static cvt_task load(QString filename, QString& err) noexcept; + + void set_converted() noexcept { + this->is_converted = true; + this->is_built = false; + this->is_exported = false; + } + + void set_built() noexcept { + assert(this->is_converted); + this->is_built = true; + this->is_exported = false; + } + + void set_exported() noexcept { + assert(this->is_converted); + assert(this->is_built); + this->is_exported = true; + } + + void set_unconverted() noexcept { + this->is_converted = false; + this->is_built = false; + this->is_exported = false; + } }; Q_DECLARE_METATYPE(cvt_task); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 002d38dd..409d113a 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -185,7 +185,8 @@ class Kernel { // can do in wait4Image: /// set original image from ARGB32 matrix (col-major) - virtual void setRawImage(const uint32_t *src, int rows, int cols) = 0; + [[deprecated]] virtual void setRawImage(const uint32_t *src, int rows, + int cols) = 0; /// get accessible color count virtual unsigned short getColorCount() const = 0; /// get usable colors in ARGB32 @@ -220,8 +221,8 @@ class Kernel { bool endermanProof = false) = 0; /// get converted image - virtual void getConvertedImage(int *rows, int *cols, - uint32_t *dest) const = 0; + [[deprecated]] virtual void getConvertedImage(int *rows, int *cols, + uint32_t *dest) const = 0; /// export as map data files, returns failed files. virtual void exportAsData(const char *FolderPath, const int indexStart, int *fileCount, char **dest) const = 0; @@ -262,10 +263,19 @@ class Kernel { int *ySize = nullptr, int *zSize = nullptr) const = 0; - // extra functions + // Virtual functions added after v5.0.0. Define them in the end of vtable to + // matain binary compability + + // added in v5.1.0 virtual void setCacheDir(const char *) noexcept = 0; virtual const char *cacheDir() const noexcept = 0; virtual bool saveCache(StringDeliver &err) const noexcept = 0; + virtual void setRawImage(const uint32_t *src, int rows, int cols, + bool is_col_major) = 0; + virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, + bool expected_col_major) const = 0; + + virtual bool check_colorset_hash() const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 66470b03..fd8d6c29 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -360,7 +360,8 @@ void TokiSlopeCraft::getAvailableColors(ARGB *const ARGBDest, } } -void TokiSlopeCraft::setRawImage(const ARGB *src, int rows, int cols) { +void TokiSlopeCraft::setRawImage(const ARGB *src, int rows, int cols, + bool is_col_major) { if (kernelStep < SCL_step::wait4Image) { reportError(wind, errorFlag::HASTY_MANIPULATION, "You can only import the raw image count after you set the map " @@ -373,7 +374,7 @@ void TokiSlopeCraft::setRawImage(const ARGB *src, int rows, int cols) { return; } - this->image_cvter.set_raw_image(src, rows, cols); + this->image_cvter.set_raw_image(src, rows, cols, is_col_major); kernelStep = SCL_step::convertionReady; @@ -415,11 +416,17 @@ TokiSlopeCraft::ColorSpace TokiSlopeCraft::getColorSpace() const { return R; } -void TokiSlopeCraft::getConvertedImage(int *rows, int *cols, ARGB *dest) const { +void TokiSlopeCraft::getConvertedImage(int *rows, int *cols, ARGB *dest, + bool expected_col_major) const { EImage result = getConovertedImage(); if (rows != nullptr) *rows = result.rows(); if (cols != nullptr) *cols = result.cols(); - if (dest != nullptr) memcpy(dest, result.data(), sizeof(ARGB) * sizePic(2)); + if (!expected_col_major) { + result.transposeInPlace(); + } + if (dest != nullptr) { + memcpy(dest, result.data(), sizeof(ARGB) * sizePic(2)); + } } EImage TokiSlopeCraft::getConovertedImage() const { diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index f767d44e..a09f6738 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -145,7 +145,12 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { public: void getBaseColorInARGB32(unsigned int *const) const override; // can do in wait4Image: - void setRawImage(const unsigned int *src, int rows, int cols) override; + void setRawImage(const unsigned int *src, int rows, int cols) override { + this->setRawImage(src, rows, cols, true); + } + + void setRawImage(const uint32_t *src, int rows, int cols, + bool is_col_major) override; uint16_t getColorCount() const override; void getAvailableColors(ARGB *const, uint8_t *const, @@ -176,7 +181,11 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { unsigned short = 3, bool fireProof = false, bool endermanProof = false) override; // 构建三维结构 void getConvertedImage(int *rows, int *cols, - unsigned int *dest) const override; + unsigned int *dest) const override { + this->getConvertedImage(rows, cols, dest, true); + } + void getConvertedImage(int *rows, int *cols, uint32_t *dest, + bool expected_col_major) const override; EImage getConovertedImage() const; void getConvertedMap(int *rows, int *cols, unsigned char *) const override; // void getConvertedMap(Eigen::Arra) const; @@ -216,6 +225,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { const unsigned short *getBuild(int *xSize, int *ySize, int *zSize) const override; + // const Eigen::Tensor &getBuild() const; private: @@ -311,6 +321,11 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { } void saveCache(std::string &err) const noexcept; + + std::string task_dir() const noexcept; + std::string colorset_hash_file() const noexcept; + + bool check_colorset_hash() const noexcept override; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 891a5582..c5fdb464 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -18,10 +18,10 @@ std::string write_hash(std::string_view filename, return {}; } -const std::string_view hash_suffix{"*.sha3_512"}; - void TokiSlopeCraft::setCacheDir(const char *d) noexcept { this->cache_dir = d; + + std::filesystem::create_directories(d); } const char *TokiSlopeCraft::cacheDir() const noexcept { if (this->cache_dir.has_value()) { @@ -31,6 +31,18 @@ const char *TokiSlopeCraft::cacheDir() const noexcept { return nullptr; } +const std::string_view hash_suffix{".sha3_512"}; + +std::string TokiSlopeCraft::colorset_hash_file() const noexcept { + return fmt::format("{}/{}{}", this->cache_dir.value(), "colorset", + hash_suffix); +} + +std::string TokiSlopeCraft::task_dir() const noexcept { + return fmt::format("{}/{}", this->cache_dir.value(), + this->image_cvter.task_hash()); +} + void TokiSlopeCraft::saveCache(std::string &err) const noexcept { if (this->kernelStep < SlopeCraft::step::converted) { err = "Can not save cache before the image is converted."; @@ -42,8 +54,7 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { return; } - const std::string task_dir = fmt::format("{}/{}", this->cache_dir.value(), - this->image_cvter.task_hash()); + const std::string task_dir = this->task_dir(); namespace stdfs = std::filesystem; std::error_code ec; @@ -59,8 +70,7 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { // write colorset hash { - const std::string name_hash_colorset = fmt::format( - "{}/{}{}", this->cache_dir.value(), "colorset", hash_suffix); + const std::string name_hash_colorset = this->colorset_hash_file(); temp_err = write_hash(name_hash_colorset, TokiSlopeCraft::Allowed.hash()); if (!temp_err.empty()) { @@ -69,8 +79,7 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { } } - const std::string convert_cache_file = - fmt::format("{}/convert.sc_cache.gz", task_dir); + const std::string convert_cache_file = fmt::format("{}/convert", task_dir); if (!this->image_cvter.save_cache(convert_cache_file.c_str())) { err = fmt::format("Failed to save image cvter cache."); @@ -78,4 +87,39 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { } return; +} + +bool TokiSlopeCraft::check_colorset_hash() const noexcept { + const std::string hash_file = this->colorset_hash_file(); + std::vector buf; + { + std::ifstream ifs{hash_file, std::ios::binary}; + + if (!ifs) { // file not exist + return false; + } + + const size_t file_size = std::filesystem::file_size(hash_file); + if (file_size <= 0) { // empty file + return false; + } + + buf.resize(file_size); + + ifs.read((char *)buf.data(), file_size); + } + + const auto current_hash = TokiSlopeCraft::Allowed.hash(); + + if (current_hash.size() != buf.size()) { // length mismatch + return false; + } + + for (size_t idx = 0; idx < buf.size(); idx++) { + if (buf[idx] != current_hash[idx]) { // hash checksum failed. + return false; + } + } + + return true; } \ No newline at end of file diff --git a/cmake/configure_bxzstr.cmake b/cmake/configure_bxzstr.cmake deleted file mode 100644 index 98a9d3e7..00000000 --- a/cmake/configure_bxzstr.cmake +++ /dev/null @@ -1,20 +0,0 @@ -find_package(bxzstr) - -if(${bxzstr_FOUND}) - return() -endif() - -include(FetchContent) - -set(BZIP2_FOUND off) -set(LIBLZMA_FOUND off) -set(ZSTD_FOUND off) - -FetchContent_Declare(bxzstr - GIT_REPOSITORY https://github.com/SlopeCraft/bxzstr - GIT_TAG v1.2.1-fork - OVERRIDE_FIND_PACKAGE) - -message(STATUS "Configuring bxzstr ...") - -FetchContent_MakeAvailable(bxzstr) \ No newline at end of file diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index e3b2f1b2..129278a9 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -3,9 +3,7 @@ set(CMAKE_CXX_STANDARD 20) find_package(OpenMP REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_bxzstr.cmake) find_package(cereal REQUIRED) -find_package(bxzstr REQUIRED) add_library(MapImageCvter STATIC @@ -21,8 +19,8 @@ target_link_libraries(MapImageCvter PUBLIC ColorManip GAConverter OpenMP::OpenMP_CXX - cereal::cereal - bxzstr::bxzstr) + cereal::cereal) + target_compile_options(MapImageCvter PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_features(MapImageCvter PUBLIC cxx_std_20) diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index 08c2131e..2b422524 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -24,7 +24,7 @@ This file is part of SlopeCraft. #include #include -#include +#include #include #include @@ -74,7 +74,7 @@ void libMapImageCvt::MapImageCvter::convert_image( bool libMapImageCvt::MapImageCvter::save_cache( const char *filename) const noexcept { - bxz::ofstream ofs{filename, std::ios::binary, bxz::Compression::z, 9}; + std::ofstream ofs{filename, std::ios::binary}; if (!ofs) { return false; } From e0cdd1ff8693c3b4d7c2aad63853e6fddd8fbb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 13:08:37 +0800 Subject: [PATCH 0275/1123] load cache --- SlopeCraft/SCWind.cpp | 13 +++++- SlopeCraft/SCWind.ui | 2 +- SlopeCraftL/SlopeCraftL.h | 18 +++++--- SlopeCraftL/TokiSlopeCraft.h | 7 +++ SlopeCraftL/TokiSlopeCraft_cache.cpp | 52 +++++++++++++++++++++-- utilities/ColorManip/newTokiColor.hpp | 1 + utilities/MapImageCvter/MapImageCvter.cpp | 43 ++++++++++++++++++- utilities/MapImageCvter/MapImageCvter.h | 20 ++++++++- 8 files changed, 143 insertions(+), 13 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 4f7c0f51..15e80dc1 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -620,8 +620,8 @@ void SCWind::refresh_current_cvt_display( return; } + this->ui->lb_cvted_image->setPixmap({}); if (!this->tasks[idx].is_converted) { - this->ui->lb_cvted_image->setPixmap({}); return; } @@ -630,7 +630,16 @@ void SCWind::refresh_current_cvt_display( this->image_changed(); return; } -#warning try to load cache here + + this->kernel_set_image(idx); + + if (!this->kernel->load_convert_cache(this->selected_algo(), + this->is_dither_selected())) { + return; + } + + this->ui->lb_cvted_image->setPixmap( + QPixmap::fromImage(this->get_converted_image_from_kernel())); } void SCWind::mark_all_task_unconverted() noexcept { diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index c7019b0c..756a5361 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 1 + 0 diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 409d113a..e6ce54c5 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -266,16 +266,24 @@ class Kernel { // Virtual functions added after v5.0.0. Define them in the end of vtable to // matain binary compability - // added in v5.1.0 - virtual void setCacheDir(const char *) noexcept = 0; - virtual const char *cacheDir() const noexcept = 0; - virtual bool saveCache(StringDeliver &err) const noexcept = 0; + // added in v5.1.0 -------------------------------------------------- + // replacement for setRawImage(const uint32_t*,int,int) virtual void setRawImage(const uint32_t *src, int rows, int cols, bool is_col_major) = 0; + // replacement for getConvertedImage(int *rows, int *cols, uint32_t + // *dest)const virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, bool expected_col_major) const = 0; - + virtual void setCacheDir(const char *) noexcept = 0; + virtual const char *cacheDir() const noexcept = 0; + // requires step >= converted + virtual bool saveCache(StringDeliver &err) const noexcept = 0; + // requires step >= wait4image virtual bool check_colorset_hash() const noexcept = 0; + + // requires step >= convertion ready + virtual bool load_convert_cache(SCL_convertAlgo algo, + bool dither) noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index a09f6738..2b7867a2 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -322,10 +322,17 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void saveCache(std::string &err) const noexcept; + private: std::string task_dir() const noexcept; + std::string task_dir(uint64_t) const noexcept; + std::string task_dir(SCL_convertAlgo algo, bool dither) const noexcept; std::string colorset_hash_file() const noexcept; + static std::string conevrt_cache_filename(std::string_view taskdir) noexcept; + + public: bool check_colorset_hash() const noexcept override; + bool load_convert_cache(SCL_convertAlgo algo, bool dither) noexcept override; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index c5fdb464..706a20bb 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -39,8 +39,20 @@ std::string TokiSlopeCraft::colorset_hash_file() const noexcept { } std::string TokiSlopeCraft::task_dir() const noexcept { - return fmt::format("{}/{}", this->cache_dir.value(), - this->image_cvter.task_hash()); + return this->task_dir(this->image_cvter.task_hash()); +} + +std::string TokiSlopeCraft::task_dir(uint64_t hash) const noexcept { + return fmt::format("{}/{}", this->cache_dir.value(), hash); +} +std::string TokiSlopeCraft::task_dir(SCL_convertAlgo algo, + bool dither) const noexcept { + return this->task_dir(this->image_cvter.task_hash(algo, dither)); +} + +std::string TokiSlopeCraft::conevrt_cache_filename( + std::string_view taskdir) noexcept { + return fmt::format("{}/convert", taskdir); } void TokiSlopeCraft::saveCache(std::string &err) const noexcept { @@ -79,7 +91,8 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { } } - const std::string convert_cache_file = fmt::format("{}/convert", task_dir); + const std::string convert_cache_file = + TokiSlopeCraft::conevrt_cache_filename(task_dir); if (!this->image_cvter.save_cache(convert_cache_file.c_str())) { err = fmt::format("Failed to save image cvter cache."); @@ -90,6 +103,12 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { } bool TokiSlopeCraft::check_colorset_hash() const noexcept { + if (this->kernelStep < SCL_step::wait4Image) { + reportError(wind, errorFlag::HASTY_MANIPULATION, + "You can check for colorset only after you set the map type"); + return false; + } + const std::string hash_file = this->colorset_hash_file(); std::vector buf; { @@ -122,4 +141,31 @@ bool TokiSlopeCraft::check_colorset_hash() const noexcept { } return true; +} + +bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, + bool dither) noexcept { + if (this->kernelStep < SCL_step::convertionReady) { + reportError( + wind, errorFlag::HASTY_MANIPULATION, + "You can load convert cache only after you set the original image"); + return false; + } + + const uint64_t expected_task_hash = this->image_cvter.task_hash(algo, dither); + + const std::string expected_task_dir = this->task_dir(expected_task_hash); + + const std::string expected_cache_file = + this->conevrt_cache_filename(expected_task_dir); + + const bool ok = this->image_cvter.load_cache(expected_cache_file.c_str(), + expected_task_hash); + + if (ok) { + this->mapPic = this->image_cvter.mapcolor_matrix().cast(); + this->kernelStep = SCL_step::converted; + return true; + } + return false; } \ No newline at end of file diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 69447c92..b3aa3685 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -81,6 +81,7 @@ inline constexpr float threshold = 1e-10f; } // namespace struct convert_unit { + convert_unit() = default; explicit convert_unit(ARGB _a, ::SCL_convertAlgo _c) : _ARGB(_a), algo(_c) {} ARGB _ARGB; ::SCL_convertAlgo algo; diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index 2b422524..a5c338e7 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -80,12 +80,53 @@ bool libMapImageCvt::MapImageCvter::save_cache( } { - cereal::BinaryOutputArchive boa(ofs); + cereal::BinaryOutputArchive boa{ofs}; boa(*this); } ofs.close(); + return true; +} + +bool libMapImageCvt::MapImageCvter::examine_cache( + const char *filename, uint64_t expected_task_hash, + MapImageCvter *itermediate) const noexcept { + std::ifstream ifs{filename, std::ios::binary}; + if (!ifs) { // cache file not exist + return false; + } + MapImageCvter im; + + try { + cereal::BinaryInputArchive bia{ifs}; + bia(im); + } catch (...) { // the cache is broken + return false; + } + + if (im.task_hash() != expected_task_hash) { // the cache may be modified + return false; + } + + if (itermediate != nullptr) { + itermediate->load_from_itermediate(std::move(im)); + } + + return true; +} + +bool libMapImageCvt::MapImageCvter::load_cache( + const char *filename, uint64_t expected_task_hash) noexcept { + MapImageCvter temp; + if (!this->examine_cache(filename, expected_task_hash, &temp)) { + return false; + } + + this->load_from_itermediate(std::move(temp)); + + assert(this->_raw_image.rows() == this->_dithered_image.rows()); + assert(this->_raw_image.cols() == this->_dithered_image.cols()); return true; } \ No newline at end of file diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index df2d2c6b..793ed184 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -93,11 +93,23 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { dest[r] = &it->second; } } + // temp is a temporary container to pass ownership + void load_from_itermediate(MapImageCvter &&temp) noexcept { + this->_raw_image = std::move(temp._raw_image); + this->algo = temp.algo; + this->_color_hash = std::move(temp._color_hash); + this->_dithered_image = std::move(temp._dithered_image); + + assert(this->_raw_image.rows() == this->_dithered_image.rows()); + assert(this->_raw_image.cols() == this->_dithered_image.cols()); + } - public: + private: friend class cereal::access; template void save(archive &ar) const { + assert(this->_raw_image.rows() == this->_dithered_image.rows()); + assert(this->_raw_image.cols() == this->_dithered_image.cols()); ar(this->_raw_image); ar(this->algo); ar(this->_color_hash); @@ -110,10 +122,16 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { ar(this->algo); ar(this->_color_hash); ar(this->_dithered_image); + + assert(this->_raw_image.rows() == this->_dithered_image.rows()); + assert(this->_raw_image.cols() == this->_dithered_image.cols()); } public: bool save_cache(const char *filename) const noexcept; + bool examine_cache(const char *filename, uint64_t expected_task_hash, + MapImageCvter *itermediate = nullptr) const noexcept; + bool load_cache(const char *filename, uint64_t expected_task_hash) noexcept; }; } // namespace libMapImageCvt From 7103f6e62eee4a807cbcae7ddf88b36ebcc14cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 13:31:51 +0800 Subject: [PATCH 0276/1123] show progress during convertion --- SlopeCraft/SCWind.cpp | 50 +++++++++++++++++++++++++++++++++++++++++-- SlopeCraft/SCWind.h | 5 ++++- SlopeCraft/SCWind.ui | 22 ++++++++++++++----- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 15e80dc1..3020580b 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -21,8 +21,25 @@ SCWind::SCWind(QWidget *parent) this->kernel->setCacheDir(cache_dir.toLocal8Bit()); this->kernel->setWindPtr(this); - // this->kernel->setAlgoProgressAdd([](void *, int) {}); - // this->kernel->setAlgoProgressRangeSet([](void *, int, int, int) {}); + this->kernel->setProgressRangeSet( + [](void *_self, int min, int max, int val) { + SCWind *const self = reinterpret_cast(_self); + QProgressBar *const bar = self->current_bar(); + if (bar == nullptr) return; + + bar->setMinimum(min); + bar->setMaximum(max); + bar->setValue(val); + }); + this->kernel->setProgressAdd([](void *_self, int delta) { + SCWind *const self = reinterpret_cast(_self); + QProgressBar *const bar = self->current_bar(); + if (bar == nullptr) return; + + bar->setValue(bar->value() + delta); + }); + + this->kernel->setKeepAwake([](void *) { QApplication::processEvents(); }); } // initialize cvt pool model { @@ -355,6 +372,19 @@ std::array SCWind::algo_buttons() noexcept { return SC_SLOPECRAFT_PRIVATEMARCO_ALGO_BUTTONS; } +QProgressBar *SCWind::current_bar() noexcept { + const int cid = this->ui->tw_main->currentIndex(); + switch (cid) { + case 1: + return this->ui->pbar_cvt; + case 2: + return this->ui->pbar_export; + break; + default: + return nullptr; + } +} + void SCWind::update_button_states() noexcept { { const bool disable_3d = (this->selected_type() == SCL_mapTypes::FileOnly); @@ -582,6 +612,22 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { this->kernel_make_cache(); this->refresh_current_cvt_display(sel.value(), true); + this->ui->tw_cvt_image->setCurrentIndex(1); + // this->ui-> +} + +void SCWind::on_pb_cvt_all_clicked() noexcept { + for (int idx = 0; idx < (int)this->tasks.size(); idx++) { + auto &task = this->tasks[idx]; + if (task.is_converted) { + continue; + } + + this->kernel_set_image(idx); + this->kernel_convert_image(); + this->kernel_make_cache(); + task.set_converted(); + } } QImage SCWind::get_converted_image_from_kernel() const noexcept { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index b627d471..8950b660 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -7,7 +7,7 @@ #include #include #include - +#include #include "cvt_task.h" #include "PoolModel.h" @@ -44,6 +44,7 @@ class SCWind : public QMainWindow { void when_export_type_toggled() noexcept; void on_pb_cvt_current_clicked() noexcept; + void on_pb_cvt_all_clicked() noexcept; private: Ui::SCWind* ui; @@ -69,6 +70,8 @@ class SCWind : public QMainWindow { std::array algo_buttons() const noexcept; std::array algo_buttons() noexcept; + QProgressBar* current_bar() noexcept; + SCL_gameVersion selected_version() const noexcept; SCL_mapTypes selected_type() const noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 756a5361..88f9fa8f 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -16,7 +16,7 @@ - + 0 @@ -321,7 +321,7 @@ - + 500 @@ -329,7 +329,7 @@ - QTabWidget::East + QTabWidget::North QTabWidget::Rounded @@ -337,6 +337,18 @@ 0 + + Qt::ElideNone + + + false + + + false + + + false + 原图 @@ -542,7 +554,7 @@ - 24 + 0 @@ -706,7 +718,7 @@ - 24 + 0 From 8b9ac096ae1fec1c5e02ae006ee16cacb66438c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 14:09:51 +0800 Subject: [PATCH 0277/1123] reduce convert cache size --- utilities/MapImageCvter/MapImageCvter.h | 51 +++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 793ed184..1a98f9b4 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -29,6 +29,7 @@ This file is part of SlopeCraft. #include #include #include +#include namespace GACvter { class GAConverter; @@ -97,11 +98,16 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { void load_from_itermediate(MapImageCvter &&temp) noexcept { this->_raw_image = std::move(temp._raw_image); this->algo = temp.algo; - this->_color_hash = std::move(temp._color_hash); this->_dithered_image = std::move(temp._dithered_image); assert(this->_raw_image.rows() == this->_dithered_image.rows()); assert(this->_raw_image.cols() == this->_dithered_image.cols()); + if (this->_color_hash.empty()) { + this->_color_hash = std::move(temp._color_hash); + } else { + temp._color_hash.merge(this->_color_hash); + this->_color_hash = std::move(temp._color_hash); + } } private: @@ -112,19 +118,58 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { assert(this->_raw_image.cols() == this->_dithered_image.cols()); ar(this->_raw_image); ar(this->algo); - ar(this->_color_hash); + // ar(this->_color_hash); ar(this->_dithered_image); + // save required colorset + { + std::unordered_set colors_dithered_img; + colors_dithered_img.reserve(this->_dithered_image.size()); + for (int64_t i = 0; i < this->_dithered_image.size(); i++) { + colors_dithered_img.emplace(this->_dithered_image(i)); + } + + const size_t size_colorset = colors_dithered_img.size(); + ar(size_colorset); + for (uint32_t color : colors_dithered_img) { + auto it = + this->color_hash().find(convert_unit{color, this->convert_algo()}); + assert(it != this->color_hash().end()); + + ar(it->first, it->second); + } + } } template void load(archive &ar) { ar(this->_raw_image); ar(this->algo); - ar(this->_color_hash); + // ar(this->_color_hash); ar(this->_dithered_image); assert(this->_raw_image.rows() == this->_dithered_image.rows()); assert(this->_raw_image.cols() == this->_dithered_image.cols()); + + { + size_t size_colorset{0}; + ar(size_colorset); + for (size_t idx = 0; idx < size_colorset; idx++) { + convert_unit key; + TokiColor_t val; + ar(key, val); + + this->_color_hash.emplace(key, val); + } + + for (int64_t i = 0; i < this->_dithered_image.size(); i++) { + auto it = this->_color_hash.find( + convert_unit{this->_dithered_image(i), this->convert_algo()}); + if (it == this->_color_hash.end()) { + throw std::runtime_error{ + "One or more colors not found in cached colorhash"}; + } + } + } } public: From 001ef4cac54cf02451210af232a7b319866b5dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 14:10:28 +0800 Subject: [PATCH 0278/1123] format task hash to hex --- SlopeCraftL/TokiSlopeCraft_cache.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 706a20bb..606a0d6c 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -43,7 +43,7 @@ std::string TokiSlopeCraft::task_dir() const noexcept { } std::string TokiSlopeCraft::task_dir(uint64_t hash) const noexcept { - return fmt::format("{}/{}", this->cache_dir.value(), hash); + return fmt::format("{}/{:x}", this->cache_dir.value(), hash); } std::string TokiSlopeCraft::task_dir(SCL_convertAlgo algo, bool dither) const noexcept { @@ -70,13 +70,14 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { namespace stdfs = std::filesystem; std::error_code ec; - if (!stdfs::create_directories(task_dir, ec)) { - err = fmt::format( - "Failed to create dir named \"{}\", error code = {}, message = {}", - task_dir, ec.value(), ec.message()); - return; + if (!stdfs::is_directory(task_dir)) { + if (!stdfs::create_directories(task_dir, ec)) { + err = fmt::format( + "Failed to create dir named \"{}\", error code = {}, message = {}", + task_dir, ec.value(), ec.message()); + return; + } } - err.clear(); std::string temp_err{}; @@ -152,6 +153,10 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, return false; } + if (!this->check_colorset_hash()) { + return false; + } + const uint64_t expected_task_hash = this->image_cvter.task_hash(algo, dither); const std::string expected_task_dir = this->task_dir(expected_task_hash); From ff0db6731e6b713ab32634205bf30288f43e345e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 18:20:40 +0800 Subject: [PATCH 0279/1123] store an extra colorset hash file --- SlopeCraftL/TokiSlopeCraft.h | 5 ++++ SlopeCraftL/TokiSlopeCraft_cache.cpp | 39 +++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 2b7867a2..e166d946 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -328,7 +328,12 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string task_dir(SCL_convertAlgo algo, bool dither) const noexcept; std::string colorset_hash_file() const noexcept; + bool check_coloset_hash_by_filename(std::string_view filename) const noexcept; + static std::string conevrt_cache_filename(std::string_view taskdir) noexcept; + static std::string cache_owned_hash_filename( + std::string_view taskdir) noexcept; + bool check_cache_owned_hash(uint64_t task_hash) const noexcept; public: bool check_colorset_hash() const noexcept override; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 606a0d6c..c589af21 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -55,6 +55,11 @@ std::string TokiSlopeCraft::conevrt_cache_filename( return fmt::format("{}/convert", taskdir); } +std::string TokiSlopeCraft::cache_owned_hash_filename( + std::string_view taskdir) noexcept { + return fmt::format("{}/private_hash{}", taskdir, hash_suffix); +} + void TokiSlopeCraft::saveCache(std::string &err) const noexcept { if (this->kernelStep < SlopeCraft::step::converted) { err = "Can not save cache before the image is converted."; @@ -81,11 +86,18 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { err.clear(); std::string temp_err{}; - // write colorset hash + // write 2 colorset hash files { const std::string name_hash_colorset = this->colorset_hash_file(); + const auto hash = TokiSlopeCraft::Allowed.hash(); - temp_err = write_hash(name_hash_colorset, TokiSlopeCraft::Allowed.hash()); + temp_err = write_hash(name_hash_colorset, hash); + if (!temp_err.empty()) { + err = fmt::format("Failed to save colorset hash. Detail: {}", temp_err); + return; + } + + temp_err = write_hash(this->cache_owned_hash_filename(task_dir), hash); if (!temp_err.empty()) { err = fmt::format("Failed to save colorset hash. Detail: {}", temp_err); return; @@ -103,23 +115,23 @@ void TokiSlopeCraft::saveCache(std::string &err) const noexcept { return; } -bool TokiSlopeCraft::check_colorset_hash() const noexcept { +bool TokiSlopeCraft::check_coloset_hash_by_filename( + std::string_view filename) const noexcept { if (this->kernelStep < SCL_step::wait4Image) { reportError(wind, errorFlag::HASTY_MANIPULATION, "You can check for colorset only after you set the map type"); return false; } - const std::string hash_file = this->colorset_hash_file(); std::vector buf; { - std::ifstream ifs{hash_file, std::ios::binary}; + std::ifstream ifs{filename.data(), std::ios::binary}; if (!ifs) { // file not exist return false; } - const size_t file_size = std::filesystem::file_size(hash_file); + const size_t file_size = std::filesystem::file_size(filename.data()); if (file_size <= 0) { // empty file return false; } @@ -144,6 +156,15 @@ bool TokiSlopeCraft::check_colorset_hash() const noexcept { return true; } +bool TokiSlopeCraft::check_colorset_hash() const noexcept { + return this->check_coloset_hash_by_filename(this->colorset_hash_file()); +} + +bool TokiSlopeCraft::check_cache_owned_hash(uint64_t task_hash) const noexcept { + return this->check_coloset_hash_by_filename( + this->cache_owned_hash_filename(this->task_dir(task_hash))); +} + bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, bool dither) noexcept { if (this->kernelStep < SCL_step::convertionReady) { @@ -159,6 +180,10 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, const uint64_t expected_task_hash = this->image_cvter.task_hash(algo, dither); + if (!this->check_cache_owned_hash(expected_task_hash)) { + return false; + } + const std::string expected_task_dir = this->task_dir(expected_task_hash); const std::string expected_cache_file = @@ -173,4 +198,4 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, return true; } return false; -} \ No newline at end of file +} From 165033cacc050d40601a98c0eea338def320dbac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 18:30:33 +0800 Subject: [PATCH 0280/1123] refresh when cvt algo is changed --- SlopeCraft/SCWind.cpp | 24 +++++++++++++++++------- SlopeCraft/SCWind.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 3020580b..a22d7467 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -86,16 +86,22 @@ SCWind::SCWind(QWidget *parent) connect(this->ui->blm, &BlockListManager::changed, this, &SCWind::when_blocklist_changed); } - { - for (QRadioButton *rbp : this->export_type_buttons()) { - connect(rbp, &QRadioButton::clicked, this, - &SCWind::when_export_type_toggled); - } + + for (QRadioButton *rbp : this->export_type_buttons()) { + connect(rbp, &QRadioButton::clicked, this, + &SCWind::when_export_type_toggled); + } + + for (QRadioButton *rbp : this->preset_buttons_no_custom()) { + connect(rbp, &QRadioButton::clicked, this, &SCWind::when_preset_clicked); } { - for (QRadioButton *rbp : this->preset_buttons_no_custom()) { - connect(rbp, &QRadioButton::clicked, this, &SCWind::when_preset_clicked); + for (QRadioButton *rbp : this->algo_buttons()) { + connect(rbp, &QRadioButton::clicked, this, + &SCWind::when_algo_btn_clicked); } + connect(this->ui->cb_algo_dither, &QCheckBox::clicked, this, + &SCWind::when_algo_btn_clicked); } { @@ -692,4 +698,8 @@ void SCWind::mark_all_task_unconverted() noexcept { for (auto &task : this->tasks) { task.set_unconverted(); } +} + +void SCWind::when_algo_btn_clicked() noexcept { + this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 8950b660..2bcae33a 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -42,6 +42,7 @@ class SCWind : public QMainWindow { void when_blocklist_changed() noexcept; void when_preset_clicked() noexcept; void when_export_type_toggled() noexcept; + void when_algo_btn_clicked() noexcept; void on_pb_cvt_current_clicked() noexcept; void on_pb_cvt_all_clicked() noexcept; From 8841b659ab8f4b83a0b5a95bed860474faa6e0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 8 May 2023 19:24:40 +0800 Subject: [PATCH 0281/1123] save converted image --- SlopeCraft/SCWind.cpp | 122 ++++++++++++++++++++ SlopeCraft/SCWind.h | 4 + SlopeCraft/SCWind.ui | 254 ++++++++++++++++++++---------------------- 3 files changed, 249 insertions(+), 131 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index a22d7467..ec777444 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -270,6 +270,16 @@ SCL_mapTypes SCWind::selected_type() const noexcept { return {}; } +std::vector SCWind::selected_indices() const noexcept { + std::vector ret; + auto sel = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + ret.reserve(sel.size()); + for (auto &midx : sel) { + ret.emplace_back(midx.row()); + } + return ret; +} + std::optional SCWind::selected_cvt_task_idx() const noexcept { auto sel = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); if (sel.size() <= 0) { @@ -702,4 +712,116 @@ void SCWind::mark_all_task_unconverted() noexcept { void SCWind::when_algo_btn_clicked() noexcept { this->refresh_current_cvt_display(this->selected_cvt_task_idx()); +} + +void SCWind::on_pb_save_converted_clicked() noexcept { + const auto selected = this->selected_indices(); + if (selected.size() <= 0) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个或多个图像")); + return; + } + static QString prev_dir{""}; + if (selected.size() == 1) { + QString filename = QFileDialog::getSaveFileName(this, tr("保存转化后图像"), + prev_dir, "*.png;*.jpg"); + if (filename.isEmpty()) { + return; + } + prev_dir = QFileInfo{filename}.dir().dirName(); + + const int idx = selected.front(); + + this->export_current_cvted_image(idx, filename); + return; + } + + QString out_dir = + QFileDialog::getExistingDirectory(this, tr("保存转化后图像"), prev_dir); + if (out_dir.isEmpty()) { + return; + } + prev_dir = out_dir; + + bool yes_to_all_replace_existing{false}; + bool no_to_all_replace_existing{false}; + for (int idx : selected) { + auto &task = this->tasks[idx]; + QString filename = QStringLiteral("%1/%2.png") + .arg(out_dir) + .arg(QFileInfo{task.filename}.baseName()); + + if (QFile{filename}.exists()) { + if (no_to_all_replace_existing) { + continue; + } + if (yes_to_all_replace_existing) { + goto save_image; + } + + auto ret = QMessageBox::warning( + this, tr("将要覆盖已存在的图像"), + tr("%1将被覆盖,确认覆盖吗?").arg(filename), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No, + QMessageBox::StandardButton::YesToAll, + QMessageBox::StandardButton::NoToAll}); + bool replace{false}; + switch (ret) { + case QMessageBox::StandardButton::Yes: + replace = true; + break; + case QMessageBox::StandardButton::YesToAll: + replace = true; + yes_to_all_replace_existing = true; + break; + case QMessageBox::StandardButton::NoToAll: + replace = false; + no_to_all_replace_existing = true; + break; + default: + replace = false; + break; + } + + if (!replace) { + continue; + } + } + + save_image: + + this->export_current_cvted_image(idx, filename); + } +} + +void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { + assert(idx >= 0); + assert(idx < (int)this->tasks.size()); + + this->kernel_set_image(idx); + if (!this->kernel->load_convert_cache(this->selected_algo(), + this->is_dither_selected())) { + const auto ret = QMessageBox::warning( + this, tr("无法保存第%1个转化后图像").arg(idx + 1), + tr("该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。"), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok, + QMessageBox::StandardButton::Ignore}); + if (ret == QMessageBox::StandardButton::Ok) { + this->kernel_convert_image(); + this->kernel_make_cache(); + this->tasks[idx].set_converted(); + } else { + return; + } + } + + bool ok = this->get_converted_image_from_kernel().save(filename); + if (!ok) { + QMessageBox::warning( + this, tr("保存图像失败"), + tr("保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。") + .arg(filename)); + return; + } } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 2bcae33a..a2485d2a 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -46,6 +46,7 @@ class SCWind : public QMainWindow { void on_pb_cvt_current_clicked() noexcept; void on_pb_cvt_all_clicked() noexcept; + void on_pb_save_converted_clicked() noexcept; private: Ui::SCWind* ui; @@ -77,6 +78,7 @@ class SCWind : public QMainWindow { SCL_mapTypes selected_type() const noexcept; + std::vector selected_indices() const noexcept; std::optional selected_cvt_task_idx() const noexcept; SCL_convertAlgo selected_algo() const noexcept; @@ -107,6 +109,8 @@ class SCWind : public QMainWindow { void mark_all_task_unconverted() noexcept; + void export_current_cvted_image(int idx, QString filename) noexcept; + signals: void image_changed(); }; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 88f9fa8f..6c984a5c 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -319,8 +319,8 @@ 导入图像并转化 - - + + @@ -424,141 +424,14 @@ - - - - - 0 - 0 - - - - 转化当前图像 - - - - - - - - 0 - 0 - - - - 全部转化 - - - - - - - 转化算法 - - - - - - 抖动 - - - - - - - Lab00 - - - - - - - Lab94 - - - - - - - RGB+ - - - true - - - - - - - RGB - - - - - - - XYZ - - - - - - - GACvter - - - - - - - - - - - 0 - 0 - - - - 保存转化后图像 - - - - - - - - 当前 - - - - - 全部 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + 0 - + 0 @@ -568,6 +441,12 @@ + + + 0 + 0 + + false @@ -660,6 +539,119 @@ + + + + 转化算法 + + + + + + 抖动 + + + + + + + Lab00 + + + + + + + Lab94 + + + + + + + RGB+ + + + true + + + + + + + RGB + + + + + + + XYZ + + + + + + + GACvter + + + + + + + + + + + 0 + 0 + + + + 转化当前图像 + + + + + + + + 0 + 0 + + + + 保存转化后图像 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + 全部转化 + + + From bb55f2f31a146f1dc84586f453ee46962e8e17c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 9 May 2023 14:25:52 +0800 Subject: [PATCH 0282/1123] add serialization to schem --- utilities/Schem/CMakeLists.txt | 9 ++++++-- utilities/Schem/Schem.cpp | 21 ++++++++++++++++++ utilities/Schem/Schem.h | 39 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index f13d2f6a..e955cc51 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -10,9 +10,14 @@ add_library(Schem bit_shrink.cpp) find_package(Eigen3 REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) +find_package(cereal REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) +find_package(fmt REQUIRED) + # target_compile_options(Schem BEFORE PUBLIC -std=c++17) -target_link_libraries(Schem PUBLIC NBTWriter Eigen3::Eigen) -target_compile_features(Schem PRIVATE cxx_std_20) +target_link_libraries(Schem PUBLIC NBTWriter Eigen3::Eigen cereal::cereal fmt::fmt) +target_compile_features(Schem PUBLIC cxx_std_20) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) if(CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 07d469d2..daf3d455 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -27,6 +27,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "../NBTWriter/NBTWriter.h" #include "bit_shrink.h" @@ -46,6 +47,19 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) noexcept { this->xzy.resize(x, z, y); } +std::string Schem::check_size() const noexcept { + return check_size(this->x_range(), this->y_range(), this->z_range()); +} + +std::string Schem::check_size(int64_t x, int64_t y, int64_t z) noexcept { + if (x < 0 || y < 0 || z < 0) { + return fmt::format( + "Size in one or more dimensions is negative. x= {}, y= {}, z= {}", x, y, + z); + } + return {}; +} + void Schem::set_block_id(const char *const *const block_ids, const int num) noexcept { if (num < 0) { @@ -61,6 +75,13 @@ void Schem::set_block_id(const char *const *const block_ids, } } +void Schem::set_block_id(std::span id) noexcept { + this->block_id_list.resize(id.size()); + for (size_t idx = 0; idx < id.size(); idx++) { + this->block_id_list[idx] = id[idx]; + } +} + int64_t Schem::non_zero_count() const noexcept { int64_t val = 0; diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 19d6807f..a880cb05 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -29,6 +29,11 @@ This file is part of SlopeCraft. #include #include #include +#include +#include +#include +#include +#include #include "SC_GlobalEnums.h" @@ -81,6 +86,9 @@ class Schem { xzy.setZero(); } + std::string check_size() const noexcept; + static std::string check_size(int64_t x, int64_t y, int64_t z) noexcept; + inline void set_zero() noexcept { xzy.setZero(); } inline ele_t *data() noexcept { return xzy.data(); } @@ -160,6 +168,7 @@ class Schem { /// Schem will copy these strings void set_block_id(const char *const *const block_ids, const int num) noexcept; + void set_block_id(std::span id) noexcept; inline MCDataVersion::MCDataVersion_t MC_version_number() const noexcept { return this->MC_data_ver; @@ -222,6 +231,36 @@ class Schem { const WorldEditSchem_info &info = WorldEditSchem_info(), SCL_errorFlag *const error_flag = nullptr, std::string *const error_str = nullptr) const noexcept; + + private: + friend class cereal::access; + + template + void save(archive &ar) const { + ar(this->MC_major_ver); + ar(this->MC_data_ver); + ar(this->block_id_list); + const int64_t x{this->x_range()}, y{this->y_range()}, z{this->z_range()}; + ar(x, y, z); + ar(cereal::binary_data(this->data(), this->size())); + } + + template + void load(archive &ar) { + ar(this->MC_major_ver); + ar(this->MC_data_ver); + ar(this->block_id_list); + int64_t x, y, z; + ar(x, y, z); + { + std::string err = check_size(x, y, z); + if (!err.empty()) { + throw std::runtime_error{err}; + } + } + this->resize(x, y, z); + ar(cereal::binary_data(this->data(), this->size())); + } }; } // namespace libSchem From 4d9c82c25fbd3e309c1822366721f1a634095e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 9 May 2023 14:26:30 +0800 Subject: [PATCH 0283/1123] remove redundant members in SCL --- SlopeCraftL/TokiSlopeCraft.h | 53 ++++++++++-- SlopeCraftL/TokiSlopeCraft_build.cpp | 100 ++++++++++++---------- SlopeCraftL/TokiSlopeCraft_convert.cpp | 111 ++++++++++++------------- 3 files changed, 156 insertions(+), 108 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index e166d946..e3f3a80b 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -33,6 +33,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "Colors.h" #include "SCLDefines.h" @@ -54,6 +55,8 @@ This file is part of SlopeCraft. #include #include "WriteStringDeliver.h" +#include + /* namespace SlopeCraft { @@ -271,10 +274,12 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { AiCvterOpt AiOpt; Eigen::ArrayXXi mapPic; // stores mapColor + /* Eigen::ArrayXXi Base; Eigen::ArrayXXi HighMap; Eigen::ArrayXXi LowMap; std::unordered_map WaterList; + */ uint16_t maxAllowedHeight; uint16_t bridgeInterval; compressSettings compressMethod; @@ -294,9 +299,14 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // for build // void makeHeight_old();//构建 HighMap 和 LowMap - void makeHeight_new(); + void makeHeight_new(Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, + Eigen::ArrayXXi &LowMap, + std::unordered_map &WaterList); // void makeHeightInLine(const uint16_t c); - void buildHeight(bool = false, bool = false); // 构建 Build + void buildHeight( + bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, + const Eigen::ArrayXXi &HighMap, const Eigen::ArrayXXi &LowMap, + const std::unordered_map &WaterList); // 构建 Build void makeBridge(); // for Litematic /* @@ -313,14 +323,14 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void setCacheDir(const char *) noexcept override; const char *cacheDir() const noexcept override; - bool saveCache(StringDeliver &_err) const noexcept override { + bool saveConvertCache(StringDeliver &_err) const noexcept override { std::string err; - this->saveCache(err); + this->save_cache(err); write(_err, err); return err.empty(); } - void saveCache(std::string &err) const noexcept; + void save_cache(std::string &err) const noexcept; private: std::string task_dir() const noexcept; @@ -335,9 +345,38 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string_view taskdir) noexcept; bool check_cache_owned_hash(uint64_t task_hash) const noexcept; + private: + struct build_options { + uint16_t maxAllowedHeight; + uint16_t bridgeInterval; + compressSettings compressMethod; + glassBridgeSettings glassMethod; + }; + static uint64_t build_task_hash(const Eigen::ArrayXXi &mapPic, + std::span blkid, + const build_options &) noexcept; + uint64_t build_task_hash() const noexcept; + + std::vector schem_block_id_list() const noexcept; + + static std::string build_task_dir(std::string_view cvt_task_dir, + uint64_t build_task_hash) noexcept; + std::string build_task_dir() const noexcept; + + struct build_cache_ir { + Eigen::ArrayXXi mapPic; + libSchem::Schem schem; + }; + + static bool exmaine_build_cache(std::string_view filename, + uint64_t build_task_hash, + std::span blkid, + const build_options &bo, + build_cache_ir *ir = nullptr) noexcept; + public: - bool check_colorset_hash() const noexcept override; - bool load_convert_cache(SCL_convertAlgo algo, bool dither) noexcept override; + bool checkColorsetHash() const noexcept override; + bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 0034e8e2..e2676024 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -167,6 +167,25 @@ std::string TokiSlopeCraft::exportAsLitematic( return ""; } +std::vector TokiSlopeCraft::schem_block_id_list() + const noexcept { + std::vector temp; + temp.reserve(64); + temp.emplace_back("minecraft:air"); + + for (const auto &block : TokiSlopeCraft::blockPalette) { + std::string_view id_at_curversion = (this->mcVer == SCL_gameVersion::MC12) + ? (block.getIdOld()) + : (block.getId()); + if ("minecraft:air" == id_at_curversion) { + break; + } else { + temp.emplace_back(id_at_curversion); + } + } + return temp; +} + bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, glassBridgeSettings gBS, uint16_t bI, bool fireProof, bool endermanProof) { @@ -186,22 +205,8 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, } // cerr << "Setting block palette..." << endl; { - std::vector temp; - temp.reserve(64); - temp.emplace_back("minecraft:air"); - - for (const auto &block : TokiSlopeCraft::blockPalette) { - const char *id_at_curversion = (this->mcVer == SCL_gameVersion::MC12) - ? (block.getIdOld()) - : (block.getId()); - if (std::strcmp("minecraft:air", id_at_curversion) == 0) { - break; - } else { - temp.emplace_back(id_at_curversion); - } - } - - schem.set_block_id(temp.data(), temp.size()); + auto temp = this->schem_block_id_list(); + schem.set_block_id(temp); } schem.set_MC_major_version_number(TokiSlopeCraft::mcVer); @@ -224,23 +229,25 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, progressRangeSet(wind, 0, 9 * sizePic(2), 0); // cerr << "start makeHeight" << endl; - - mapPic = this->image_cvter.mapcolor_matrix().cast(); - progressAdd(wind, sizePic(2)); - - makeHeight_new(); - // cerr << "makeHeight finished" << endl; - progressRangeSet(wind, 0, 9 * sizePic(2), 5 * sizePic(2)); - - reportWorkingStatue(wind, workStatues::building3D); - // cerr << "start buildHeight" << endl; - buildHeight(fireProof, endermanProof); - // cerr << "buildHeight finished" << endl; - progressRangeSet(wind, 0, 9 * sizePic(2), 8 * sizePic(2)); - - reportWorkingStatue(wind, workStatues::constructingBridges); - // cerr << "start makeBridge" << endl; - makeBridge(); + { + Eigen::ArrayXXi Base, HighMap, LowMap; + std::unordered_map WaterList; + progressAdd(wind, sizePic(2)); + + makeHeight_new(Base, HighMap, LowMap, WaterList); + // cerr << "makeHeight finished" << endl; + progressRangeSet(wind, 0, 9 * sizePic(2), 5 * sizePic(2)); + + reportWorkingStatue(wind, workStatues::building3D); + // cerr << "start buildHeight" << endl; + buildHeight(fireProof, endermanProof, Base, HighMap, LowMap, WaterList); + // cerr << "buildHeight finished" << endl; + progressRangeSet(wind, 0, 9 * sizePic(2), 8 * sizePic(2)); + + reportWorkingStatue(wind, workStatues::constructingBridges); + // cerr << "start makeBridge" << endl; + makeBridge(); + } // cerr << "makeBridge finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 9 * sizePic(2)); @@ -251,24 +258,26 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, return true; } -void TokiSlopeCraft::makeHeight_new() { +void TokiSlopeCraft::makeHeight_new( + Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, + std::unordered_map &WaterList) { Base.setZero(sizePic(0) + 1, sizePic(1)); - WaterList.clear(); HighMap.setZero(sizePic(0) + 1, sizePic(1)); LowMap.setZero(sizePic(0) + 1, sizePic(1)); + WaterList.clear(); bool allowNaturalCompress = compressMethod == compressSettings::Both || compressMethod == compressSettings::NaturalOnly; // std::vector src; // cerr << "makeHeight_new\n"; - if ((mapPic - 4 * (mapPic / 4) >= 3).any()) { + if ((this->mapPic - 4 * (this->mapPic / 4) >= 3).any()) { std::string msg = - "Fatal error : SlopeCraftLib3 found map color with depth 3 in a " + "Fatal error : SlopeCraftL found map color with depth 3 in a " "vanilla map.\n Map contents (map color matrix in col-major) :\n["; - for (int c = 0; c < mapPic.cols(); c++) { - for (int r = 0; r < mapPic.rows(); r++) { - msg += std::to_string(mapPic(r, c)) + ','; + for (int c = 0; c < this->mapPic.cols(); c++) { + for (int r = 0; r < this->mapPic.rows(); r++) { + msg += std::to_string(this->mapPic(r, c)) + ','; } msg += ";\n"; } @@ -282,7 +291,7 @@ void TokiSlopeCraft::makeHeight_new() { // cerr << "Coloumn " << c << '\n'; HeightLine HL; // getTokiColorPtr(c,&src[0]); - HL.make(mapPic.col(c), allowNaturalCompress); + HL.make(this->mapPic.col(c), allowNaturalCompress); if (HL.maxHeight() > maxAllowedHeight && (compressMethod == compressSettings::ForcedOnly || @@ -303,7 +312,7 @@ void TokiSlopeCraft::makeHeight_new() { } Eigen::ArrayXi temp; HL.make(&ptr[0], Compressor->getResult(), allowNaturalCompress, &temp); - mapPic.col(c) = temp; + this->mapPic.col(c) = temp; } Base.col(c) = HL.getBase(); @@ -325,7 +334,10 @@ void TokiSlopeCraft::makeHeight_new() { // schem.y_range() = HighMap.maxCoeff() + 1; // y } -void TokiSlopeCraft::buildHeight(bool fireProof, bool endermanProof) { +void TokiSlopeCraft::buildHeight( + bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, + const Eigen::ArrayXXi &, const Eigen::ArrayXXi &LowMap, + const std::unordered_map &WaterList) { /* { std::array tempSize3D({schem.x_range(), schem.y_range(), @@ -388,7 +400,7 @@ schem.z_range()}); Build.resize(tempSize3D); progressAdd(wind, sizePic(2)); - for (auto it = WaterList.cbegin(); it != WaterList.cend(); it++) { + for (auto it = WaterList.cbegin(); it != WaterList.cend(); ++it) { x = TokiCol(it->first) + 1; z = TokiRow(it->first); y = waterHigh(it->second); diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp index cf893724..4bb9cf37 100644 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ b/SlopeCraftL/TokiSlopeCraft_convert.cpp @@ -126,18 +126,15 @@ bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { void TokiSlopeCraft::exportAsData(const char *FolderPath, const int indexStart, int *fileCount, char **dest) const { std::vector uFL = exportAsData(FolderPath, indexStart); - if (fileCount != nullptr) - *fileCount = uFL.size(); + if (fileCount != nullptr) *fileCount = uFL.size(); if (dest != nullptr) for (uint16_t i = 0; i < uFL.size(); i++) { - if (dest[i] != nullptr) - std::strcpy(dest[i], uFL[i].data()); + if (dest[i] != nullptr) std::strcpy(dest[i], uFL[i].data()); } } std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, int indexStart) const { - std::vector failed_file_list; if (kernelStep < SCL_step::converted) { @@ -158,7 +155,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, // const int maxcc=cols*128; progressRangeSet(wind, 0, 128 * rows * cols, 0); - int offset[2] = {0, 0}; // r,c + int offset[2] = {0, 0}; // r,c int currentIndex = indexStart; reportWorkingStatue(wind, workStatues::writingMapDataFiles); @@ -184,20 +181,20 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, } switch (mcVer) { - case SCL_gameVersion::MC12: - case SCL_gameVersion::MC13: - break; - case SCL_gameVersion::MC14: - case SCL_gameVersion::MC15: - case SCL_gameVersion::MC16: - case SCL_gameVersion::MC17: - case SCL_gameVersion::MC18: - case SCL_gameVersion::MC19: - MapFile.writeInt("DataVersion", mcVersion2VersionNumber(mcVer)); - break; - default: - cerr << "Wrong game version!\n"; - break; + case SCL_gameVersion::MC12: + case SCL_gameVersion::MC13: + break; + case SCL_gameVersion::MC14: + case SCL_gameVersion::MC15: + case SCL_gameVersion::MC16: + case SCL_gameVersion::MC17: + case SCL_gameVersion::MC18: + case SCL_gameVersion::MC19: + MapFile.writeInt("DataVersion", mcVersion2VersionNumber(mcVer)); + break; + default: + cerr << "Wrong game version!\n"; + break; } static const std::string ExportedBy = "Exported by SlopeCraft " + @@ -212,43 +209,43 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, MapFile.writeInt("xCenter", 0); MapFile.writeInt("zCenter", 0); switch (mcVer) { - case SCL_gameVersion::MC12: - MapFile.writeByte("dimension", 114); - MapFile.writeShort("height", 128); - MapFile.writeShort("width", 128); - break; - case SCL_gameVersion::MC13: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 889464); - break; - case SCL_gameVersion::MC14: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 0); - MapFile.writeByte("locked", 1); - break; - case SCL_gameVersion::MC15: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 0); - MapFile.writeByte("locked", 1); - break; - case SCL_gameVersion::MC16: - case SCL_gameVersion::MC17: - case SCL_gameVersion::MC18: - case SCL_gameVersion::MC19: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeString("dimension", "minecraft:overworld"); - MapFile.writeByte("locked", 1); - break; - default: - cerr << "Wrong game version!\n"; - this->reportError(this->wind, errorFlag::UNKNOWN_MAJOR_GAME_VERSION, - "Unknown major game version!"); - failed_file_list.emplace_back(current_filename); - continue; + case SCL_gameVersion::MC12: + MapFile.writeByte("dimension", 114); + MapFile.writeShort("height", 128); + MapFile.writeShort("width", 128); + break; + case SCL_gameVersion::MC13: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 889464); + break; + case SCL_gameVersion::MC14: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 0); + MapFile.writeByte("locked", 1); + break; + case SCL_gameVersion::MC15: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 0); + MapFile.writeByte("locked", 1); + break; + case SCL_gameVersion::MC16: + case SCL_gameVersion::MC17: + case SCL_gameVersion::MC18: + case SCL_gameVersion::MC19: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeString("dimension", "minecraft:overworld"); + MapFile.writeByte("locked", 1); + break; + default: + cerr << "Wrong game version!\n"; + this->reportError(this->wind, errorFlag::UNKNOWN_MAJOR_GAME_VERSION, + "Unknown major game version!"); + failed_file_list.emplace_back(current_filename); + continue; } MapFile.writeByteArrayHead("colors", 16384); From 170c8711e2ae341f9990b22c21ea9fe7a80e08fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 9 May 2023 14:26:55 +0800 Subject: [PATCH 0284/1123] change cache-related interface function name --- SlopeCraft/SCWind.cpp | 12 ++--- SlopeCraftL/CMakeLists.txt | 2 + SlopeCraftL/SlopeCraftL.h | 7 ++- SlopeCraftL/TokiSlopeCraft_cache.cpp | 65 +++++++++++++++++++++++++--- 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index ec777444..3b59ca26 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -602,7 +602,7 @@ void SCWind::kernel_make_cache() noexcept { err.resize(4096); SlopeCraft::StringDeliver sd{err.data(), err.size()}; - if (!this->kernel->saveCache(sd)) { + if (!this->kernel->saveConvertCache(sd)) { QString qerr = QString::fromUtf8(sd.data); QMessageBox::warning(this, tr("缓存失败"), tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); @@ -610,7 +610,7 @@ void SCWind::kernel_make_cache() noexcept { } bool SCWind::kernel_check_colorset_hash() noexcept { - return this->kernel->check_colorset_hash(); + return this->kernel->checkColorsetHash(); } void SCWind::on_pb_cvt_current_clicked() noexcept { @@ -695,8 +695,8 @@ void SCWind::refresh_current_cvt_display( this->kernel_set_image(idx); - if (!this->kernel->load_convert_cache(this->selected_algo(), - this->is_dither_selected())) { + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { return; } @@ -800,8 +800,8 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { assert(idx < (int)this->tasks.size()); this->kernel_set_image(idx); - if (!this->kernel->load_convert_cache(this->selected_algo(), - this->is_dither_selected())) { + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { const auto ret = QMessageBox::warning( this, tr("无法保存第%1个转化后图像").arg(idx + 1), tr("该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。"), diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 9bdf2084..9b6fb4a5 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -2,6 +2,7 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) @@ -66,6 +67,7 @@ target_include_directories(SlopeCraftL INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(SlopeCraftL PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} ${SlopeCraft_HeuristicFlow_include_dir} + ${SlopeCraft_Chocobo1_Hash_include_dir} ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/utilities) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index e6ce54c5..7d3d0c6d 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -277,13 +277,12 @@ class Kernel { virtual void setCacheDir(const char *) noexcept = 0; virtual const char *cacheDir() const noexcept = 0; // requires step >= converted - virtual bool saveCache(StringDeliver &err) const noexcept = 0; + virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; // requires step >= wait4image - virtual bool check_colorset_hash() const noexcept = 0; + virtual bool checkColorsetHash() const noexcept = 0; // requires step >= convertion ready - virtual bool load_convert_cache(SCL_convertAlgo algo, - bool dither) noexcept = 0; + virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index c589af21..2121f72b 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -4,6 +4,7 @@ #include #include #include +#include std::string write_hash(std::string_view filename, const std::vector &hash) noexcept { @@ -60,7 +61,7 @@ std::string TokiSlopeCraft::cache_owned_hash_filename( return fmt::format("{}/private_hash{}", taskdir, hash_suffix); } -void TokiSlopeCraft::saveCache(std::string &err) const noexcept { +void TokiSlopeCraft::save_cache(std::string &err) const noexcept { if (this->kernelStep < SlopeCraft::step::converted) { err = "Can not save cache before the image is converted."; return; @@ -156,7 +157,7 @@ bool TokiSlopeCraft::check_coloset_hash_by_filename( return true; } -bool TokiSlopeCraft::check_colorset_hash() const noexcept { +bool TokiSlopeCraft::checkColorsetHash() const noexcept { return this->check_coloset_hash_by_filename(this->colorset_hash_file()); } @@ -165,8 +166,8 @@ bool TokiSlopeCraft::check_cache_owned_hash(uint64_t task_hash) const noexcept { this->cache_owned_hash_filename(this->task_dir(task_hash))); } -bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, - bool dither) noexcept { +bool TokiSlopeCraft::loadConvertCache(SCL_convertAlgo algo, + bool dither) noexcept { if (this->kernelStep < SCL_step::convertionReady) { reportError( wind, errorFlag::HASTY_MANIPULATION, @@ -174,7 +175,7 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, return false; } - if (!this->check_colorset_hash()) { + if (!this->checkColorsetHash()) { return false; } @@ -199,3 +200,57 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, } return false; } + +uint64_t TokiSlopeCraft::build_task_hash(const Eigen::ArrayXXi &mapPic, + std::span blkid, + const build_options &bo) noexcept { + Chocobo1::MD5 hash; + { + const int64_t rows{mapPic.rows()}, cols{mapPic.cols()}; + hash.addData(&rows, sizeof(rows)); + hash.addData(&cols, sizeof(cols)); + } + hash.addData(mapPic.data(), mapPic.size() * sizeof(mapPic(0))); + + for (auto str : blkid) { + hash.addData(str.data(), str.size()); + } + + hash.addData(&bo.maxAllowedHeight, sizeof(bo.maxAllowedHeight)); + hash.addData(&bo.bridgeInterval, sizeof(bo.bridgeInterval)); + hash.addData(&bo.compressMethod, sizeof(bo.compressMethod)); + hash.addData(&bo.glassMethod, sizeof(bo.glassMethod)); + + hash.finalize(); + + auto bytes = hash.toArray(); + + static_assert(bytes.size() == 16); + + const uint64_t *const hash_data = (const uint64_t *)bytes.data(); + return hash_data[0] ^ hash_data[1]; +} + +uint64_t TokiSlopeCraft::build_task_hash() const noexcept { + assert(this->kernelStep >= SCL_step::builded); + auto sbil = this->schem_block_id_list(); + return build_task_hash( + this->mapPic, sbil, + build_options{this->maxAllowedHeight, this->bridgeInterval, + this->compressMethod, this->glassMethod}); +} + +std::string TokiSlopeCraft::build_task_dir(std::string_view cvt_task_dir, + uint64_t build_task_hash) noexcept { + return fmt::format("{}/{:x}", cvt_task_dir, build_task_hash); +} + +std::string TokiSlopeCraft::build_task_dir() const noexcept { + return build_task_dir(this->task_dir(), this->build_task_hash()); +} + +bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, + uint64_t build_task_hash, + std::span blkid, + const build_options &bo, + build_cache_ir *ir) noexcept {} \ No newline at end of file From 6b3cbc33e348e401970131f471581edc5ab5165a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 9 May 2023 14:48:05 +0800 Subject: [PATCH 0285/1123] write build cache for SCL --- SlopeCraftL/TokiSlopeCraft.h | 14 ++++----- SlopeCraftL/TokiSlopeCraft_cache.cpp | 47 ++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index e3f3a80b..5b1b0271 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -56,6 +56,7 @@ This file is part of SlopeCraft. #include "WriteStringDeliver.h" #include +#include /* namespace SlopeCraft @@ -232,11 +233,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // const Eigen::Tensor &getBuild() const; private: -#ifdef SCL_CAPI - friend struct Kernel; -#else - friend class Kernel; -#endif // #ifdef SLOPECRAFTL_CAPI // friend class TokiColor; // friend void * allowedRGB(); // friend void * allowedMap(); @@ -325,12 +321,12 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool saveConvertCache(StringDeliver &_err) const noexcept override { std::string err; - this->save_cache(err); + this->save_convert_cache(err); write(_err, err); return err.empty(); } - void save_cache(std::string &err) const noexcept; + void save_convert_cache(std::string &err) const noexcept; private: std::string task_dir() const noexcept; @@ -362,6 +358,10 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static std::string build_task_dir(std::string_view cvt_task_dir, uint64_t build_task_hash) noexcept; std::string build_task_dir() const noexcept; + static std::string build_cache_filename( + std::string_view build_task_dir) noexcept; + + std::string make_build_cache() const noexcept; struct build_cache_ir { Eigen::ArrayXXi mapPic; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 2121f72b..104e7841 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -6,6 +6,7 @@ #include #include +namespace stdfs = std::filesystem; std::string write_hash(std::string_view filename, const std::vector &hash) noexcept { std::ofstream ofs{filename.data(), std::ios::binary}; @@ -61,7 +62,7 @@ std::string TokiSlopeCraft::cache_owned_hash_filename( return fmt::format("{}/private_hash{}", taskdir, hash_suffix); } -void TokiSlopeCraft::save_cache(std::string &err) const noexcept { +void TokiSlopeCraft::save_convert_cache(std::string &err) const noexcept { if (this->kernelStep < SlopeCraft::step::converted) { err = "Can not save cache before the image is converted."; return; @@ -249,8 +250,50 @@ std::string TokiSlopeCraft::build_task_dir() const noexcept { return build_task_dir(this->task_dir(), this->build_task_hash()); } +std::string TokiSlopeCraft::build_cache_filename( + std::string_view build_task_dir) noexcept { + return fmt::format("{}/build", build_task_dir); +} + +std::string TokiSlopeCraft::make_build_cache() const noexcept { + if (this->kernelStep < SlopeCraft::step::builded) { + return "Can not save cache before the 3d structure id built."; + } + + const std::string build_cache_dir = build_task_dir(); + if (!stdfs::is_directory(build_cache_dir)) { + std::error_code ec; + + if (!stdfs::create_directories(build_cache_dir, ec)) { + return fmt::format( + "Failed to create dir named \"{}\", error code = {}, message = {}", + build_cache_dir, ec.value(), ec.message()); + } + } + const std::string build_cache_file = build_cache_filename(build_cache_dir); + { + std::ofstream ofs{build_cache_file, std::ios::binary}; + + if (!ofs) { + return fmt::format("ofstream failed to open cache file {}", + build_cache_file); + } + + { + cereal::BinaryOutputArchive boa{ofs}; + boa(this->mapPic); + boa(this->schem); + } + ofs.close(); + } + + return {}; +} + bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, uint64_t build_task_hash, std::span blkid, const build_options &bo, - build_cache_ir *ir) noexcept {} \ No newline at end of file + build_cache_ir *ir) noexcept { +#warning read and exmaine cache here. +} From 79b7241207a9e500f28c42e6630e03cc59c6f2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 9 May 2023 23:14:44 +0800 Subject: [PATCH 0286/1123] export task show converted tasks only --- SlopeCraft/PoolModel.cpp | 27 ++ SlopeCraft/PoolModel.h | 57 +++- SlopeCraft/SCWind.cpp | 20 +- SlopeCraft/SCWind.h | 9 +- SlopeCraft/SCWind.ui | 343 +++++++++++++------------ SlopeCraftL/SlopeCraftL.h | 7 +- SlopeCraftL/TokiSlopeCraft.h | 11 +- SlopeCraftL/TokiSlopeCraft_cache.cpp | 5 +- utilities/ColorManip/seralize_funs.hpp | 14 +- utilities/Schem/Schem.h | 1 + 10 files changed, 305 insertions(+), 189 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 050c18e3..911598d1 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -195,4 +195,31 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, this->refresh(); return true; +} + +ExportPoolModel::ExportPoolModel(QObject* parent, task_pool_t* poolptr) + : PoolModel(parent, poolptr) {} + +ExportPoolModel::~ExportPoolModel() {} + +QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { + const int fidx = this->export_idx_to_full_idx(midx.row()); + assert(fidx >= 0); + assert(fidx < (int)this->pool->size()); + + if (role == Qt::ItemDataRole::DisplayRole) { + return this->pool->at(fidx).filename; + } + + if (role == Qt::ItemDataRole::DecorationRole) { + assert(this->_listview != nullptr); + if (this->_listview->viewMode() == QListView::ViewMode::ListMode) { + return QVariant{}; + } + auto raw_image = QPixmap::fromImage(this->pool->at(fidx).original_image); + auto img = raw_image.scaledToWidth(this->_listview->size().width()); + return QIcon{raw_image}; + } + + return QVariant{}; } \ No newline at end of file diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index db35c959..e161189a 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -16,7 +16,12 @@ class PoolModel : public QAbstractListModel { explicit PoolModel(QObject* parent = nullptr, task_pool_t* poolptr = nullptr); ~PoolModel(); - int rowCount(const QModelIndex&) const override { return this->pool->size(); } + int rowCount(const QModelIndex& midx) const override { + if (midx.isValid()) { + return 0; + } + return this->pool->size(); + } QModelIndex parent(const QModelIndex&) const override { return QModelIndex{}; @@ -24,6 +29,7 @@ class PoolModel : public QAbstractListModel { QVariant data(const QModelIndex& idx, int role) const override; + public slots: void refresh() noexcept { emit dataChanged(this->index(0, 0), this->index(this->rowCount({}), 0)); } @@ -61,4 +67,53 @@ class CvtPoolModel : public PoolModel { int column, const QModelIndex& parent) override; }; +class ExportPoolModel : public PoolModel { + Q_OBJECT + public: + explicit ExportPoolModel(QObject* parent = nullptr, + task_pool_t* poolptr = nullptr); + ~ExportPoolModel(); + + int rowCount(const QModelIndex& midx) const override { + if (midx.isValid()) { + return 0; + } + int num = 0; + for (const auto& i : *this->pool) { + if (i.is_converted) { + num++; + } + } + return num; + } + + std::vector iteration_map() const noexcept { + std::vector ret; + ret.reserve(this->pool->size()); + for (int i = 0; i < (int)this->pool->size(); i++) { + if (this->pool->at(i).is_converted) { + ret.emplace_back(i); + } + } + return ret; + } + + int export_idx_to_full_idx(int eidx) const noexcept { + assert(eidx >= 0); + for (int fidx = 0; fidx < (int)this->pool->size(); fidx++) { + if (pool->at(fidx).is_converted) { + eidx--; + } + if (eidx < 0) { + return fidx; + } + } + + assert(false); + return INT_MAX; + } + + QVariant data(const QModelIndex& idx, int role) const override; +}; + #endif // SLOPECRAFT_SLOPECRAFT_POOLMODEL_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 3b59ca26..bcf40862 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -50,14 +50,18 @@ SCWind::SCWind(QWidget *parent) &QItemSelectionModel::selectionChanged, this, &SCWind::when_cvt_pool_selectionChanged); - this->export_pool_model = new PoolModel{this, &this->tasks}; + this->export_pool_model = new ExportPoolModel{this, &this->tasks}; this->ui->lview_pool_export->setModel(this->export_pool_model); this->export_pool_model->set_listview(this->ui->lview_pool_export); connect(this, &SCWind::image_changed, this->cvt_pool_model, &CvtPoolModel::refresh); connect(this, &SCWind::image_changed, this->export_pool_model, - &PoolModel::refresh); + &ExportPoolModel::refresh); + connect(this, &SCWind::image_changed, [this]() { + this->ui->lview_pool_cvt->doItemsLayout(); + this->ui->lview_pool_export->doItemsLayout(); + }); } // initialize blm @@ -629,6 +633,8 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { this->kernel_make_cache(); this->refresh_current_cvt_display(sel.value(), true); this->ui->tw_cvt_image->setCurrentIndex(1); + + emit this->image_changed(); // this->ui-> } @@ -644,6 +650,7 @@ void SCWind::on_pb_cvt_all_clicked() noexcept { this->kernel_make_cache(); task.set_converted(); } + emit this->image_changed(); } QImage SCWind::get_converted_image_from_kernel() const noexcept { @@ -689,7 +696,7 @@ void SCWind::refresh_current_cvt_display( if (!kernel_check_colorset_hash()) { this->mark_all_task_unconverted(); - this->image_changed(); + emit this->image_changed(); return; } @@ -799,6 +806,8 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); + bool have_image_cvted{false}; + this->kernel_set_image(idx); if (!this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { @@ -811,11 +820,16 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { this->kernel_convert_image(); this->kernel_make_cache(); this->tasks[idx].set_converted(); + have_image_cvted = true; } else { return; } } + if (have_image_cvted) { + emit this->image_changed(); + } + bool ok = this->get_converted_image_from_kernel().save(filename); if (!ok) { QMessageBox::warning( diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index a2485d2a..b21868fc 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -22,6 +22,13 @@ class SCWind : public QMainWindow { public: explicit SCWind(QWidget* parent = nullptr); ~SCWind(); + enum class export_type { + litematica, + vanilla_structure, + WE_schem, + flat_diagram, + data_file + }; private slots: void on_pb_add_image_clicked() noexcept; void on_pb_remove_image_clicked() noexcept; @@ -54,7 +61,7 @@ class SCWind : public QMainWindow { task_pool_t tasks; CvtPoolModel* cvt_pool_model{nullptr}; - PoolModel* export_pool_model{nullptr}; + ExportPoolModel* export_pool_model{nullptr}; std::array default_presets; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 6c984a5c..8201075f 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -722,6 +722,16 @@ 0 + + + + 项目池 + + + Qt::AlignCenter + + + @@ -777,13 +787,13 @@ - - + + - 项目池 + Icon mode - - Qt::AlignCenter + + true @@ -802,6 +812,109 @@ + + + + 其他选项 + + + + + + 防火 + + + + + + + 防末影人 + + + + + + + + + + 压缩高度 + + + + + + 有损压缩 + + + true + + + + + + + 无损压缩 + + + + + + + + + + 最大允许高度: + + + 14 + + + 32767 + + + 256 + + + + + + + + + + 搭桥 + + + + + + 允许搭桥 + + + + + + + + + + 搭桥间隔: + + + 1 + + + 4096 + + + 5 + + + + + + @@ -1093,149 +1206,7 @@ - - - - 压缩高度 - - - - - - 有损压缩 - - - true - - - - - - - 无损压缩 - - - - - - - - - - 最大允许高度: - - - 14 - - - 32767 - - - 256 - - - - - - - - - - 预览 - - - - - - 预览材料表 - - - - - - - 预览压缩效果 - - - - - - - 预构建三维结构 - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - QFrame::Box - - - QFrame::Sunken - - - - - - - - - - 搭桥 - - - - - - 允许搭桥 - - - - - - - - - - 搭桥间隔: - - - 1 - - - 4096 - - - 5 - - - - - - - - - - 全部导出 - - - - + 大小与方块数量 @@ -1258,28 +1229,62 @@ - - - - 其他选项 + + + + 0 - - - - - 防火 - - - - - - - 防末影人 - - - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 全部导出 + + + + + + + 预览 + + + + + + 预览材料表 + + + + + + + 预览压缩效果 + + + + + + + 预构建三维结构 + + + + + + + diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 7d3d0c6d..d208c185 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -276,13 +276,16 @@ class Kernel { bool expected_col_major) const = 0; virtual void setCacheDir(const char *) noexcept = 0; virtual const char *cacheDir() const noexcept = 0; - // requires step >= converted - virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; // requires step >= wait4image virtual bool checkColorsetHash() const noexcept = 0; + // requires step >= converted + virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; // requires step >= convertion ready virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; + + // requires step >= built + virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 5b1b0271..55201c85 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -328,6 +328,13 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void save_convert_cache(std::string &err) const noexcept; + bool saveBuildCache(StringDeliver &_err) const noexcept override { + std::string err = this->make_build_cache(); + write(_err, err); + return err.empty(); + } + std::string make_build_cache() const noexcept; + private: std::string task_dir() const noexcept; std::string task_dir(uint64_t) const noexcept; @@ -361,8 +368,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static std::string build_cache_filename( std::string_view build_task_dir) noexcept; - std::string make_build_cache() const noexcept; - struct build_cache_ir { Eigen::ArrayXXi mapPic; libSchem::Schem schem; @@ -370,8 +375,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static bool exmaine_build_cache(std::string_view filename, uint64_t build_task_hash, - std::span blkid, - const build_options &bo, build_cache_ir *ir = nullptr) noexcept; public: diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 104e7841..1892987d 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace stdfs = std::filesystem; std::string write_hash(std::string_view filename, @@ -291,9 +292,7 @@ std::string TokiSlopeCraft::make_build_cache() const noexcept { } bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, - uint64_t build_task_hash, - std::span blkid, - const build_options &bo, + uint64_t expected_task_hash, build_cache_ir *ir) noexcept { #warning read and exmaine cache here. } diff --git a/utilities/ColorManip/seralize_funs.hpp b/utilities/ColorManip/seralize_funs.hpp index 97332f41..8f1e4d92 100644 --- a/utilities/ColorManip/seralize_funs.hpp +++ b/utilities/ColorManip/seralize_funs.hpp @@ -7,22 +7,24 @@ #include namespace cereal { -template -void save(archive &ar, const Eigen::ArrayXX &img) { +template +void save(archive &ar, const Eigen::ArrayXX &img) { + static_assert(std::is_arithmetic_v, "T must be arithmetic"); ar(cereal::make_size_tag(img.rows())); ar(cereal::make_size_tag(img.cols())); - ar(cereal::binary_data(img.data(), img.size() * sizeof(ARGB))); + ar(cereal::binary_data(img.data(), img.size() * sizeof(T))); } -template -void load(archive &ar, Eigen::ArrayXX &img) { +template +void load(archive &ar, Eigen::ArrayXX &img) { + static_assert(std::is_arithmetic_v, "T must be arithmetic"); Eigen::Index rows{0}, cols{0}; ar(cereal::make_size_tag(rows)); ar(cereal::make_size_tag(cols)); img.resize(rows, cols); - ar(cereal::binary_data(img.data(), rows * cols * sizeof(ARGB))); + ar(cereal::binary_data(img.data(), rows * cols * sizeof(T))); } } // namespace cereal diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index a880cb05..ad5fd20e 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -33,6 +33,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include #include "SC_GlobalEnums.h" From 0af391346841fb49fdb461bd299672d4a1661346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 10 May 2023 12:49:16 +0800 Subject: [PATCH 0287/1123] display icons --- SlopeCraft/CMakeLists.txt | 7 ++ SlopeCraft/PoolModel.cpp | 97 +++++++++++++++++++++++-- SlopeCraft/PoolModel.h | 12 +++ SlopeCraft/others/images/converted.png | Bin 0 -> 1016 bytes SlopeCraft/others/images/empty.png | Bin 0 -> 465 bytes 5 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 SlopeCraft/others/images/converted.png create mode 100644 SlopeCraft/others/images/empty.png diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index a8da4ea4..68df2dfa 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -63,6 +63,13 @@ set_target_properties(SlopeCraft PROPERTIES WIN32_EXECUTABLE TRUE ) +file(GLOB SlopeCraft_qrc_images "${CMAKE_CURRENT_SOURCE_DIR}/others/images/*.png") +message(STATUS "SlopeCraft_qrc_images = ${SlopeCraft_qrc_images}") +qt_add_resources(SlopeCraft "SC_images" + PREFIX "/images/" + BASE ${CMAKE_CURRENT_SOURCE_DIR}/others/images + FILES ${SlopeCraft_qrc_images}) + qt_finalize_executable(SlopeCraft) if(${WIN32}) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 911598d1..2ed0db71 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -2,15 +2,28 @@ #include #include #include +#include +#include PoolModel::PoolModel(QObject* parent, task_pool_t* poolptr) : QAbstractListModel(parent), pool(poolptr) {} PoolModel::~PoolModel() {} +const QPixmap& PoolModel::icon_empty() noexcept { + static QPixmap img{":/images/empty.png"}; + return img; +} + +const QPixmap& PoolModel::icon_converted() noexcept { + static QPixmap img{":/images/converted.png"}; + return img; +} + QVariant PoolModel::data(const QModelIndex& idx, int role) const { + const auto& task = this->pool->at(idx.row()); if (role == Qt::ItemDataRole::DisplayRole) { - return this->pool->at(idx.row()).filename; + return task.filename; } if (role == Qt::ItemDataRole::DecorationRole) { @@ -18,15 +31,78 @@ QVariant PoolModel::data(const QModelIndex& idx, int role) const { if (this->_listview->viewMode() == QListView::ViewMode::ListMode) { return QVariant{}; } - auto raw_image = - QPixmap::fromImage(this->pool->at(idx.row()).original_image); + auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - return QIcon{raw_image}; + + if (!task.is_converted) { + this->draw_icon(img, icon_empty(), 0); + } else { + this->draw_icon(img, icon_converted(), 0); + } + + return QIcon{img}; } return QVariant{}; } +QPixmap scale_up_to_3232(const QPixmap& original_pixmap, + QSize min_size) noexcept { + const QSize old_size = original_pixmap.size(); + const QSize new_size{std::min(old_size.width(), min_size.width()), + std::min(old_size.height(), min_size.height())}; + if (old_size == new_size) { + return original_pixmap; + } + QImage new_img{new_size, QImage::Format_ARGB32}; + memset(new_img.scanLine(0), 0, new_img.sizeInBytes()); + { + const QImage old_img{ + original_pixmap.toImage().convertToFormat(QImage::Format_ARGB32)}; + const uint32_t* const src = + reinterpret_cast(old_img.scanLine(0)); + uint32_t* const dst = reinterpret_cast(new_img.scanLine(0)); + + for (int r = 0; r < old_size.height(); r++) { + for (int c = 0; c < old_size.width(); c++) { + dst[r * new_size.width() + c] = src[r * old_size.width() + c]; + } + } + } + return QPixmap::fromImage(new_img); +} + +void PoolModel::draw_icon(QPixmap& image, const QPixmap& icon, int index, + QWidget* ptr_to_report_error) noexcept { + assert(index >= 0); + if (icon.size() != QSize{32, 32}) [[unlikely]] { + QMessageBox::critical( + ptr_to_report_error, QObject::tr("绘制图标时发现错误"), + tr("被绘制的图标尺寸应当是32*32,但实际上是%1*%" + "2。这属于SlopeCraft内部错误,请向开发者反馈。SlopeCraft必须崩溃。") + .arg(icon.size().height()) + .arg(icon.size().width())); + abort(); + return; + } + { + const QSize expected_min_size{(index + 1) * 32, 32}; + + if (image.height() < expected_min_size.height() || + image.width() < expected_min_size.width()) [[unlikely]] { + image = scale_up_to_3232(image, expected_min_size); + } + } + QPainter painter{&image}; + + const QSize img_size = image.size(); + + const int x = img_size.width() - (index + 1) * 32; + const int y = img_size.height() - 32; + painter.drawPixmap(x, y, icon); + painter.end(); +} + CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) : PoolModel(parent, poolptr) {} @@ -207,8 +283,10 @@ QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { assert(fidx >= 0); assert(fidx < (int)this->pool->size()); + const auto& task = this->pool->at(fidx); + if (role == Qt::ItemDataRole::DisplayRole) { - return this->pool->at(fidx).filename; + return task.filename; } if (role == Qt::ItemDataRole::DecorationRole) { @@ -216,9 +294,14 @@ QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { if (this->_listview->viewMode() == QListView::ViewMode::ListMode) { return QVariant{}; } - auto raw_image = QPixmap::fromImage(this->pool->at(fidx).original_image); + auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - return QIcon{raw_image}; + if (!task.is_built) { + this->draw_icon(img, icon_empty(), 0); + } else { + this->draw_icon(img, icon_converted(), 0); + } + return QIcon{img}; } return QVariant{}; diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index e161189a..8794dc1f 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -5,6 +5,7 @@ #include #include #include +#include class PoolModel : public QAbstractListModel { Q_OBJECT @@ -12,6 +13,9 @@ class PoolModel : public QAbstractListModel { task_pool_t* pool{nullptr}; QListView* _listview{nullptr}; + static const QPixmap& icon_empty() noexcept; + static const QPixmap& icon_converted() noexcept; + public: explicit PoolModel(QObject* parent = nullptr, task_pool_t* poolptr = nullptr); ~PoolModel(); @@ -44,6 +48,14 @@ class PoolModel : public QAbstractListModel { return this->_listview; } void set_listview(QListView* lv) noexcept { this->_listview = lv; } + + static void draw_icon(QPixmap& image, const QPixmap& icon, int index, + QWidget* ptr_to_report_error) noexcept; + + void draw_icon(QPixmap& image, const QPixmap& icon, + int index) const noexcept { + draw_icon(image, icon, index, this->_listview); + } }; class CvtPoolModel : public PoolModel { diff --git a/SlopeCraft/others/images/converted.png b/SlopeCraft/others/images/converted.png new file mode 100644 index 0000000000000000000000000000000000000000..cae9ffbe78b7f88939ef4f21125aec98d0b7f153 GIT binary patch literal 1016 zcmVQ)JzGibSx%kM`mzm-e76E``$Q#r=S>Eto@F5v)t0Segpk?MK>!hgK6v z7YZ7W%Sf@5l>xVGS@1BMGD~6|eS1hEiB0^dW83FA^Stx>zt6|K@8jZtX_^)Vt^qFr z^*CeOzy>fEi^XQkU%1M^mw|a85DtfP?d|P~*Xu==;MG z&-{Krkw`>RRkgVoZKPt(hlYoT-AzqRj=^VUW=N${1cSkfG)3m%BsP}rkj_%wytKe>O;c9TvIO1V)a+0;R zwF>_tv)&Cj(rO3c06V|#lD(cIl}gds*;%os#B?9^@k}N|GMW5G@F&q6$?sD1_V(6X zf2e?!l@)@o1bH<>qKd%VaImFV^Qq6+9nDL5>8L#kv zUhqvOlSdYFVm@nRgrTT$ZS7mGIqG_9JoB&X>MT(%08_too@cptZG? z>FH^n#{Xn5D*y^2W(y)lMn)Wg*AyVjGSO(158j;ONi@gaA4L(D3L@_Qe5WdWF|l+a zI6%$*D~SNO@%A{r+XZ0VB?X1+^mK6#Q8Kfs%;#uYFh{!U_1H zDL5!%baWJeo6+ld-|~>v^8E14;;G=r7Emri2*LR1IE#ym3=9mM`V2YIAt1{#V`F3V z^z_it(c#G5p{jrf*$4dg^kMB)&%?dne>@TBeEkL5&$k~>z}bfZ2Cr5OD8(shu5>BUWjvr_T6HN4gCF0000(Xkqt|Fh$ zXR<6KNs>H{;|}l!jJ4L=PXP;GNhy1y(WvQp9%aNB!)mp^P1?zuy;|&E`G`0waK_QYtU==08nBDU}0L z0StWK?@)0pb0C1W>$+9*vCOsru3oj@q+kkeoLZn3s0C_)TA&uF1w`?6t~v!%0H-X= zDi^TKlK^%}lH^qjSmsUu^Ei$>#+b_B#u#i%nm5<$^=l9WPlv Date: Wed, 10 May 2023 13:47:06 +0800 Subject: [PATCH 0288/1123] add a better build api for SCL --- SlopeCraftL/TokiSlopeCraft.h | 26 +++++++-------- SlopeCraftL/TokiSlopeCraft_build.cpp | 48 ++++++++++++++++------------ SlopeCraftL/TokiSlopeCraft_cache.cpp | 7 ++-- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 55201c85..aff3f020 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -179,11 +179,16 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { } // can do in converted: - bool build(compressSettings = SCL_compressSettings::noCompress, - unsigned short = 256, - glassBridgeSettings = SCL_glassBridgeSettings::noBridge, - unsigned short = 3, bool fireProof = false, - bool endermanProof = false) override; // 构建三维结构 + // 构建三维结构 + bool build(compressSettings cs = SCL_compressSettings::noCompress, + unsigned short mah = 256, + glassBridgeSettings gbs = SCL_glassBridgeSettings::noBridge, + unsigned short gi = 3, bool fp = false, bool ep = false) override { + return this->build(build_options{SC_VERSION_U64, mah, gi, cs, gbs, fp, ep}); + } + + bool build(const build_options &option) noexcept override; + void getConvertedImage(int *rows, int *cols, unsigned int *dest) const override { this->getConvertedImage(rows, cols, dest, true); @@ -276,10 +281,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { Eigen::ArrayXXi LowMap; std::unordered_map WaterList; */ - uint16_t maxAllowedHeight; - uint16_t bridgeInterval; - compressSettings compressMethod; - glassBridgeSettings glassMethod; + build_options build_opt; libSchem::Schem schem; std::optional cache_dir{""}; @@ -349,12 +351,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool check_cache_owned_hash(uint64_t task_hash) const noexcept; private: - struct build_options { - uint16_t maxAllowedHeight; - uint16_t bridgeInterval; - compressSettings compressMethod; - glassBridgeSettings glassMethod; - }; static uint64_t build_task_hash(const Eigen::ArrayXXi &mapPic, std::span blkid, const build_options &) noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index e2676024..c4c99074 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -186,9 +186,13 @@ std::vector TokiSlopeCraft::schem_block_id_list() return temp; } -bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, - glassBridgeSettings gBS, uint16_t bI, bool fireProof, - bool endermanProof) { +bool TokiSlopeCraft::build(const build_options &option) noexcept { + /* + bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, + glassBridgeSettings gBS, uint16_t bI, bool + fireProof, bool endermanProof){ + */ + if (kernelStep < SCL_step::converted) { reportError( wind, errorFlag::HASTY_MANIPULATION, @@ -196,7 +200,7 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, cerr << "hasty!" << endl; return false; } - if (mAH < 14) { + if (option.maxAllowedHeight < 14) { cerr << "maxAllowedHeight is less than 14!" << endl; reportError(wind, errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, "Your maximum allowed height is less than 14, which made lossy " @@ -215,15 +219,17 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, // cerr << "ready to build" << endl; - compressMethod = cS; - glassMethod = gBS; + this->build_opt.compressMethod = option.compressMethod; + this->build_opt.glassMethod = option.glassMethod; if (isFlat() || !isVanilla()) { - compressMethod = compressSettings::noCompress; - glassMethod = glassBridgeSettings::noBridge; + this->build_opt.compressMethod = compressSettings::noCompress; + this->build_opt.glassMethod = glassBridgeSettings::noBridge; } - maxAllowedHeight = mAH; - bridgeInterval = bI; + this->build_opt.maxAllowedHeight = option.maxAllowedHeight; + this->build_opt.bridgeInterval = option.bridgeInterval; + this->build_opt.fire_proof = option.fire_proof; + this->build_opt.enderman_proof = option.enderman_proof; reportWorkingStatue(wind, workStatues::buidingHeighMap); @@ -240,7 +246,8 @@ bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, reportWorkingStatue(wind, workStatues::building3D); // cerr << "start buildHeight" << endl; - buildHeight(fireProof, endermanProof, Base, HighMap, LowMap, WaterList); + buildHeight(this->build_opt.fire_proof, this->build_opt.enderman_proof, + Base, HighMap, LowMap, WaterList); // cerr << "buildHeight finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 8 * sizePic(2)); @@ -265,8 +272,9 @@ void TokiSlopeCraft::makeHeight_new( HighMap.setZero(sizePic(0) + 1, sizePic(1)); LowMap.setZero(sizePic(0) + 1, sizePic(1)); WaterList.clear(); - bool allowNaturalCompress = compressMethod == compressSettings::Both || - compressMethod == compressSettings::NaturalOnly; + bool allowNaturalCompress = + this->build_opt.compressMethod == compressSettings::Both || + this->build_opt.compressMethod == compressSettings::NaturalOnly; // std::vector src; // cerr << "makeHeight_new\n"; @@ -293,17 +301,17 @@ void TokiSlopeCraft::makeHeight_new( // getTokiColorPtr(c,&src[0]); HL.make(this->mapPic.col(c), allowNaturalCompress); - if (HL.maxHeight() > maxAllowedHeight && - (compressMethod == compressSettings::ForcedOnly || - compressMethod == compressSettings::Both)) { + if (HL.maxHeight() > this->build_opt.maxAllowedHeight && + (this->build_opt.compressMethod == compressSettings::ForcedOnly || + this->build_opt.compressMethod == compressSettings::Both)) { std::vector ptr(getImageRows()); this->image_cvter.col_TokiColor_ptrs(c, ptr.data()); // getTokiColorPtr(c, &ptr[0]); Compressor->setSource(HL.getBase(), &ptr[0]); - bool success = - Compressor->compress(maxAllowedHeight, allowNaturalCompress); + bool success = Compressor->compress(this->build_opt.maxAllowedHeight, + allowNaturalCompress); if (!success) { std::string msg = "Failed to compress the 3D structure at coloum " + std::to_string(c); @@ -416,7 +424,7 @@ schem.z_range()}); Build.resize(tempSize3D); void TokiSlopeCraft::makeBridge() { if (mapType != mapTypes::Slope) return; - if (glassMethod != glassBridgeSettings::withBridge) return; + if (this->build_opt.glassMethod != glassBridgeSettings::withBridge) return; int step = sizePic(2) / schem.y_range(); @@ -425,7 +433,7 @@ void TokiSlopeCraft::makeBridge() { for (uint32_t y = 0; y < schem.y_range(); y++) { keepAwake(wind); progressAdd(wind, step); - if (y % (bridgeInterval + 1) == 0) { + if (y % (this->build_opt.bridgeInterval + 1) == 0) { std::array start, extension; // x,z,y start[0] = 0; start[1] = 0; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 1892987d..6faf8ae2 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -222,6 +222,8 @@ uint64_t TokiSlopeCraft::build_task_hash(const Eigen::ArrayXXi &mapPic, hash.addData(&bo.bridgeInterval, sizeof(bo.bridgeInterval)); hash.addData(&bo.compressMethod, sizeof(bo.compressMethod)); hash.addData(&bo.glassMethod, sizeof(bo.glassMethod)); + hash.addData(&bo.fire_proof, sizeof(bo.fire_proof)); + hash.addData(&bo.enderman_proof, sizeof(bo.enderman_proof)); hash.finalize(); @@ -236,10 +238,7 @@ uint64_t TokiSlopeCraft::build_task_hash(const Eigen::ArrayXXi &mapPic, uint64_t TokiSlopeCraft::build_task_hash() const noexcept { assert(this->kernelStep >= SCL_step::builded); auto sbil = this->schem_block_id_list(); - return build_task_hash( - this->mapPic, sbil, - build_options{this->maxAllowedHeight, this->bridgeInterval, - this->compressMethod, this->glassMethod}); + return build_task_hash(this->mapPic, sbil, this->build_opt); } std::string TokiSlopeCraft::build_task_dir(std::string_view cvt_task_dir, From eb20b28f325fa087ae16aba6cc2e5f6496ced50d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 10 May 2023 18:40:34 +0800 Subject: [PATCH 0289/1123] build 3d and save cache --- SlopeCraft/PoolModel.cpp | 5 +- SlopeCraft/PoolModel.h | 15 ++++ SlopeCraft/SCWind.cpp | 169 ++++++++++++++++++++++++++++++++++++-- SlopeCraft/SCWind.h | 42 +++++++++- SlopeCraft/SCWind.ui | 140 +++++++++++++++---------------- SlopeCraftL/SlopeCraftL.h | 17 +++- 6 files changed, 304 insertions(+), 84 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 2ed0db71..75246851 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -162,9 +162,8 @@ QMimeData* CvtPoolModel::mimeData(const QModelIndexList& indexes) const { return ret; } -bool CvtPoolModel::canDropMimeData(const QMimeData* data, Qt::DropAction, - int row, int col, - const QModelIndex& parent) const { +bool CvtPoolModel::canDropMimeData(const QMimeData* data, Qt::DropAction, int, + int col, const QModelIndex& parent) const { if (parent.isValid()) { return false; } diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index 8794dc1f..400c922a 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -125,6 +125,21 @@ class ExportPoolModel : public PoolModel { return INT_MAX; } + cvt_task* export_idx_to_task_ptr(int eidx) const noexcept { + assert(eidx >= 0); + for (int fidx = 0; fidx < (int)this->pool->size(); fidx++) { + if (pool->at(fidx).is_converted) { + eidx--; + } + if (eidx < 0) { + return &this->pool->at(fidx); + } + } + + assert(false); + return nullptr; + } + QVariant data(const QModelIndex& idx, int role) const override; }; diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index bcf40862..de03ea24 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -53,6 +53,9 @@ SCWind::SCWind(QWidget *parent) this->export_pool_model = new ExportPoolModel{this, &this->tasks}; this->ui->lview_pool_export->setModel(this->export_pool_model); this->export_pool_model->set_listview(this->ui->lview_pool_export); + connect(this->ui->lview_pool_export->selectionModel(), + &QItemSelectionModel::selectionChanged, this, + &SCWind::when_export_pool_selectionChanged); connect(this, &SCWind::image_changed, this->cvt_pool_model, &CvtPoolModel::refresh); @@ -107,7 +110,7 @@ SCWind::SCWind(QWidget *parent) connect(this->ui->cb_algo_dither, &QCheckBox::clicked, this, &SCWind::when_algo_btn_clicked); } - + // setup presets { try { this->default_presets[0] = @@ -293,6 +296,26 @@ std::optional SCWind::selected_cvt_task_idx() const noexcept { return sel.front().row(); } +std::vector SCWind::selected_export_task_list() const noexcept { + auto selected_eidx = + this->ui->lview_pool_export->selectionModel()->selectedIndexes(); + std::vector ret; + ret.reserve(selected_eidx.size()); + for (auto &midx : selected_eidx) { + ret.emplace_back( + this->export_pool_model->export_idx_to_task_ptr(midx.row())); + } + return ret; +} +std::optional SCWind::selected_export_task() const noexcept { + auto selected = this->selected_export_task_list(); + if (selected.empty()) { + return std::nullopt; + } + + return selected.front(); +} + SCL_convertAlgo SCWind::selected_algo() const noexcept { if (this->ui->rb_algo_RGB->isChecked()) { return SCL_convertAlgo::RGB; @@ -321,6 +344,64 @@ bool SCWind::is_dither_selected() const noexcept { return this->ui->cb_algo_dither->isChecked(); } +bool SCWind::is_lossless_compression_selected() const noexcept { + return this->ui->cb_compress_lossless->isChecked(); +} +bool SCWind::is_lossy_compression_selected() const noexcept { + return this->ui->cb_compress_lossy->isChecked(); +} +int SCWind::current_max_height() const noexcept { + return this->ui->sb_max_height->value(); +} + +SCL_compressSettings SCWind::current_compress_method() const noexcept { + if (this->is_lossless_compression_selected()) { + if (this->is_lossy_compression_selected()) { + return SCL_compressSettings::Both; + } else { + return SCL_compressSettings::NaturalOnly; + } + } else { + if (this->is_lossless_compression_selected()) { + return SCL_compressSettings::ForcedOnly; + } else { + return SCL_compressSettings::noCompress; + } + } +} + +bool SCWind::is_glass_bridge_selected() const noexcept { + return this->ui->cb_glass_bridge->isChecked(); +} +int SCWind::current_glass_brigde_interval() const noexcept { + return this->ui->sb_glass_bridge_interval->value(); +} +SCL_glassBridgeSettings SCWind::current_glass_method() const noexcept { + if (this->is_glass_bridge_selected()) { + return SCL_glassBridgeSettings::withBridge; + } + return SCL_glassBridgeSettings::noBridge; +} + +bool SCWind::is_fire_proof_selected() const noexcept { + return this->ui->cb_fireproof->isChecked(); +} +bool SCWind::is_enderman_proof_selected() const noexcept { + return this->ui->cb_enderproof->isChecked(); +} + +SlopeCraft::Kernel::build_options SCWind::current_build_option() + const noexcept { + return SlopeCraft::Kernel::build_options{ + SC_VERSION_U64, + (uint16_t)this->current_max_height(), + (uint16_t)this->current_glass_brigde_interval(), + this->current_compress_method(), + this->current_glass_method(), + this->is_fire_proof_selected(), + this->is_enderman_proof_selected()}; +} + void SCWind::when_version_buttons_toggled() noexcept { this->ui->blm->when_version_updated(); this->when_blocklist_changed(); @@ -601,7 +682,7 @@ void SCWind::kernel_convert_image() noexcept { } } -void SCWind::kernel_make_cache() noexcept { +void SCWind::kernel_make_cvt_cache() noexcept { std::string err; err.resize(4096); SlopeCraft::StringDeliver sd{err.data(), err.size()}; @@ -630,7 +711,7 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { this->kernel_convert_image(); this->tasks[sel.value()].set_converted(); - this->kernel_make_cache(); + this->kernel_make_cvt_cache(); this->refresh_current_cvt_display(sel.value(), true); this->ui->tw_cvt_image->setCurrentIndex(1); @@ -647,7 +728,7 @@ void SCWind::on_pb_cvt_all_clicked() noexcept { this->kernel_set_image(idx); this->kernel_convert_image(); - this->kernel_make_cache(); + this->kernel_make_cvt_cache(); task.set_converted(); } emit this->image_changed(); @@ -818,7 +899,7 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { QMessageBox::StandardButton::Ignore}); if (ret == QMessageBox::StandardButton::Ok) { this->kernel_convert_image(); - this->kernel_make_cache(); + this->kernel_make_cvt_cache(); this->tasks[idx].set_converted(); have_image_cvted = true; } else { @@ -838,4 +919,82 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { .arg(filename)); return; } +} + +void SCWind::on_cb_compress_lossy_toggled(bool checked) noexcept { + this->ui->sb_max_height->setEnabled(checked); +} + +void SCWind::kernel_build_3d() noexcept { + if (!this->kernel->build(this->current_build_option())) { + QMessageBox::warning(this, tr("构建三维结构失败"), + tr("构建三维结构时,出现错误。可能是因为尝试跳步。")); + return; + } +} + +void SCWind::on_pb_build3d_clicked() noexcept { + auto taskopt = this->selected_export_task(); + if (!taskopt.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + assert(taskopt.value() != nullptr); + + cvt_task &task = *taskopt.value(); + + if (!task.is_converted) [[unlikely]] { + QMessageBox::warning(this, tr("该图像尚未被转化"), + tr("必须先转化一个图像,然后再为它构建三维结构")); + return; + } + + this->kernel_build_3d(); + this->kernel_make_build_cache(); + + task.set_built(); + this->refresh_current_build_display(&task, true); +} + +void SCWind::refresh_current_build_display( + std::optional taskp, bool is_image_built_in_kernel) noexcept { + this->ui->lb_show_3dsize->setText(tr("大小:")); + this->ui->lb_show_block_count->setText(tr("方块数量:")); + if (!taskp.has_value()) { + return; + } + + int x{-1}, y{-1}, z{-1}; + int64_t block_count{-1}; + if (is_image_built_in_kernel) { + this->kernel->get3DSize(&x, &y, &z); + block_count = this->kernel->getBlockCounts(); + } else { + if (taskp.value()->is_built) { +#warning load build cache here + } else { + return; + } + } + + this->ui->lb_show_3dsize->setText( + tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); + this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); +} + +void SCWind::when_export_pool_selectionChanged() noexcept { + this->refresh_current_build_display(this->selected_export_task()); +} + +void SCWind::kernel_make_build_cache() noexcept { + std::string err; + err.resize(4096); + SlopeCraft::StringDeliver sd{err.data(), err.size()}; + + if (!this->kernel->saveBuildCache(sd)) { + QString qerr = QString::fromUtf8(sd.data); + QMessageBox::warning(this, tr("缓存失败"), + tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); + } } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index b21868fc..59b8ee29 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -33,6 +33,7 @@ class SCWind : public QMainWindow { void on_pb_add_image_clicked() noexcept; void on_pb_remove_image_clicked() noexcept; void on_cb_lv_cvt_icon_mode_clicked() noexcept; + void on_cb_compress_lossy_toggled(bool checked) noexcept; void on_pb_load_preset_clicked() noexcept; void on_pb_save_preset_clicked() noexcept; @@ -44,6 +45,7 @@ class SCWind : public QMainWindow { void on_pb_prefer_logs_clicked() noexcept; void when_cvt_pool_selectionChanged() noexcept; + void when_export_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; void when_type_buttons_toggled() noexcept; void when_blocklist_changed() noexcept; @@ -55,6 +57,8 @@ class SCWind : public QMainWindow { void on_pb_cvt_all_clicked() noexcept; void on_pb_save_converted_clicked() noexcept; + void on_pb_build3d_clicked() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; @@ -88,9 +92,28 @@ class SCWind : public QMainWindow { std::vector selected_indices() const noexcept; std::optional selected_cvt_task_idx() const noexcept; + std::vector selected_export_task_list() const noexcept; + std::optional selected_export_task() const noexcept; + SCL_convertAlgo selected_algo() const noexcept; bool is_dither_selected() const noexcept; + bool is_lossless_compression_selected() const noexcept; + bool is_lossy_compression_selected() const noexcept; + int current_max_height() const noexcept; + SCL_compressSettings current_compress_method() const noexcept; + + bool is_glass_bridge_selected() const noexcept; + int current_glass_brigde_interval() const noexcept; + SCL_glassBridgeSettings current_glass_method() const noexcept; + + bool is_fire_proof_selected() const noexcept; + bool is_enderman_proof_selected() const noexcept; + + SlopeCraft::Kernel::build_options current_build_option() const noexcept; + + // kernel related functions + void kernel_set_type() noexcept; void update_button_states() noexcept; @@ -98,22 +121,33 @@ class SCWind : public QMainWindow { void kernel_set_image(int idx) noexcept; void kernel_convert_image() noexcept; - void kernel_make_cache() noexcept; + void kernel_make_cvt_cache() noexcept; bool kernel_check_colorset_hash() noexcept; + void kernel_build_3d() noexcept; + void kernel_make_build_cache() noexcept; + void refresh_current_cvt_display(std::optional idx, bool is_image_coneverted_in_kernel) noexcept; - QImage get_converted_image_from_kernel() const noexcept; - void refresh_current_cvt_display(std::optional idx) noexcept { this->refresh_current_cvt_display(idx, false); } - void refresh_current_cvt_display() noexcept { this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } + QImage get_converted_image_from_kernel() const noexcept; + + void refresh_current_build_display(std::optional taskp, + bool is_image_built_in_kernel) noexcept; + void refresh_current_build_display(std::optional taskp) noexcept { + return this->refresh_current_build_display(taskp, false); + } + void refresh_current_build_display() noexcept { + this->refresh_current_build_display(this->selected_export_task()); + } + void mark_all_task_unconverted() noexcept; void export_current_cvted_image(int idx, QString filename) noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 8201075f..17e8fa75 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 0 + 2 @@ -658,62 +658,7 @@ 导出 - - - - - 0 - - - - - Litematica - - - true - - - - - - - 结构方块文件 - - - - - - - WE原理图 - - - - - - - false - - - 平面示意图 - - - - - - - 地图文件 - - - - - - - - - 0 - - - + @@ -787,16 +732,61 @@ - - + + + + + + 0 + + + + + + + 0 + + + - Icon mode + Litematica true + + + + 结构方块文件 + + + + + + + WE原理图 + + + + + + + false + + + 平面示意图 + + + + + + + 地图文件 + + + @@ -918,13 +908,13 @@ - + 0 0 - 2 + 0 @@ -1008,7 +998,7 @@ - + 0 0 @@ -1025,7 +1015,7 @@ - + 0 0 @@ -1038,7 +1028,7 @@ - + 0 0 @@ -1058,7 +1048,7 @@ - + 0 0 @@ -1071,7 +1061,7 @@ - + 0 0 @@ -1084,7 +1074,7 @@ - + 0 0 @@ -1097,7 +1087,7 @@ - + 0 0 @@ -1214,6 +1204,12 @@ + + + 0 + 0 + + 大小: @@ -1221,6 +1217,12 @@ + + + 0 + 0 + + 方块数量: diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index d208c185..43d3b4e1 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -213,11 +213,11 @@ class Kernel { // can do in converted: /// construct 3D structure - virtual bool build( + [[deprecated]] virtual bool build( ::SCL_compressSettings = ::SCL_compressSettings::noCompress, - unsigned short = 256, + uint16_t maxAllowedHeight = 256, ::SCL_glassBridgeSettings = ::SCL_glassBridgeSettings::noBridge, - unsigned short = 3, bool fireProof = false, + uint16_t glassInterval = 3, bool fireProof = false, bool endermanProof = false) = 0; /// get converted image @@ -284,6 +284,17 @@ class Kernel { // requires step >= convertion ready virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; + struct build_options { + uint64_t version{SC_VERSION_U64}; + uint16_t maxAllowedHeight; + uint16_t bridgeInterval; + compressSettings compressMethod; + glassBridgeSettings glassMethod; + bool fire_proof; + bool enderman_proof; + }; + + virtual bool build(const build_options &option) noexcept = 0; // requires step >= built virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; }; From f7ad6a97c1aa2db281515d931275c248118bd421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 10 May 2023 19:23:20 +0800 Subject: [PATCH 0290/1123] load build cache for SCL --- SlopeCraftL/SlopeCraftL.h | 4 ++ SlopeCraftL/TokiSlopeCraft.h | 13 ++++++ SlopeCraftL/TokiSlopeCraft_build.cpp | 5 +-- SlopeCraftL/TokiSlopeCraft_cache.cpp | 60 +++++++++++++++++++++++++++- SlopeCraftL/simpleBlock.h | 11 +++++ 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 43d3b4e1..b60d38c0 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -122,6 +122,8 @@ class AbstractBlock { virtual void copyTo(AbstractBlock *b) const noexcept = 0; /// set this block to air virtual void clear() noexcept; + + virtual const char *idForVersion(SCL_gameVersion ver) const noexcept = 0; }; class BlockListInterface { @@ -297,6 +299,8 @@ class Kernel { virtual bool build(const build_options &option) noexcept = 0; // requires step >= built virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; + + virtual bool loadBuildCache(const build_options &option) noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index aff3f020..853430ed 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -335,6 +335,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { write(_err, err); return err.empty(); } + + bool loadBuildCache(const build_options &option) noexcept override; std::string make_build_cache() const noexcept; private: @@ -366,6 +368,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { struct build_cache_ir { Eigen::ArrayXXi mapPic; + build_options build_option; libSchem::Schem schem; }; @@ -378,5 +381,15 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override; }; +template +void serialize(SlopeCraft::Kernel::build_options &opt, archive &ar) noexcept { + ar(opt.maxAllowedHeight); + ar(opt.bridgeInterval); + ar(opt.compressMethod); + ar(opt.glassMethod); + ar(opt.fire_proof); + ar(opt.enderman_proof); +} + // bool compressFile(const char *sourcePath, const char *destPath); #endif // TOKISLOPECRAFT_H diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index c4c99074..f3e58738 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -174,9 +174,8 @@ std::vector TokiSlopeCraft::schem_block_id_list() temp.emplace_back("minecraft:air"); for (const auto &block : TokiSlopeCraft::blockPalette) { - std::string_view id_at_curversion = (this->mcVer == SCL_gameVersion::MC12) - ? (block.getIdOld()) - : (block.getId()); + std::string_view id_at_curversion = + block.idForVersion(TokiSlopeCraft::mcVer); if ("minecraft:air" == id_at_curversion) { break; } else { diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 6faf8ae2..d0ecb613 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -282,6 +282,7 @@ std::string TokiSlopeCraft::make_build_cache() const noexcept { { cereal::BinaryOutputArchive boa{ofs}; boa(this->mapPic); + boa(this->build_opt); boa(this->schem); } ofs.close(); @@ -293,5 +294,62 @@ std::string TokiSlopeCraft::make_build_cache() const noexcept { bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, uint64_t expected_task_hash, build_cache_ir *ir) noexcept { -#warning read and exmaine cache here. + build_cache_ir temp; + { + if (!stdfs::is_regular_file(filename)) { + return false; + } + std::ifstream ifs{filename.data(), std::ios::binary}; + cereal::BinaryInputArchive bia{ifs}; + try { + bia(temp.mapPic); + bia(temp.build_option); + bia(temp.schem); + } catch (std::exception &) { + return false; + } + } + { + std::vector blkids; + blkids.reserve(temp.schem.palette().size()); + for (const auto &bid : temp.schem.palette()) { + blkids.emplace_back(bid); + } + + const uint64_t hash = + TokiSlopeCraft::build_task_hash(temp.mapPic, blkids, temp.build_option); + + if (hash != expected_task_hash) { + return false; + } + } + + if (ir != nullptr) { + *ir = std::move(temp); + } + return true; } + +bool TokiSlopeCraft::loadBuildCache(const build_options &option) noexcept { + if (this->kernelStep < SCL_step::converted) { + reportError(wind, errorFlag::HASTY_MANIPULATION, + "You can load build cache only after you convert a image"); + return false; + } + const std::string cache_filename = + this->build_cache_filename(this->task_dir()); + auto sbil = this->schem_block_id_list(); + const uint64_t expected_hash = build_task_hash(this->mapPic, sbil, option); + + build_cache_ir ir; + if (!this->exmaine_build_cache(cache_filename, expected_hash, &ir)) { + return false; + } + + this->mapPic = std::move(ir.mapPic); + this->build_opt = option; + this->schem = std::move(ir.schem); + + this->kernelStep = SCL_step::builded; + return true; +} \ No newline at end of file diff --git a/SlopeCraftL/simpleBlock.h b/SlopeCraftL/simpleBlock.h index 8d4e104f..4403b2f7 100644 --- a/SlopeCraftL/simpleBlock.h +++ b/SlopeCraftL/simpleBlock.h @@ -114,6 +114,17 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { static bool dealBlockId(const std::string &id, std::string &netBlockId, stringList *proName, stringList *proVal); + + const char *idForVersion(SCL_gameVersion ver) const noexcept override { + if (ver >= SCL_gameVersion::MC13) { + return this->getId(); + } + + if (this->idOld.empty()) { + return this->getId(); + } + return this->getIdOld(); + }; // simpleBlock& operator =(const simpleBlock &); }; From 65d4ae7a3b78fbe663b18a2e9f563648020e2321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 11:18:43 +0800 Subject: [PATCH 0291/1123] load cache successfully --- SlopeCraft/SCWind.cpp | 20 +++++++++++++------- SlopeCraft/SCWind.h | 1 - SlopeCraftL/TokiSlopeCraft.h | 11 +---------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 19 +++++++++++++++++-- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index de03ea24..46fddc2d 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -967,16 +967,22 @@ void SCWind::refresh_current_build_display( int x{-1}, y{-1}, z{-1}; int64_t block_count{-1}; - if (is_image_built_in_kernel) { - this->kernel->get3DSize(&x, &y, &z); - block_count = this->kernel->getBlockCounts(); - } else { - if (taskp.value()->is_built) { -#warning load build cache here + { + if (is_image_built_in_kernel) { + // the caller garentee that the image is built in kernel } else { - return; + if (taskp.value()->is_built) { + // try to load cache + if (!this->kernel->loadBuildCache(this->current_build_option())) { + return; + } + } else { + return; + } } } + this->kernel->get3DSize(&x, &y, &z); + block_count = this->kernel->getBlockCounts(); this->ui->lb_show_3dsize->setText( tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 59b8ee29..8de34d17 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -113,7 +113,6 @@ class SCWind : public QMainWindow { SlopeCraft::Kernel::build_options current_build_option() const noexcept; // kernel related functions - void kernel_set_type() noexcept; void update_button_states() noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 853430ed..0c55d439 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -281,6 +281,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { Eigen::ArrayXXi LowMap; std::unordered_map WaterList; */ + build_options build_opt; libSchem::Schem schem; @@ -381,15 +382,5 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override; }; -template -void serialize(SlopeCraft::Kernel::build_options &opt, archive &ar) noexcept { - ar(opt.maxAllowedHeight); - ar(opt.bridgeInterval); - ar(opt.compressMethod); - ar(opt.glassMethod); - ar(opt.fire_proof); - ar(opt.enderman_proof); -} - // bool compressFile(const char *sourcePath, const char *destPath); #endif // TOKISLOPECRAFT_H diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index d0ecb613..4636e246 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -254,6 +254,21 @@ std::string TokiSlopeCraft::build_cache_filename( std::string_view build_task_dir) noexcept { return fmt::format("{}/build", build_task_dir); } +namespace cereal { +template +void save(archive &ar, const SlopeCraft::Kernel::build_options &opt) noexcept { + ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, + opt.glassMethod); + ar(opt.fire_proof, opt.enderman_proof); +} + +template +void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { + ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, + opt.glassMethod); + ar(opt.fire_proof, opt.enderman_proof); +} +} // namespace cereal std::string TokiSlopeCraft::make_build_cache() const noexcept { if (this->kernelStep < SlopeCraft::step::builded) { @@ -336,10 +351,10 @@ bool TokiSlopeCraft::loadBuildCache(const build_options &option) noexcept { "You can load build cache only after you convert a image"); return false; } - const std::string cache_filename = - this->build_cache_filename(this->task_dir()); auto sbil = this->schem_block_id_list(); const uint64_t expected_hash = build_task_hash(this->mapPic, sbil, option); + const std::string cache_filename = this->build_cache_filename( + this->build_task_dir(this->task_dir(), expected_hash)); build_cache_ir ir; if (!this->exmaine_build_cache(cache_filename, expected_hash, &ir)) { From e0a5811db225e4f8fd8f1f4f2731de0267907d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 11:30:19 +0800 Subject: [PATCH 0292/1123] use gz compressed build cache to reduce size --- SlopeCraftL/CMakeLists.txt | 5 ++++- SlopeCraftL/TokiSlopeCraft_cache.cpp | 11 +++++++---- cmake/configure_zstr.cmake | 10 ++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 cmake/configure_zstr.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 9b6fb4a5..f72d9299 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -3,11 +3,13 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_zstr.cmake) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) +find_package(zstr) set(SlopeCraft_SCL_windows_rc_files) @@ -82,7 +84,8 @@ set(SlopeCraft_SCL_link_libs Schem MapImageCvter fmt::fmt - Eigen3::Eigen) + Eigen3::Eigen + zstr::zstr) # link to dependents target_link_libraries(SlopeCraftL PUBLIC ${SlopeCraft_SCL_link_libs}) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 4636e246..651f710f 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -7,6 +7,8 @@ #include #include +#include + namespace stdfs = std::filesystem; std::string write_hash(std::string_view filename, const std::vector &hash) noexcept { @@ -252,7 +254,7 @@ std::string TokiSlopeCraft::build_task_dir() const noexcept { std::string TokiSlopeCraft::build_cache_filename( std::string_view build_task_dir) noexcept { - return fmt::format("{}/build", build_task_dir); + return fmt::format("{}/build.gz", build_task_dir); } namespace cereal { template @@ -287,8 +289,8 @@ std::string TokiSlopeCraft::make_build_cache() const noexcept { } const std::string build_cache_file = build_cache_filename(build_cache_dir); { - std::ofstream ofs{build_cache_file, std::ios::binary}; - + // std::ofstream ofs{build_cache_file, std::ios::binary}; + zstr::ofstream ofs{build_cache_file, std::ios::binary, Z_BEST_COMPRESSION}; if (!ofs) { return fmt::format("ofstream failed to open cache file {}", build_cache_file); @@ -314,7 +316,8 @@ bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, if (!stdfs::is_regular_file(filename)) { return false; } - std::ifstream ifs{filename.data(), std::ios::binary}; + // std::ifstream ifs{filename.data(), std::ios::binary}; + zstr::ifstream ifs{filename.data(), std::ios::binary}; cereal::BinaryInputArchive bia{ifs}; try { bia(temp.mapPic); diff --git a/cmake/configure_zstr.cmake b/cmake/configure_zstr.cmake new file mode 100644 index 00000000..2eae3697 --- /dev/null +++ b/cmake/configure_zstr.cmake @@ -0,0 +1,10 @@ +# https://github.com/mateidavid/zstr + +include(FetchContent) + +FetchContent_Declare(zstr + GIT_REPOSITORY + https://github.com/mateidavid/zstr.git GIT_TAG v1.0.7 + OVERRIDE_FIND_PACKAGE) + +FetchContent_MakeAvailable(zstr) \ No newline at end of file From 980309df905a1b75d3c022d956eb5abc918476f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 13:36:50 +0800 Subject: [PATCH 0293/1123] add PrewiewWind --- SlopeCraft/CMakeLists.txt | 7 +- SlopeCraft/PreviewWind.cpp | 9 ++ SlopeCraft/PreviewWind.h | 25 ++++++ SlopeCraft/PreviewWind.ui | 161 ++++++++++++++++++++++++++++++++++ SlopeCraft/SCWind.cpp | 53 ++++++++++- SlopeCraft/SCWind.h | 1 + SlopeCraft/SCWind.ui | 4 +- SlopeCraftL/SlopeCraftL.h | 5 +- SlopeCraftL/TokiSlopeCraft.h | 3 +- SlopeCraftMain/previewwind.ui | 6 +- 10 files changed, 261 insertions(+), 13 deletions(-) create mode 100644 SlopeCraft/PreviewWind.cpp create mode 100644 SlopeCraft/PreviewWind.h create mode 100644 SlopeCraft/PreviewWind.ui diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 68df2dfa..b960fb46 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -20,18 +20,21 @@ set(SlopeCraft_headers SCWind.h cvt_task.h PoolModel.h - AdaptiveListView.h) + AdaptiveListView.h + PreviewWind.h) set(SlopeCraft_sources SCWind.cpp cvt_task.cpp PoolModel.cpp AdaptiveListView.cpp + PreviewWind.cpp main.cpp ${SlopeCraft_rc_files}) set(SlopeCraft_uis - SCWind.ui) + SCWind.ui + PreviewWind.ui) set(SlopeCraft_project_files ${SlopeCraft_headers} diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp new file mode 100644 index 00000000..dedcb0fe --- /dev/null +++ b/SlopeCraft/PreviewWind.cpp @@ -0,0 +1,9 @@ +#include "PreviewWind.h" +#include "ui_PreviewWind.h" + +PreviewWind::PreviewWind(const SlopeCraft::Kernel* kernel, QWidget* parent) + : QDialog(parent), ui(new Ui::PreviewWind) { + this->ui->setupUi(this); +} + +PreviewWind::~PreviewWind() { delete this->ui; } \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h new file mode 100644 index 00000000..e92cc622 --- /dev/null +++ b/SlopeCraft/PreviewWind.h @@ -0,0 +1,25 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_PREVIEWWIND_H +#define SLOPECRAFT_SLOPECRAFT_PREVIEWWIND_H + +#include +#include +class PreviewWind; + +namespace Ui { +class PreviewWind; +} + +class PreviewWind : public QDialog { + Q_OBJECT + private: + Ui::PreviewWind* ui; + + void setup_widget(const SlopeCraft::Kernel* kernel) noexcept; + + public: + explicit PreviewWind(const SlopeCraft::Kernel* kernel, + QWidget* parent = nullptr); + ~PreviewWind(); +}; + +#endif // SLOPECRAFT_SLOPECRAFT_PREVIEWWIND_H \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui new file mode 100644 index 00000000..185c7b93 --- /dev/null +++ b/SlopeCraft/PreviewWind.ui @@ -0,0 +1,161 @@ + + + PreviewWind + + + + 0 + 0 + 604 + 444 + + + + 查看材料列表 + + + + + + + + + QFrame::StyledPanel + + + + + + + + + + + 0 + 0 + + + + 投影尺寸 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + 总体积 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 24 + + + + 总方块数 + + + Qt::AlignCenter + + + + + + + + + + QFrame::StyledPanel + + + + + + + + + + + 0 + 0 + + + + 切换单位 + + + + + + + + 0 + 24 + + + + + + + QFrame::StyledPanel + + + + + + + + + + false + + + false + + + true + + + + 方块 + + + + + id + + + + + 数量 + + + + + + + + + diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 46fddc2d..77eb3243 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -972,7 +972,12 @@ void SCWind::refresh_current_build_display( // the caller garentee that the image is built in kernel } else { if (taskp.value()->is_built) { - // try to load cache + // try to load convert cache + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + return; + } + // try to load build cache if (!this->kernel->loadBuildCache(this->current_build_option())) { return; } @@ -1003,4 +1008,50 @@ void SCWind::kernel_make_build_cache() noexcept { QMessageBox::warning(this, tr("缓存失败"), tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); } +} + +void SCWind::on_pb_preview_materials_clicked() noexcept { + auto taskopt = this->selected_export_task(); + if (!taskopt.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + assert(taskopt.value() != nullptr); + + cvt_task &task = *taskopt.value(); + if (!task.is_converted) [[unlikely]] { + QMessageBox::warning(this, tr("该图像尚未被转化"), + tr("必须先转化一个图像,然后再为它构建三维结构")); + return; + } + QString errtitle; + QString errmsg; + // try to load cache + [this, &errtitle, &errmsg]() { + if (this->kernel->queryStep() >= SCL_step::builded) { + return; + } + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + errtitle = tr("该图像尚未被转化"); + errmsg = + tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" + "新转化该图像。"); + return; + } + if (!this->kernel->loadBuildCache(this->current_build_option())) { + errtitle = tr("尚未构建三维结构"); + errmsg = tr( + "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" + "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + } + }(); + + if (!errtitle.isEmpty()) { + QMessageBox::warning(this, errtitle, errmsg); + return; + } + +#warning show mat list here } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 8de34d17..8710f168 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -58,6 +58,7 @@ class SCWind : public QMainWindow { void on_pb_save_converted_clicked() noexcept; void on_pb_build3d_clicked() noexcept; + void on_pb_preview_materials_clicked() noexcept; private: Ui::SCWind* ui; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 17e8fa75..622aed7a 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 2 + 0 @@ -658,7 +658,7 @@ 导出 - + diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index b60d38c0..507c4a98 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -261,9 +261,8 @@ class Kernel { /// get sum block count virtual int64_t getBlockCounts() const = 0; /// get 3d structure in 3d-matrix (col major) - virtual const unsigned short *getBuild(int *xSize = nullptr, - int *ySize = nullptr, - int *zSize = nullptr) const = 0; + virtual const uint16_t *getBuild(int *xSize = nullptr, int *ySize = nullptr, + int *zSize = nullptr) const = 0; // Virtual functions added after v5.0.0. Define them in the end of vtable to // matain binary compability diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 0c55d439..22c59175 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -232,8 +232,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { int64_t getBlockCounts(std::vector *) const; int64_t getBlockCounts() const override; - const unsigned short *getBuild(int *xSize, int *ySize, - int *zSize) const override; + const uint16_t *getBuild(int *xSize, int *ySize, int *zSize) const override; // const Eigen::Tensor &getBuild() const; diff --git a/SlopeCraftMain/previewwind.ui b/SlopeCraftMain/previewwind.ui index a5a2d24a..11f258a4 100644 --- a/SlopeCraftMain/previewwind.ui +++ b/SlopeCraftMain/previewwind.ui @@ -48,7 +48,7 @@ - 1 + 0 @@ -119,8 +119,8 @@ 0 0 - 568 - 335 + 566 + 329 From 125509752e0e551bdf10e11a244958e6c5362067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 13:44:53 +0800 Subject: [PATCH 0294/1123] get schem palette from kernel --- SlopeCraftL/SlopeCraftL.h | 8 ++++++++ SlopeCraftL/TokiSlopeCraft.h | 3 +++ SlopeCraftL/TokiSlopeCraft_build.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 507c4a98..3f783c4e 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -293,13 +293,21 @@ class Kernel { glassBridgeSettings glassMethod; bool fire_proof; bool enderman_proof; + + // added + // bool connect_mushrooms; }; virtual bool build(const build_options &option) noexcept = 0; // requires step >= built virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; + // requires step >= converted virtual bool loadBuildCache(const build_options &option) noexcept = 0; + + // requires step >= built + virtual int getSchemPalette(const char **dest_id, + size_t dest_capacity) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 22c59175..c7c75f69 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -379,6 +379,9 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { public: bool checkColorsetHash() const noexcept override; bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override; + + int getSchemPalette(const char **dest_id, + size_t dest_capacity) const noexcept override; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index f3e58738..95a81cbb 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -586,3 +586,29 @@ std::string TokiSlopeCraft::exportAsWESchem( return ""; } + +int TokiSlopeCraft::getSchemPalette(const char **dest_id, + size_t dest_capacity) const noexcept { + if (kernelStep < SCL_step::builded) { + reportError(wind, errorFlag::HASTY_MANIPULATION, + "You can only export a map to structure after you build the 3D " + "structure."); + return -1; + } + + const int ret = this->schem.palette_size(); + + if (dest_id == nullptr || dest_capacity <= 0) { + return ret; + } + + size_t write_counter = 0; + for (const auto &id : this->schem.palette()) { + if (write_counter < dest_capacity) { + dest_id[write_counter] = id.c_str(); + write_counter++; + } + } + + return ret; +} \ No newline at end of file From 3b353a112d58f5cf3469a3443a55ed9292cc60a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 21:03:06 +0800 Subject: [PATCH 0295/1123] process mushroom --- utilities/Schem/CMakeLists.txt | 14 +- utilities/Schem/Schem.h | 2 + utilities/Schem/mushroom.cpp | 254 +++++++++++++++++++++++++++++++++ utilities/Schem/mushroom.h | 101 +++++++++++++ 4 files changed, 368 insertions(+), 3 deletions(-) create mode 100644 utilities/Schem/mushroom.cpp create mode 100644 utilities/Schem/mushroom.h diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index e955cc51..19b472db 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -4,19 +4,27 @@ project(Schem VERSION ${SlopeCraft_version} LANGUAGES CXX) add_library(Schem Schem.h - Schem.cpp bit_shrink.h - bit_shrink.cpp) + bit_shrink.cpp + mushroom.h + mushroom.cpp) find_package(Eigen3 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) find_package(cereal REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_magic_enum.cmake) +find_package(magic_enum REQUIRED) # target_compile_options(Schem BEFORE PUBLIC -std=c++17) -target_link_libraries(Schem PUBLIC NBTWriter Eigen3::Eigen cereal::cereal fmt::fmt) +target_link_libraries(Schem PUBLIC + NBTWriter + Eigen3::Eigen + cereal::cereal + fmt::fmt + magic_enum::magic_enum) target_compile_features(Schem PUBLIC cxx_std_20) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index ad5fd20e..ef3713eb 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -217,6 +217,8 @@ class Schem { void process_mushroom_states() noexcept; + void process_mushroom_states_fast() noexcept; + public: bool export_litematic(std::string_view filename, const litematic_info &info = litematic_info(), diff --git a/utilities/Schem/mushroom.cpp b/utilities/Schem/mushroom.cpp new file mode 100644 index 00000000..652491e6 --- /dev/null +++ b/utilities/Schem/mushroom.cpp @@ -0,0 +1,254 @@ +#include "mushroom.h" +#include +#include +#include +#include +namespace lsi = libSchem::internal; + +#include "Schem.h" + +std::optional lsi::pureid_to_type( + std::string_view pid) noexcept { + if (pid == "brown_mushroom_block") { + return mushroom_type::brown; + } + if (pid == "red_mushroom_block") { + return mushroom_type::red; + } + if (pid == "mushroom_stem") { + return mushroom_type::stem; + } + return std::nullopt; +} + +bool lsi::is_mushroom(std::string_view blkid) noexcept { + blkid::char_range pure_name; + if (!blkid::process_blk_id(blkid, nullptr, &pure_name, nullptr)) { + // invalid block id + return false; + } + + return pureid_to_type({pure_name.begin(), pure_name.end()}).has_value(); +} + +lsi::mushroom_state::mushroom_state(std::array _stoma) + : m_is_stoma{_stoma} {} + +std::string lsi::mushroom_state::to_block_state_list() const noexcept { + return fmt::format("up={},down={},north={},south={},east={},west={}", + m_is_stoma[0], m_is_stoma[1], m_is_stoma[2], m_is_stoma[3], + m_is_stoma[4], m_is_stoma[5]); +} + +uint8_t lsi::mushroom_state::to_compressed_bits() const noexcept { + uint8_t ret{0}; + for (bool val : this->m_is_stoma) { + ret |= uint8_t(val); + ret = ret << 1; + } + + return ret; +} + +std::optional private_fun_bsl_to_mushroom_state( + const std::vector> + &bs) noexcept { + using namespace lsi; + std::array stoma; + stoma.fill(0); + std::array set_times; + set_times.fill(0); + + for (const auto &pair : bs) { + std::string_view key_str{pair.first.begin(), pair.first.end()}; + auto key = magic_enum::enum_cast(key_str); + if (!key.has_value()) { + // invalid key + return std::nullopt; + } + + const auto dir = key.value(); + std::string_view value_str{pair.second.begin(), pair.second.end()}; + + bool val; + bool is_val_ok{false}; + if (value_str == "true") { + val = true; + is_val_ok = true; + } + if (value_str == "false") { + val = false; + is_val_ok = true; + } + + if (!is_val_ok) { + return std::nullopt; + } + + stoma[size_t(dir)] = val; + set_times[size_t(dir)]++; + } + + for (auto times : set_times) { + if (times > 1) { + return std::nullopt; + } + } + + return mushroom_state{stoma}; +} + +std::optional lsi::mushroom_state::from_block_state_list( + std::string_view bsl) noexcept { + using namespace blkid; + std::vector> bs; + + if (!blkid::process_state_list({&*bsl.begin(), &*bsl.end()}, &bs, nullptr)) { + // invalid blockstatelist + return std::nullopt; + } + + return private_fun_bsl_to_mushroom_state(bs); +} + +std::string_view lsi::mushroom_block::pureid() const noexcept { + switch (this->m_type) { + case mushroom_type::brown: + return "brown_mushroom_block"; + case mushroom_type::red: + return "red_mushroom_block"; + case mushroom_type::stem: + return "mushroom_stem"; + } + + return "Invalid enum value"; +} + +std::string lsi::mushroom_block::id(bool with_namespacename) const noexcept { + std::string_view nsn = (with_namespacename ? "minecraft::" : ""); + return fmt::format("{}{}[{}]", nsn, this->pureid(), + m_state.to_block_state_list()); +} + +std::optional lsi::mushroom_block::from_block_id( + std::string_view blikd) noexcept { + using namespace blkid; + + char_range pure_id; + std::vector> bs; + if (!process_blk_id(blikd, nullptr, &pure_id, &bs)) { + return std::nullopt; + } + + auto type = pureid_to_type({pure_id.begin(), pure_id.end()}); + if (!type.has_value()) { + return std::nullopt; + } + + auto state = private_fun_bsl_to_mushroom_state(bs); + if (!state.has_value()) { + return std::nullopt; + } + + mushroom_block ret; + ret.m_state = state.value(); + ret.m_type = type.value(); + return ret; +} + +struct mushroom_map { + using ele_t = libSchem::Schem::ele_t; + std::unordered_map + blk_to_ele; + std::unordered_map ele_to_blk; + std::vector *palette{nullptr}; + + inline bool is_mushroom(ele_t e) const noexcept { + return this->ele_to_blk.contains(e); + } + + inline ele_t operator[](libSchem::internal::mushroom_block mb) noexcept { + auto it = this->blk_to_ele.find(mb); + if (it != this->blk_to_ele.end()) { + return it->second; + } + const ele_t new_idx = this->palette->size(); + this->palette->emplace_back(mb.id(true)); + + this->blk_to_ele.emplace(mb, new_idx); + this->ele_to_blk.emplace(new_idx, mb); + return new_idx; + } + + inline libSchem::internal::mushroom_block at(ele_t idx) const noexcept { + assert(this->is_mushroom(idx)); + return this->ele_to_blk.at(idx); + } + + inline void emplace(ele_t ele, + libSchem::internal::mushroom_block blk) noexcept { + this->blk_to_ele.emplace(blk, ele); + this->ele_to_blk.emplace(ele, blk); + } +}; + +void libSchem::Schem::process_mushroom_states_fast() noexcept { + using libSchem::internal::direction; + using libSchem::internal::mushroom_block; + mushroom_map mmap; + mmap.blk_to_ele.reserve(64 * 3); + mmap.ele_to_blk.reserve(64 * 3); + mmap.palette = &this->block_id_list; + + for (ele_t i = 0; i < this->block_id_list.size(); i++) { + const auto &id = this->block_id_list[i]; + + auto mb = mushroom_block::from_block_id(id); + if (!mb.has_value()) { + continue; + } + + mmap.ele_to_blk.emplace(i, mb.value()); + mmap.blk_to_ele.emplace(mb.value(), i); + } + + auto &self = *this; + + for (int64_t y = 0; y < this->y_range(); y++) { + for (int64_t z = 0; z < this->z_range(); z++) { + for (int64_t x = 0; x < this->x_range(); x++) { + // skip if not a mushroom + if (!mmap.is_mushroom(self(x, y, z))) { + continue; + } + + mushroom_block cur_blk = mmap.at(self(x, y, z)); + + if ((x > 0) && mmap.is_mushroom(self(x - 1, y, z))) { + cur_blk.state().set_stoma(direction::west, true); + } + if ((x < this->x_range() - 1) && mmap.is_mushroom(self(x + 1, y, z))) { + cur_blk.state().set_stoma(direction::east, true); + } + + if ((y > 0) && mmap.is_mushroom(self(x, y - 1, z))) { + cur_blk.state().set_stoma(direction::down, true); + } + if ((y < this->y_range() - 1) && mmap.is_mushroom(self(x, y + 1, z))) { + cur_blk.state().set_stoma(direction::up, true); + } + + if ((z > 0) && mmap.is_mushroom(self(x, y, z - 1))) { + cur_blk.state().set_stoma(direction::north, true); + } + if ((z < this->z_range() - 1) && mmap.is_mushroom(self(x, y, z + 1))) { + cur_blk.state().set_stoma(direction::south, true); + } + + // this step append a new block id when necessary, it's not read only + self(x, y, z) = mmap[cur_blk]; + } + } + } +} \ No newline at end of file diff --git a/utilities/Schem/mushroom.h b/utilities/Schem/mushroom.h new file mode 100644 index 00000000..872daeec --- /dev/null +++ b/utilities/Schem/mushroom.h @@ -0,0 +1,101 @@ +#ifndef SLOPECRAFT_UTILITIES_SCHEM_MUSHROOM_H +#define SLOPECRAFT_UTILITIES_SCHEM_MUSHROOM_H +#include +#include +#include +#include +#include +#include + +namespace libSchem { +namespace internal { + +enum class mushroom_type : uint8_t { red, brown, stem }; +enum class direction : uint8_t { up, down, north, south, east, west }; + +bool is_mushroom(std::string_view blkid) noexcept; + +std::optional pureid_to_type(std::string_view pid) noexcept; + +class mushroom_state { + private: + std::array m_is_stoma{false, false, false, false, false}; + + public: + mushroom_state() = default; + mushroom_state(std::array _stoma); + inline bool is_stoma(direction dir) const noexcept { + assert(size_t(dir) < 6); + return this->m_is_stoma[size_t(dir)]; + } + + inline void set_stoma(direction dir, bool set_to_stoma) noexcept { + assert(size_t(dir) < 6); + this->m_is_stoma[size_t(dir)] = set_to_stoma; + } + + std::string to_block_state_list() const noexcept; + + static std::optional from_block_state_list( + std::string_view bsl) noexcept; + + uint8_t to_compressed_bits() const noexcept; + + inline bool operator==(const mushroom_state another) const noexcept { + return this->to_compressed_bits() == another.to_compressed_bits(); + } +}; + +struct mushroom_state_hash { + inline uint64_t operator()(mushroom_state ms) const noexcept { + return std::hash()(ms.to_compressed_bits()); + } +}; + +class mushroom_block { + private: + // std::string m_pureid{""}; + mushroom_state m_state; + mushroom_type m_type; + + public: + inline mushroom_state& state() noexcept { return this->m_state; } + inline mushroom_state state() const noexcept { return this->m_state; } + inline void set_state(mushroom_state ms) noexcept { this->m_state = ms; } + + std::string_view pureid() const noexcept; + + /* +inline void set_pureid(std::string_view pid) noexcept { + this->m_pureid = pid; +} +*/ + + inline mushroom_type type() const noexcept { return this->m_type; } + + inline void set_type(mushroom_type mt) noexcept { this->m_type = mt; } + + std::string id(bool with_namespacename = true) const noexcept; + + static std::optional from_block_id( + std::string_view blikd) noexcept; + + inline bool operator==(const mushroom_block another) const noexcept { + return (this->m_state == another.m_state) && + (this->m_type == another.m_type); + } +}; + +struct mushroom_block_hash { + inline uint64_t operator()(mushroom_block mb) const noexcept { + const uint16_t upper = uint8_t(mb.type()); + const uint16_t lower = mb.state().to_compressed_bits(); + + return std::hash()((upper << 8) | lower); + } +}; + +} // namespace internal +} // namespace libSchem + +#endif // SLOPECRAFT_UTILITIES_SCHEM_MUSHROOM_H \ No newline at end of file From 316a827362fd1403951cdb5dc040ef959c3ec980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 21:19:14 +0800 Subject: [PATCH 0296/1123] Add new api for 3 exports --- SlopeCraftL/SlopeCraftL.h | 63 ++++++++++++++++++++-------- SlopeCraftL/TokiSlopeCraft.h | 50 ++++++++++++++++++---- SlopeCraftL/TokiSlopeCraft_build.cpp | 36 ++++++++-------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 5 ++- 4 files changed, 110 insertions(+), 44 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 3f783c4e..73313612 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -233,14 +233,15 @@ class Kernel { // can do in builded: /// export map into litematica files (*.litematic) - virtual void exportAsLitematic(const char *localEncoding_TargetName, - const char *utf8_LiteName, - const char *utf8_RegionName, - char *localEncoding_returnVal) const = 0; + [[deprecated]] virtual void exportAsLitematic( + const char *localEncoding_TargetName, const char *utf8_LiteName, + const char *utf8_RegionName, char *localEncoding_returnVal) const = 0; + /// export map into Structure files (*.NBT) - virtual void exportAsStructure(const char *localEncoding_TargetName, - char *localEncoding_FileName) const = 0; - virtual void exportAsWESchem( + [[deprecated]] virtual void exportAsStructure( + const char *localEncoding_TargetName, + char *localEncoding_FileName) const = 0; + [[deprecated]] virtual void exportAsWESchem( const char *localEncoding_fileName, const int (&offset)[3] = {0, 0, 0}, const int (&weOffset)[3] = {0, 0, 0}, const char *utf8_Name = "", const char *const *const utf8_requiredMods = nullptr, @@ -267,7 +268,7 @@ class Kernel { // Virtual functions added after v5.0.0. Define them in the end of vtable to // matain binary compability - // added in v5.1.0 -------------------------------------------------- + // introduced in v5.1.0 ----------------------------------------------------- // replacement for setRawImage(const uint32_t*,int,int) virtual void setRawImage(const uint32_t *src, int rows, int cols, bool is_col_major) = 0; @@ -287,15 +288,15 @@ class Kernel { struct build_options { uint64_t version{SC_VERSION_U64}; - uint16_t maxAllowedHeight; - uint16_t bridgeInterval; - compressSettings compressMethod; - glassBridgeSettings glassMethod; - bool fire_proof; - bool enderman_proof; - - // added - // bool connect_mushrooms; + uint16_t maxAllowedHeight{256}; + uint16_t bridgeInterval{3}; + compressSettings compressMethod{::SCL_compressSettings::noCompress}; + glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; + bool fire_proof{false}; + bool enderman_proof{false}; + + // added in v5.1.0 + bool connect_mushrooms{false}; }; virtual bool build(const build_options &option) noexcept = 0; @@ -308,6 +309,34 @@ class Kernel { // requires step >= built virtual int getSchemPalette(const char **dest_id, size_t dest_capacity) const noexcept = 0; + + struct litematic_options { + uint64_t version{SC_VERSION_U64}; + const char *litename_utf8 = "by SlopeCraft"; + const char *region_name_utf8 = "by SlopeCraft"; + }; + virtual bool exportAsLitematic( + const char *filename_local, + const litematic_options &option) const noexcept = 0; + + struct vanilla_structure_options { + uint64_t version{SC_VERSION_U64}; + bool is_air_structure_void{true}; + }; + virtual bool exportStructure( + const char *filename_local, + const vanilla_structure_options &option) const noexcept = 0; + + struct WE_schem_options { + uint64_t version{SC_VERSION_U64}; + int offset[3] = {0, 0, 0}; + int we_offset[3] = {0, 0, 0}; + const char *const *required_mods_name_utf8{nullptr}; + int num_required_mods{0}; + }; + virtual bool exportAsWESchem( + const char *filename_local, + const WE_schem_options &option) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index c7c75f69..2b3df2f0 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -204,13 +204,14 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // can do in builded: void exportAsLitematic(const char *TargetName, const char *LiteName, const char *RegionName, char *FileName) const override; - std::string exportAsLitematic(const std::string &TargetName, // Local - const std::string &LiteName, // Utf8 - const std::string &RegionName // Utf8 + std::string exportAsLitematic(std::string_view TargetName, // Local + std::string_view LiteName, // Utf8 + std::string_view RegionName // Utf8 ) const; void exportAsStructure(const char *TargetName, char *FileName) const override; - std::string exportAsStructure(const std::string &) const; + std::string exportAsStructure(std::string_view filename, + bool is_air_structure_void) const; void exportAsWESchem(const char *fileName, const int (&offset)[3], const int (&weOffset)[3], const char *Name, @@ -218,10 +219,11 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { const int requiredModsCount, char *returnVal) const override; - std::string exportAsWESchem( - const std::string &, const std::array &offset, - const std::array &weOffset, const char *Name, - const std::vector &requiredMods) const; + std::string exportAsWESchem(std::string_view filename, + std::span offset, + std::span weOffset, + std::string_view Name, + std::span requiredMods) const; void get3DSize(int *x, int *y, int *z) const override; int getHeight() const override; @@ -382,6 +384,38 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { int getSchemPalette(const char **dest_id, size_t dest_capacity) const noexcept override; + + bool exportAsLitematic( + const char *filename_local, + const litematic_options &option) const noexcept override { + auto err = this->exportAsLitematic(filename_local, option.litename_utf8, + option.region_name_utf8); + return err.empty(); + } + + bool exportStructure( + const char *filename_local, + const vanilla_structure_options &option) const noexcept override { + auto err = + this->exportAsStructure(filename_local, option.is_air_structure_void); + return err.empty(); + } + + bool exportAsWESchem(const char *filename_local, + const WE_schem_options &option) const noexcept override { + const bool have_req = option.num_required_mods > 0 && + option.required_mods_name_utf8 != nullptr; + std::span sp{}; + + if (have_req) { + sp = {option.required_mods_name_utf8, + option.num_required_mods + option.required_mods_name_utf8}; + } + auto err = this->exportAsWESchem(filename_local, option.offset, + option.we_offset, "", sp); + + return err.empty(); + } }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 95a81cbb..ac2aa0f6 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -134,8 +134,8 @@ void TokiSlopeCraft::exportAsLitematic(const char *TargetName, } std::string TokiSlopeCraft::exportAsLitematic( - const std::string &TargetName, const std::string &LiteName, - const std::string &RegionName) const { + std::string_view TargetName, std::string_view LiteName, + std::string_view RegionName) const { if (kernelStep < SCL_step::builded) { reportError(wind, errorFlag::HASTY_MANIPULATION, "You can only export a map to litematic after you build the 3D " @@ -225,10 +225,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { this->build_opt.glassMethod = glassBridgeSettings::noBridge; } - this->build_opt.maxAllowedHeight = option.maxAllowedHeight; - this->build_opt.bridgeInterval = option.bridgeInterval; - this->build_opt.fire_proof = option.fire_proof; - this->build_opt.enderman_proof = option.enderman_proof; + this->build_opt = option; reportWorkingStatue(wind, workStatues::buidingHeighMap); @@ -254,6 +251,10 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "start makeBridge" << endl; makeBridge(); } + + if (option.connect_mushrooms) { + this->schem.process_mushroom_states_fast(); + } // cerr << "makeBridge finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 9 * sizePic(2)); @@ -481,13 +482,13 @@ void TokiSlopeCraft::makeBridge() { void TokiSlopeCraft::exportAsStructure(const char *TargetName, char *FileName) const { - std::string temp = exportAsStructure(TargetName); + std::string temp = exportAsStructure(TargetName, true); if (FileName != nullptr) std::strcpy(temp.data(), FileName); } std::string TokiSlopeCraft::exportAsStructure( - const std::string &TargetName) const { + std::string_view filename, bool is_air_structure_void) const { if (kernelStep < SCL_step::builded) { reportError(wind, errorFlag::HASTY_MANIPULATION, "You can only export a map to structure after you build the 3D " @@ -500,8 +501,8 @@ std::string TokiSlopeCraft::exportAsStructure( errorFlag flag = errorFlag::NO_ERROR_OCCUR; std::string error_string; - const bool success = - schem.export_structure(TargetName, true, &flag, &error_string); + const bool success = schem.export_structure(filename, is_air_structure_void, + &flag, &error_string); if (!success) { this->reportError(this->wind, flag, error_string.data()); @@ -535,8 +536,8 @@ void TokiSlopeCraft::exportAsWESchem(const char *fileName, _reqMods.emplace_back(requiredMods[idx]); } - const std::string retVal = this->exportAsWESchem( - std::string(fileName), _offset, _weOffset, Name, _reqMods); + const std::string retVal = + this->exportAsWESchem(fileName, _offset, _weOffset, Name, _reqMods); if (returnVal != nullptr) { strcpy(returnVal, retVal.data()); } @@ -544,9 +545,9 @@ void TokiSlopeCraft::exportAsWESchem(const char *fileName, } std::string TokiSlopeCraft::exportAsWESchem( - const std::string &targetName, const std::array &offset, - const std::array &, const char *Name, - const std::vector &requiredMods) const { + std::string_view filename, std::span offset, + std::span weOffset, std::string_view Name, + std::span requiredMods) const { if (kernelStep < SCL_step::builded) { reportError(wind, errorFlag::HASTY_MANIPULATION, "You can only export a map to structure after you build the 3D " @@ -562,7 +563,8 @@ std::string TokiSlopeCraft::exportAsWESchem( libSchem::WorldEditSchem_info info; info.schem_name_utf8 = Name; - info.offset = offset; + memcpy(info.offset.data(), offset.data(), sizeof(info.offset)); + memcpy(info.WE_offset.data(), weOffset.data(), sizeof(info.WE_offset)); info.required_mods_utf8.resize(requiredMods.size()); @@ -575,7 +577,7 @@ std::string TokiSlopeCraft::exportAsWESchem( errorFlag flag = errorFlag::NO_ERROR_OCCUR; std::string error_string; const bool success = - schem.export_WESchem(targetName, info, &flag, &error_string); + schem.export_WESchem(filename, info, &flag, &error_string); if (!success) { this->reportError(this->wind, flag, error_string.data()); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 651f710f..9092b396 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -226,6 +226,7 @@ uint64_t TokiSlopeCraft::build_task_hash(const Eigen::ArrayXXi &mapPic, hash.addData(&bo.glassMethod, sizeof(bo.glassMethod)); hash.addData(&bo.fire_proof, sizeof(bo.fire_proof)); hash.addData(&bo.enderman_proof, sizeof(bo.enderman_proof)); + hash.addData(&bo.connect_mushrooms, sizeof(bo.connect_mushrooms)); hash.finalize(); @@ -261,14 +262,14 @@ template void save(archive &ar, const SlopeCraft::Kernel::build_options &opt) noexcept { ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, opt.glassMethod); - ar(opt.fire_proof, opt.enderman_proof); + ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); } template void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, opt.glassMethod); - ar(opt.fire_proof, opt.enderman_proof); + ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); } } // namespace cereal From acf58aa79aa17d26b6f9407484da380f91712ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 11 May 2023 21:21:05 +0800 Subject: [PATCH 0297/1123] add connect mushroom option in ui --- SlopeCraft/CMakeLists.txt | 1 + SlopeCraft/SCWind.cpp | 400 +++----------------------------- SlopeCraft/SCWind.h | 6 + SlopeCraft/SCWind.ui | 10 + SlopeCraft/SCWind_slots.cpp | 450 ++++++++++++++++++++++++++++++++++++ 5 files changed, 504 insertions(+), 363 deletions(-) create mode 100644 SlopeCraft/SCWind_slots.cpp diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index b960fb46..fd5e8652 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -25,6 +25,7 @@ set(SlopeCraft_headers set(SlopeCraft_sources SCWind.cpp + SCWind_slots.cpp cvt_task.cpp PoolModel.cpp AdaptiveListView.cpp diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 77eb3243..0b99782d 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -149,71 +149,6 @@ SCWind::~SCWind() { SlopeCraft::SCL_destroyKernel(this->kernel); } -void SCWind::on_pb_add_image_clicked() noexcept { - auto files = - QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;*.jpg"); - - if (files.empty()) { - return; - } - - QString err; - for (const auto &filename : files) { - auto task = cvt_task::load(filename, err); - - if (!err.isEmpty()) { - auto ret = QMessageBox::critical( - this, tr("打开图像失败"), - tr("无法打开图像 %1 。常见原因:图像尺寸太大。\n详细信息: %2") - .arg(filename) - .arg(err), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}); - - if (ret == QMessageBox::Ignore) { - continue; - } else { - abort(); - } - } - - this->tasks.emplace_back(task); - } - - emit this->image_changed(); - if (this->ui->lview_pool_cvt->viewMode() == QListView::ViewMode::IconMode) { - this->ui->lview_pool_cvt->doItemsLayout(); - } -} - -void SCWind::on_pb_remove_image_clicked() noexcept { - auto selected = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); - - if (selected.empty()) { - return; - } - - for (const auto &qmi : selected) { - const int idx = qmi.row(); - this->tasks.erase(this->tasks.begin() + idx); - } - - emit this->image_changed(); -} - -void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { - const bool is_icon_mode = this->ui->cb_lv_cvt_icon_mode->isChecked(); - this->ui->lview_pool_cvt->setViewMode((is_icon_mode) - ? (QListView::ViewMode::IconMode) - : (QListView::ViewMode::ListMode)); - - this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); - - this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 0); - - this->cvt_pool_model->refresh(); -} - void SCWind::when_cvt_pool_selectionChanged() noexcept { const auto selected_idx = this->selected_cvt_task_idx(); @@ -389,17 +324,33 @@ bool SCWind::is_fire_proof_selected() const noexcept { bool SCWind::is_enderman_proof_selected() const noexcept { return this->ui->cb_enderproof->isChecked(); } +bool SCWind::is_connect_mushroom_selected() const noexcept { + return this->ui->cb_connect_mushroom->isChecked(); +} SlopeCraft::Kernel::build_options SCWind::current_build_option() const noexcept { return SlopeCraft::Kernel::build_options{ - SC_VERSION_U64, - (uint16_t)this->current_max_height(), - (uint16_t)this->current_glass_brigde_interval(), - this->current_compress_method(), - this->current_glass_method(), - this->is_fire_proof_selected(), - this->is_enderman_proof_selected()}; + .maxAllowedHeight = (uint16_t)this->current_max_height(), + .bridgeInterval = (uint16_t)this->current_glass_brigde_interval(), + .compressMethod = this->current_compress_method(), + .glassMethod = this->current_glass_method(), + .fire_proof = this->is_fire_proof_selected(), + .enderman_proof = this->is_enderman_proof_selected(), + .connect_mushrooms = this->is_connect_mushroom_selected()}; +} + +SCWind::export_type SCWind::selected_export_type() const noexcept { + auto btns = this->export_type_buttons(); + static_assert(btns.size() == 5); + + for (int i = 0; i < 5; i++) { + if (btns[i]->isChecked()) { + return SCWind::export_type{i}; + } + } + assert(false); + return {}; } void SCWind::when_version_buttons_toggled() noexcept { @@ -554,110 +505,6 @@ void SCWind::when_export_type_toggled() noexcept { this->update_button_states(); } -void SCWind::on_pb_load_preset_clicked() noexcept { - static QString prev_dir{""}; - QString file = QFileDialog::getOpenFileName(this, tr("选择预设文件"), - prev_dir, "*.sc_preset_json"); - - if (file.isEmpty()) { - return; - } - - prev_dir = QFileInfo{file}.dir().canonicalPath(); - QString err; - blockListPreset preset = load_preset(file, err); - if (!err.isEmpty()) { - QMessageBox::warning(this, tr("解析预设文件失败"), - tr("预设文件%1存在错误:%2").arg(file).arg(err)); - return; - } - - this->ui->blm->loadPreset(preset); -} - -void SCWind::on_pb_save_preset_clicked() noexcept { - static QString prev_dir{""}; - QString file = QFileDialog::getSaveFileName(this, tr("保存当前预设"), - prev_dir, "*.sc_preset_json"); - - if (file.isEmpty()) { - return; - } - - prev_dir = QFileInfo{file}.dir().canonicalPath(); - - blockListPreset preset = this->ui->blm->to_preset(); - { - QString str = serialize_preset(preset); - - QFile qf{file}; - qf.open(QFile::OpenMode{QIODevice::WriteOnly | QIODevice::Text}); - - if (!qf.isOpen()) { - QMessageBox::warning(this, tr("保存预设文件失败"), - tr("无法生成预设文件%1 ,错误信息:%2") - .arg(file) - .arg(qf.errorString())); - return; - } - - qf.write(str.toUtf8()); - qf.close(); - } -} - -inline int impl_select_blk_by_id( - const std::vector &blks, - std::string_view keyword) noexcept { - int result = -1; - for (int idx = 0; idx < int(blks.size()); idx++) { - std::string_view id{blks[idx]->getId()}; - const auto find = id.find(keyword); - - if (find != std::string_view::npos) { - result = idx; - break; - } - } - - return result; -} - -void SCWind::on_pb_prefer_concrete_clicked() noexcept { - this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "concrete"); - }); -} - -void SCWind::on_pb_prefer_wool_clicked() noexcept { - this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "wool"); - }); -} - -void SCWind::on_pb_prefer_glass_clicked() noexcept { - this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "stained_glass"); - }); -} - -void SCWind::on_pb_prefer_planks_clicked() noexcept { - this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "planks"); - }); -} - -void SCWind::on_pb_prefer_logs_clicked() noexcept { - this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "log"); - }); -} - void SCWind::kernel_set_image(int idx) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); @@ -698,42 +545,6 @@ bool SCWind::kernel_check_colorset_hash() noexcept { return this->kernel->checkColorsetHash(); } -void SCWind::on_pb_cvt_current_clicked() noexcept { - const auto sel = this->selected_cvt_task_idx(); - - if (!sel.has_value()) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个图像")); - return; - } - - this->kernel_set_image(sel.value()); - this->kernel_convert_image(); - this->tasks[sel.value()].set_converted(); - - this->kernel_make_cvt_cache(); - this->refresh_current_cvt_display(sel.value(), true); - this->ui->tw_cvt_image->setCurrentIndex(1); - - emit this->image_changed(); - // this->ui-> -} - -void SCWind::on_pb_cvt_all_clicked() noexcept { - for (int idx = 0; idx < (int)this->tasks.size(); idx++) { - auto &task = this->tasks[idx]; - if (task.is_converted) { - continue; - } - - this->kernel_set_image(idx); - this->kernel_convert_image(); - this->kernel_make_cvt_cache(); - task.set_converted(); - } - emit this->image_changed(); -} - QImage SCWind::get_converted_image_from_kernel() const noexcept { assert(this->kernel->queryStep() >= SCL_step::converted); @@ -802,87 +613,6 @@ void SCWind::when_algo_btn_clicked() noexcept { this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } -void SCWind::on_pb_save_converted_clicked() noexcept { - const auto selected = this->selected_indices(); - if (selected.size() <= 0) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个或多个图像")); - return; - } - static QString prev_dir{""}; - if (selected.size() == 1) { - QString filename = QFileDialog::getSaveFileName(this, tr("保存转化后图像"), - prev_dir, "*.png;*.jpg"); - if (filename.isEmpty()) { - return; - } - prev_dir = QFileInfo{filename}.dir().dirName(); - - const int idx = selected.front(); - - this->export_current_cvted_image(idx, filename); - return; - } - - QString out_dir = - QFileDialog::getExistingDirectory(this, tr("保存转化后图像"), prev_dir); - if (out_dir.isEmpty()) { - return; - } - prev_dir = out_dir; - - bool yes_to_all_replace_existing{false}; - bool no_to_all_replace_existing{false}; - for (int idx : selected) { - auto &task = this->tasks[idx]; - QString filename = QStringLiteral("%1/%2.png") - .arg(out_dir) - .arg(QFileInfo{task.filename}.baseName()); - - if (QFile{filename}.exists()) { - if (no_to_all_replace_existing) { - continue; - } - if (yes_to_all_replace_existing) { - goto save_image; - } - - auto ret = QMessageBox::warning( - this, tr("将要覆盖已存在的图像"), - tr("%1将被覆盖,确认覆盖吗?").arg(filename), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, - QMessageBox::StandardButton::No, - QMessageBox::StandardButton::YesToAll, - QMessageBox::StandardButton::NoToAll}); - bool replace{false}; - switch (ret) { - case QMessageBox::StandardButton::Yes: - replace = true; - break; - case QMessageBox::StandardButton::YesToAll: - replace = true; - yes_to_all_replace_existing = true; - break; - case QMessageBox::StandardButton::NoToAll: - replace = false; - no_to_all_replace_existing = true; - break; - default: - replace = false; - break; - } - - if (!replace) { - continue; - } - } - - save_image: - - this->export_current_cvted_image(idx, filename); - } -} - void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); @@ -921,10 +651,6 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { } } -void SCWind::on_cb_compress_lossy_toggled(bool checked) noexcept { - this->ui->sb_max_height->setEnabled(checked); -} - void SCWind::kernel_build_3d() noexcept { if (!this->kernel->build(this->current_build_option())) { QMessageBox::warning(this, tr("构建三维结构失败"), @@ -933,30 +659,6 @@ void SCWind::kernel_build_3d() noexcept { } } -void SCWind::on_pb_build3d_clicked() noexcept { - auto taskopt = this->selected_export_task(); - if (!taskopt.has_value()) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个图像")); - return; - } - assert(taskopt.value() != nullptr); - - cvt_task &task = *taskopt.value(); - - if (!task.is_converted) [[unlikely]] { - QMessageBox::warning(this, tr("该图像尚未被转化"), - tr("必须先转化一个图像,然后再为它构建三维结构")); - return; - } - - this->kernel_build_3d(); - this->kernel_make_build_cache(); - - task.set_built(); - this->refresh_current_build_display(&task, true); -} - void SCWind::refresh_current_build_display( std::optional taskp, bool is_image_built_in_kernel) noexcept { this->ui->lb_show_3dsize->setText(tr("大小:")); @@ -1010,48 +712,20 @@ void SCWind::kernel_make_build_cache() noexcept { } } -void SCWind::on_pb_preview_materials_clicked() noexcept { - auto taskopt = this->selected_export_task(); - if (!taskopt.has_value()) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个图像")); - return; - } - assert(taskopt.value() != nullptr); - - cvt_task &task = *taskopt.value(); - if (!task.is_converted) [[unlikely]] { - QMessageBox::warning(this, tr("该图像尚未被转化"), - tr("必须先转化一个图像,然后再为它构建三维结构")); - return; - } - QString errtitle; - QString errmsg; - // try to load cache - [this, &errtitle, &errmsg]() { - if (this->kernel->queryStep() >= SCL_step::builded) { - return; - } - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - errtitle = tr("该图像尚未被转化"); - errmsg = - tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" - "新转化该图像。"); - return; - } - if (!this->kernel->loadBuildCache(this->current_build_option())) { - errtitle = tr("尚未构建三维结构"); - errmsg = tr( - "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" - "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); - } - }(); - - if (!errtitle.isEmpty()) { - QMessageBox::warning(this, errtitle, errmsg); - return; +QString extension_of_export_type(SCWind::export_type et) noexcept { + switch (et) { + case SCWind::export_type::litematica: + return "litematic"; + case SCWind::export_type::vanilla_structure: + return "nbt"; + case SCWind::export_type::WE_schem: + return "schem"; + case SCWind::export_type::flat_diagram: + return "png"; + case SCWind::export_type::data_file: + return "dat"; } -#warning show mat list here + assert(false); + return "Invalid_export_type"; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 8710f168..ba51ea4d 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -59,6 +59,7 @@ class SCWind : public QMainWindow { void on_pb_build3d_clicked() noexcept; void on_pb_preview_materials_clicked() noexcept; + void on_pb_export_all_clicked() noexcept; private: Ui::SCWind* ui; @@ -110,9 +111,12 @@ class SCWind : public QMainWindow { bool is_fire_proof_selected() const noexcept; bool is_enderman_proof_selected() const noexcept; + bool is_connect_mushroom_selected() const noexcept; SlopeCraft::Kernel::build_options current_build_option() const noexcept; + export_type selected_export_type() const noexcept; + // kernel related functions void kernel_set_type() noexcept; @@ -156,4 +160,6 @@ class SCWind : public QMainWindow { void image_changed(); }; +QString extension_of_export_type(SCWind::export_type) noexcept; + #endif // SLOPECRAFT_SLOPECRAFT_SCWIND_H \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 622aed7a..d3c9fc42 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -822,6 +822,16 @@ + + + + 连接蘑菇块 + + + true + + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp new file mode 100644 index 00000000..3c1386b3 --- /dev/null +++ b/SlopeCraft/SCWind_slots.cpp @@ -0,0 +1,450 @@ +#include "SCWind.h" +#include "ui_SCWind.h" +#include +#include +#include +#include + +void SCWind::on_pb_add_image_clicked() noexcept { + auto files = + QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;*.jpg"); + + if (files.empty()) { + return; + } + + QString err; + for (const auto &filename : files) { + auto task = cvt_task::load(filename, err); + + if (!err.isEmpty()) { + auto ret = QMessageBox::critical( + this, tr("打开图像失败"), + tr("无法打开图像 %1 。常见原因:图像尺寸太大。\n详细信息: %2") + .arg(filename) + .arg(err), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, + QMessageBox::StandardButton::Ignore}); + + if (ret == QMessageBox::Ignore) { + continue; + } else { + abort(); + } + } + + this->tasks.emplace_back(task); + } + + emit this->image_changed(); + if (this->ui->lview_pool_cvt->viewMode() == QListView::ViewMode::IconMode) { + this->ui->lview_pool_cvt->doItemsLayout(); + } +} + +void SCWind::on_pb_remove_image_clicked() noexcept { + auto selected = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + + if (selected.empty()) { + return; + } + + for (const auto &qmi : selected) { + const int idx = qmi.row(); + this->tasks.erase(this->tasks.begin() + idx); + } + + emit this->image_changed(); +} + +void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { + const bool is_icon_mode = this->ui->cb_lv_cvt_icon_mode->isChecked(); + this->ui->lview_pool_cvt->setViewMode((is_icon_mode) + ? (QListView::ViewMode::IconMode) + : (QListView::ViewMode::ListMode)); + + this->ui->lview_pool_cvt->setFlow(QListView::Flow::TopToBottom); + + this->ui->lview_pool_cvt->setSpacing(is_icon_mode ? 16 : 0); + + this->cvt_pool_model->refresh(); +} + +void SCWind::on_pb_load_preset_clicked() noexcept { + static QString prev_dir{""}; + QString file = QFileDialog::getOpenFileName(this, tr("选择预设文件"), + prev_dir, "*.sc_preset_json"); + + if (file.isEmpty()) { + return; + } + + prev_dir = QFileInfo{file}.dir().canonicalPath(); + QString err; + blockListPreset preset = load_preset(file, err); + if (!err.isEmpty()) { + QMessageBox::warning(this, tr("解析预设文件失败"), + tr("预设文件%1存在错误:%2").arg(file).arg(err)); + return; + } + + this->ui->blm->loadPreset(preset); +} + +void SCWind::on_pb_save_preset_clicked() noexcept { + static QString prev_dir{""}; + QString file = QFileDialog::getSaveFileName(this, tr("保存当前预设"), + prev_dir, "*.sc_preset_json"); + + if (file.isEmpty()) { + return; + } + + prev_dir = QFileInfo{file}.dir().canonicalPath(); + + blockListPreset preset = this->ui->blm->to_preset(); + { + QString str = serialize_preset(preset); + + QFile qf{file}; + qf.open(QFile::OpenMode{QIODevice::WriteOnly | QIODevice::Text}); + + if (!qf.isOpen()) { + QMessageBox::warning(this, tr("保存预设文件失败"), + tr("无法生成预设文件%1 ,错误信息:%2") + .arg(file) + .arg(qf.errorString())); + return; + } + + qf.write(str.toUtf8()); + qf.close(); + } +} + +inline int impl_select_blk_by_id( + const std::vector &blks, + std::string_view keyword) noexcept { + int result = -1; + for (int idx = 0; idx < int(blks.size()); idx++) { + std::string_view id{blks[idx]->getId()}; + const auto find = id.find(keyword); + + if (find != std::string_view::npos) { + result = idx; + break; + } + } + + return result; +} + +void SCWind::on_pb_prefer_concrete_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "concrete"); + }); +} + +void SCWind::on_pb_prefer_wool_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "wool"); + }); +} + +void SCWind::on_pb_prefer_glass_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "stained_glass"); + }); +} + +void SCWind::on_pb_prefer_planks_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "planks"); + }); +} + +void SCWind::on_pb_prefer_logs_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "log"); + }); +} + +void SCWind::on_pb_cvt_current_clicked() noexcept { + const auto sel = this->selected_cvt_task_idx(); + + if (!sel.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + + this->kernel_set_image(sel.value()); + this->kernel_convert_image(); + this->tasks[sel.value()].set_converted(); + + this->kernel_make_cvt_cache(); + this->refresh_current_cvt_display(sel.value(), true); + this->ui->tw_cvt_image->setCurrentIndex(1); + + emit this->image_changed(); + // this->ui-> +} + +void SCWind::on_pb_cvt_all_clicked() noexcept { + for (int idx = 0; idx < (int)this->tasks.size(); idx++) { + auto &task = this->tasks[idx]; + if (task.is_converted) { + continue; + } + + this->kernel_set_image(idx); + this->kernel_convert_image(); + this->kernel_make_cvt_cache(); + task.set_converted(); + } + emit this->image_changed(); +} + +void SCWind::on_pb_save_converted_clicked() noexcept { + const auto selected = this->selected_indices(); + if (selected.size() <= 0) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个或多个图像")); + return; + } + static QString prev_dir{""}; + if (selected.size() == 1) { + QString filename = QFileDialog::getSaveFileName(this, tr("保存转化后图像"), + prev_dir, "*.png;*.jpg"); + if (filename.isEmpty()) { + return; + } + prev_dir = QFileInfo{filename}.dir().dirName(); + + const int idx = selected.front(); + + this->export_current_cvted_image(idx, filename); + return; + } + + QString out_dir = + QFileDialog::getExistingDirectory(this, tr("保存转化后图像"), prev_dir); + if (out_dir.isEmpty()) { + return; + } + prev_dir = out_dir; + + bool yes_to_all_replace_existing{false}; + bool no_to_all_replace_existing{false}; + for (int idx : selected) { + auto &task = this->tasks[idx]; + QString filename = QStringLiteral("%1/%2.png") + .arg(out_dir) + .arg(QFileInfo{task.filename}.baseName()); + + if (QFile{filename}.exists()) { + if (no_to_all_replace_existing) { + continue; + } + if (yes_to_all_replace_existing) { + goto save_image; + } + + auto ret = QMessageBox::warning( + this, tr("将要覆盖已存在的图像"), + tr("%1将被覆盖,确认覆盖吗?").arg(filename), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No, + QMessageBox::StandardButton::YesToAll, + QMessageBox::StandardButton::NoToAll}); + bool replace{false}; + switch (ret) { + case QMessageBox::StandardButton::Yes: + replace = true; + break; + case QMessageBox::StandardButton::YesToAll: + replace = true; + yes_to_all_replace_existing = true; + break; + case QMessageBox::StandardButton::NoToAll: + replace = false; + no_to_all_replace_existing = true; + break; + default: + replace = false; + break; + } + + if (!replace) { + continue; + } + } + + save_image: + + this->export_current_cvted_image(idx, filename); + } +} + +void SCWind::on_cb_compress_lossy_toggled(bool checked) noexcept { + this->ui->sb_max_height->setEnabled(checked); +} + +void SCWind::on_pb_build3d_clicked() noexcept { + auto taskopt = this->selected_export_task(); + if (!taskopt.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + assert(taskopt.value() != nullptr); + + cvt_task &task = *taskopt.value(); + + if (!task.is_converted) [[unlikely]] { + QMessageBox::warning(this, tr("该图像尚未被转化"), + tr("必须先转化一个图像,然后再为它构建三维结构")); + return; + } + + this->kernel_build_3d(); + this->kernel_make_build_cache(); + + task.set_built(); + this->refresh_current_build_display(&task, true); +} + +void SCWind::on_pb_preview_materials_clicked() noexcept { + auto taskopt = this->selected_export_task(); + if (!taskopt.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + assert(taskopt.value() != nullptr); + + cvt_task &task = *taskopt.value(); + if (!task.is_converted) [[unlikely]] { + QMessageBox::warning(this, tr("该图像尚未被转化"), + tr("必须先转化一个图像,然后再为它构建三维结构")); + return; + } + QString errtitle; + QString errmsg; + // try to load cache + [this, &errtitle, &errmsg]() { + if (this->kernel->queryStep() >= SCL_step::builded) { + return; + } + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + errtitle = tr("该图像尚未被转化"); + errmsg = + tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" + "新转化该图像。"); + return; + } + if (!this->kernel->loadBuildCache(this->current_build_option())) { + errtitle = tr("尚未构建三维结构"); + errmsg = tr( + "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" + "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + } + }(); + + if (!errtitle.isEmpty()) { + QMessageBox::warning(this, errtitle, errmsg); + return; + } + +#warning show mat list here +} + +void SCWind::on_pb_export_all_clicked() noexcept { + auto tasks_to_export = this->selected_export_task_list(); + + if (tasks_to_export.size() <= 0) { + QMessageBox::warning(this, tr("无可导出的任务"), + tr("任务池为空,请先转化一个或一些图像")); + return; + } + QString dir; + { + static QString prev_dir{""}; + dir = QFileDialog::getExistingDirectory(this, tr("选择导出位置"), prev_dir, + QFileDialog::Options{}); + if (dir.isEmpty()) { + return; + } + prev_dir = dir; + } + + auto get_export_name = [dir, this](const cvt_task &t) -> QString { + return QStringLiteral("%1/%2.%3") + .arg(dir) + .arg(QFileInfo{t.filename}.baseName()) + .arg(extension_of_export_type(this->selected_export_type())); + }; + + // warn if some files will be covered + { + QString warning_list{}; + + for (auto taskp : tasks_to_export) { + QString filename = get_export_name(*taskp); + if (QFile{filename}.exists()) { + if (warning_list.isEmpty()) { + warning_list = filename; + } else { + warning_list.append('\n'); + warning_list.append(filename); + } + } + } + + if (!warning_list.isEmpty()) { + auto ret = QMessageBox::warning( + this, tr("将要覆盖已经存在的文件"), + tr("确定要覆盖这些文件吗?以下文件将被覆盖:\n%1").arg(warning_list), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No}); + if (ret != QMessageBox::StandardButton::Yes) { + return; + } + } + } + + for (auto taskp : tasks_to_export) { + auto set_img_and_convert = [this, taskp]() { + this->kernel_set_image(taskp - this->tasks.data()); + this->kernel_convert_image(); + taskp->set_converted(); + }; + + // this step make sure the image is converted in kernel + if (!taskp->is_converted) { + set_img_and_convert(); + } else { + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + set_img_and_convert(); + } + } + + if (!taskp->is_built) { + this->kernel_build_3d(); + } else { + if (!this->kernel->loadBuildCache(this->current_build_option())) { + this->kernel_build_3d(); + } + } + taskp->set_built(); + +#warning export here + } +} \ No newline at end of file From a996b04703a3d731d5153eaab20bd10f6c3205c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 00:49:32 +0800 Subject: [PATCH 0298/1123] fix a behavior problem --- SlopeCraft/SCWind.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0b99782d..0910d6b2 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -596,6 +596,8 @@ void SCWind::refresh_current_cvt_display( if (!this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { + this->tasks[idx].set_unconverted(); + emit this->image_changed(); return; } From 97e1632ca4d6ac657c1c538c3cf962942a7d715b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 02:13:28 +0800 Subject: [PATCH 0299/1123] configure heu by FetchContent --- SlopeCraftL/CMakeLists.txt | 7 ++- cmake/find_HeuristicFlow.cmake | 56 +++---------------- utilities/ColorManip/CMakeLists.txt | 5 +- .../GAConverter/CMakeLists.txt | 4 +- 4 files changed, 16 insertions(+), 56 deletions(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index f72d9299..bd94e17d 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -9,7 +9,8 @@ find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) -find_package(zstr) +find_package(zstr REQUIRED) +find_package(Heu REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -68,7 +69,6 @@ target_compile_features(SlopeCraftL PRIVATE cxx_std_20) target_include_directories(SlopeCraftL INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(SlopeCraftL PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} - ${SlopeCraft_HeuristicFlow_include_dir} ${SlopeCraft_Chocobo1_Hash_include_dir} ${CMAKE_SOURCE_DIR} @@ -85,7 +85,8 @@ set(SlopeCraft_SCL_link_libs MapImageCvter fmt::fmt Eigen3::Eigen - zstr::zstr) + zstr::zstr + Heu::Genetic) # link to dependents target_link_libraries(SlopeCraftL PUBLIC ${SlopeCraft_SCL_link_libs}) diff --git a/cmake/find_HeuristicFlow.cmake b/cmake/find_HeuristicFlow.cmake index 3cfad27c..cc968b0a 100644 --- a/cmake/find_HeuristicFlow.cmake +++ b/cmake/find_HeuristicFlow.cmake @@ -1,53 +1,11 @@ -set(SlopeCraft_download_HeuristicFlow OFF) -if(NOT DEFINED SlopeCraft_HeuristicFlow_include_dir) - # try to find Heu in the 3rdParty directory - if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/HeuristicFlow/HeuristicFlow/Genetic) - message(STATUS "Found HeuristicFlow in 3rdParty/HeusiticFlow") - set(SlopeCraft_HeuristicFlow_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/HeuristicFlow) +include(FetchContent) - else() - set(SlopeCraft_download_HeuristicFlow ON) - endif() +FetchContent_Declare(Heu + GIT_REPOSITORY https://github.com/SlopeCraft/HeuristicFlow.git + GIT_TAG v1.6.4 + OVERRIDE_FIND_PACKAGE) -else() - #examine whether the input is valid - if(EXISTS ${SlopeCraft_HeuristicFlow_include_dir}/HeuristicFlow/Genetic) - # is valid - message("The value of SlopeCraft_HeuristicFlow_include_dir is valid. SlopeCraft will have access to Heu") +FetchContent_MakeAvailable(Heu) - else() - message(WARNING - "The value of SlopeCraft_HeuristicFlow_include_dir is invalid. Failed to find file : " - ${SlopeCraft_HeuristicFlow_include_dir}/HeuristicFlow/Genetic) - set(SlopeCraft_download_HeuristicFlow ON) - endif() -endif() - - -# download -if(${SlopeCraft_download_HeuristicFlow}) - #if() - message(STATUS "Cloning HeuristicFlow...") - execute_process( - COMMAND git clone https://github.com/SlopeCraft/HeuristicFlow.git - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty - COMMAND_ERROR_IS_FATAL ANY - ECHO_ERROR_VARIABLE - ECHO_OUTPUT_VARIABLE - ) - - message(STATUS "Successfully cloned HeuristicFlow. Checking out to tag v1.6.2.2") - execute_process( - COMMAND git checkout v1.6.2.2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty/HeuristicFlow - COMMAND_ERROR_IS_FATAL ANY - ECHO_ERROR_VARIABLE - ) - - message(STATUS "HeuristicFlow is ready") - - set(SlopeCraft_download_HeuristicFlow OFF) - set(SlopeCraft_HeuristicFlow_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/HeuristicFlow) - -endif() +find_package(Heu 1.6.4 REQUIRED) \ No newline at end of file diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 49db36e8..e897fdfd 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -6,6 +6,7 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) # include_directories(../SlopeCraftL) find_package(OpenMP REQUIRED) find_package(Eigen3 REQUIRED) +find_package(Heu REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) @@ -35,8 +36,8 @@ target_include_directories(ColorManip PUBLIC ${CMAKE_SOURCE_DIR}/utilities ${SlopeCraft_Chocobo1_Hash_include_dir}) -target_include_directories(ColorManip PRIVATE - ${SlopeCraft_HeuristicFlow_include_dir}) +target_link_libraries(ColorManip PRIVATE + Heu::Genetic) target_link_libraries(ColorManip PUBLIC OpenMP::OpenMP_CXX diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index b35b04a1..31535c78 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -3,6 +3,7 @@ project(SlopeCraft_GAConverter VERSION ${SlopeCraft_version} LANGUAGES CXX) # set(CMAKE_CXX_STANDARD 20) find_package(OpenMP REQUIRED) +find_package(Heu REQUIRED) set(SlopeCraft_GAConverter_sources @@ -19,12 +20,11 @@ set(SlopeCraft_GAConverter_sources add_library(GAConverter STATIC ${SlopeCraft_GAConverter_sources}) target_include_directories(GAConverter PUBLIC - ${SlopeCraft_HeuristicFlow_include_dir} ../../ColorManip ) find_package(Eigen3 REQUIRED) -target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen) +target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen Heu::Genetic) target_compile_features(GAConverter PRIVATE cxx_std_20) From befcb2a37d23f6f900dca273d631909dc17f019c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 19:24:12 +0800 Subject: [PATCH 0300/1123] fixed schem load and save --- utilities/Schem/Schem.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index ef3713eb..8ea7909e 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -245,7 +245,8 @@ class Schem { ar(this->block_id_list); const int64_t x{this->x_range()}, y{this->y_range()}, z{this->z_range()}; ar(x, y, z); - ar(cereal::binary_data(this->data(), this->size())); + ar(cereal::binary_data(this->xzy.data(), + this->xzy.size() * sizeof(uint16_t))); } template @@ -262,7 +263,8 @@ class Schem { } } this->resize(x, y, z); - ar(cereal::binary_data(this->data(), this->size())); + ar(cereal::binary_data(this->xzy.data(), + this->xzy.size() * sizeof(uint16_t))); } }; From 2dd2a97e0582f0ca3a32ee7151067134ab73dbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 19:24:32 +0800 Subject: [PATCH 0301/1123] check size when loading eigen matrix --- utilities/ColorManip/seralize_funs.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utilities/ColorManip/seralize_funs.hpp b/utilities/ColorManip/seralize_funs.hpp index 8f1e4d92..9079e408 100644 --- a/utilities/ColorManip/seralize_funs.hpp +++ b/utilities/ColorManip/seralize_funs.hpp @@ -23,6 +23,10 @@ void load(archive &ar, Eigen::ArrayXX &img) { ar(cereal::make_size_tag(rows)); ar(cereal::make_size_tag(cols)); + if (rows < 0 || cols < 0) { + throw std::runtime_error{"Negative size"}; + } + img.resize(rows, cols); ar(cereal::binary_data(img.data(), rows * cols * sizeof(T))); } From 6fa29ad80e4eaea5528b8b3f451b6e56cf682da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 19:24:54 +0800 Subject: [PATCH 0302/1123] redesign cache --- SlopeCraftL/SlopeCraftL.h | 21 +- SlopeCraftL/TokiSlopeCraft.h | 151 ++++++----- SlopeCraftL/TokiSlopeCraft_cache.cpp | 363 +++++++++++++++++++++++++-- utilities/ColorManip/CMakeLists.txt | 2 +- utilities/ColorManip/hash.cpp | 4 +- utilities/ColorManip/newColorSet.hpp | 29 ++- 6 files changed, 472 insertions(+), 98 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 73313612..9cacb88a 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -269,6 +269,8 @@ class Kernel { // matain binary compability // introduced in v5.1.0 ----------------------------------------------------- + virtual void setCacheDir(const char *) noexcept = 0; + virtual const char *cacheDir() const noexcept = 0; // replacement for setRawImage(const uint32_t*,int,int) virtual void setRawImage(const uint32_t *src, int rows, int cols, bool is_col_major) = 0; @@ -276,16 +278,6 @@ class Kernel { // *dest)const virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, bool expected_col_major) const = 0; - virtual void setCacheDir(const char *) noexcept = 0; - virtual const char *cacheDir() const noexcept = 0; - // requires step >= wait4image - virtual bool checkColorsetHash() const noexcept = 0; - // requires step >= converted - virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; - - // requires step >= convertion ready - virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; - struct build_options { uint64_t version{SC_VERSION_U64}; uint16_t maxAllowedHeight{256}; @@ -298,8 +290,15 @@ class Kernel { // added in v5.1.0 bool connect_mushrooms{false}; }; - virtual bool build(const build_options &option) noexcept = 0; + // requires step >= wait4image + // virtual bool checkColorsetHash() const noexcept = 0; + // requires step >= converted + virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; + + // requires step >= convertion ready + virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; + // requires step >= built virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 2b3df2f0..d5e96600 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -208,6 +208,37 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string_view LiteName, // Utf8 std::string_view RegionName // Utf8 ) const; + bool exportAsLitematic( + const char *filename_local, + const litematic_options &option) const noexcept override { + auto err = this->exportAsLitematic(filename_local, option.litename_utf8, + option.region_name_utf8); + return err.empty(); + } + + bool exportStructure( + const char *filename_local, + const vanilla_structure_options &option) const noexcept override { + auto err = + this->exportAsStructure(filename_local, option.is_air_structure_void); + return err.empty(); + } + + bool exportAsWESchem(const char *filename_local, + const WE_schem_options &option) const noexcept override { + const bool have_req = option.num_required_mods > 0 && + option.required_mods_name_utf8 != nullptr; + std::span sp{}; + + if (have_req) { + sp = {option.required_mods_name_utf8, + option.num_required_mods + option.required_mods_name_utf8}; + } + auto err = this->exportAsWESchem(filename_local, option.offset, + option.we_offset, "", sp); + + return err.empty(); + } void exportAsStructure(const char *TargetName, char *FileName) const override; std::string exportAsStructure(std::string_view filename, @@ -330,36 +361,71 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { return err.empty(); } - void save_convert_cache(std::string &err) const noexcept; + bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override { + return this->load_convert_cache(algo, dither); + } + + int getSchemPalette(const char **dest_id, + size_t dest_capacity) const noexcept override; bool saveBuildCache(StringDeliver &_err) const noexcept override { - std::string err = this->make_build_cache(); + std::string err; + this->save_build_cache(err); write(_err, err); return err.empty(); } - bool loadBuildCache(const build_options &option) noexcept override; - std::string make_build_cache() const noexcept; + bool loadBuildCache(const build_options &option) noexcept override { + return this->load_build_cache(option); + } private: - std::string task_dir() const noexcept; - std::string task_dir(uint64_t) const noexcept; - std::string task_dir(SCL_convertAlgo algo, bool dither) const noexcept; - std::string colorset_hash_file() const noexcept; - - bool check_coloset_hash_by_filename(std::string_view filename) const noexcept; - - static std::string conevrt_cache_filename(std::string_view taskdir) noexcept; - static std::string cache_owned_hash_filename( - std::string_view taskdir) noexcept; - bool check_cache_owned_hash(uint64_t task_hash) const noexcept; + // determined by mcver, map type and allowed colorest + static std::vector type_hash() noexcept; + static std::string type_dir_of(std::string_view root_cache_dir) noexcept; + inline std::string current_type_dir() const noexcept { + return type_dir_of(this->cache_dir.value()); + } + std::string type_hash_filename() const noexcept; + std::string save_type_hash() const noexcept; + bool check_type_hash() const noexcept; + + // determined by image, convert algo and dither + static std::string convert_dir(std::string_view type_dir, + uint64_t task_hash) noexcept; + std::string convert_dir_of(SCL_convertAlgo algo, bool dither) const noexcept; + std::string current_convert_dir() const noexcept; + static std::string convert_cache_filename_of( + std::string_view convert_dir) noexcept; + std::string current_convert_cache_filename() const noexcept; + void save_convert_cache(std::string &err) const noexcept; + bool load_convert_cache(SCL_convertAlgo algo, bool dither) noexcept; + + // determined by mapPic, palette from type and build_options + static std::vector build_task_hash_of( + const Eigen::ArrayXXi &mapPic, std::span blkids, + const build_options &opt) noexcept; + std::vector current_build_task_hash() const noexcept; + static std::string build_dir_of(std::string_view convert_dir, + uint64_t short_hash) noexcept; + std::string current_build_dir() const noexcept; + static std::string build_cache_filename_of( + std::string_view build_dir) noexcept; + std::string current_build_cache_filename() const noexcept; + void save_build_cache(std::string &err) const noexcept; + struct build_cache_ir { + Eigen::ArrayXXi mapPic; + build_options build_option; + libSchem::Schem schem; + }; + static std::string build_hash_filename_of( + std::string_view build_dir) noexcept; + bool exmaine_build_cache(const build_options &opt, + std::span expected_sha3_512, + build_cache_ir *ir) const noexcept; + bool load_build_cache(const build_options &opt) noexcept; private: - static uint64_t build_task_hash(const Eigen::ArrayXXi &mapPic, - std::span blkid, - const build_options &) noexcept; - uint64_t build_task_hash() const noexcept; - std::vector schem_block_id_list() const noexcept; static std::string build_task_dir(std::string_view cvt_task_dir, @@ -368,54 +434,9 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static std::string build_cache_filename( std::string_view build_task_dir) noexcept; - struct build_cache_ir { - Eigen::ArrayXXi mapPic; - build_options build_option; - libSchem::Schem schem; - }; - static bool exmaine_build_cache(std::string_view filename, uint64_t build_task_hash, build_cache_ir *ir = nullptr) noexcept; - - public: - bool checkColorsetHash() const noexcept override; - bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override; - - int getSchemPalette(const char **dest_id, - size_t dest_capacity) const noexcept override; - - bool exportAsLitematic( - const char *filename_local, - const litematic_options &option) const noexcept override { - auto err = this->exportAsLitematic(filename_local, option.litename_utf8, - option.region_name_utf8); - return err.empty(); - } - - bool exportStructure( - const char *filename_local, - const vanilla_structure_options &option) const noexcept override { - auto err = - this->exportAsStructure(filename_local, option.is_air_structure_void); - return err.empty(); - } - - bool exportAsWESchem(const char *filename_local, - const WE_schem_options &option) const noexcept override { - const bool have_req = option.num_required_mods > 0 && - option.required_mods_name_utf8 != nullptr; - std::span sp{}; - - if (have_req) { - sp = {option.required_mods_name_utf8, - option.num_required_mods + option.required_mods_name_utf8}; - } - auto err = this->exportAsWESchem(filename_local, option.offset, - option.we_offset, "", sp); - - return err.empty(); - } }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 9092b396..7ad18cde 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -5,13 +5,15 @@ #include #include #include +#include #include #include namespace stdfs = std::filesystem; +// common utilities ------------------------------------ std::string write_hash(std::string_view filename, - const std::vector &hash) noexcept { + std::span hash) noexcept { std::ofstream ofs{filename.data(), std::ios::binary}; if (!ofs) { @@ -23,6 +25,52 @@ std::string write_hash(std::string_view filename, return {}; } +bool examine_hash_file(std::string_view filename, + std::span expected) noexcept { + if (!stdfs::is_regular_file(filename)) { + return false; + } + const uint64_t filesize = stdfs::file_size(filename); + if (filesize != expected.size()) { + return false; + } + { + std::ifstream ifs{filename.data(), std::ios::binary}; + if (!ifs) { + return false; + } + + for (uint8_t exp_val : expected) { + uint8_t val{0}; + ifs.read((char *)&val, sizeof(val)); + if (val != exp_val) { + return false; + } + } + ifs.close(); + } + + return true; +} + +bool create_dir_r_if_not_exist(std::string_view dir, + std::string &err) noexcept { + err.clear(); + if (stdfs::is_directory(dir)) { + return true; + } + std::error_code ec; + if (stdfs::create_directories(dir, ec)) { + return true; + } + + err = fmt::format( + "Cache directory \"{}\" does not exists, and std::filesystem failed to " + "create this dir. Error code = {}, message = {}.", + dir, ec.value(), ec.message()); + return false; +} + void TokiSlopeCraft::setCacheDir(const char *d) noexcept { this->cache_dir = d; @@ -38,6 +86,302 @@ const char *TokiSlopeCraft::cacheDir() const noexcept { const std::string_view hash_suffix{".sha3_512"}; +#define SC_HASH_ADD_DATA(hasher, obj) hasher.addData(&obj, sizeof(obj)); + +uint64_t to_short_hash(std::span full_hash) noexcept { + assert(full_hash.size() % 8 == 0); + uint64_t ret = 0; + std::span hash_u64{(const uint64_t *)full_hash.data(), + full_hash.size() / sizeof(uint64_t)}; + for (uint64_t val : hash_u64) { + ret = ret ^ val; + } + return ret; +} +// type hash and dir ------------------------------------ +std::vector TokiSlopeCraft::type_hash() noexcept { + Chocobo1::SHA3_512 hash; + SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mapType); + SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mcVer); + + TokiSlopeCraft::Allowed.hash_add_data(hash); + + hash.finalize(); + return hash.toVector(); +} + +std::string TokiSlopeCraft::type_dir_of(std::string_view cache_dir) noexcept { + return fmt::format("{}/{:x}", cache_dir, to_short_hash(type_hash())); +} + +std::string TokiSlopeCraft::type_hash_filename() const noexcept { + assert(this->kernelStep >= SCL_step::wait4Image); + return fmt::format("{}/{}{}", this->current_type_dir(), "type", hash_suffix); +} + +std::string TokiSlopeCraft::save_type_hash() const noexcept { + if (this->kernelStep < SCL_step::wait4Image) { + return "Set map type before you export type hash."; + } + std::string err; + if (!create_dir_r_if_not_exist(this->current_type_dir(), err)) { + return err; + } + + err = write_hash(this->type_hash_filename(), this->type_hash()); + return err; +} + +bool TokiSlopeCraft::check_type_hash() const noexcept { + return examine_hash_file(this->type_hash_filename(), this->type_hash()); +} + +// convert hash, dir and cache ------------------------------------ +std::string TokiSlopeCraft::convert_dir(std::string_view type_dir, + uint64_t short_hash) noexcept { + return fmt::format("{}/{:x}", type_dir, short_hash); +} + +std::string TokiSlopeCraft::convert_dir_of(SCL_convertAlgo algo, + bool dither) const noexcept { + assert(this->kernelStep >= SCL_step::convertionReady); + return convert_dir(this->current_type_dir(), + this->image_cvter.task_hash(algo, dither)); +} + +std::string TokiSlopeCraft::current_convert_dir() const noexcept { + assert(this->kernelStep >= SCL_step::converted); + return this->convert_dir_of(this->image_cvter.convert_algo(), + this->image_cvter.is_dither()); +} + +std::string TokiSlopeCraft::convert_cache_filename_of( + std::string_view convert_dir) noexcept { + return fmt::format("{}/convert", convert_dir); +} + +std::string TokiSlopeCraft::current_convert_cache_filename() const noexcept { + assert(this->kernelStep >= SCL_step::converted); + return convert_cache_filename_of(this->current_convert_dir()); +} + +void TokiSlopeCraft::save_convert_cache(std::string &err) const noexcept { + err.clear(); + if (this->kernelStep < SlopeCraft::step::converted) { + err = "Can not save cache before the image is converted."; + return; + } + this->save_type_hash(); + const std::string convert_dir = this->current_convert_dir(); + if (!create_dir_r_if_not_exist(convert_dir, err)) { + return; + } + + std::string filename = convert_cache_filename_of(convert_dir); + if (!this->image_cvter.save_cache(filename.c_str())) { + err = fmt::format("this->image_cvter.save_cache failed to create {}", + filename); + return; + } + return; +} + +bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, + bool dither) noexcept { + if (this->kernelStep < SlopeCraft::step::convertionReady) { + // "Can not save cache before the image is converted."; + return false; + } + + if (!this->check_type_hash()) { // type hash mismatch + return false; + } + + libMapImageCvt::MapImageCvter temp; + const uint64_t expected_hash = this->image_cvter.task_hash(algo, dither); + const std::string filename = this->convert_cache_filename_of( + convert_dir(this->current_type_dir(), expected_hash)); + if (!this->image_cvter.load_cache(filename.c_str(), expected_hash)) { + return false; + } + + this->mapPic = this->image_cvter.mapcolor_matrix().cast(); + this->kernelStep = SCL_step::converted; + return true; +} + +// build hash, dir and cache ------------------------------------ +namespace cereal { +template +void save(archive &ar, const SlopeCraft::Kernel::build_options &opt) noexcept { + ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, + opt.glassMethod); + ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); +} + +template +void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { + ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, + opt.glassMethod); + ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); +} +} // namespace cereal +std::vector TokiSlopeCraft::build_task_hash_of( + const Eigen::ArrayXXi &mapPic, std::span blkids, + const build_options &opt) noexcept { + Chocobo1::SHA3_512 hash; + { + const int64_t rows{mapPic.rows()}; + const int64_t cols{mapPic.cols()}; + SC_HASH_ADD_DATA(hash, rows); + SC_HASH_ADD_DATA(hash, cols); + hash.addData(mapPic.data(), mapPic.size() * sizeof(uint32_t)); + } + + for (auto blkid : blkids) { + hash.addData(blkid.data(), blkid.size()); + } + { + SC_HASH_ADD_DATA(hash, opt.maxAllowedHeight); + SC_HASH_ADD_DATA(hash, opt.bridgeInterval); + SC_HASH_ADD_DATA(hash, opt.compressMethod); + SC_HASH_ADD_DATA(hash, opt.glassMethod); + SC_HASH_ADD_DATA(hash, opt.fire_proof); + SC_HASH_ADD_DATA(hash, opt.enderman_proof); + } + + return hash.finalize().toVector(); +} + +std::vector TokiSlopeCraft::current_build_task_hash() const noexcept { + assert(this->kernelStep >= SCL_step::converted); + auto abil = this->schem_block_id_list(); + return build_task_hash_of(this->mapPic, abil, this->build_opt); +} + +std::string TokiSlopeCraft::build_dir_of(std::string_view convert_dir, + uint64_t short_hash) noexcept { + return fmt::format("{}/{}", convert_dir, short_hash); +} + +std::string TokiSlopeCraft::current_build_dir() const noexcept { + assert(this->kernelStep >= SCL_step::converted); + return build_dir_of(this->current_convert_dir(), + to_short_hash(this->current_build_task_hash())); +} + +std::string TokiSlopeCraft::build_cache_filename_of( + std::string_view build_dir) noexcept { + return fmt::format("{}/build.gz", build_dir); +} + +std::string TokiSlopeCraft::current_build_cache_filename() const noexcept { + assert(this->kernelStep >= SCL_step::builded); + return build_cache_filename_of(this->current_build_dir()); +} + +std::string TokiSlopeCraft::build_hash_filename_of( + std::string_view build_dir) noexcept { + return fmt::format("{}/build_task_hash{}", build_dir, hash_suffix); +} + +void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { + err.clear(); + + if (this->kernelStep < SCL_step::builded) { + err = "Can not save cache before 3d is built."; + return; + } + + const std::string build_dir = this->current_build_dir(); + if (!create_dir_r_if_not_exist(build_dir, err)) { + return; + } + + const std::string filename = build_cache_filename_of(build_dir); + { + // std::ofstream ofs{build_cache_file, std::ios::binary}; + zstr::ofstream ofs{filename, std::ios::binary, Z_DEFAULT_COMPRESSION}; + if (!ofs) { + err = fmt::format("ofstream failed to open cache file {}", filename); + return; + } + + { + cereal::BinaryOutputArchive boa{ofs}; + boa(this->mapPic); + boa(this->build_opt); + boa(this->schem); + } + ofs.close(); + } + + auto sha3_512 = this->current_build_task_hash(); + err += write_hash(build_hash_filename_of(build_dir), sha3_512); + return; +} + +bool TokiSlopeCraft::exmaine_build_cache( + const build_options &opt, std::span expected_sha3_512, + build_cache_ir *ir) const noexcept { + assert(this->kernelStep >= SCL_step::converted); + const std::string build_dir = build_dir_of(this->current_convert_dir(), + to_short_hash(expected_sha3_512)); + + if (!examine_hash_file(this->build_hash_filename_of(build_dir), + expected_sha3_512)) { + return false; + } + + build_cache_ir temp; + try { + auto filename = this->build_cache_filename_of(build_dir); + zstr::ifstream ifs{filename, std::ios::binary}; + if (!ifs) { + return false; + } + + { + cereal::BinaryInputArchive bia{ifs}; + bia(temp.mapPic); + bia(temp.build_option); + bia(temp.schem); + } + ifs.close(); + } catch (...) { + return false; + } + + if (ir != nullptr) { + *ir = std::move(temp); + } + + return true; +} + +bool TokiSlopeCraft::load_build_cache(const build_options &opt) noexcept { + if (this->kernelStep < SCL_step::converted) { + return false; + } + + auto sbil = this->schem_block_id_list(); + auto expected_hash = this->build_task_hash_of(this->mapPic, sbil, opt); + + build_cache_ir ir; + + if (!this->exmaine_build_cache(opt, expected_hash, &ir)) { + return false; + } + + this->mapPic = std::move(ir.mapPic); + this->build_opt = opt; + this->schem = std::move(ir.schem); + + this->kernelStep = SCL_step::builded; + return true; +} + +/* std::string TokiSlopeCraft::colorset_hash_file() const noexcept { return fmt::format("{}/{}{}", this->cache_dir.value(), "colorset", hash_suffix); @@ -257,21 +601,6 @@ std::string TokiSlopeCraft::build_cache_filename( std::string_view build_task_dir) noexcept { return fmt::format("{}/build.gz", build_task_dir); } -namespace cereal { -template -void save(archive &ar, const SlopeCraft::Kernel::build_options &opt) noexcept { - ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, - opt.glassMethod); - ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); -} - -template -void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { - ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, - opt.glassMethod); - ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); -} -} // namespace cereal std::string TokiSlopeCraft::make_build_cache() const noexcept { if (this->kernelStep < SlopeCraft::step::builded) { @@ -371,4 +700,4 @@ bool TokiSlopeCraft::loadBuildCache(const build_options &option) noexcept { this->kernelStep = SCL_step::builded; return true; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index e897fdfd..5950b2e0 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -22,8 +22,8 @@ add_library(ColorManip newColorSet.hpp newTokiColor.hpp StaticMembers.cpp - hash.cpp + hash.cpp colorset_maptical.hpp imageConvert.hpp newColorSet.hpp diff --git a/utilities/ColorManip/hash.cpp b/utilities/ColorManip/hash.cpp index e1c4b6a0..fff57061 100644 --- a/utilities/ColorManip/hash.cpp +++ b/utilities/ColorManip/hash.cpp @@ -2,7 +2,7 @@ #include "imageConvert.hpp" #include - +/* std::vector internal::hash_of_colorset( const hash_temp &temp) noexcept { Chocobo1::SHA3_512 stream; @@ -21,6 +21,8 @@ std::vector internal::hash_of_colorset( return stream.finalize().toVector(); } +*/ + std::vector libImageCvt::hash_of_image( Eigen::Map> img) noexcept { Chocobo1::SHA3_512 stream; diff --git a/utilities/ColorManip/newColorSet.hpp b/utilities/ColorManip/newColorSet.hpp index a9b164df..d5e95e2c 100644 --- a/utilities/ColorManip/newColorSet.hpp +++ b/utilities/ColorManip/newColorSet.hpp @@ -42,7 +42,7 @@ struct hash_temp { bool is_maptical; }; -std::vector hash_of_colorset(const hash_temp &) noexcept; +// std::vector hash_of_colorset(const hash_temp &) noexcept; } // namespace internal @@ -83,8 +83,9 @@ class colorset_new : public std::conditional_t< return NAN; } + private: template - std::vector hash() const noexcept { + internal::hash_temp hash_temp() const noexcept { internal::hash_temp temp; temp.color_count = this->color_count(); temp.color_ptrs[0] = {this->rgb_data(0), this->rgb_data(1), @@ -98,9 +99,31 @@ class colorset_new : public std::conditional_t< temp.color_id_ptr = this->map_data(); temp.is_maptical = is_not_optical; - + return temp; + } + /* + template + std::vector hash() const noexcept { return internal::hash_of_colorset(temp); } + */ + + public: + template + void hash_add_data(hash_stream &stream) const noexcept { + auto temp = this->hash_temp(); + + for (const auto &cptrs : temp.color_ptrs) { + for (const float *fptr : cptrs) { + stream.addData(fptr, temp.color_count * sizeof(float)); + } + } + + stream.addData(temp.color_id_ptr, + temp.color_count * + (temp.is_maptical ? sizeof(uint8_t) : sizeof(uint16_t))); + stream.addData(&temp.color_count, sizeof(temp.color_count)); + } }; #endif // SCL_NEWCOLORSET_HPP \ No newline at end of file From 35f1b556d5668f14c88c9ffb8a145286ae2ed8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 19:25:29 +0800 Subject: [PATCH 0303/1123] use new cache design --- SlopeCraft/SCWind.cpp | 17 ++++++++--------- SlopeCraft/SCWind.h | 2 +- SlopeCraft/SCWind_slots.cpp | 8 ++++++++ SlopeCraft/cvt_task.h | 5 +++++ 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0910d6b2..06770ab9 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -541,10 +541,6 @@ void SCWind::kernel_make_cvt_cache() noexcept { } } -bool SCWind::kernel_check_colorset_hash() noexcept { - return this->kernel->checkColorsetHash(); -} - QImage SCWind::get_converted_image_from_kernel() const noexcept { assert(this->kernel->queryStep() >= SCL_step::converted); @@ -586,11 +582,12 @@ void SCWind::refresh_current_cvt_display( return; } - if (!kernel_check_colorset_hash()) { - this->mark_all_task_unconverted(); - emit this->image_changed(); - return; - } + /* + if (!kernel_check_colorset_hash()) { + this->mark_all_task_unconverted(); + emit this->image_changed(); + return; + }*/ this->kernel_set_image(idx); @@ -679,10 +676,12 @@ void SCWind::refresh_current_build_display( // try to load convert cache if (!this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { + taskp.value()->set_unconverted(); return; } // try to load build cache if (!this->kernel->loadBuildCache(this->current_build_option())) { + taskp.value()->set_unbuilt(); return; } } else { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index ba51ea4d..4aba864f 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -127,7 +127,7 @@ class SCWind : public QMainWindow { void kernel_make_cvt_cache() noexcept; - bool kernel_check_colorset_hash() noexcept; + // bool kernel_check_colorset_hash() noexcept; void kernel_build_3d() noexcept; void kernel_make_build_cache() noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 3c1386b3..1d081770 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -311,6 +311,14 @@ void SCWind::on_pb_build3d_clicked() noexcept { tr("必须先转化一个图像,然后再为它构建三维结构")); return; } + { + const int gidx = taskopt.value() - this->tasks.data(); + this->kernel_set_image(gidx); + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + this->kernel_convert_image(); + } + } this->kernel_build_3d(); this->kernel_make_build_cache(); diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 9c3b3039..5716f5a9 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -38,6 +38,11 @@ struct cvt_task { this->is_built = false; this->is_exported = false; } + + void set_unbuilt() noexcept { + this->is_built = false; + this->is_exported = false; + } }; Q_DECLARE_METATYPE(cvt_task); From d68fd375b2753b8ca1273e9e1d31c335dc6ea815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 12 May 2023 19:46:00 +0800 Subject: [PATCH 0304/1123] add `connect_mushrooms` to hash --- SlopeCraftL/TokiSlopeCraft_cache.cpp | 327 +-------------------------- 1 file changed, 5 insertions(+), 322 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 7ad18cde..4e18938e 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -89,7 +89,9 @@ const std::string_view hash_suffix{".sha3_512"}; #define SC_HASH_ADD_DATA(hasher, obj) hasher.addData(&obj, sizeof(obj)); uint64_t to_short_hash(std::span full_hash) noexcept { - assert(full_hash.size() % 8 == 0); + assert(full_hash.size() >= 8); + return *reinterpret_cast(full_hash.data()); + /* uint64_t ret = 0; std::span hash_u64{(const uint64_t *)full_hash.data(), full_hash.size() / sizeof(uint64_t)}; @@ -97,6 +99,7 @@ uint64_t to_short_hash(std::span full_hash) noexcept { ret = ret ^ val; } return ret; + */ } // type hash and dir ------------------------------------ std::vector TokiSlopeCraft::type_hash() noexcept { @@ -248,6 +251,7 @@ std::vector TokiSlopeCraft::build_task_hash_of( SC_HASH_ADD_DATA(hash, opt.glassMethod); SC_HASH_ADD_DATA(hash, opt.fire_proof); SC_HASH_ADD_DATA(hash, opt.enderman_proof); + SC_HASH_ADD_DATA(hash, opt.connect_mushrooms); } return hash.finalize().toVector(); @@ -380,324 +384,3 @@ bool TokiSlopeCraft::load_build_cache(const build_options &opt) noexcept { this->kernelStep = SCL_step::builded; return true; } - -/* -std::string TokiSlopeCraft::colorset_hash_file() const noexcept { - return fmt::format("{}/{}{}", this->cache_dir.value(), "colorset", - hash_suffix); -} - -std::string TokiSlopeCraft::task_dir() const noexcept { - return this->task_dir(this->image_cvter.task_hash()); -} - -std::string TokiSlopeCraft::task_dir(uint64_t hash) const noexcept { - return fmt::format("{}/{:x}", this->cache_dir.value(), hash); -} -std::string TokiSlopeCraft::task_dir(SCL_convertAlgo algo, - bool dither) const noexcept { - return this->task_dir(this->image_cvter.task_hash(algo, dither)); -} - -std::string TokiSlopeCraft::conevrt_cache_filename( - std::string_view taskdir) noexcept { - return fmt::format("{}/convert", taskdir); -} - -std::string TokiSlopeCraft::cache_owned_hash_filename( - std::string_view taskdir) noexcept { - return fmt::format("{}/private_hash{}", taskdir, hash_suffix); -} - -void TokiSlopeCraft::save_convert_cache(std::string &err) const noexcept { - if (this->kernelStep < SlopeCraft::step::converted) { - err = "Can not save cache before the image is converted."; - return; - } - - if (!this->cache_dir.has_value()) { - err = "cache dir is not set."; - return; - } - - const std::string task_dir = this->task_dir(); - - namespace stdfs = std::filesystem; - std::error_code ec; - if (!stdfs::is_directory(task_dir)) { - if (!stdfs::create_directories(task_dir, ec)) { - err = fmt::format( - "Failed to create dir named \"{}\", error code = {}, message = {}", - task_dir, ec.value(), ec.message()); - return; - } - } - err.clear(); - std::string temp_err{}; - - // write 2 colorset hash files - { - const std::string name_hash_colorset = this->colorset_hash_file(); - const auto hash = TokiSlopeCraft::Allowed.hash(); - - temp_err = write_hash(name_hash_colorset, hash); - if (!temp_err.empty()) { - err = fmt::format("Failed to save colorset hash. Detail: {}", temp_err); - return; - } - - temp_err = write_hash(this->cache_owned_hash_filename(task_dir), hash); - if (!temp_err.empty()) { - err = fmt::format("Failed to save colorset hash. Detail: {}", temp_err); - return; - } - } - - const std::string convert_cache_file = - TokiSlopeCraft::conevrt_cache_filename(task_dir); - - if (!this->image_cvter.save_cache(convert_cache_file.c_str())) { - err = fmt::format("Failed to save image cvter cache."); - return; - } - - return; -} - -bool TokiSlopeCraft::check_coloset_hash_by_filename( - std::string_view filename) const noexcept { - if (this->kernelStep < SCL_step::wait4Image) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can check for colorset only after you set the map type"); - return false; - } - - std::vector buf; - { - std::ifstream ifs{filename.data(), std::ios::binary}; - - if (!ifs) { // file not exist - return false; - } - - const size_t file_size = std::filesystem::file_size(filename.data()); - if (file_size <= 0) { // empty file - return false; - } - - buf.resize(file_size); - - ifs.read((char *)buf.data(), file_size); - } - - const auto current_hash = TokiSlopeCraft::Allowed.hash(); - - if (current_hash.size() != buf.size()) { // length mismatch - return false; - } - - for (size_t idx = 0; idx < buf.size(); idx++) { - if (buf[idx] != current_hash[idx]) { // hash checksum failed. - return false; - } - } - - return true; -} - -bool TokiSlopeCraft::checkColorsetHash() const noexcept { - return this->check_coloset_hash_by_filename(this->colorset_hash_file()); -} - -bool TokiSlopeCraft::check_cache_owned_hash(uint64_t task_hash) const noexcept { - return this->check_coloset_hash_by_filename( - this->cache_owned_hash_filename(this->task_dir(task_hash))); -} - -bool TokiSlopeCraft::loadConvertCache(SCL_convertAlgo algo, - bool dither) noexcept { - if (this->kernelStep < SCL_step::convertionReady) { - reportError( - wind, errorFlag::HASTY_MANIPULATION, - "You can load convert cache only after you set the original image"); - return false; - } - - if (!this->checkColorsetHash()) { - return false; - } - - const uint64_t expected_task_hash = this->image_cvter.task_hash(algo, dither); - - if (!this->check_cache_owned_hash(expected_task_hash)) { - return false; - } - - const std::string expected_task_dir = this->task_dir(expected_task_hash); - - const std::string expected_cache_file = - this->conevrt_cache_filename(expected_task_dir); - - const bool ok = this->image_cvter.load_cache(expected_cache_file.c_str(), - expected_task_hash); - - if (ok) { - this->mapPic = this->image_cvter.mapcolor_matrix().cast(); - this->kernelStep = SCL_step::converted; - return true; - } - return false; -} - -uint64_t TokiSlopeCraft::build_task_hash(const Eigen::ArrayXXi &mapPic, - std::span blkid, - const build_options &bo) noexcept { - Chocobo1::MD5 hash; - { - const int64_t rows{mapPic.rows()}, cols{mapPic.cols()}; - hash.addData(&rows, sizeof(rows)); - hash.addData(&cols, sizeof(cols)); - } - hash.addData(mapPic.data(), mapPic.size() * sizeof(mapPic(0))); - - for (auto str : blkid) { - hash.addData(str.data(), str.size()); - } - - hash.addData(&bo.maxAllowedHeight, sizeof(bo.maxAllowedHeight)); - hash.addData(&bo.bridgeInterval, sizeof(bo.bridgeInterval)); - hash.addData(&bo.compressMethod, sizeof(bo.compressMethod)); - hash.addData(&bo.glassMethod, sizeof(bo.glassMethod)); - hash.addData(&bo.fire_proof, sizeof(bo.fire_proof)); - hash.addData(&bo.enderman_proof, sizeof(bo.enderman_proof)); - hash.addData(&bo.connect_mushrooms, sizeof(bo.connect_mushrooms)); - - hash.finalize(); - - auto bytes = hash.toArray(); - - static_assert(bytes.size() == 16); - - const uint64_t *const hash_data = (const uint64_t *)bytes.data(); - return hash_data[0] ^ hash_data[1]; -} - -uint64_t TokiSlopeCraft::build_task_hash() const noexcept { - assert(this->kernelStep >= SCL_step::builded); - auto sbil = this->schem_block_id_list(); - return build_task_hash(this->mapPic, sbil, this->build_opt); -} - -std::string TokiSlopeCraft::build_task_dir(std::string_view cvt_task_dir, - uint64_t build_task_hash) noexcept { - return fmt::format("{}/{:x}", cvt_task_dir, build_task_hash); -} - -std::string TokiSlopeCraft::build_task_dir() const noexcept { - return build_task_dir(this->task_dir(), this->build_task_hash()); -} - -std::string TokiSlopeCraft::build_cache_filename( - std::string_view build_task_dir) noexcept { - return fmt::format("{}/build.gz", build_task_dir); -} - -std::string TokiSlopeCraft::make_build_cache() const noexcept { - if (this->kernelStep < SlopeCraft::step::builded) { - return "Can not save cache before the 3d structure id built."; - } - - const std::string build_cache_dir = build_task_dir(); - if (!stdfs::is_directory(build_cache_dir)) { - std::error_code ec; - - if (!stdfs::create_directories(build_cache_dir, ec)) { - return fmt::format( - "Failed to create dir named \"{}\", error code = {}, message = {}", - build_cache_dir, ec.value(), ec.message()); - } - } - const std::string build_cache_file = build_cache_filename(build_cache_dir); - { - // std::ofstream ofs{build_cache_file, std::ios::binary}; - zstr::ofstream ofs{build_cache_file, std::ios::binary, Z_BEST_COMPRESSION}; - if (!ofs) { - return fmt::format("ofstream failed to open cache file {}", - build_cache_file); - } - - { - cereal::BinaryOutputArchive boa{ofs}; - boa(this->mapPic); - boa(this->build_opt); - boa(this->schem); - } - ofs.close(); - } - - return {}; -} - -bool TokiSlopeCraft::exmaine_build_cache(std::string_view filename, - uint64_t expected_task_hash, - build_cache_ir *ir) noexcept { - build_cache_ir temp; - { - if (!stdfs::is_regular_file(filename)) { - return false; - } - // std::ifstream ifs{filename.data(), std::ios::binary}; - zstr::ifstream ifs{filename.data(), std::ios::binary}; - cereal::BinaryInputArchive bia{ifs}; - try { - bia(temp.mapPic); - bia(temp.build_option); - bia(temp.schem); - } catch (std::exception &) { - return false; - } - } - { - std::vector blkids; - blkids.reserve(temp.schem.palette().size()); - for (const auto &bid : temp.schem.palette()) { - blkids.emplace_back(bid); - } - - const uint64_t hash = - TokiSlopeCraft::build_task_hash(temp.mapPic, blkids, temp.build_option); - - if (hash != expected_task_hash) { - return false; - } - } - - if (ir != nullptr) { - *ir = std::move(temp); - } - return true; -} - -bool TokiSlopeCraft::loadBuildCache(const build_options &option) noexcept { - if (this->kernelStep < SCL_step::converted) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can load build cache only after you convert a image"); - return false; - } - auto sbil = this->schem_block_id_list(); - const uint64_t expected_hash = build_task_hash(this->mapPic, sbil, option); - const std::string cache_filename = this->build_cache_filename( - this->build_task_dir(this->task_dir(), expected_hash)); - - build_cache_ir ir; - if (!this->exmaine_build_cache(cache_filename, expected_hash, &ir)) { - return false; - } - - this->mapPic = std::move(ir.mapPic); - this->build_opt = option; - this->schem = std::move(ir.schem); - - this->kernelStep = SCL_step::builded; - return true; -}*/ \ No newline at end of file From 31153e08292bbc753acb6ac51d39a4bc25a37726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 15:37:37 +0800 Subject: [PATCH 0305/1123] add --force and --no-translations to windeployqt --- CMakeLists.txt | 3 +++ MapViewer/install.cmake | 5 +++-- SlopeCraft/install.cmake | 5 +++-- VisualCraft/install.cmake | 5 +++-- cmake/deploy_qt.cmake.in | 2 +- imageCutter/install.cmake | 5 +++-- vccl/install.cmake | 5 +++-- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bcfa211..2cf2558f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,6 +119,9 @@ include_directories(${CMAKE_BINARY_DIR}/utilities) if(${WIN32}) add_custom_target(SC_create_all_symlinks COMMENT "A interface target to create all symlinks on windows") + + add_custom_target(SC_deploy_all + COMMENT "A interface target to run windeployqt for all targets") endif() # Sub dirss ------------------------------------------------------------------ diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 59453549..97705a9d 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -10,10 +10,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") ) # Run windeployqt at build time - add_custom_target(Windeployqt-MapViewer ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} MapViewer.exe + add_custom_target(Windeployqt-MapViewer + COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations MapViewer.exe WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MapViewer) + add_dependencies(SC_deploy_all Windeployqt-MapViewer) # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index aa7497be..4d3f800b 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -64,10 +64,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") ) # Run windeployqt at build time - add_custom_target(Windeployqt-SlopeCraft ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe + add_custom_target(Windeployqt-SlopeCraft + COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations SlopeCraft.exe WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS SlopeCraft) + add_dependencies(SC_deploy_all Windeployqt-SlopeCraft) # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index dbf68f65..5038d0a6 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -13,10 +13,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") DESTINATION .) # Run windeployqt at build time - add_custom_target(Windeployqt-VisualCraft ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} VisualCraft.exe + add_custom_target(Windeployqt-VisualCraft + COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations VisualCraft.exe WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS VisualCraft) + add_dependencies(SC_deploy_all Windeployqt-VisualCraft) # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index c9880c88..a6f5eab4 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -3,7 +3,7 @@ if(${WIN32}) message(STATUS "Running windeployqt for @AppName@ ...") execute_process( - COMMAND "@SlopeCraft_Qt_windeployqt_executable@" "@AppName@.exe" + COMMAND "@SlopeCraft_Qt_windeployqt_executable@" --force --no-translations "@AppName@.exe" WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 7317f153..4a2c823d 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -10,10 +10,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") ) # Run windeployqt at build time - add_custom_target(Windeployqt-imageCutter ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} imageCutter.exe + add_custom_target(Windeployqt-imageCutter + COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations imageCutter.exe WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS imageCutter) + add_dependencies(SC_deploy_all Windeployqt-imageCutter) # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) diff --git a/vccl/install.cmake b/vccl/install.cmake index ce2c9643..93aa5710 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -11,10 +11,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") DESTINATION .) # Run windeployqt at build time - add_custom_target(Windeployqt-vccl ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} vccl.exe + add_custom_target(Windeployqt-vccl + COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations vccl.exe WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS vccl) + add_dependencies(SC_deploy_all Windeployqt-vccl) # Run windeployqt at install time install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) From b38ffa07da6b56e8cf85af538faa9cb9e385a339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 18:13:41 +0800 Subject: [PATCH 0306/1123] fix build without avx --- CMakeLists.txt | 6 ++++ utilities/ColorManip/colorset_optical.hpp | 37 ++++++++++++----------- utilities/ColorManip/newTokiColor.hpp | 13 +++++--- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cf2558f..1c8af3bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,12 @@ endif() # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) +if(NOT ${SlopeCraft_vectorize}) + if(NOT ${SlopeCraft_GPU_API} STREQUAL "None") + message(STATUS "You enabled GPU boosting, but disabled vectorization") + endif() +endif() + if(${SlopeCraft_vectorize}) include(CheckCXXCompilerFlag) add_definitions("-DSC_VECTORIZE_AVX2") diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index c6ac44cf..f731be06 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -29,16 +29,16 @@ This file is part of SlopeCraft. #include class alignas(32) colorset_optical_base { -protected: + protected: std::array __rgb; std::array __hsv; std::array __lab; std::array __xyz; -private: + private: int _color_count; -public: + public: inline int color_count() const noexcept { return _color_count; } inline float RGB(int r, int c) const noexcept { return __rgb[c](r); } @@ -57,7 +57,7 @@ class alignas(32) colorset_optical_base { inline auto xyz(int c) const noexcept { return __xyz[c].head(_color_count); } inline const float *xyz_data(int c) const noexcept { return __xyz[c].data(); } -protected: + protected: void resize(int new_color_count) noexcept { if (new_color_count < 0) { new_color_count = 0; @@ -75,7 +75,7 @@ class alignas(32) colorset_optical_base { }; class colorset_optical_basic : public colorset_optical_base { -public: + public: /// in the basic colorset, id=idx; inline uint16_t color_id(uint16_t idx) const noexcept { return idx; } colorset_optical_basic() { this->resize(0); } @@ -132,17 +132,17 @@ class colorset_optical_basic : public colorset_optical_base { return color_id; } - inline uint16_t - colorindex_of_colorid(const uint16_t color_id) const noexcept { + inline uint16_t colorindex_of_colorid( + const uint16_t color_id) const noexcept { return this->colorindex_of_id(color_id); } }; class colorset_optical_allowed : public colorset_optical_base { -public: + public: static constexpr uint16_t invalid_color_id = 0xFFFF; -private: + private: Eigen::Array __color_id; void resize(int new_color_count) { @@ -151,7 +151,7 @@ class colorset_optical_allowed : public colorset_optical_base { __color_id.fill(invalid_color_id); } -public: + public: colorset_optical_allowed() { this->resize(0); } bool apply_allowed(const colorset_optical_basic &src, @@ -199,11 +199,11 @@ class colorset_optical_allowed : public colorset_optical_base { }; class TempVecOptical : public Eigen::Map { -public: + public: static constexpr size_t capacity = 65536; using Base_t = Eigen::Map; -public: + public: TempVecOptical(int rows, int cols) : Base_t((float *)SC_aligned_alloc(64, capacity * sizeof(float)), rows, cols) { @@ -229,18 +229,19 @@ class TempVecOptical : public Eigen::Map { }; class newtokicolor_base_optical { -public: - using TempVectorXf_t = TempVecOptical; + public: + // using TempVectorXf_t = TempVecOptical; + using TempVectorXf_t = Eigen::ArrayXf; using result_t = uint16_t; -protected: + protected: result_t result_color_id{ - colorset_optical_allowed::invalid_color_id}; // the final color index -public: + colorset_optical_allowed::invalid_color_id}; // the final color index + public: inline result_t color_id() const noexcept { return result_color_id; } inline bool is_result_computed() const noexcept { return (result_color_id != colorset_optical_allowed::invalid_color_id); } }; -#endif // COLORMANIP_COLORSET_OPTICAL_HPP \ No newline at end of file +#endif // COLORMANIP_COLORSET_OPTICAL_HPP \ No newline at end of file diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index b3aa3685..f28fb2ed 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -384,7 +384,8 @@ class newTokiColor auto Diff0_2 = (Allowed->rgb(0) - c3[0]).square(); auto Diff1_2 = (Allowed->rgb(1) - c3[1]).square(); auto Diff2_2 = (Allowed->rgb(2) - c3[2]).square(); - TempVectorXf_t Diff = Diff0_2 + Diff1_2 + Diff2_2; + TempVectorXf_t Diff{Allowed->color_count(), 1}; + Diff = Diff0_2 + Diff1_2 + Diff2_2; #endif // Data.CurrentColor-=allowedColors; @@ -673,7 +674,8 @@ class newTokiColor auto Diff1_2 = (Allowed->xyz(1) - c3[1]).square(); auto Diff2_2 = (Allowed->xyz(2) - c3[2]).square(); - TempVectorXf_t Diff = Diff0_2 + Diff1_2 + Diff2_2; + TempVectorXf_t Diff(Allowed->color_count(), 1); + Diff = Diff0_2 + Diff1_2 + Diff2_2; #endif // Data.CurrentColor-=allowedColors; return find_result(Diff); @@ -798,7 +800,9 @@ class newTokiColor // const ColorList &allowedColors = Allowed->Lab; auto deltaL_2 = (Allowed->lab(0) - L).square(); float C1_2 = a * a + b * b; - TempVectorXf_t C2_2 = Allowed->lab(1).square() + Allowed->lab(2).square(); + + TempVectorXf_t C2_2(Allowed->color_count(), 1); + C2_2 = Allowed->lab(1).square() + Allowed->lab(2).square(); auto deltaCab_2 = (sqrt(C1_2) - C2_2.sqrt()).square(); auto deltaHab_2 = (Allowed->lab(1) - a).square() + (Allowed->lab(2) - b).square() - deltaCab_2; @@ -807,7 +811,8 @@ class newTokiColor // K2=0.015f float SC_2 = (sqrt(C1_2) * 0.045f + 1.0f) * (sqrt(C1_2) * 0.045f + 1.0f); auto SH_2 = (C2_2.sqrt() * 0.015f + 1.0f).square(); - TempVectorXf_t Diff = deltaL_2 + deltaCab_2 / SC_2 + deltaHab_2 / SH_2; + TempVectorXf_t Diff(Allowed->color_count(), 1); + Diff = deltaL_2 + deltaCab_2 / SC_2 + deltaHab_2 / SH_2; #endif return find_result(Diff); } From 8463c3d644d6488afd87462b369bb1c70b924e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 18:28:30 +0800 Subject: [PATCH 0307/1123] add build without avx to github action --- .github/workflows/build-dev.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 2238c9a2..6529f807 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -175,9 +175,14 @@ jobs: matrix: build_type: [Debug, Release] gpu_api: [None] + vectorize: [true, false] + exclude: + - gpu_api: OpenCL + vectorize: false env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} + VECTORIZE: ${{ matrix.vectorize }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | @@ -290,7 +295,7 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - name: CMake build run: | From 7848528ff9c84db3a7b7fd9ed0345b7132ad4a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 18:29:28 +0800 Subject: [PATCH 0308/1123] add build without avx to github action --- .github/workflows/build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 6529f807..b683b45f 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -329,14 +329,14 @@ jobs: - name: Upload zip pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-windows-zip + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip path: pack/SlopeCraft*.zip if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-windows-7z + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z path: pack/SlopeCraft*.7z if-no-files-found: error From 1c19ed1a8b6605c75bb80114571d8d96b78b86d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 18:48:25 +0800 Subject: [PATCH 0309/1123] remove --force to windeployqt for install --- cmake/deploy_qt.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index a6f5eab4..29692553 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -3,7 +3,7 @@ if(${WIN32}) message(STATUS "Running windeployqt for @AppName@ ...") execute_process( - COMMAND "@SlopeCraft_Qt_windeployqt_executable@" --force --no-translations "@AppName@.exe" + COMMAND "@SlopeCraft_Qt_windeployqt_executable@" --no-translations "@AppName@.exe" WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) From ac804b288aac5c1a64f8fae0bb7ffdaa45c69a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 19:10:17 +0800 Subject: [PATCH 0310/1123] hide memory error in vcl (temporarily) --- utilities/ColorManip/colorset_optical.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index f731be06..08b3624b 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -230,8 +230,8 @@ class TempVecOptical : public Eigen::Map { class newtokicolor_base_optical { public: - // using TempVectorXf_t = TempVecOptical; - using TempVectorXf_t = Eigen::ArrayXf; + using TempVectorXf_t = TempVecOptical; + // using TempVectorXf_t = Eigen::ArrayXf; using result_t = uint16_t; protected: From d4f2281fa9e7f595f759733e00947d31d5d79a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 19:10:31 +0800 Subject: [PATCH 0311/1123] add sanitizer options --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c8af3bc..54722e00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,8 @@ option(SlopeCraft_update_ts_no_obsolete "Remove obsolete translations from ts fi option(SlopeCraft_gprof "Profile with gprof" OFF) +option(SlopeCraft_sanitize "Build with sanitizer" OFF) + # manage the install prefix -------------------------------------------------- if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) @@ -100,6 +102,10 @@ if(${SlopeCraft_gprof}) add_link_options("-pg") endif() +if(${SlopeCraft_sanitize}) + set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fsanitize=address") +endif() + add_compile_definitions(_USE_MATH_DEFINES) add_compile_definitions(SCL_FIND_GlobalEnums_BY_PATH) add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) From 9e39fb47e2f8ea3f7edd959483725465dd6dffa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 13 May 2023 22:04:56 +0800 Subject: [PATCH 0312/1123] rewrite colordiff of RGB and XYZ --- utilities/ColorManip/ColorDiff.cpp | 47 +++++++++++- utilities/ColorManip/ColorManip.h | 7 ++ utilities/ColorManip/newColorSet.hpp | 18 ++++- utilities/ColorManip/newTokiColor.hpp | 105 ++++---------------------- 4 files changed, 83 insertions(+), 94 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 490c5ba2..d478d39c 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -23,6 +23,8 @@ This file is part of SlopeCraft. #include "ColorManip.h" #include +#include "newTokiColor.hpp" + inline float square(float x) { return x * x; } constexpr float thre = 1e-10f; @@ -76,7 +78,6 @@ float color_diff_RGB_plus(const float r1, const float g1, const float b1, float color_diff_HSV(float h1, float s1, float v1, float h2, float s2, float v2) noexcept { - const float sv_1 = s1 * v1; const float sv_2 = s2 * v2; @@ -85,4 +86,48 @@ float color_diff_HSV(float h1, float s1, float v1, float h2, float s2, const float dZ = 50.0f * (v1 - v2); return dX * dX + dY * dY + dZ * dZ; +} + +void colordiff_RGB_batch(std::span r1p, std::span g1p, + std::span b1p, + std::span rgb2, + std::span dest) noexcept { + assert(r1p.size() == g1p.size()); + assert(g1p.size() == b1p.size()); + assert(b1p.size() == dest.size()); + + const int color_count = r1p.size(); + +#ifdef SC_VECTORIZE_AVX2 + const __m256 r2 = _mm256_set1_ps(rgb2[0]); + const __m256 g2 = _mm256_set1_ps(rgb2[1]); + const __m256 b2 = _mm256_set1_ps(rgb2[2]); + + for (int i = 0; i < color_count; i += num_float_per_m256) { + const int offset = i; + assert(offset + num_float_per_m256 < color_count); + __m256 r1 = _mm256_load_ps(r1p.data() + offset); + __m256 g1 = _mm256_load_ps(g1p.data() + offset); + __m256 b1 = _mm256_load_ps(b1p.data() + offset); + + __m256 dr = _mm256_sub_ps(r1, r2); + __m256 dg = _mm256_sub_ps(g1, g2); + __m256 db = _mm256_sub_ps(b1, b2); + + dr = _mm256_mul_ps(dr, dr); + dg = _mm256_mul_ps(dg, dg); + db = _mm256_mul_ps(db, db); + + _mm256_store_ps(dest.data() + offset, + _mm256_add_ps(dr, _mm256_add_ps(dg, db))); + } + const int loop_start = + (color_count / num_float_per_m256) * num_float_per_m256; +#else + const int loop_start = 0; +#endif + for (int i = loop_start; i < color_count; i++) { + dest[i] = square(r1p[i] - rgb2[0]) + square(g1p[i] - rgb2[1]) + + square(b1p[i] - rgb2[2]); + } } \ No newline at end of file diff --git a/utilities/ColorManip/ColorManip.h b/utilities/ColorManip/ColorManip.h index ee909e8a..997dcf31 100644 --- a/utilities/ColorManip/ColorManip.h +++ b/utilities/ColorManip/ColorManip.h @@ -24,6 +24,8 @@ This file is part of SlopeCraft. #define COLORMANIP_COLORMANIP_H #include +#include +#include // #include using ARGB = uint32_t; @@ -71,4 +73,9 @@ float color_diff_RGB_plus(const float r1, const float g1, const float b1, float color_diff_HSV(float h1, float s1, float v1, float h2, float s2, float v2) noexcept; +void colordiff_RGB_batch(std::span r1, std::span g1, + std::span b1, + std::span rgb2, + std::span dest) noexcept; + #endif \ No newline at end of file diff --git a/utilities/ColorManip/newColorSet.hpp b/utilities/ColorManip/newColorSet.hpp index d5e95e2c..2893f612 100644 --- a/utilities/ColorManip/newColorSet.hpp +++ b/utilities/ColorManip/newColorSet.hpp @@ -28,7 +28,7 @@ This file is part of SlopeCraft. #include #include #include - +#include #include // using Eigen::Dynamic; @@ -83,6 +83,22 @@ class colorset_new : public std::conditional_t< return NAN; } + std::span rgb_data_span(int ch) const noexcept { + return {this->rgb_data(ch), (size_t)this->color_count()}; + } + + std::span hsv_data_span(int ch) const noexcept { + return {this->hsv_data(ch), (size_t)this->color_count()}; + } + + std::span lab_data_span(int ch) const noexcept { + return {this->lab_data(ch), (size_t)this->color_count()}; + } + + std::span xyz_data_span(int ch) const noexcept { + return {this->xyz_data(ch), (size_t)this->color_count()}; + } + private: template internal::hash_temp hash_temp() const noexcept { diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index f28fb2ed..0363cd5d 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -342,51 +342,11 @@ class newTokiColor } auto applyRGB(const Eigen::Array3f &c3) noexcept { -#ifdef SC_VECTORIZE_AVX2 TempVectorXf_t Diff(Allowed->color_count(), 1); - Diff.resize(Allowed->color_count(), 1); - - // Diff.resize(Allowed->color_count(), 1); - // std::vector Diff; - // Diff.resize(Allowed->color_count()); - __m256 r2 = _mm256_set1_ps(c3[0]); - __m256 g2 = _mm256_set1_ps(c3[1]); - __m256 b2 = _mm256_set1_ps(c3[2]); - - //__m256 *const destp = (__m256 *)Diff.data(); - - for (int i = 0; i * num_float_per_m256 < Allowed->color_count(); i++) { - __m256 r1 = _mm256_load_ps(Allowed->rgb_data(0) + i * num_float_per_m256); - __m256 g1 = _mm256_load_ps(Allowed->rgb_data(1) + i * num_float_per_m256); - __m256 b1 = _mm256_load_ps(Allowed->rgb_data(2) + i * num_float_per_m256); - - __m256 dr = _mm256_sub_ps(r1, r2); - __m256 dg = _mm256_sub_ps(g1, g2); - __m256 db = _mm256_sub_ps(b1, b2); - - dr = _mm256_mul_ps(dr, dr); - dg = _mm256_mul_ps(dg, dg); - db = _mm256_mul_ps(db, db); - - _mm256_store_ps(Diff.data() + i * num_float_per_m256, - _mm256_add_ps(dr, _mm256_add_ps(dg, db))); - // destp[i] = ; - } - - for (int i = - (Allowed->color_count() / num_float_per_m256) * num_float_per_m256; - i < Allowed->color_count(); i++) { - Diff[i] = (Allowed->RGB(i, 0) - c3[0]) * (Allowed->RGB(i, 0) - c3[0]) + - (Allowed->RGB(i, 1) - c3[1]) * (Allowed->RGB(i, 1) - c3[1]) + - (Allowed->RGB(i, 2) - c3[2]) * (Allowed->RGB(i, 2) - c3[2]); - } -#else - auto Diff0_2 = (Allowed->rgb(0) - c3[0]).square(); - auto Diff1_2 = (Allowed->rgb(1) - c3[1]).square(); - auto Diff2_2 = (Allowed->rgb(2) - c3[2]).square(); - TempVectorXf_t Diff{Allowed->color_count(), 1}; - Diff = Diff0_2 + Diff1_2 + Diff2_2; -#endif + std::span diff_span{Diff.data(), (size_t)Diff.size()}; + std::span c3span{c3.data(), 3}; + colordiff_RGB_batch(Allowed->rgb_data_span(0), Allowed->rgb_data_span(1), + Allowed->rgb_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; const auto ret = find_result(Diff); @@ -631,54 +591,15 @@ class newTokiColor } auto applyXYZ(const Eigen::Array3f &c3) noexcept { -#ifdef SC_VECTORIZE_AVX2 TempVectorXf_t Diff(Allowed->color_count(), 1); + std::span diff_span{Diff.data(), (size_t)Diff.size()}; + std::span c3span{c3.data(), 3}; + colordiff_RGB_batch(Allowed->xyz_data_span(0), Allowed->xyz_data_span(1), + Allowed->xyz_data_span(2), c3span, diff_span); - // const __m256 *const x1p = (const __m256 *)Allowed->xyz_data(0); - // const __m256 *const y1p = (const __m256 *)Allowed->xyz_data(1); - // const __m256 *const z1p = (const __m256 *)Allowed->xyz_data(2); - - __m256 x2 = _mm256_set1_ps(c3[0]); - __m256 y2 = _mm256_set1_ps(c3[1]); - __m256 z2 = _mm256_set1_ps(c3[2]); - - //__m256 *const destp = (__m256 *)Diff.data(); - - for (int i = 0; i * num_float_per_m256 < Allowed->color_count(); i++) { - __m256 x1 = _mm256_load_ps(Allowed->xyz_data(0) + i * num_float_per_m256); - __m256 y1 = _mm256_load_ps(Allowed->xyz_data(1) + i * num_float_per_m256); - __m256 z1 = _mm256_load_ps(Allowed->xyz_data(2) + i * num_float_per_m256); - - __m256 dx = _mm256_sub_ps(x1, x2); - __m256 dy = _mm256_sub_ps(y1, y2); - __m256 dz = _mm256_sub_ps(z1, z2); - - dx = _mm256_mul_ps(dx, dx); - dy = _mm256_mul_ps(dy, dy); - dz = _mm256_mul_ps(dz, dz); - - _mm256_store_ps(Diff.data() + i * num_float_per_m256, - _mm256_add_ps(dx, _mm256_add_ps(dy, dz))); - // destp[i] = _mm256_add_ps(dx, _mm256_add_ps(dy, dz)); - } - - for (int i = - (Allowed->color_count() / num_float_per_m256) * num_float_per_m256; - i < Allowed->color_count(); i++) { - Diff(i) = (Allowed->XYZ(i, 0) - c3[0]) * (Allowed->XYZ(i, 0) - c3[0]) + - (Allowed->XYZ(i, 1) - c3[1]) * (Allowed->XYZ(i, 1) - c3[1]) + - (Allowed->XYZ(i, 2) - c3[2]) * (Allowed->XYZ(i, 2) - c3[2]); - } -#else - auto Diff0_2 = (Allowed->xyz(0) - c3[0]).square(); - auto Diff1_2 = (Allowed->xyz(1) - c3[1]).square(); - auto Diff2_2 = (Allowed->xyz(2) - c3[2]).square(); - - TempVectorXf_t Diff(Allowed->color_count(), 1); - Diff = Diff0_2 + Diff1_2 + Diff2_2; -#endif // Data.CurrentColor-=allowedColors; - return find_result(Diff); + const auto ret = find_result(Diff); + return ret; } auto applyLab94(const Eigen::Array3f &c3) noexcept { @@ -819,9 +740,9 @@ class newTokiColor auto applyLab00(const Eigen::Array3f &c3) noexcept { // int tempIndex = 0; - float L1s = c3[0]; - float a1s = c3[1]; - float b1s = c3[2]; + const float L1s = c3[0]; + const float a1s = c3[1]; + const float b1s = c3[2]; // const ColorList &allow = Allowed->Lab; TempVectorXf_t Diff(Allowed->color_count(), 1); From ee9af79b5def62bd41dc0fb4666727682f7f4d75 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 May 2023 17:24:51 +0800 Subject: [PATCH 0313/1123] add git attribute --- .gitattribute | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitattribute diff --git a/.gitattribute b/.gitattribute new file mode 100644 index 00000000..8777bfc1 --- /dev/null +++ b/.gitattribute @@ -0,0 +1,5 @@ +* text=crlf +*.bat text eol=crlf +*.sh text eol=lf +*.jpg -text +*.png -text \ No newline at end of file From db521b25e74510c813161a542cc6c4106ef4a9e5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 May 2023 17:28:41 +0800 Subject: [PATCH 0314/1123] update git attribute --- .gitattribute | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitattribute b/.gitattribute index 8777bfc1..2e0ce43b 100644 --- a/.gitattribute +++ b/.gitattribute @@ -2,4 +2,16 @@ *.bat text eol=crlf *.sh text eol=lf *.jpg -text -*.png -text \ No newline at end of file +*.png -text + +*.h eol=crlf +*.hpp eol=crlf +*.c eol=crlf +*.cpp eol=crlf +*.ui eol=crlf +*.cmake eol=crlf +*.txt eol=crlf +*.json eol=crlf +*.in eol=crlf +*.ts eol=crlf +*.md eol=crlf \ No newline at end of file From dd09d18bf2335afa23ebc34678983a7de0428711 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 May 2023 17:32:55 +0800 Subject: [PATCH 0315/1123] fix build with gcc13 --- utilities/GPUWrapper/GPU_interface.h | 1 + utilities/ProcessBlockId/process_block_id.h | 1 + utilities/Schem/mushroom.h | 1 + 3 files changed, 3 insertions(+) diff --git a/utilities/GPUWrapper/GPU_interface.h b/utilities/GPUWrapper/GPU_interface.h index 731b9da4..c5be0b97 100644 --- a/utilities/GPUWrapper/GPU_interface.h +++ b/utilities/GPUWrapper/GPU_interface.h @@ -26,6 +26,7 @@ This file is part of SlopeCraft. #include "../SC_GlobalEnums.h" #include #include +#include namespace gpu_wrapper { diff --git a/utilities/ProcessBlockId/process_block_id.h b/utilities/ProcessBlockId/process_block_id.h index cf1c1340..17540e1b 100644 --- a/utilities/ProcessBlockId/process_block_id.h +++ b/utilities/ProcessBlockId/process_block_id.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace blkid { diff --git a/utilities/Schem/mushroom.h b/utilities/Schem/mushroom.h index 872daeec..31ef79b4 100644 --- a/utilities/Schem/mushroom.h +++ b/utilities/Schem/mushroom.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace libSchem { namespace internal { From de52438754b21bfc8a6781d73603eebb73f04837 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 May 2023 19:00:02 +0800 Subject: [PATCH 0316/1123] fix out-of-bounds accessing error in color diff --- CMakeLists.txt | 3 + utilities/ColorManip/ColorDiff.cpp | 359 ++++++++++++++++++++- utilities/ColorManip/ColorManip.h | 15 + utilities/ColorManip/colorset_optical.hpp | 4 +- utilities/ColorManip/newTokiColor.hpp | 371 ++-------------------- vccl/add_test_vccl.cmake | 52 +-- 6 files changed, 430 insertions(+), 374 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54722e00..5c6c2d0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,9 @@ option(SlopeCraft_gprof "Profile with gprof" OFF) option(SlopeCraft_sanitize "Build with sanitizer" OFF) +set(SlopeCraft_vccl_test_gpu_platform_idx 0 CACHE STRING "The opencl platform index used to test vccl") +set(SlopeCraft_vccl_test_gpu_device_idx 0 CACHE STRING "The opencl device index used to test vccl") + # manage the install prefix -------------------------------------------------- if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index d478d39c..c46afd3c 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -22,7 +22,6 @@ This file is part of SlopeCraft. #include "ColorManip.h" #include - #include "newTokiColor.hpp" inline float square(float x) { return x * x; } @@ -88,6 +87,46 @@ float color_diff_HSV(float h1, float s1, float v1, float h2, float s2, return dX * dX + dY * dY + dZ * dZ; } +#ifdef SC_VECTORIZE_AVX2 +#include +#include + +constexpr int num_float_per_m256 = 256 / 32; + +union alignas(32) f32_i32 { + float f32[8]; + int i32[8]; + __m256i m256i; +}; + +inline void take_abs_f32_8(float *p) noexcept { + for (size_t i = 0; i < 8; i++) { + *p = std::abs(*p); + } +} + +/** + * This function is a candidate when the real instruction can't be used. + */ + +/** + * This function is a candidate when the real instruction can't be used. + */ +inline __m256 _mm256_acos_ps__manually(__m256 x) noexcept { + alignas(32) float y[num_float_per_m256]; + + _mm256_store_ps(y, x); + + for (int i = 0; i < num_float_per_m256; i++) { + y[i] = std::acos(y[i]); + } + + return _mm256_load_ps(y); +} + +// #warning rua~ +#endif // SC_VECTORIZE_AVX2 + void colordiff_RGB_batch(std::span r1p, std::span g1p, std::span b1p, std::span rgb2, @@ -103,9 +142,9 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, const __m256 g2 = _mm256_set1_ps(rgb2[1]); const __m256 b2 = _mm256_set1_ps(rgb2[2]); - for (int i = 0; i < color_count; i += num_float_per_m256) { + for (int i = 0; i + num_float_per_m256 <= color_count; + i += num_float_per_m256) { const int offset = i; - assert(offset + num_float_per_m256 < color_count); __m256 r1 = _mm256_load_ps(r1p.data() + offset); __m256 g1 = _mm256_load_ps(g1p.data() + offset); __m256 b1 = _mm256_load_ps(b1p.data() + offset); @@ -130,4 +169,318 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, dest[i] = square(r1p[i] - rgb2[0]) + square(g1p[i] - rgb2[1]) + square(b1p[i] - rgb2[2]); } +} + +void colordiff_RGBplus_batch(std::span r1p, + std::span g1p, + std::span b1p, + std::span c3, + std::span dest) noexcept { + assert(r1p.size() == g1p.size()); + assert(g1p.size() == b1p.size()); + assert(b1p.size() == dest.size()); + + const int color_count = r1p.size(); + const float _r2 = c3[0], _g2 = c3[1], _b2 = c3[2]; +#ifdef SC_VECTORIZE_AVX2 + + const __m256 r2 = _mm256_set1_ps(_r2), g2 = _mm256_set1_ps(_g2), + b2 = _mm256_set1_ps(_b2); + const __m256 thre = _mm256_set1_ps(threshold); + + const float rr_plus_gg_plus_bb_2 = (_r2 * _r2 + _g2 * _g2 + _b2 * _b2); + constexpr float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; + + for (int i = 0; i + num_float_per_m256 <= color_count; + i += num_float_per_m256) { + __m256 r1 = _mm256_load_ps(r1p.data() + i); + __m256 g1 = _mm256_load_ps(g1p.data() + i); + __m256 b1 = _mm256_load_ps(b1p.data() + i); + + __m256 deltaR = _mm256_sub_ps(r1, r2); + __m256 deltaG = _mm256_sub_ps(g1, g2); + __m256 deltaB = _mm256_sub_ps(b1, b2); + + __m256 SqrModSquare; + { + __m256 temp_r = _mm256_mul_ps(r1, r1); + __m256 temp_g = _mm256_mul_ps(g1, g1); + __m256 temp_b = _mm256_mul_ps(b1, b1); + + SqrModSquare = _mm256_add_ps( + _mm256_add_ps(temp_r, temp_g), + _mm256_add_ps(temp_b, _mm256_set1_ps(rr_plus_gg_plus_bb_2))); + } + + __m256 sigma_rgb; + { + __m256 temp1 = _mm256_add_ps(r1, g1); + __m256 temp2 = _mm256_add_ps(g1, _mm256_set1_ps(_r2 + _g2 + _b2)); + sigma_rgb = + _mm256_mul_ps(_mm256_add_ps(temp1, temp2), _mm256_set1_ps(1.0f / 3)); + } + __m256 sigma_rgb_plus_thre = + _mm256_add_ps(sigma_rgb, _mm256_set1_ps(threshold)); + + const __m256 r1_plus_r2 = _mm256_add_ps(r1, r2); + const __m256 g1_plus_g2 = _mm256_add_ps(g1, g2); + const __m256 b1_plus_b2 = _mm256_add_ps(b1, b2); + __m256 S_r, S_g, S_b; + { + const __m256 m256_1f = _mm256_set1_ps(1.0f); + __m256 temp_r = _mm256_div_ps(r1_plus_r2, sigma_rgb_plus_thre); + __m256 temp_g = _mm256_div_ps(g1_plus_g2, sigma_rgb_plus_thre); + __m256 temp_b = _mm256_div_ps(b1_plus_b2, sigma_rgb_plus_thre); + + S_r = _mm256_min_ps(temp_r, m256_1f); + S_g = _mm256_min_ps(temp_g, m256_1f); + S_b = _mm256_min_ps(temp_b, m256_1f); + } + + __m256 sumRGBsquare; + { + __m256 r1r2 = _mm256_mul_ps(r1, r2); + __m256 g1g2 = _mm256_mul_ps(g1, g2); + __m256 b1b2 = _mm256_mul_ps(b1, b2); + sumRGBsquare = _mm256_add_ps(r1r2, _mm256_add_ps(g1g2, b1b2)); + } + + __m256 theta; + { + __m256 temp1 = + _mm256_div_ps(sumRGBsquare, _mm256_add_ps(SqrModSquare, thre)); + //__m256 _mm256_rsqrt_ps (__m256 a) + /* + __m256 temp1 = _mm256_mul_ps( + sumRGBsquare, _mm256_rsqrt_ps(_mm256_add_ps(SqrModSquare, thre))); + */ + temp1 = _mm256_div_ps(temp1, _mm256_set1_ps(1.01f)); + __m256 temp2; + { + alignas(32) float arr[8]; + _mm256_store_ps(arr, temp1); + for (size_t i = 0; i < 8; i++) { + arr[i] = std::acos(arr[i]); + } + temp2 = _mm256_load_ps(arr); + } + //__m256 temp2 = _mm256_acos_ps__manually(temp1); + theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0f / M_PI)); + } + + alignas(32) float arr[8]; + __m256 OnedDeltaR = + _mm256_div_ps((_mm256_store_ps(arr, deltaR), take_abs_f32_8(arr), + _mm256_load_ps(arr)), + _mm256_add_ps(r1_plus_r2, thre)); + __m256 OnedDeltaG = + _mm256_div_ps((_mm256_store_ps(arr, deltaG), take_abs_f32_8(arr), + _mm256_load_ps(arr)), + _mm256_add_ps(g1_plus_g2, thre)); + __m256 OnedDeltaB = + _mm256_div_ps((_mm256_store_ps(arr, deltaB), take_abs_f32_8(arr), + _mm256_load_ps(arr)), + _mm256_add_ps(b1_plus_b2, thre)); + + __m256 sumOnedDelta = _mm256_add_ps(_mm256_add_ps(OnedDeltaR, OnedDeltaG), + _mm256_add_ps(OnedDeltaB, thre)); + + __m256 S_tr = _mm256_div_ps( + OnedDeltaR, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_r, S_r))); + __m256 S_tg = _mm256_div_ps( + OnedDeltaG, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_g, S_g))); + __m256 S_tb = _mm256_div_ps( + OnedDeltaB, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_b, S_b))); + + __m256 S_theta = _mm256_add_ps(S_tr, _mm256_add_ps(S_tg, S_tb)); + + __m256 S_ratio; + { + __m256 max_r = _mm256_max_ps(r1, r2); + __m256 max_g = _mm256_max_ps(g1, g2); + __m256 max_b = _mm256_max_ps(b1, b2); + S_ratio = _mm256_max_ps(max_r, _mm256_max_ps(max_g, max_b)); + } + + __m256 diff; + { + __m256 temp_r = _mm256_mul_ps( + _mm256_mul_ps(_mm256_mul_ps(S_r, S_r), _mm256_mul_ps(deltaR, deltaR)), + _mm256_set1_ps(w_r)); + __m256 temp_g = _mm256_mul_ps( + _mm256_mul_ps(_mm256_mul_ps(S_g, S_g), _mm256_mul_ps(deltaG, deltaG)), + _mm256_set1_ps(w_g)); + __m256 temp_b = _mm256_mul_ps( + _mm256_mul_ps(_mm256_mul_ps(S_b, S_b), _mm256_mul_ps(deltaB, deltaB)), + _mm256_set1_ps(w_b)); + __m256 wr_plus_wr_plus_wb = _mm256_set1_ps(w_r + w_b + w_g); + __m256 temp_X = + _mm256_div_ps(_mm256_add_ps(_mm256_add_ps(temp_r, temp_g), temp_b), + wr_plus_wr_plus_wb); + + __m256 temp_Y = _mm256_mul_ps(_mm256_mul_ps(S_theta, S_ratio), + _mm256_mul_ps(theta, theta)); + + diff = _mm256_add_ps(temp_X, temp_Y); + } + + _mm256_store_ps(dest.data() + i, diff); + } + + const int loop_start = + (color_count / num_float_per_m256) * num_float_per_m256; +#else + const int loop_start = 0; +#endif + + for (int i = loop_start; i < color_count; i++) { + dest[i] = color_diff_RGB_plus(r1p[i], g1p[i], b1p[i], _r2, _g2, _b2); + } +} + +void colordiff_HSV_batch(std::span h1p, std::span s1p, + std::span v1p, + std::span hsv2, + std::span dest) noexcept { + assert(h1p.size() == s1p.size()); + assert(s1p.size() == v1p.size()); + assert(v1p.size() == dest.size()); + + const int color_count = h1p.size(); + + for (int idx = 0; idx < color_count; idx++) { + const float diff = + color_diff_HSV(hsv2[0], hsv2[1], hsv2[2], h1p[idx], s1p[idx], v1p[idx]); + dest[idx] = diff; + } +} + +void colordiff_Lab94_batch(std::span l1p, + std::span a1p, + std::span b1p, + std::span lab2, + std::span dest) noexcept { + const auto &c3 = lab2; + + assert(l1p.size() == a1p.size()); + assert(a1p.size() == b1p.size()); + assert(b1p.size() == dest.size()); + + const int color_count = l1p.size(); + +#ifdef SC_VECTORIZE_AVX2 + const __m256 L2 = _mm256_set1_ps(c3[0]); + const __m256 a2 = _mm256_set1_ps(c3[1]); + const __m256 b2 = _mm256_set1_ps(c3[2]); + //__m256 C1_2; + __m256 SC_2, sqrt_C1_2; + { + // float L = c3[0]; + float a = c3[1]; + float b = c3[2]; + float _C1_2 = a * a + b * b; + float _SC_2 = (sqrt(_C1_2) * 0.045f + 1.0f) * (sqrt(_C1_2) * 0.045f + 1.0f); + + // C1_2 = _mm256_set1_ps(_C1_2); + SC_2 = _mm256_set1_ps(_SC_2); + sqrt_C1_2 = _mm256_set1_ps(sqrt(_C1_2)); + } + + for (int i = 0; i + num_float_per_m256 <= color_count; + i += num_float_per_m256) { + __m256 L1 = _mm256_load_ps(l1p.data() + i); + __m256 a1 = _mm256_load_ps(a1p.data() + i); + __m256 b1 = _mm256_load_ps(b1p.data() + i); + // auto deltaL_2 = (Allowed->lab(0) - L).square(); + + __m256 deltaL_2; + { + __m256 Ldiff = _mm256_sub_ps(L1, L2); + deltaL_2 = _mm256_mul_ps(Ldiff, Ldiff); + } + + __m256 C2_2 = _mm256_add_ps(_mm256_mul_ps(a1, a1), _mm256_mul_ps(b1, b1)); + + __m256 deltaCab_2; + { + __m256 temp = _mm256_sub_ps(sqrt_C1_2, _mm256_sqrt_ps(C2_2)); + deltaCab_2 = _mm256_mul_ps(temp, temp); + } + + __m256 deltaHab_2; + { + __m256 a_diff = _mm256_sub_ps(a1, a2); + __m256 b_diff = _mm256_sub_ps(b1, b2); + + deltaHab_2 = _mm256_add_ps(_mm256_mul_ps(a_diff, a_diff), + _mm256_mul_ps(b_diff, b_diff)); + deltaHab_2 = _mm256_sub_ps(deltaHab_2, deltaCab_2); + } + + // constexpr float SL = 1; + // constexpr float kL = 1; + // constexpr float K1 = 0.045f; + constexpr float K2 = 0.015f; + + __m256 SH_2; + { + __m256 temp = + _mm256_add_ps(_mm256_mul_ps(_mm256_sqrt_ps(C2_2), _mm256_set1_ps(K2)), + _mm256_set1_ps(1.0f)); + SH_2 = _mm256_mul_ps(temp, temp); + } + + __m256 diff; + { + __m256 temp_C = _mm256_div_ps(deltaCab_2, SC_2); + __m256 temp_H = _mm256_div_ps(deltaHab_2, SH_2); + diff = _mm256_add_ps(deltaL_2, _mm256_add_ps(temp_C, temp_H)); + } + + _mm256_store_ps(dest.data() + i, diff); + } + + const int loop_start = + (color_count / num_float_per_m256) * num_float_per_m256; +#else + const int loop_start = 0; + +#endif + + { + const float L = c3[0]; + const float a = c3[1]; + const float b = c3[2]; + const float _C1_2 = a * a + b * b; + const float _SC_2 = + (sqrt(_C1_2) * 0.045f + 1.0f) * (sqrt(_C1_2) * 0.045f + 1.0f); + + for (int i = loop_start; i < color_count; i++) { + // auto deltaL_2 = (Allowed->lab(0) - L).square(); + + const float deltaL_2 = (l1p[i] - L) * (l1p[i] - L); + + const float C2_2 = a1p[i] * a1p[i] + b1p[i] * b1p[i]; + float deltaCab_2; + { + float temp = sqrt(_C1_2) - sqrt(C2_2); + deltaCab_2 = temp * temp; + } + + float deltaHab_2; + { + float diff_a = a1p[i] - a; + float diff_b = b1p[i] - b; + deltaHab_2 = diff_a * diff_a + diff_b * diff_b; + } + + float SH_2; + { + float temp = sqrt(C2_2) * 0.015f + 1.0f; + SH_2 = temp * temp; + } + // delete &SH_2; + dest[i] = deltaL_2 + deltaCab_2 / _SC_2 + deltaHab_2 / SH_2; + } + } } \ No newline at end of file diff --git a/utilities/ColorManip/ColorManip.h b/utilities/ColorManip/ColorManip.h index 997dcf31..d6b8e083 100644 --- a/utilities/ColorManip/ColorManip.h +++ b/utilities/ColorManip/ColorManip.h @@ -78,4 +78,19 @@ void colordiff_RGB_batch(std::span r1, std::span g1, std::span rgb2, std::span dest) noexcept; +void colordiff_RGBplus_batch(std::span r1, std::span g1, + std::span b1, + std::span rgb2, + std::span dest) noexcept; + +void colordiff_HSV_batch(std::span h1, std::span s1, + std::span v1, + std::span hsv2, + std::span dest) noexcept; + +void colordiff_Lab94_batch(std::span l1, std::span a1, + std::span b1, + std::span lab2, + std::span dest) noexcept; + #endif \ No newline at end of file diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index 08b3624b..f731be06 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -230,8 +230,8 @@ class TempVecOptical : public Eigen::Map { class newtokicolor_base_optical { public: - using TempVectorXf_t = TempVecOptical; - // using TempVectorXf_t = Eigen::ArrayXf; + // using TempVectorXf_t = TempVecOptical; + using TempVectorXf_t = Eigen::ArrayXf; using result_t = uint16_t; protected: diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 0363cd5d..e233bc28 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -35,45 +35,6 @@ This file is part of SlopeCraft. #include #include -#ifdef SC_VECTORIZE_AVX2 -#include -#include - -constexpr int num_float_per_m256 = 256 / 32; - -union alignas(32) f32_i32 { - float f32[8]; - int i32[8]; - __m256i m256i; -}; - -inline void take_abs_f32_8(float *p) noexcept { - for (size_t i = 0; i < 8; i++) { - *p = std::abs(*p); - } -} - -/** - * This function is a candidate when the real instruction can't be used. - */ - -/** - * This function is a candidate when the real instruction can't be used. - */ -inline __m256 _mm256_acos_ps__manually(__m256 x) noexcept { - alignas(32) float y[num_float_per_m256]; - - _mm256_store_ps(y, x); - - for (int i = 0; i < num_float_per_m256; i++) { - y[i] = std::acos(y[i]); - } - - return _mm256_load_ps(y); -} - -// #warning rua~ -#endif // SC_VECTORIZE_AVX2 // using Eigen::Dynamic; namespace { @@ -275,15 +236,8 @@ class newTokiColor this->sideSelectivity[1] = 1e35f; this->sideResult[1] = 0; - // using Base_t::DepthCount; - // using Base_t::needFindSide; - if (!Base_t::needFindSide) return; - // qDebug("开始doSide"); - // qDebug()<<"size(Diff)=["<Result % 4) { case 3: return; @@ -334,10 +288,7 @@ class newTokiColor } // sideSelectivity[0]-=1.0;sideSelectivity[1]-=1.0; // sideSelectivity[0]*=100.0;sideSelectivity[1]*=100.0; - /* - qDebug()<<"side[0]=["< Date: Mon, 15 May 2023 12:43:36 +0800 Subject: [PATCH 0317/1123] ignore builds --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index abe28211..1d645c9d 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,4 @@ binaries/* ### CLion ### .idea/* -cmake-build-debug/* +cmake-build-* From c47b06d9cf0c4895c2821258dc705871b87552c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 16 May 2023 05:54:25 +0800 Subject: [PATCH 0318/1123] get export options --- SlopeCraft/CMakeLists.txt | 2 + SlopeCraft/SCWind.cpp | 87 +++++++++++++++++++++++++++++++++++++++ SlopeCraft/SCWind.h | 7 ++++ SlopeCraft/SCWind.ui | 3 ++ 4 files changed, 99 insertions(+) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index fd5e8652..1c60efc8 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -46,6 +46,8 @@ qt_add_executable(SlopeCraft MANUAL_FINALIZATION ${SlopeCraft_project_files}) +target_compile_features(SlopeCraft PRIVATE cxx_std_20) + target_link_libraries(SlopeCraft PRIVATE Qt6::Core Qt6::Widgets diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 06770ab9..170f4caf 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -729,4 +729,91 @@ QString extension_of_export_type(SCWind::export_type et) noexcept { assert(false); return "Invalid_export_type"; +} + +std::optional +SCWind::current_litematic_option(QString &err) const noexcept { + err.clear(); + static std::string litename; + static std::string region_name; + + litename = this->ui->le_lite_name->text().toUtf8().data(); + region_name = this->ui->le_lite_region_name->text().toUtf8().data(); + + return SlopeCraft::Kernel::litematic_options{ + .litename_utf8 = litename.data(), .region_name_utf8 = region_name.data()}; +} + +std::optional +SCWind::current_nbt_option(QString &err) const noexcept { + err.clear(); + + return SlopeCraft::Kernel::vanilla_structure_options{ + .is_air_structure_void = this->ui->cb_nbt_air_void->isChecked()}; +} + +std::optional +SCWind::current_schem_option(QString &err) const noexcept { + err.clear(); + + SlopeCraft::Kernel::WE_schem_options ret; + + { + const std::array le_offset{this->ui->le_WE_offset_X, + this->ui->le_WE_offset_Y, + this->ui->le_WE_offset_Z}; + + for (size_t idx = 0; idx < le_offset.size(); idx++) { + bool ok; + + ret.offset[idx] = le_offset[idx]->text().toInt(&ok); + if (!ok) { + err = tr("WE原理图参数有错:输入给offset的值\"%" + "1\"不是一个有效的坐标,应当输入一个整数。") + .arg(le_offset[idx]->text()); + return std::nullopt; + } + } + } + + { + const std::array le_weoffset{this->ui->le_WE_weoffset_X, + this->ui->le_WE_weoffset_Y, + this->ui->le_WE_weoffset_Z}; + + for (size_t idx = 0; idx < le_weoffset.size(); idx++) { + bool ok; + + ret.we_offset[idx] = le_weoffset[idx]->text().toInt(&ok); + if (!ok) { + err = tr("WE原理图参数有错:输入给we offset的值\"%" + "1\"不是一个有效的数字,应当输入一个整数。") + .arg(le_weoffset[idx]->text()); + return std::nullopt; + } + } + } + static std::string region_name; + region_name = this->ui->le_WE_region_name->text().toUtf8().data(); + + static std::vector mod_charp; + { + static std::vector mod_names; + + const auto mod_names_q = + this->ui->le_WE_mods->toPlainText().replace("\r\n", "\n").split('\n'); + + mod_names.resize(mod_names_q.size()); + mod_charp.resize(mod_names_q.size()); + + for (int idx = 0; idx < mod_names_q.size(); idx++) { + mod_names[idx] = mod_names_q[idx].toUtf8().data(); + mod_charp[idx] = mod_names[idx].c_str(); + } + } + + ret.num_required_mods = mod_charp.size(); + ret.required_mods_name_utf8 = mod_charp.data(); + + return ret; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 4aba864f..66e50c35 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -117,6 +117,13 @@ class SCWind : public QMainWindow { export_type selected_export_type() const noexcept; + std::optional current_litematic_option( + QString& err) const noexcept; + std::optional + current_nbt_option(QString& err) const noexcept; + std::optional current_schem_option( + QString& err) const noexcept; + // kernel related functions void kernel_set_type() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index d3c9fc42..3f10c84e 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1122,6 +1122,9 @@ 0 + + 在这里输入依赖mod的名字。用换行符分割多个mod + From acc9f45da3797ac7e0fc8912de61c93ae0705ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 16 May 2023 18:50:25 +0800 Subject: [PATCH 0319/1123] add indenpent flat_diagram utility --- SlopeCraftL/CMakeLists.txt | 7 +- VisualCraftL/TokiVC_flagdiagram.cpp | 2 - utilities/CMakeLists.txt | 1 + utilities/FlatDiagram/CMakeLists.txt | 22 ++++ utilities/FlatDiagram/FlatDiagram.cpp | 156 ++++++++++++++++++++++++++ utilities/FlatDiagram/FlatDiagram.h | 63 +++++++++++ 6 files changed, 246 insertions(+), 5 deletions(-) create mode 100644 utilities/FlatDiagram/CMakeLists.txt create mode 100644 utilities/FlatDiagram/FlatDiagram.cpp create mode 100644 utilities/FlatDiagram/FlatDiagram.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index bd94e17d..f59c21c8 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -75,14 +75,15 @@ target_include_directories(SlopeCraftL PRIVATE ${CMAKE_SOURCE_DIR}/utilities) set(SlopeCraft_SCL_link_libs - - ZLIB::ZLIB - OpenMP::OpenMP_CXX GAConverter ColorManip NBTWriter Schem MapImageCvter + FlatDiagram + + ZLIB::ZLIB + OpenMP::OpenMP_CXX fmt::fmt Eigen3::Eigen zstr::zstr diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index 7debbc05..37961008 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -23,8 +23,6 @@ This file is part of SlopeCraft. #include "TokiVC.h" #include "VCL_internal.h" #include "VisualCraftL.h" -#include -#include #ifdef min #undef min diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index f280dba9..04babc71 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(uiPack) add_subdirectory(MapImageCvter) add_subdirectory(VersionDialog) add_subdirectory(VCLConfigLoader) +add_subdirectory(FlatDiagram) function(SC_process_boolean value_name) if(${${value_name}}) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt new file mode 100644 index 00000000..61a83fa8 --- /dev/null +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -0,0 +1,22 @@ +project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) + +find_package(PNG REQUIRED) + +include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) +find_package(Eigen3 REQUIRED) + +include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) +find_package(fmt REQUIRED) + +add_library(FlatDiagram STATIC + FlatDiagram.h + FlatDiagram.cpp) + +target_include_directories(FlatDiagram INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(FlatDiagram + PUBLIC + ColorManip + PNG::PNG + Eigen3::Eigen + fmt::fmt) +target_compile_features(FlatDiagram PUBLIC cxx_std_20) \ No newline at end of file diff --git a/utilities/FlatDiagram/FlatDiagram.cpp b/utilities/FlatDiagram/FlatDiagram.cpp new file mode 100644 index 00000000..c48d9a93 --- /dev/null +++ b/utilities/FlatDiagram/FlatDiagram.cpp @@ -0,0 +1,156 @@ +#include "FlatDiagram.h" +#include +#include +#include +#include + +#include + +using EImgRowMajor_t = + Eigen::Array; + +void libFlatDiagram::reverse_color(uint32_t *ptr, size_t num_pixels) noexcept { + // this can be vertorized by compiler optimization + for (uint32_t *p = ptr; p < ptr + num_pixels; p++) { + *p = reverse_color(*p); + } +} + +void libFlatDiagram::ARGB_to_AGBR(uint32_t *ptr, size_t num_pixels) noexcept { + for (uint32_t *p = ptr; p < ptr + num_pixels; p++) { + const uint32_t A = getA(*p); + *p = (*p) << 8 | A; + *p = reverse_byte(*p); + } +} + +void libFlatDiagram::draw_flat_diagram_to_memory( + uint32_t *image_u8c3_rowmajor, const fd_option &opt, + const get_blk_image_callback_t &blk_image_at) { + Eigen::Map map{ + image_u8c3_rowmajor, (opt.row_end - opt.row_start) * 16, opt.cols * 16}; + + memset(image_u8c3_rowmajor, 0, map.size() * sizeof(uint32_t)); + + // copy block images + for (int64_t r = opt.row_start; r < opt.row_end; r++) { + const int r_pixel_beg = (r - opt.row_start) * 16; + for (int64_t c = 0; c < opt.cols; c++) { + const int c_pixel_beg = c * 16; + /* + const bool is_src_aligned = + (reinterpret_cast( + blkp->project_image_on_exposed_face.data()) % + 32) == 0; + const bool is_aligned = is_dst_aligned && is_src_aligned; + */ + + map.block<16, 16>(r_pixel_beg, c_pixel_beg) = blk_image_at(r, c); + } + } + + for (int64_t br = opt.row_start; br < opt.row_end; br++) { + if ((opt.split_line_row_margin > 0) && + (br % opt.split_line_row_margin == 0)) { + const int64_t pr = (br - opt.row_start) * 16; + + reverse_color(&map(pr, 0), map.cols()); + } + } + + for (int64_t bc = 0; bc < opt.cols; bc++) { + if ((opt.split_line_col_margin > 0) && + (bc % opt.split_line_col_margin == 0)) { + const int64_t pc = bc * 16; + + for (int64_t pr = 0; pr < map.rows(); pr++) { + map(pr, pc) = reverse_color(map(pr, pc)); + } + } + } +} + +std::string libFlatDiagram::export_flat_diagram( + std::string_view png_filename, const fd_option &opt, + const get_blk_image_callback_t &blk_image_at, + std::span> texts) noexcept { + const int64_t rows_capacity_by_blocks = 64; + + EImgRowMajor_t buffer(rows_capacity_by_blocks * 16, opt.cols * 16); + + FILE *fp = fopen(png_filename.data(), "wb"); + + if (fp == nullptr) { + return fmt::format("fopen failed to create png file {}.", png_filename); + } + + png_struct *png = + png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (png == nullptr) { + fclose(fp); + return fmt::format("fopen failed to create png struct for png file {}.", + png_filename); + } + + png_info *png_info = png_create_info_struct(png); + if (png_info == nullptr) { + png_destroy_write_struct(&png, &png_info); + fclose(fp); + return fmt::format( + "fopen failed to create png info struct for png file {}.", + png_filename); + } + + png_init_io(png, fp); + + png_set_compression_level(png, opt.png_compress_level); + + png_set_compression_mem_level(png, opt.png_compress_memory_level); + + // png_set_text_compression_level(png, 8); + + png_set_IHDR(png, png_info, opt.cols * 16, 16 * (opt.row_end - opt.row_start), + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, png_info); + + { + std::vector png_txts; + png_txts.reserve(texts.size()); + for (auto &[first, second] : texts) { + png_text temp; + temp.compression = -1; + temp.key = first.data(); + temp.text = second.data(); + png_txts.emplace_back(temp); + } + + png_set_text(png, png_info, png_txts.data(), png_txts.size()); + } + + for (int64_t ridx = opt.row_start; ridx < opt.row_end; + ridx += rows_capacity_by_blocks) { + const int64_t rows_this_time = + std::min(opt.row_end - ridx, rows_capacity_by_blocks); + memset(buffer.data(), 0xFF, buffer.size() * sizeof(uint32_t)); + + fd_option opt_temp = opt; + opt_temp.row_start = ridx; + opt_temp.row_end = ridx + rows_this_time; + + draw_flat_diagram_to_memory(buffer.data(), opt, blk_image_at); + + ARGB_to_AGBR(buffer.data(), rows_this_time * 16 * opt.cols * 16); + + for (int64_t pix_r = 0; pix_r < rows_this_time * 16; pix_r++) { + png_write_row(png, reinterpret_cast(&buffer(pix_r, 0))); + } + } + + png_write_end(png, png_info); + + png_destroy_write_struct(&png, &png_info); + fclose(fp); + + return {}; +} \ No newline at end of file diff --git a/utilities/FlatDiagram/FlatDiagram.h b/utilities/FlatDiagram/FlatDiagram.h new file mode 100644 index 00000000..e9d841c0 --- /dev/null +++ b/utilities/FlatDiagram/FlatDiagram.h @@ -0,0 +1,63 @@ +#ifndef SLOPECRAFT_UTILITIES_FLATDIAGRAM_FLATDIAGRAM_H +#define SLOPECRAFT_UTILITIES_FLATDIAGRAM_FLATDIAGRAM_H + +#include +#include +#include +#include +#include +#include + +namespace libFlatDiagram { + +constexpr uint32_t reverse_color(uint32_t ARGB_src) noexcept { + return ARGB32(255 - getR(ARGB_src), 255 - getG(ARGB_src), + 255 - getB(ARGB_src), getA(ARGB_src)); +} + +constexpr uint32_t reverse_byte(uint32_t v) noexcept { + const uint32_t a = (v & 0xFF'00'00'00) >> 24; + const uint32_t b = (v & 0x00'FF'00'00) >> 8; + const uint32_t c = (v & 0x00'00'FF'00) << 8; + const uint32_t d = (v & 0x00'00'00'FF) << 24; + + return a | b | c | d; +} + +void reverse_color(uint32_t *ptr, size_t num_pixels) noexcept; + +void ARGB_to_AGBR(uint32_t *ptr, size_t num_pixels) noexcept; + +struct fd_option { + // [row_start,row_end) * [o,col_count) will be written + int64_t row_start; // by block + int64_t row_end; // by block + int64_t cols; // by block + int32_t split_line_row_margin; // 0 or negative number means no split lines + int32_t split_line_col_margin; // 0 or negative number means no split lines + int png_compress_level{9}; + int png_compress_memory_level{8}; +}; + +using block_img_ref_t = + Eigen::Map>; + +constexpr size_t ret_size = sizeof(block_img_ref_t); + +using get_blk_image_callback_t = + std::function; + +constexpr size_t callback_size = sizeof(get_blk_image_callback_t); + +void draw_flat_diagram_to_memory(uint32_t *image_u8c3_rowmajor, + const fd_option &opt, + const get_blk_image_callback_t &blk_image_at); + +std::string export_flat_diagram( + std::string_view png_filename, const fd_option &opt, + const get_blk_image_callback_t &blk_image_at, + std::span> texts) noexcept; + +} // namespace libFlatDiagram + +#endif // SLOPECRAFT_UTILITIES_FLATDIAGRAM_FLATDIAGRAM_H \ No newline at end of file From 2848fed00c84252974d3ca14d66092d141d9858d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 16 May 2023 19:48:14 +0800 Subject: [PATCH 0320/1123] attribute extra mushroom to given block palette --- SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 113 +++++++++++++++------ 1 file changed, 82 insertions(+), 31 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index 96adbc55..6e442a88 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -29,17 +29,12 @@ void TokiSlopeCraft::getColorMapPtrs(const float **const r, const float **const g, const float **const b, const unsigned char **m, int *rows) { - if (r != nullptr) - *r = TokiSlopeCraft::Allowed.rgb_data(0); - if (g != nullptr) - *g = TokiSlopeCraft::Allowed.rgb_data(1); - if (b != nullptr) - *b = TokiSlopeCraft::Allowed.rgb_data(2); - - if (m != nullptr) - *m = TokiSlopeCraft::Allowed.map_data(); - if (rows != nullptr) - *rows = TokiSlopeCraft::Allowed.color_count(); + if (r != nullptr) *r = TokiSlopeCraft::Allowed.rgb_data(0); + if (g != nullptr) *g = TokiSlopeCraft::Allowed.rgb_data(1); + if (b != nullptr) *b = TokiSlopeCraft::Allowed.rgb_data(2); + + if (m != nullptr) *m = TokiSlopeCraft::Allowed.map_data(); + if (rows != nullptr) *rows = TokiSlopeCraft::Allowed.color_count(); } const float *TokiSlopeCraft::getBasicColorMapPtrs() { @@ -48,25 +43,81 @@ const float *TokiSlopeCraft::getBasicColorMapPtrs() { uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { switch (g) { - case SCL_gameVersion::ANCIENT: - return 114514; - case SCL_gameVersion::MC12: - return 1631; - case SCL_gameVersion::MC13: - return 1976; - case SCL_gameVersion::MC14: - return 2230; - case SCL_gameVersion::MC15: - return 2230; - case SCL_gameVersion::MC16: - return 2586; - case SCL_gameVersion::MC17: - return 2730; - case SCL_gameVersion::MC18: - return 2865; - case SCL_gameVersion::MC19: - return 3105; // 1.19.0 - default: - return 1919810; + case SCL_gameVersion::ANCIENT: + return 114514; + case SCL_gameVersion::MC12: + return 1631; + case SCL_gameVersion::MC13: + return 1976; + case SCL_gameVersion::MC14: + return 2230; + case SCL_gameVersion::MC15: + return 2230; + case SCL_gameVersion::MC16: + return 2586; + case SCL_gameVersion::MC17: + return 2730; + case SCL_gameVersion::MC18: + return 2865; + case SCL_gameVersion::MC19: + return 3105; // 1.19.0 + default: + return 1919810; + } +} + +#include +#include + +const simpleBlock *TokiSlopeCraft::find_block_for_idx( + int idx, std::string_view blkid) noexcept { + if (idx < 0) { + return nullptr; } + + if (idx < (int)TokiSlopeCraft::blockPalette.size()) { + return &TokiSlopeCraft::blockPalette[idx]; + } + + // the block must be mushroom + namespace lsi = libSchem::internal; + using lsi::mushroom_type; + + blkid::char_range pure_id_range; + // invalid block id + if (!blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { + return nullptr; + } + + std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; + + auto mush_type_opt = lsi::pureid_to_type(pure_id); + if (!mush_type_opt.has_value()) { + return nullptr; + } + + uint8_t expected_basecolor = 0; + switch (mush_type_opt.value()) { + case mushroom_type::red: + expected_basecolor = 28; + break; + case mushroom_type::brown: + expected_basecolor = 10; + break; + case mushroom_type::stem: + expected_basecolor = 3; + break; + } + + const simpleBlock *blkp = find_block_for_idx(expected_basecolor, {}); + + if (blkp == nullptr) { + return nullptr; + } + + if (lsi::pureid_to_type(blkp->id) != mush_type_opt) { + return nullptr; + } + + return blkp; } \ No newline at end of file From b515ca671fdb19b498c22e48a8d8d2dafa88d02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 16 May 2023 19:48:39 +0800 Subject: [PATCH 0321/1123] add flatdiagram function to SCL --- SlopeCraftL/SlopeCraftL.h | 12 ++++ SlopeCraftL/TokiSlopeCraft.h | 17 +++++ SlopeCraftL/TokiSlopeCraft_build.cpp | 95 ++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 9cacb88a..dc90f29b 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -336,6 +336,18 @@ class Kernel { virtual bool exportAsWESchem( const char *filename_local, const WE_schem_options &option) const noexcept = 0; + + struct flag_diagram_options { + const uint64_t lib_version{SC_VERSION_U64}; + + int32_t split_line_row_margin; // 0 or negative number means no split lines + int32_t split_line_col_margin; // 0 or negative number means no split lines + int png_compress_level{9}; + int png_compress_memory_level{8}; + }; + virtual bool exportAsFlatDiagram( + const char *filename_local, const flag_diagram_options &option, + StringDeliver *err = nullptr) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index d5e96600..c3b110af 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -256,6 +256,20 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string_view Name, std::span requiredMods) const; + bool exportAsFlatDiagram(const char *filename_local, + const flag_diagram_options &option, + StringDeliver *_err) const noexcept override { + std::string err = this->exportAsFlatDiagram(filename_local, option); + if (_err != nullptr) { + write(*_err, err); + } + return err.empty(); + } + + std::string exportAsFlatDiagram( + std::string_view filename, + const flag_diagram_options &option) const noexcept; + void get3DSize(int *x, int *y, int *z) const override; int getHeight() const override; int getXRange() const override; @@ -437,6 +451,9 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static bool exmaine_build_cache(std::string_view filename, uint64_t build_task_hash, build_cache_ir *ir = nullptr) noexcept; + + static const simpleBlock *find_block_for_idx(int idx, + std::string_view blkid) noexcept; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index ac2aa0f6..bb12b706 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -613,4 +613,99 @@ int TokiSlopeCraft::getSchemPalette(const char **dest_id, } return ret; +} + +#include +#include + +std::string TokiSlopeCraft::exportAsFlatDiagram( + std::string_view filename, + const flag_diagram_options &option) const noexcept { + if (kernelStep < SCL_step::builded) { + return "You can only export a flat diagram after you build the 3D " + "structure."; + } + + if (TokiSlopeCraft::mapType != SCL_mapTypes::Flat) { + return "Only flat maps can be exported to flat diagram."; + } + + libFlatDiagram::fd_option fdopt; + // set up fdopt + { + fdopt.row_start = 0; + fdopt.row_end = this->schem.z_range(); + fdopt.cols = this->schem.x_range(); + fdopt.split_line_row_margin = option.split_line_row_margin; + fdopt.split_line_col_margin = option.split_line_col_margin; + fdopt.png_compress_level = option.png_compress_level; + fdopt.png_compress_memory_level = option.png_compress_memory_level; + } + + std::vector> img_list_rmj; + img_list_rmj.reserve(this->schem.palette_size()); + + for (int pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { + if (pblkid == 0) { + img_list_rmj.emplace_back(); + img_list_rmj[0].setZero(); + continue; + } + std::string_view id = this->schem.palette()[pblkid]; + const simpleBlock *blkp = + TokiSlopeCraft::find_block_for_idx(pblkid - 1, id); + if (blkp == nullptr) { + std::string blkid_full; + blkid_full.reserve(64 * 2048); + for (const auto &blk : TokiSlopeCraft::blockPalette) { + blkid_full += blk.id; + blkid_full.push_back('\n'); + } + + return fmt::format( + "SlopeCraftL internal error. Failed to find block image for \"{}\". " + "In the 3d structure, the corresponding block idx is {}.\nThe whole " + "block palette is as below: {}", + id, pblkid, blkid_full); + } + + img_list_rmj.emplace_back(blkp->image.transpose()); + } + + auto block_at_callback = [this, &img_list_rmj]( + int64_t r, + int64_t c) -> libFlatDiagram::block_img_ref_t { + if (r < 0 || c < 0 || r >= this->schem.z_range() || + c >= this->schem.x_range()) { + return libFlatDiagram::block_img_ref_t{img_list_rmj.at(0).data()}; + } + + const int ele = this->schem(c, 0, r); + assert(ele >= 0 && ele < this->schem.palette_size()); + + return libFlatDiagram::block_img_ref_t{img_list_rmj.at(ele).data()}; + }; + + std::array, 4> txt{ + std::make_pair( + "Title", "Flat diagram generated by SlopeCraftL."), + std::make_pair("Software", "SlopeCraftL"), + std::make_pair( + "Description", + "This image is a flat diagram created by SlopeCraftL, which is is " + "a subproject of SlopeCraft, developed by TokiNoBug."), + std::make_pair( + "Comment", + "SlopeCraft is a free software published " + "under GPLv3 license. You can find " + "its repository at https://github.com/SlopeCraft/SlopeCraft")}; + + auto err = libFlatDiagram::export_flat_diagram(filename, fdopt, + block_at_callback, txt); + + if (err.empty()) { + return {}; + } + + return fmt::format("Failed to export flat diagram. Details: {}", err); } \ No newline at end of file From ae0a3da5279c809c63f121c9c446448f1774ce1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 16 May 2023 19:48:57 +0800 Subject: [PATCH 0322/1123] update png info of VCL --- VisualCraftL/TokiVC_flagdiagram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index 37961008..8a148ad1 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -237,9 +237,9 @@ bool TokiVC::export_flag_diagram(const char *png_filename, "a subproject of SlopeCraft, developed by TokiNoBug."), std::make_pair( "Comment", - "VisualCraftL is a free software published " + "SlopeCraft is a free software published " "under GPLv3 license. You can find " - "its repository at https://github.com/ToKiNoBug/SlopeCraft")}; + "its repository at https://github.com/SlopeCraft/SlopeCraft")}; std::array png_txts; From 54b8660c6ddc49256dc97364e405a79fc55d3136 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 May 2023 00:58:56 +0800 Subject: [PATCH 0323/1123] fix crashing for small images --- SlopeCraft/PoolModel.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 75246851..80bacec9 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -57,18 +57,11 @@ QPixmap scale_up_to_3232(const QPixmap& original_pixmap, QImage new_img{new_size, QImage::Format_ARGB32}; memset(new_img.scanLine(0), 0, new_img.sizeInBytes()); { - const QImage old_img{ - original_pixmap.toImage().convertToFormat(QImage::Format_ARGB32)}; - const uint32_t* const src = - reinterpret_cast(old_img.scanLine(0)); - uint32_t* const dst = reinterpret_cast(new_img.scanLine(0)); - - for (int r = 0; r < old_size.height(); r++) { - for (int c = 0; c < old_size.width(); c++) { - dst[r * new_size.width() + c] = src[r * old_size.width() + c]; - } - } + QPainter p{&new_img}; + p.drawPixmap(0, 0, original_pixmap); + p.end(); } + return QPixmap::fromImage(new_img); } From 592a6a1ca3f8566b4808fa45b494e10b1eccdef7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 May 2023 01:03:36 +0800 Subject: [PATCH 0324/1123] rename functions in SCL --- SlopeCraftL/SlopeCraftL.h | 15 +++++++++------ SlopeCraftL/TokiSlopeCraft.h | 16 ++++++++-------- SlopeCraftL/TokiSlopeCraft_build.cpp | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index dc90f29b..e5151bf5 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -322,7 +322,7 @@ class Kernel { uint64_t version{SC_VERSION_U64}; bool is_air_structure_void{true}; }; - virtual bool exportStructure( + virtual bool exportAsStructure( const char *filename_local, const vanilla_structure_options &option) const noexcept = 0; @@ -338,16 +338,19 @@ class Kernel { const WE_schem_options &option) const noexcept = 0; struct flag_diagram_options { - const uint64_t lib_version{SC_VERSION_U64}; + uint64_t lib_version{SC_VERSION_U64}; - int32_t split_line_row_margin; // 0 or negative number means no split lines - int32_t split_line_col_margin; // 0 or negative number means no split lines + // 0 or negative number means no split lines + int32_t split_line_row_margin{0}; + // 0 or negative number means no split lines + int32_t split_line_col_margin{0}; int png_compress_level{9}; int png_compress_memory_level{8}; + StringDeliver *err{nullptr}; }; virtual bool exportAsFlatDiagram( - const char *filename_local, const flag_diagram_options &option, - StringDeliver *err = nullptr) const noexcept = 0; + const char *filename_local, + const flag_diagram_options &option) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index c3b110af..0e22c08e 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -216,7 +216,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { return err.empty(); } - bool exportStructure( + bool exportAsStructure( const char *filename_local, const vanilla_structure_options &option) const noexcept override { auto err = @@ -256,17 +256,17 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::string_view Name, std::span requiredMods) const; - bool exportAsFlatDiagram(const char *filename_local, - const flag_diagram_options &option, - StringDeliver *_err) const noexcept override { - std::string err = this->exportAsFlatDiagram(filename_local, option); - if (_err != nullptr) { - write(*_err, err); + bool exportAsFlatDiagram( + const char *filename_local, + const flag_diagram_options &option) const noexcept override { + std::string err = this->export_flat_diagram(filename_local, option); + if (option.err != nullptr) { + write(*option.err, err); } return err.empty(); } - std::string exportAsFlatDiagram( + std::string export_flat_diagram( std::string_view filename, const flag_diagram_options &option) const noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index bb12b706..54b7038d 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -618,7 +618,7 @@ int TokiSlopeCraft::getSchemPalette(const char **dest_id, #include #include -std::string TokiSlopeCraft::exportAsFlatDiagram( +std::string TokiSlopeCraft::export_flat_diagram( std::string_view filename, const flag_diagram_options &option) const noexcept { if (kernelStep < SCL_step::builded) { From 71ebf67ace2474f418c11db5e1320d6878184b02 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 May 2023 01:04:26 +0800 Subject: [PATCH 0325/1123] implement 4 export --- SlopeCraft/SCWind.cpp | 28 ++++++++- SlopeCraft/SCWind.h | 2 + SlopeCraft/SCWind_slots.cpp | 111 ++++++++++++++++++++++++++++++++++-- 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 170f4caf..4ead9c75 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -722,7 +722,7 @@ QString extension_of_export_type(SCWind::export_type et) noexcept { case SCWind::export_type::WE_schem: return "schem"; case SCWind::export_type::flat_diagram: - return "png"; + return "flat-diagram.png"; case SCWind::export_type::data_file: return "dat"; } @@ -816,4 +816,30 @@ SCWind::current_schem_option(QString &err) const noexcept { ret.required_mods_name_utf8 = mod_charp.data(); return ret; +} + +std::optional +SCWind::current_flatdiagram_option(QString &err) const noexcept { + err.clear(); + + int row_margin = this->ui->sb_flatdiagram_hmargin->value(); + int col_margin = this->ui->sb_flatdiagram_vmargin->value(); + + if (row_margin <= 0 || col_margin <= 0) { + err = + tr("平面示意图的分割线间距无效:水平间距为 %1, 垂直间距为 %2, " + "但间距必须为正数。"); + return std::nullopt; + } + + if (!this->ui->cb_flatdiagram_hline->isChecked()) { + row_margin = -1; + } + + if (!this->ui->cb_flatdiagram_vline->isChecked()) { + col_margin = -1; + } + + return SlopeCraft::Kernel::flag_diagram_options{ + .split_line_row_margin = row_margin, .split_line_col_margin = col_margin}; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 66e50c35..86a88bb8 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -123,6 +123,8 @@ class SCWind : public QMainWindow { current_nbt_option(QString& err) const noexcept; std::optional current_schem_option( QString& err) const noexcept; + std::optional + current_flatdiagram_option(QString& err) const noexcept; // kernel related functions void kernel_set_type() noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 1d081770..ad4c5fd4 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -6,8 +6,12 @@ #include void SCWind::on_pb_add_image_clicked() noexcept { - auto files = - QFileDialog::getOpenFileNames(this, tr("选择图片"), "", "*.png;*.jpg"); +#ifdef WIN32 + const char *filter = "*.png;*.jpg"; +#else + const char *filter = "*.png;;*.jpg"; +#endif + auto files = QFileDialog::getOpenFileNames(this, tr("选择图片"), "", filter); if (files.empty()) { return; @@ -373,10 +377,69 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { #warning show mat list here } +#define SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked \ + if (!temp.has_value()) { \ + process_err(err); \ + return; \ + } + +#define SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked \ + if (report_err_fun(export_name, taskp) == \ + QMessageBox::StandardButton::Ignore) { \ + continue; \ + } else { \ + return; \ + } + void SCWind::on_pb_export_all_clicked() noexcept { auto tasks_to_export = this->selected_export_task_list(); - if (tasks_to_export.size() <= 0) { + const auto export_type = this->selected_export_type(); + SlopeCraft::Kernel::litematic_options opt_lite; + SlopeCraft::Kernel::vanilla_structure_options opt_nbt; + SlopeCraft::Kernel::WE_schem_options opt_WE; + SlopeCraft::Kernel::flag_diagram_options opt_fd; + { + QString err; + auto process_err = [this](const QString &err) { + QMessageBox::warning(this, tr("导出设置有错"), + tr("导出设置存在如下错误:\n%1").arg(err)); + }; + switch (export_type) { + case export_type::litematica: { + auto temp = this->current_litematic_option(err); + SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked; + opt_lite = temp.value(); + break; + } + case export_type::vanilla_structure: { + auto temp = this->current_nbt_option(err); + SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked; + opt_nbt = temp.value(); + break; + } + case export_type::WE_schem: { + auto temp = this->current_schem_option(err); + SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked; + opt_WE = temp.value(); + break; + } + case export_type::flat_diagram: { + auto temp = this->current_flatdiagram_option(err); + SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked; + opt_fd = temp.value(); + break; + } + default: + QMessageBox::warning( + this, tr("你点错按钮了"), + tr("导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个" + "按钮,这可能是一个小小的bug(特性)。")); + return; + } + } + + if (tasks_to_export.empty()) { QMessageBox::warning(this, tr("无可导出的任务"), tr("任务池为空,请先转化一个或一些图像")); return; @@ -453,6 +516,46 @@ void SCWind::on_pb_export_all_clicked() noexcept { } taskp->set_built(); -#warning export here + const std::string export_name = + get_export_name(*taskp).toLocal8Bit().data(); + + auto report_err_fun = [this](std::string_view export_name, + const cvt_task *taskp) { + return QMessageBox::warning( + this, tr("导出失败"), + tr("导出%1时失败。原图像文件名为%" + "2\n点击Ignore将跳过这个图像,点击Cancel将放弃导出任务。") + .arg(export_name.data()) + .arg(taskp->filename), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, + QMessageBox::StandardButton::Cancel}); + }; + + switch (export_type) { + case export_type::litematica: + if (!this->kernel->exportAsLitematic(export_name.c_str(), opt_lite)) { + SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; + } + break; + + case export_type::vanilla_structure: + if (!this->kernel->exportAsStructure(export_name.c_str(), opt_nbt)) { + SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; + } + break; + case export_type::WE_schem: + if (!this->kernel->exportAsWESchem(export_name.c_str(), opt_WE)) { + SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; + } + break; + case export_type::flat_diagram: + if (!this->kernel->exportAsFlatDiagram(export_name.c_str(), opt_fd)) { + SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; + } + break; + default: + assert(false); + return; + } } } \ No newline at end of file From fd10080134373ecae0603184a5c23256a9b2ae78 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 May 2023 13:55:23 +0800 Subject: [PATCH 0326/1123] fixed color diff computation --- utilities/ColorManip/ColorDiff.cpp | 70 +++++++++++++++------------ utilities/ColorManip/newTokiColor.hpp | 11 ++++- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index c46afd3c..ea0cd2e9 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -34,7 +34,7 @@ float color_diff_RGB_plus(const float r1, const float g1, const float b1, constexpr float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; const float SqrModSquare = - (r1 * r1 + g1 * g1 + b1 * b1) * (r2 * r2 + g2 * g2 + b2 * b2); + std::sqrt((r1 * r1 + g1 * g1 + b1 * b1) * (r2 * r2 + g2 * g2 + b2 * b2)); const float deltaR = r1 - r2; const float deltaG = g1 - g2; @@ -72,6 +72,9 @@ float color_diff_RGB_plus(const float r1, const float g1, const float b1, (w_r + w_g + w_b) + S_theta * S_ratio * theta * theta; + assert(!std::isnan(result)); + assert(result >= 0); + return result; } @@ -101,27 +104,8 @@ union alignas(32) f32_i32 { inline void take_abs_f32_8(float *p) noexcept { for (size_t i = 0; i < 8; i++) { - *p = std::abs(*p); - } -} - -/** - * This function is a candidate when the real instruction can't be used. - */ - -/** - * This function is a candidate when the real instruction can't be used. - */ -inline __m256 _mm256_acos_ps__manually(__m256 x) noexcept { - alignas(32) float y[num_float_per_m256]; - - _mm256_store_ps(y, x); - - for (int i = 0; i < num_float_per_m256; i++) { - y[i] = std::acos(y[i]); + p[i] = std::abs(p[i]); } - - return _mm256_load_ps(y); } // #warning rua~ @@ -171,6 +155,16 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, } } +#define SC_PRIVATE_MARCO_assert_if_nan(vec) \ + { \ + float temp[8]; \ + _mm256_store_ps(temp, (vec)); \ + for (float f : temp) { \ + assert(!std::isnan(f)); \ + assert(f >= 0); \ + } \ + } + void colordiff_RGBplus_batch(std::span r1p, std::span g1p, std::span b1p, @@ -180,6 +174,8 @@ void colordiff_RGBplus_batch(std::span r1p, assert(g1p.size() == b1p.size()); assert(b1p.size() == dest.size()); + std::fill(dest.begin(), dest.end(), NAN); + const int color_count = r1p.size(); const float _r2 = c3[0], _g2 = c3[1], _b2 = c3[2]; #ifdef SC_VECTORIZE_AVX2 @@ -203,14 +199,18 @@ void colordiff_RGBplus_batch(std::span r1p, __m256 SqrModSquare; { - __m256 temp_r = _mm256_mul_ps(r1, r1); - __m256 temp_g = _mm256_mul_ps(g1, g1); - __m256 temp_b = _mm256_mul_ps(b1, b1); + const __m256 temp_r = _mm256_mul_ps(r1, r1); + const __m256 temp_g = _mm256_mul_ps(g1, g1); + const __m256 temp_b = _mm256_mul_ps(b1, b1); + + const __m256 rr_plus_gg_plus_bb_1 = + _mm256_add_ps(temp_r, _mm256_add_ps(temp_g, temp_b)); - SqrModSquare = _mm256_add_ps( - _mm256_add_ps(temp_r, temp_g), - _mm256_add_ps(temp_b, _mm256_set1_ps(rr_plus_gg_plus_bb_2))); + SqrModSquare = _mm256_mul_ps(rr_plus_gg_plus_bb_1, + _mm256_set1_ps(rr_plus_gg_plus_bb_2)); + SqrModSquare = _mm256_sqrt_ps(SqrModSquare); } + SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); __m256 sigma_rgb; { @@ -259,13 +259,14 @@ void colordiff_RGBplus_batch(std::span r1p, { alignas(32) float arr[8]; _mm256_store_ps(arr, temp1); - for (size_t i = 0; i < 8; i++) { - arr[i] = std::acos(arr[i]); + for (float &f : arr) { + f = std::acos(f); + assert(!std::isnan(f)); } temp2 = _mm256_load_ps(arr); } //__m256 temp2 = _mm256_acos_ps__manually(temp1); - theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0f / M_PI)); + theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0 / M_PI)); } alignas(32) float arr[8]; @@ -322,6 +323,15 @@ void colordiff_RGBplus_batch(std::span r1p, _mm256_mul_ps(theta, theta)); diff = _mm256_add_ps(temp_X, temp_Y); + + { + float temp[8]; + _mm256_store_ps(temp, diff); + for (float f : temp) { + assert(!std::isnan(f)); + assert(f >= 0); + } + } } _mm256_store_ps(dest.data() + i, diff); diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index e233bc28..80d51903 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -35,7 +35,6 @@ This file is part of SlopeCraft. #include #include - // using Eigen::Dynamic; namespace { inline constexpr float threshold = 1e-10f; @@ -189,6 +188,12 @@ class newTokiColor private: auto find_result(const TempVectorXf_t &diff) noexcept { + if (diff.isNaN().any()) { + for (int idx = 0; idx < diff.size(); idx++) { + assert(!std::isnan(diff[idx])); + assert(diff[idx] >= 0); + } + } int tempidx = 0; this->ResultDiff = diff.minCoeff(&tempidx); @@ -209,6 +214,8 @@ class newTokiColor float min = diff[0]; for (int i = 1; i < int(diff.size()); i++) { + assert(!std::isnan(diff[i])); + assert(diff[i] >= 0); if (diff[i] < min) { minidx = i; min = diff[i]; @@ -411,7 +418,7 @@ class newTokiColor std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; colordiff_Lab94_batch(Allowed->lab_data_span(0), Allowed->lab_data_span(1), - Allowed->lab_data_span(2), c3span, diff_span); + Allowed->lab_data_span(2), c3span, diff_span); return find_result(Diff); } From 7dbdc0fd93a3a66e538491b8b330c0d1fa9ec94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 17 May 2023 21:03:56 +0800 Subject: [PATCH 0327/1123] add a interface to get block palette --- SlopeCraftL/SlopeCraftL.cpp | 5 +++ SlopeCraftL/SlopeCraftL.h | 2 + SlopeCraftL/TokiSlopeCraft.cpp | 50 ++++++++++++++++++---- SlopeCraftL/TokiSlopeCraft.h | 4 ++ SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 23 ++++++++++ 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 89467bda..06e3d05c 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -245,4 +245,9 @@ SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { } SCL_EXPORT uint8_t SCL_maxBaseColor() { return 61; } + +SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) { + return TokiSlopeCraft::getBlockPalette(blkpp, capacity); +} } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index e5151bf5..4c745758 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -412,6 +412,8 @@ SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); SCL_EXPORT uint8_t SCL_maxBaseColor(); +SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, + size_t capacity_in_elements); // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index fd8d6c29..b916fbb1 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -520,18 +520,50 @@ void TokiSlopeCraft::getBlockCounts(int *total, int detail[64]) const { } int64_t TokiSlopeCraft::getBlockCounts(std::vector *dest) const { - if (dest == nullptr) { - return -1; - } if (kernelStep < SCL_step::builded) return -1; - dest->resize(64); - for (int i = 0; i < 64; i++) (*dest)[i] = 0; + + const bool is_dest_nonnull = (dest != nullptr); + if (is_dest_nonnull) { + dest->resize(64); + for (int i = 0; i < 64; i++) dest->at(i) = 0; + } + + int64_t total = 0; + + // map ele_t in schem to index in blockPalette(material index) + std::vector map_ele_to_material; + { + map_ele_to_material.resize(TokiSlopeCraft::blockPalette.size()); + std::fill(map_ele_to_material.begin(), map_ele_to_material.end(), -1); + + for (int ele = 1; ele < this->schem.palette_size(); ele++) { + std::string_view blkid = this->schem.palette()[ele]; + + const simpleBlock *sbp = + TokiSlopeCraft::find_block_for_idx(ele - 1, blkid); + assert(sbp != nullptr); + + int64_t idx = sbp - TokiSlopeCraft::blockPalette.data(); + assert(idx >= 0); + assert(idx < (int64_t)TokiSlopeCraft::blockPalette.size()); + + map_ele_to_material[ele] = idx; + } + } + for (int i = 0; i < schem.size(); i++) { - if (schem(i)) (*dest)[schem(i) - 1]++; + if (schem(i) == 0) { + continue; + } + + total++; + if (is_dest_nonnull) { + const int mat_idx = map_ele_to_material[schem(i)]; + assert(mat_idx >= 0); + dest->at(mat_idx)++; + } } - int totalBlockCount = 0; - for (int i = 0; i < 64; i++) totalBlockCount += (*dest)[i]; - return totalBlockCount; + return total; } int64_t TokiSlopeCraft::getBlockCounts() const { diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 0e22c08e..8db959fe 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -454,6 +454,10 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static const simpleBlock *find_block_for_idx(int idx, std::string_view blkid) noexcept; + + public: + static int getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) noexcept; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index 6e442a88..c63e6faf 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -120,4 +120,27 @@ const simpleBlock *TokiSlopeCraft::find_block_for_idx( } return blkp; +} + +int TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) noexcept { + const size_t palette_size = std::min( + SCL_maxBaseColor() + 1, TokiSlopeCraft::blockPalette.size()); + if (blkpp == nullptr || capacity <= 0) { + return palette_size; + } + + for (size_t idx = 0; idx < palette_size; idx++) { + if (capacity <= idx) { + break; + } + + blkpp[idx] = &TokiSlopeCraft::blockPalette[idx]; + } + + for (size_t idx = palette_size; idx < capacity; idx++) { + blkpp[idx] = nullptr; + } + + return palette_size; } \ No newline at end of file From 5010e36d59291e73083572e724ddc91b6981e542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 17 May 2023 21:04:28 +0800 Subject: [PATCH 0328/1123] implement preview wind --- SlopeCraft/PreviewWind.cpp | 114 ++++++++++++++++++++++++++++++++- SlopeCraft/PreviewWind.h | 48 +++++++++++++- SlopeCraft/PreviewWind.ui | 121 ++++++++++++++---------------------- SlopeCraft/SCWind_slots.cpp | 15 +++++ 4 files changed, 220 insertions(+), 78 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index dedcb0fe..ff4de09d 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -1,9 +1,119 @@ #include "PreviewWind.h" #include "ui_PreviewWind.h" +#include +#include -PreviewWind::PreviewWind(const SlopeCraft::Kernel* kernel, QWidget* parent) +PreviewWind::PreviewWind(QWidget* parent) : QDialog(parent), ui(new Ui::PreviewWind) { this->ui->setupUi(this); + + this->mmp = new MaterialModel(this); + this->mmp->set_mat_list_pointer(&this->mat_list); + // this->ui->tv_mat->setModel(this->mmp); + + // connect(this->mmp,&QAbstractTableModel::dataChanged,this->ui->tv_mat,&QTableView::) +} + +PreviewWind::~PreviewWind() { delete this->ui; } + +void PreviewWind::set_size(std::span size) & noexcept { + QString size_str = + QStringLiteral("%1 × %2 × %3").arg(size[0]).arg(size[1]).arg(size[2]); + + this->ui->lb_show_size->setText(size_str); + + this->ui->lb_show_volume->setText( + QString::number(size[0] * size[1] * size[2])); +} + +void PreviewWind::set_total_count(int count) & noexcept { + this->ui->lb_block_count->setText(QString::number(count)); +} + +void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { + std::array count_list; + count_list.fill(0); + + { + int total_blks{0}; + kernel->getBlockCounts(&total_blks, count_list.data()); + this->set_total_count(total_blks); + } + std::vector blkp_arr; + { + int num = SlopeCraft::SCL_getBlockPalette(nullptr, 0); + blkp_arr.resize(num); + SlopeCraft::SCL_getBlockPalette(blkp_arr.data(), blkp_arr.size()); + } + + this->mat_list.resize(blkp_arr.size()); + for (size_t idx = 0; idx < blkp_arr.size(); idx++) { + this->mat_list[idx] = + material_item{.blk = blkp_arr[idx], .count = count_list[idx]}; + } + + { + std::array sz; + kernel->get3DSize(&sz[0], &sz[1], &sz[2]); + this->set_size(sz); + } + + this->ui->tv_mat->setModel(this->mmp); + this->mmp->refresh(); + this->ui->tv_mat->doItemsLayout(); } -PreviewWind::~PreviewWind() { delete this->ui; } \ No newline at end of file +MaterialModel::MaterialModel(QObject* parent) : QAbstractTableModel(parent) {} + +MaterialModel::~MaterialModel() {} + +void MaterialModel::refresh() noexcept { + emit this->dataChanged( + this->index(0, 0), + this->index(this->rowCount() - 1, this->columnCount() - 1)); +} + +QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { + if (!qmi.isValid()) { + return {}; + } + + const int r = qmi.row(); + const int c = qmi.column(); + + if (r >= (int)this->mat_list->size()) { + return {}; + } + if (c >= 2) { + return {}; + } + + const auto& mat = this->mat_list->at(r); + + if (role == Qt::ItemDataRole::DisplayRole) { + if (c == 0) { + return QString::fromUtf8(mat.blk->getNameZH()); + } + + if (c == 1) { + return QString::number(mat.count); + } + } + + if (role == Qt::ItemDataRole::DecorationRole) { + if (c == 0) { + QImage img{16, 16, QImage::Format_ARGB32}; + mat.blk->getImage((uint32_t*)img.scanLine(0), true); + return QIcon{QPixmap::fromImage(img)}; + } + } + + return {}; +} + +int MaterialModel::columnCount(const QModelIndex&) const noexcept { return 2; } + +int MaterialModel::rowCount(const QModelIndex&) const noexcept { + // const int rows = this->mat_list->size(); + return this->mat_list->size(); +} \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h index e92cc622..dac897e2 100644 --- a/SlopeCraft/PreviewWind.h +++ b/SlopeCraft/PreviewWind.h @@ -3,23 +3,65 @@ #include #include +#include +#include +#include + class PreviewWind; +class MaterialModel; namespace Ui { class PreviewWind; } +struct material_item { + const SlopeCraft::AbstractBlock* blk{nullptr}; + int count{0}; +}; + class PreviewWind : public QDialog { Q_OBJECT private: Ui::PreviewWind* ui; + std::vector mat_list; + MaterialModel* mmp{nullptr}; - void setup_widget(const SlopeCraft::Kernel* kernel) noexcept; + void set_size(std::span size) & noexcept; + void set_total_count(int count) & noexcept; public: - explicit PreviewWind(const SlopeCraft::Kernel* kernel, - QWidget* parent = nullptr); + explicit PreviewWind(QWidget* parent = nullptr); ~PreviewWind(); + + const auto& material_list() const noexcept { return this->mat_list; } + void setup_data(const SlopeCraft::Kernel* kernel) noexcept; +}; + +class MaterialModel : public QAbstractTableModel { + Q_OBJECT + private: + const std::vector* mat_list{nullptr}; + + public: + explicit MaterialModel(QObject* parent = nullptr); + ~MaterialModel(); + + auto mat_list_pointer() const noexcept { return this->mat_list; } + + void set_mat_list_pointer(const std::vector* mlp) noexcept { + this->mat_list = mlp; + } + + public slots: + void refresh() noexcept; + + public: + QVariant data(const QModelIndex& qmi, + int role = Qt::DisplayRole) const noexcept override; + int columnCount( + const QModelIndex& parent = QModelIndex{}) const noexcept override; + int rowCount( + const QModelIndex& parent = QModelIndex{}) const noexcept override; }; #endif // SLOPECRAFT_SLOPECRAFT_PREVIEWWIND_H \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index 185c7b93..a4fec5ab 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -14,8 +14,27 @@ 查看材料列表 - - + + + + + 0 + 24 + + + + + + + QFrame::StyledPanel + + + + + + + + @@ -43,6 +62,32 @@ + + + + + + + QFrame::StyledPanel + + + + + + + + + + + 0 + 0 + + + + 切换单位 + + + @@ -81,78 +126,8 @@ - - - - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - 切换单位 - - - - - - - - 0 - 24 - - - - - - - QFrame::StyledPanel - - - - - - - - - false - - - false - - - true - - - - 方块 - - - - - id - - - - - 数量 - - - + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index ad4c5fd4..3487b4ed 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -4,6 +4,7 @@ #include #include #include +#include void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 @@ -374,6 +375,20 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { return; } + PreviewWind *pw = new PreviewWind{this}; + + pw->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); + pw->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); + // bb->setAttribute(Qt::WidgetAttribute::WA_NativeWindow, true); + pw->setWindowFlag(Qt::WindowType::Window, true); + + // connect(this, &VCWind::signal_allowed_colorset_changed, pw, + // &QWidget::deleteLater); + + pw->show(); + + pw->setup_data(this->kernel); + #warning show mat list here } From c9a1986d17abddcd6798e9640414b90971a68b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 00:05:16 +0800 Subject: [PATCH 0329/1123] conceal a weird bug about _mm256_store_ps --- utilities/ColorManip/ColorDiff.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index ea0cd2e9..fb949943 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -157,11 +157,13 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, #define SC_PRIVATE_MARCO_assert_if_nan(vec) \ { \ - float temp[8]; \ - _mm256_store_ps(temp, (vec)); \ - for (float f : temp) { \ - assert(!std::isnan(f)); \ - assert(f >= 0); \ + std::array temp; \ + { \ + _mm256_store_ps(temp.data(), (vec)); \ + for (float f : temp) { \ + assert(!std::isnan(f)); \ + assert(f >= 0); \ + } \ } \ } @@ -210,7 +212,7 @@ void colordiff_RGBplus_batch(std::span r1p, _mm256_set1_ps(rr_plus_gg_plus_bb_2)); SqrModSquare = _mm256_sqrt_ps(SqrModSquare); } - SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); + // SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); __m256 sigma_rgb; { @@ -323,10 +325,12 @@ void colordiff_RGBplus_batch(std::span r1p, _mm256_mul_ps(theta, theta)); diff = _mm256_add_ps(temp_X, temp_Y); - - { + if (false) { float temp[8]; - _mm256_store_ps(temp, diff); + _mm256_store_ps(temp, + diff); // this line crashes on win11, the address of + // temp[7] is 0xfffffffff. I can't understand + // this, maybe a compiler-error? for (float f : temp) { assert(!std::isnan(f)); assert(f >= 0); From 290acb8849663b3a72d8c42dd975fdb1f2606198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 00:06:24 +0800 Subject: [PATCH 0330/1123] finish preview wind --- SlopeCraft/PreviewWind.cpp | 94 ++++++++++++++++++++++++-- SlopeCraft/PreviewWind.h | 8 ++- SlopeCraft/PreviewWind.ui | 129 +++++++++++++++--------------------- SlopeCraft/SCWind_slots.cpp | 2 - 4 files changed, 150 insertions(+), 83 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index ff4de09d..9f8b71c5 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -2,6 +2,7 @@ #include "ui_PreviewWind.h" #include #include +#include PreviewWind::PreviewWind(QWidget* parent) : QDialog(parent), ui(new Ui::PreviewWind) { @@ -12,22 +13,27 @@ PreviewWind::PreviewWind(QWidget* parent) // this->ui->tv_mat->setModel(this->mmp); // connect(this->mmp,&QAbstractTableModel::dataChanged,this->ui->tv_mat,&QTableView::) + + connect(this->ui->cb_show_in_stacks, &QCheckBox::toggled, this->mmp, + &MaterialModel::refresh); + connect(this->ui->cb_sort_option, &QComboBox::currentIndexChanged, this->mmp, + &MaterialModel::refresh); } PreviewWind::~PreviewWind() { delete this->ui; } void PreviewWind::set_size(std::span size) & noexcept { QString size_str = - QStringLiteral("%1 × %2 × %3").arg(size[0]).arg(size[1]).arg(size[2]); + tr("大小:%1 × %2 × %3").arg(size[0]).arg(size[1]).arg(size[2]); this->ui->lb_show_size->setText(size_str); this->ui->lb_show_volume->setText( - QString::number(size[0] * size[1] * size[2])); + tr("体积:%1").arg(size[0] * size[1] * size[2])); } void PreviewWind::set_total_count(int count) & noexcept { - this->ui->lb_block_count->setText(QString::number(count)); + this->ui->lb_block_count->setText(tr("方块总数:%1").arg(count)); } void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { @@ -63,7 +69,24 @@ void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { this->ui->tv_mat->doItemsLayout(); } -MaterialModel::MaterialModel(QObject* parent) : QAbstractTableModel(parent) {} +bool PreviewWind::is_unit_stack() const noexcept { + return this->ui->cb_show_in_stacks->isChecked(); +} + +PreviewWind::sort_option PreviewWind::current_sort_option() const noexcept { + const int cidx = this->ui->cb_sort_option->currentIndex(); + switch (cidx) { + case 1: + return sort_option::ascending; + case 2: + return sort_option::descending; + default: + return sort_option::no_sort; + } +} + +MaterialModel::MaterialModel(PreviewWind* parent) + : QAbstractTableModel(parent), pwind(parent) {} MaterialModel::~MaterialModel() {} @@ -73,6 +96,32 @@ void MaterialModel::refresh() noexcept { this->index(this->rowCount() - 1, this->columnCount() - 1)); } +QString format_num(int num, int stack_size) noexcept { + assert(stack_size > 0); + const int sb_size = stack_size * 27; + + const int sb_num = num / sb_size; + num -= sb_num * sb_size; + + const int stack_num = num / stack_size; + num -= stack_num * stack_size; + + const int left_num = num; + + if (sb_num > 0) { + return MaterialModel::tr("%1 盒 + %2 组 + %3 个") + .arg(sb_num) + .arg(stack_num) + .arg(left_num); + } + + if (stack_num > 0) { + return MaterialModel::tr("%1 组 + %2 个").arg(stack_num).arg(left_num); + } + + return MaterialModel::tr("%1 个").arg(left_num); +} + QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { if (!qmi.isValid()) { return {}; @@ -88,7 +137,35 @@ QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { return {}; } - const auto& mat = this->mat_list->at(r); + using it_t = std::vector::const_iterator; + std::vector its; + { + its.reserve(this->mat_list->size()); + + for (auto it = this->mat_list->begin(); it != this->mat_list->end(); ++it) { + its.emplace_back(it); + } + + const auto sort_opt = this->pwind->current_sort_option(); + + if (sort_opt != PreviewWind::sort_option::no_sort) { + auto sort_fun = [sort_opt](it_t a, it_t b) -> bool { + if (a->count == b->count) { + return a->blk < b->blk; + } + + if (sort_opt == PreviewWind::sort_option::ascending) { + return a->count < b->count; + } + + return a->count > b->count; + }; + + std::sort(its.begin(), its.end(), sort_fun); + } + } + + const auto& mat = *its[r]; if (role == Qt::ItemDataRole::DisplayRole) { if (c == 0) { @@ -96,7 +173,12 @@ QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { } if (c == 1) { - return QString::number(mat.count); + if (!this->pwind->is_unit_stack()) { + return QString::number(mat.count); + } + + const int stack_size = (r == 12) ? 1 : 64; + return format_num(mat.count, stack_size); } } diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h index dac897e2..c466e1bb 100644 --- a/SlopeCraft/PreviewWind.h +++ b/SlopeCraft/PreviewWind.h @@ -35,15 +35,21 @@ class PreviewWind : public QDialog { const auto& material_list() const noexcept { return this->mat_list; } void setup_data(const SlopeCraft::Kernel* kernel) noexcept; + + enum class sort_option { no_sort, ascending, descending }; + + bool is_unit_stack() const noexcept; + sort_option current_sort_option() const noexcept; }; class MaterialModel : public QAbstractTableModel { Q_OBJECT private: const std::vector* mat_list{nullptr}; + const PreviewWind* const pwind; public: - explicit MaterialModel(QObject* parent = nullptr); + explicit MaterialModel(PreviewWind* parent = nullptr); ~MaterialModel(); auto mat_list_pointer() const noexcept { return this->mat_list; } diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index a4fec5ab..2992ef8f 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -14,27 +14,8 @@ 查看材料列表 - - - - - 0 - 24 - - - - - - - QFrame::StyledPanel - - - - - - - - + + @@ -46,24 +27,30 @@ - - + + - + 0 0 - 投影尺寸 + 按组显示 - - Qt::AlignCenter + + true - - + + + + + 0 + 24 + + @@ -75,59 +62,53 @@ - - - - - 0 - 0 - - - - 切换单位 + + + + - - - - - - - 0 - 0 - + + QFrame::StyledPanel - 总体积 - - - Qt::AlignCenter + - - - - - 0 - 0 - - - - - 0 - 24 - - - - 总方块数 - - - Qt::AlignCenter - + + + + false + + + 200 + + + true + + + true + - - + + + + + 不排序 + + + + + 升序 + + + + + 降序 + + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 3487b4ed..3eab71e5 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -388,8 +388,6 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { pw->show(); pw->setup_data(this->kernel); - -#warning show mat list here } #define SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked \ From 519e05e12e26445d32311f80718a0564ede4dc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 01:16:25 +0800 Subject: [PATCH 0331/1123] remove useless code --- SlopeCraft/others/no_use/PoolWidget.cpp | 14 ----- SlopeCraft/others/no_use/PoolWidget.h | 25 -------- SlopeCraft/others/no_use/PoolWidget.ui | 79 ------------------------- 3 files changed, 118 deletions(-) delete mode 100644 SlopeCraft/others/no_use/PoolWidget.cpp delete mode 100644 SlopeCraft/others/no_use/PoolWidget.h delete mode 100644 SlopeCraft/others/no_use/PoolWidget.ui diff --git a/SlopeCraft/others/no_use/PoolWidget.cpp b/SlopeCraft/others/no_use/PoolWidget.cpp deleted file mode 100644 index b6503769..00000000 --- a/SlopeCraft/others/no_use/PoolWidget.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "PoolWidget.h" -#include "ui_PoolWidget.h" - -PoolWidget::PoolWidget(QWidget* parent) - : QWidget(parent), ui(new Ui::PoolWidget) { - this->ui->setupUi(this); -} - -PoolWidget::~PoolWidget() { delete this->ui; } - -void PoolWidget::set_task(const cvt_task& task) noexcept { - this->ui->lb_image->setPixmap(QPixmap::fromImage(task.original_image)); - this->ui->lb_name->setText(task.filename); -} \ No newline at end of file diff --git a/SlopeCraft/others/no_use/PoolWidget.h b/SlopeCraft/others/no_use/PoolWidget.h deleted file mode 100644 index 36416c3b..00000000 --- a/SlopeCraft/others/no_use/PoolWidget.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H -#define SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H - -#include -#include "cvt_task.h" - -class PoolWidget; - -namespace Ui { -class PoolWidget; -} - -class PoolWidget : public QWidget { - Q_OBJECT - private: - Ui::PoolWidget* ui; - - public: - explicit PoolWidget(QWidget* parent = nullptr); - ~PoolWidget(); - - void set_task(const cvt_task& task) noexcept; -}; - -#endif // SLOPECRAFT_SLOPECRAFT_POOLWIDGET_H \ No newline at end of file diff --git a/SlopeCraft/others/no_use/PoolWidget.ui b/SlopeCraft/others/no_use/PoolWidget.ui deleted file mode 100644 index b3b4d99a..00000000 --- a/SlopeCraft/others/no_use/PoolWidget.ui +++ /dev/null @@ -1,79 +0,0 @@ - - - PoolWidget - - - - 0 - 0 - 373 - 346 - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - - - Qt::AlignCenter - - - - - - - - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - AdaptiveLabel - QLabel -
AdaptiveLabel.h
-
-
- - -
From 3de8f424650d65370b2ab98bb77356ebc958544c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 01:17:18 +0800 Subject: [PATCH 0332/1123] pretty the chart --- SlopeCraft/PreviewWind.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index 2992ef8f..74a34e0f 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -77,6 +77,12 @@
+ + true + + + false + false From 41ea7926d5727867e7196694630517b4fc532d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 01:17:49 +0800 Subject: [PATCH 0333/1123] auto correct files --- SlopeCraft/PoolModel.cpp | 4 ++-- SlopeCraft/SCWind.cpp | 6 +++--- SlopeCraft/SCWind.ui | 4 ++-- SlopeCraft/SCWind_slots.cpp | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 80bacec9..d2b5f132 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -71,8 +71,8 @@ void PoolModel::draw_icon(QPixmap& image, const QPixmap& icon, int index, if (icon.size() != QSize{32, 32}) [[unlikely]] { QMessageBox::critical( ptr_to_report_error, QObject::tr("绘制图标时发现错误"), - tr("被绘制的图标尺寸应当是32*32,但实际上是%1*%" - "2。这属于SlopeCraft内部错误,请向开发者反馈。SlopeCraft必须崩溃。") + tr("被绘制的图标尺寸应当是 32*32,但实际上是%1*%" + "2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。") .arg(icon.size().height()) .arg(icon.size().width())); abort(); diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 4ead9c75..a7eebcd9 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -768,7 +768,7 @@ SCWind::current_schem_option(QString &err) const noexcept { ret.offset[idx] = le_offset[idx]->text().toInt(&ok); if (!ok) { - err = tr("WE原理图参数有错:输入给offset的值\"%" + err = tr("WE 原理图参数有错:输入给 offset 的值\"%" "1\"不是一个有效的坐标,应当输入一个整数。") .arg(le_offset[idx]->text()); return std::nullopt; @@ -786,7 +786,7 @@ SCWind::current_schem_option(QString &err) const noexcept { ret.we_offset[idx] = le_weoffset[idx]->text().toInt(&ok); if (!ok) { - err = tr("WE原理图参数有错:输入给we offset的值\"%" + err = tr("WE 原理图参数有错:输入给 we offset 的值\"%" "1\"不是一个有效的数字,应当输入一个整数。") .arg(le_weoffset[idx]->text()); return std::nullopt; @@ -827,7 +827,7 @@ SCWind::current_flatdiagram_option(QString &err) const noexcept { if (row_margin <= 0 || col_margin <= 0) { err = - tr("平面示意图的分割线间距无效:水平间距为 %1, 垂直间距为 %2, " + tr("平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, " "但间距必须为正数。"); return std::nullopt; } diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 3f10c84e..b6227385 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1110,7 +1110,7 @@ - 依赖mod名称 + 依赖 mod 名称 @@ -1123,7 +1123,7 @@ - 在这里输入依赖mod的名字。用换行符分割多个mod + 在这里输入依赖 mod 的名字。用换行符分割多个 mod diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 3eab71e5..5d847326 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -25,7 +25,7 @@ void SCWind::on_pb_add_image_clicked() noexcept { if (!err.isEmpty()) { auto ret = QMessageBox::critical( this, tr("打开图像失败"), - tr("无法打开图像 %1 。常见原因:图像尺寸太大。\n详细信息: %2") + tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") .arg(filename) .arg(err), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, @@ -116,7 +116,7 @@ void SCWind::on_pb_save_preset_clicked() noexcept { if (!qf.isOpen()) { QMessageBox::warning(this, tr("保存预设文件失败"), - tr("无法生成预设文件%1 ,错误信息:%2") + tr("无法生成预设文件%1,错误信息:%2") .arg(file) .arg(qf.errorString())); return; @@ -447,7 +447,7 @@ void SCWind::on_pb_export_all_clicked() noexcept { QMessageBox::warning( this, tr("你点错按钮了"), tr("导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个" - "按钮,这可能是一个小小的bug(特性)。")); + "按钮,这可能是一个小小的 bug(特性)。")); return; } } @@ -537,7 +537,7 @@ void SCWind::on_pb_export_all_clicked() noexcept { return QMessageBox::warning( this, tr("导出失败"), tr("导出%1时失败。原图像文件名为%" - "2\n点击Ignore将跳过这个图像,点击Cancel将放弃导出任务。") + "2\n点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。") .arg(export_name.data()) .arg(taskp->filename), QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, From 7b1890b641d6a983e21608d782e33d9f54aba108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 01:17:59 +0800 Subject: [PATCH 0334/1123] add lupdate target --- SlopeCraft/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 1c60efc8..460c6a17 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -78,6 +78,12 @@ qt_add_resources(SlopeCraft "SC_images" qt_finalize_executable(SlopeCraft) +if(ON) + qt_add_lupdate(SlopeCraft + TS_FILES others/SlopeCraft_en_US.ts + ) +endif() + if(${WIN32}) add_custom_target(SC_create_symlink_SC COMMAND mklink SlopeCraftL.dll "..\\SlopeCraftL\\SlopeCraftL.dll" From d30fba05b1da354326a0254f4f6467c7ed7d939b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 15:00:33 +0800 Subject: [PATCH 0335/1123] display export table --- SlopeCraft/CMakeLists.txt | 15 +-- SlopeCraft/ExportTableModel.cpp | 130 ++++++++++++++++++++++++ SlopeCraft/ExportTableModel.h | 44 ++++++++ SlopeCraft/PreviewWind.ui | 3 + SlopeCraft/SCWind.cpp | 16 +++ SlopeCraft/SCWind.h | 12 +++ SlopeCraft/SCWind.ui | 6 +- utilities/ColorManip/ColorDiff.cpp | 8 +- utilities/MapImageCvter/MapImageCvter.h | 1 + 9 files changed, 223 insertions(+), 12 deletions(-) create mode 100644 SlopeCraft/ExportTableModel.cpp create mode 100644 SlopeCraft/ExportTableModel.h diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 460c6a17..b20d7dc4 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -21,7 +21,8 @@ set(SlopeCraft_headers cvt_task.h PoolModel.h AdaptiveListView.h - PreviewWind.h) + PreviewWind.h + ExportTableModel.h) set(SlopeCraft_sources SCWind.cpp @@ -30,6 +31,8 @@ set(SlopeCraft_sources PoolModel.cpp AdaptiveListView.cpp PreviewWind.cpp + ExportTableModel.cpp + main.cpp ${SlopeCraft_rc_files}) @@ -76,13 +79,11 @@ qt_add_resources(SlopeCraft "SC_images" BASE ${CMAKE_CURRENT_SOURCE_DIR}/others/images FILES ${SlopeCraft_qrc_images}) -qt_finalize_executable(SlopeCraft) +qt_add_lupdate(SlopeCraft + TS_FILES others/SlopeCraft_en_US.ts +) -if(ON) - qt_add_lupdate(SlopeCraft - TS_FILES others/SlopeCraft_en_US.ts - ) -endif() +qt_finalize_executable(SlopeCraft) if(${WIN32}) add_custom_target(SC_create_symlink_SC diff --git a/SlopeCraft/ExportTableModel.cpp b/SlopeCraft/ExportTableModel.cpp new file mode 100644 index 00000000..d26ca4ee --- /dev/null +++ b/SlopeCraft/ExportTableModel.cpp @@ -0,0 +1,130 @@ +#include "ExportTableModel.h" +#include "SCWind.h" + +ExportTableModel::ExportTableModel(SCWind* parent, const task_pool_t* poolptr) + : QAbstractTableModel(parent), pool{poolptr} {} + +ExportTableModel::~ExportTableModel() {} + +const SCWind* ExportTableModel::scwind() const noexcept { + return dynamic_cast(this->parent()); +} + +QSize map_size_of_images(QSize image_size) noexcept { + const int width = std::ceil(image_size.width() / 128.0); + const int height = std::ceil(image_size.height() / 128.0); + return QSize{width, height}; +} + +map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, + int asked_idx) noexcept { + assert(asked_idx >= 0 && asked_idx < (int)pool.size()); + + int current_start_seq = first_map_seq_num; + + for (int idx = 0; idx < asked_idx; idx++) { + const auto current_map_size = + map_size_of_images(pool[idx].original_image.size()); + const int current_map_num = + current_map_size.height() * current_map_size.width(); + + current_start_seq += current_map_num; + } + + const auto cms = map_size_of_images(pool[asked_idx].original_image.size()); + const int cmn = cms.height() * cms.width(); + + return map_range{current_start_seq, current_start_seq + cmn - 1}; +} + +QString map_data_filename(QString dir, int seq_number) noexcept { + return QStringLiteral("%1/map_%2.dat").arg(dir).arg(seq_number); +} + +void ExportTableModel::refresh() noexcept { + // emit + emit this->layoutChanged(); + emit this->dataChanged(this->index(0, 0), this->index(this->rowCount({}), + this->columnCount({}))); +} + +int ExportTableModel::rowCount(const QModelIndex&) const noexcept { + return this->pool->size(); +} + +int ExportTableModel::columnCount(const QModelIndex&) const noexcept { + return 6; +} + +QVariant ExportTableModel::data(const QModelIndex& qmi, + int role) const noexcept { + if (!qmi.isValid()) { + return {}; + } + + const int r = qmi.row(); + const int c = qmi.column(); + + if (r < 0 || r >= (int)this->pool->size()) { + return {}; + } + + const auto& task = this->pool->at(r); + + if (role == Qt::ItemDataRole::DisplayRole) { + const QSize map_size = map_size_of_images(task.original_image.size()); + + const int map_count = map_size.height() * map_size.width(); + const int beg_idx = this->scwind()->current_map_begin_seq_number(); + const auto range = map_range_at_index(*this->pool, beg_idx, r); + + switch (c) { + case 0: + return task.filename; + case 1: + return QStringLiteral("%1 × %2") + .arg(task.original_image.height()) + .arg(task.original_image.width()); + case 2: + return QStringLiteral("%1 × %2 = %3") + .arg(map_size.height()) + .arg(map_size.width()) + .arg(map_count); + case 3: + return QStringLiteral("%1 ~ %2").arg(range.first).arg(range.last); + case 4: + return map_data_filename(this->scwind()->data_export_dir(), + range.first); + case 5: + return map_data_filename(this->scwind()->data_export_dir(), range.last); + } + } + + return {}; +} + +QVariant ExportTableModel::headerData(int section, Qt::Orientation orientation, + int role) const noexcept { + if (orientation != Qt::Orientation::Horizontal || + role != Qt::ItemDataRole::DisplayRole || + section > this->columnCount({})) { + return QAbstractTableModel::headerData(section, orientation, role); + } + + switch (section) { + case 0: + return tr("原图文件名"); + case 1: + return tr("图像大小"); + case 2: + return tr("地图大小"); + case 3: + return tr("地图序号范围"); + case 4: + return tr("第一个地图文件名"); + case 5: + return tr("最后一个地图文件名"); + default: + return QAbstractTableModel::headerData(section, orientation, role); + } +} \ No newline at end of file diff --git a/SlopeCraft/ExportTableModel.h b/SlopeCraft/ExportTableModel.h new file mode 100644 index 00000000..61cb73dd --- /dev/null +++ b/SlopeCraft/ExportTableModel.h @@ -0,0 +1,44 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_EXPORTTABLEMODEL_H +#define SLOPECRAFT_SLOPECRAFT_EXPORTTABLEMODEL_H + +#include +#include "cvt_task.h" + +class SCWind; + +class ExportTableModel : public QAbstractTableModel { + Q_OBJECT + private: + const task_pool_t* pool{nullptr}; + + public: + explicit ExportTableModel(SCWind* parent, const task_pool_t* poolptr); + ~ExportTableModel(); + + int rowCount(const QModelIndex&) const noexcept override; + int columnCount(const QModelIndex&) const noexcept override; + + QVariant data(const QModelIndex&, int role) const noexcept override; + + const SCWind* scwind() const noexcept; + + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const noexcept override; + + public slots: + void refresh() noexcept; +}; + +QSize map_size_of_images(QSize image_size) noexcept; + +struct map_range { + int first{-1}; + int last{-1}; +}; + +map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, + int asked_idx) noexcept; + +QString map_data_filename(QString dir, int seq_number) noexcept; + +#endif // SLOPECRAFT_SLOPECRAFT_EXPORTTABLEMODEL_H \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index 74a34e0f..8a414521 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -99,6 +99,9 @@
+ + 2 + 不排序 diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index a7eebcd9..33f8c83c 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) @@ -66,6 +67,17 @@ SCWind::SCWind(QWidget *parent) this->ui->lview_pool_export->doItemsLayout(); }); } + { + this->export_table_model = new ExportTableModel{this, &this->tasks}; + this->ui->tview_export_fileonly->setModel(this->export_table_model); + + connect(this, &SCWind::image_changed, this->export_table_model, + &ExportTableModel::refresh); + connect(this->ui->sb_file_start_idx, &QSpinBox::valueChanged, + this->export_table_model, &ExportTableModel::refresh); + connect(this, &SCWind::image_changed, this->export_table_model, + &ExportTableModel::refresh); + } // initialize blm { @@ -842,4 +854,8 @@ SCWind::current_flatdiagram_option(QString &err) const noexcept { return SlopeCraft::Kernel::flag_diagram_options{ .split_line_row_margin = row_margin, .split_line_col_margin = col_margin}; +} + +int SCWind::current_map_begin_seq_number() const noexcept { + return this->ui->sb_file_start_idx->value(); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 86a88bb8..097651dc 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -10,6 +10,7 @@ #include #include "cvt_task.h" #include "PoolModel.h" +#include "ExportTableModel.h" class SCWind; @@ -68,9 +69,13 @@ class SCWind : public QMainWindow { task_pool_t tasks; CvtPoolModel* cvt_pool_model{nullptr}; ExportPoolModel* export_pool_model{nullptr}; + ExportTableModel* export_table_model{nullptr}; std::array default_presets; + QString fileonly_export_dir{""}; + + public: std::array version_buttons() noexcept; std::array version_buttons() const noexcept; @@ -126,6 +131,13 @@ class SCWind : public QMainWindow { std::optional current_flatdiagram_option(QString& err) const noexcept; + int current_map_begin_seq_number() const noexcept; + + inline QString data_export_dir() const noexcept { + return this->fileonly_export_dir; + } + + private: // kernel related functions void kernel_set_type() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index b6227385..b2024a18 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1333,7 +1333,11 @@ - + + + true + + diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index fb949943..2e9a0c02 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -157,7 +157,7 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, #define SC_PRIVATE_MARCO_assert_if_nan(vec) \ { \ - std::array temp; \ + alignas(32) std::array temp; \ { \ _mm256_store_ps(temp.data(), (vec)); \ for (float f : temp) { \ @@ -212,7 +212,7 @@ void colordiff_RGBplus_batch(std::span r1p, _mm256_set1_ps(rr_plus_gg_plus_bb_2)); SqrModSquare = _mm256_sqrt_ps(SqrModSquare); } - // SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); + SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); __m256 sigma_rgb; { @@ -325,8 +325,8 @@ void colordiff_RGBplus_batch(std::span r1p, _mm256_mul_ps(theta, theta)); diff = _mm256_add_ps(temp_X, temp_Y); - if (false) { - float temp[8]; + if (true) { + alignas(32) float temp[8]; _mm256_store_ps(temp, diff); // this line crashes on win11, the address of // temp[7] is 0xfffffffff. I can't understand diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 1a98f9b4..57ef2710 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -126,6 +126,7 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { colors_dithered_img.reserve(this->_dithered_image.size()); for (int64_t i = 0; i < this->_dithered_image.size(); i++) { colors_dithered_img.emplace(this->_dithered_image(i)); + colors_dithered_img.emplace(this->_raw_image(i)); } const size_t size_colorset = colors_dithered_img.size(); From ba3e9dc8033d357d7c2e16926f6d03590db5363d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 18:32:35 +0800 Subject: [PATCH 0336/1123] export fileonly --- SlopeCraft/ExportTableModel.cpp | 5 +-- SlopeCraft/SCWind.h | 8 ++-- SlopeCraft/SCWind.ui | 10 ++--- SlopeCraft/SCWind_slots.cpp | 69 +++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/SlopeCraft/ExportTableModel.cpp b/SlopeCraft/ExportTableModel.cpp index d26ca4ee..64185411 100644 --- a/SlopeCraft/ExportTableModel.cpp +++ b/SlopeCraft/ExportTableModel.cpp @@ -93,10 +93,9 @@ QVariant ExportTableModel::data(const QModelIndex& qmi, case 3: return QStringLiteral("%1 ~ %2").arg(range.first).arg(range.last); case 4: - return map_data_filename(this->scwind()->data_export_dir(), - range.first); + return QStringLiteral("map_%1.dat").arg(range.first); case 5: - return map_data_filename(this->scwind()->data_export_dir(), range.last); + return QStringLiteral("map_%1.dat").arg(range.last); } } diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 097651dc..30a1d9f3 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -62,6 +62,8 @@ class SCWind : public QMainWindow { void on_pb_preview_materials_clicked() noexcept; void on_pb_export_all_clicked() noexcept; + void on_pb_export_file_clicked() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; @@ -73,7 +75,7 @@ class SCWind : public QMainWindow { std::array default_presets; - QString fileonly_export_dir{""}; + // QString fileonly_export_dir{""}; public: std::array version_buttons() noexcept; @@ -133,10 +135,6 @@ class SCWind : public QMainWindow { int current_map_begin_seq_number() const noexcept; - inline QString data_export_dir() const noexcept { - return this->fileonly_export_dir; - } - private: // kernel related functions void kernel_set_type() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index b2024a18..b0b0aed7 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1334,6 +1334,9 @@ + + true + true @@ -1351,13 +1354,6 @@ - - - - 设置导出文件夹 - - - diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 5d847326..6f1323fb 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -571,4 +571,73 @@ void SCWind::on_pb_export_all_clicked() noexcept { return; } } +} + +void SCWind::on_pb_export_file_clicked() noexcept { + static QString prev_dir{""}; + const QString dir = + QFileDialog::getExistingDirectory(this, tr("设置导出位置"), prev_dir); + + if (dir.isEmpty()) { + return; + } + + prev_dir = dir; + + const int seq_first = this->current_map_begin_seq_number(); + { + int exisiting_num = 0; + QString to_be_replaced{""}; + to_be_replaced.reserve(4096); + + const int seq_last = + map_range_at_index(this->tasks, seq_first, this->tasks.size() - 1).last; + + for (int seq = seq_first; seq <= seq_last; seq++) { + QString filename = map_data_filename(dir, seq); + if (QFile{filename}.exists()) { + if (exisiting_num > 0) { + to_be_replaced.push_back('\n'); + } + to_be_replaced.append(filename); + exisiting_num++; + } + } + + if (exisiting_num > 0) { + const auto ret = QMessageBox::warning( + this, tr("%1 个文件将被替换").arg(exisiting_num), + tr("以下文件将被替换:\n%1\n点击 Yes " + "将替换它们,点击 No 将取消这次导出。") + .arg(to_be_replaced), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No}); + + if (ret != QMessageBox::StandardButton::Yes) { + return; + } + } + } + + for (int idx = 0; idx < int(this->tasks.size()); idx++) { + auto &task = this->tasks.at(idx); + this->kernel_set_image(idx); + bool need_to_convert{true}; + if (task.is_converted) { + if (this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + need_to_convert = false; + } + } + + if (need_to_convert) { + this->kernel_convert_image(); + } + + const int cur_seq_beg = + map_range_at_index(this->tasks, seq_first, idx).first; + + this->kernel->exportAsData(dir.toLocal8Bit().data(), cur_seq_beg, nullptr, + nullptr); + } } \ No newline at end of file From 5c06e3f4b468f8f0732141c00b5a83bedd07307e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 18 May 2023 19:18:50 +0800 Subject: [PATCH 0337/1123] tried to compile with clang, but failed --- SlopeCraftL/PrimGlassBuilder.cpp | 95 ++++++++++------------------ SlopeCraftL/PrimGlassBuilder.h | 18 +++--- SlopeCraftL/TokiSlopeCraft_build.cpp | 12 ++-- 3 files changed, 51 insertions(+), 74 deletions(-) diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/PrimGlassBuilder.cpp index 5ecf6c29..3630c728 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/PrimGlassBuilder.cpp @@ -94,8 +94,7 @@ bool pairedEdge::connectWith(TokiPos P) const { } void pairedEdge::drawEdge(glassMap &map, bool drawHead) const { - if (lengthSquare <= 2) - return; + if (lengthSquare <= 2) return; float length = sqrt(lengthSquare); Eigen::Vector2f startPoint(TokiRow(first), TokiCol(first)); Eigen::Vector2f endPoint(TokiRow(second), TokiCol(second)); @@ -122,14 +121,7 @@ void pairedEdge::drawEdge(glassMap &map, bool drawHead) const { (drawHead ? PrimGlassBuilder::target : PrimGlassBuilder::air); } -#ifdef WITH_QT -PrimGlassBuilder::PrimGlassBuilder(QObject *parent) - : QObject(parent) -#else -PrimGlassBuilder::PrimGlassBuilder() -#endif -{ -} +PrimGlassBuilder::PrimGlassBuilder() {} glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, walkableMap *walkable) { // clock_t lastTime=std::clock(); @@ -141,34 +133,25 @@ glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, std::vector> walkableMaps(rowCount); std::vector> targetMaps(rowCount); - // std::cerr<<"开始分区分块,共["<make4SingleMap( targetMaps[r][c], (walkable == nullptr) ? nullptr : (&walkableMaps[r][c])); @@ -183,15 +166,13 @@ glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, pairedEdge temp = connectSingleMaps( algos[r][c], TokiRC(unitL * r, unitL * c), algos[r + 1][c], TokiRC(unitL * (r + 1), unitL * c)); - if (temp.lengthSquare > 2) - interRegionEdges.emplace(temp); + if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } if (c + 1 < colCount) { pairedEdge temp = connectSingleMaps( algos[r][c], TokiRC(unitL * r, unitL * c), algos[r][c + 1], TokiRC(unitL * r, unitL * (c + 1))); - if (temp.lengthSquare > 2) - interRegionEdges.emplace(temp); + if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } } // qDebug()<<"分区间搭桥完毕,将搭建"< unitL || _targetMap.cols() > unitL) { - // qDebug("错误!make4SingleMap不应当收到超过unitL*unitL的图"); + // qDebug("错误!make4SingleMap 不应当收到超过 unitL*unitL 的图"); return glassMap(0, 0); } targetPoints.clear(); @@ -271,14 +250,12 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, return result; } - for (auto it = tree.cbegin(); it != tree.cend(); it++) - it->drawEdge(result); + for (auto it = tree.cbegin(); it != tree.cend(); it++) it->drawEdge(result); for (auto it = targetPoints.cbegin(); it != targetPoints.cend(); it++) result(TokiRow(*it), TokiCol(*it)) = 0; - if (walkable != nullptr) - *walkable = result; + if (walkable != nullptr) *walkable = result; for (auto it = targetPoints.cbegin(); it != targetPoints.cend(); it++) { result(TokiRow(*it), TokiCol(*it)) = 0; @@ -292,7 +269,6 @@ pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, TokiPos offset1, const PrimGlassBuilder *map2, TokiPos offset2) { - if (map1->targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) return pairedEdge(); @@ -315,11 +291,9 @@ pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, r2 = offsetR2 + TokiRow(*jt); c2 = offsetC2 + TokiCol(*jt); current = pairedEdge(r1, c1, r2, c2); - if (current.lengthSquare <= 2) - return current; + if (current.lengthSquare <= 2) return current; - if (min.lengthSquare > current.lengthSquare) - min = current; + if (min.lengthSquare > current.lengthSquare) min = current; } return min; } @@ -351,11 +325,9 @@ void PrimGlassBuilder::runPrim() { std::stack::iterator> eraseTask; - while (!eraseTask.empty()) - eraseTask.pop(); + while (!eraseTask.empty()) eraseTask.pop(); while (foundCount < targetPoints.size()) { - while (!eraseTask.empty()) { edges.erase(eraseTask.top()); eraseTask.pop(); @@ -397,7 +369,7 @@ void PrimGlassBuilder::runPrim() { bool fy = isFound[(it)->endIdx]; if (fx && fy) { eraseTask.emplace(it); - it++; // 如果一条边的首尾都是已经被连接到的点,那么移除这条边 + it++; // 如果一条边的首尾都是已经被连接到的点,那么移除这条边 continue; } bool ux = !fx; @@ -411,8 +383,8 @@ void PrimGlassBuilder::runPrim() { } // 将选中边装入树中, - // 并从集合unsearched中删除选中边的两个端点, - // 向集合found中加入选中边的两个端点 + // 并从集合 unsearched 中删除选中边的两个端点, + // 向集合 found 中加入选中边的两个端点 { // TokiPos x=selectedEdge->beg(); // TokiPos y=selectedEdge->end(); @@ -430,7 +402,7 @@ void PrimGlassBuilder::runPrim() { // emit keepAwake(); // } } - // qDebug("prim算法完毕"); + // qDebug("prim 算法完毕"); } EImage TokiMap2EImage(const TokiMap &tm) { @@ -438,10 +410,8 @@ EImage TokiMap2EImage(const TokiMap &tm) { result.setConstant(airColor); for (uint16_t r = 0; r < tm.rows(); r++) for (uint16_t c = 0; c < tm.cols(); c++) { - if (tm(r, c) == 1) - result(r, c) = glassColor; - if (tm(r, c) > 1) - result(r, c) = targetColor; + if (tm(r, c) == 1) result(r, c) = glassColor; + if (tm(r, c) > 1) result(r, c) = targetColor; } return result; } @@ -465,10 +435,8 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, min.lengthSquare = 0x7FFFFFFF; for (auto t2 = target2.cbegin(); t2 != target2.cend(); t2++) { temp = pairedEdge(*t1, *t2); - if (min.lengthSquare > temp.lengthSquare) - min = temp; - if (min.lengthSquare <= 2) - break; + if (min.lengthSquare > temp.lengthSquare) min = temp; + if (min.lengthSquare <= 2) break; } linkEdges.emplace_back(min); } @@ -479,8 +447,7 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, for (auto it = linkEdges.cbegin(); it != linkEdges.cend(); it++) it->drawEdge(result); - if (walkable != nullptr) - *walkable = result; + if (walkable != nullptr) *walkable = result; for (auto t = target1.cbegin(); t != target1.cend(); t++) { result(TokiRow(*t), TokiCol(*t)) = PrimGlassBuilder::air; @@ -495,13 +462,21 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, return result; } -TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) { +template +TokiMap impl_ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { assert(raw.dimension(2) == 1); TokiMap result(raw.dimension(0), raw.dimension(1)); result.setZero(); for (int i = 0; i < raw.size(); i++) - if (raw(i) > 1) - result(i) = PrimGlassBuilder::target; + if (raw(i) > 1) result(i) = PrimGlassBuilder::target; return result; } + +TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { + return impl_ySlice2TokiMap(raw); +} + +TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { + return impl_ySlice2TokiMap(raw); +} \ No newline at end of file diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/PrimGlassBuilder.h index 3cac912f..7049b81f 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/PrimGlassBuilder.h @@ -47,7 +47,7 @@ typedef TokiMap glassMap; typedef TokiMap walkableMap; class edge { -public: + public: edge(); edge(uint32_t begIdx, uint32_t endIdx); // edge(uint32_t begIdx,uint32_t endIdx); @@ -66,7 +66,7 @@ class edge { }; class pairedEdge : public std::pair { -public: + public: pairedEdge(); pairedEdge(TokiPos, TokiPos); pairedEdge(uint16_t r1, uint16_t c1, uint16_t r2, uint16_t c2); @@ -77,17 +77,19 @@ class pairedEdge : public std::pair { void drawEdge(glassMap &, bool drawHead = false) const; }; -TokiMap ySlice2TokiMap(const Eigen::Tensor &); +TokiMap ySlice2TokiMap(const Eigen::Tensor &) noexcept; +TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &) noexcept; glassMap connectBetweenLayers(const TokiMap &, const TokiMap &, walkableMap *walkable); -// 返回值是架构在相对较高的一层上的,walkable是各层俯视图叠加 +// 返回值是架构在相对较高的一层上的,walkable 是各层俯视图叠加 class PrimGlassBuilder { -public: + public: PrimGlassBuilder(); - template friend class tf::ObjectPool; + template + friend class tf::ObjectPool; void *_object_pool_block; static const uint32_t unitL = 32; @@ -100,7 +102,7 @@ class PrimGlassBuilder { void (**progressAddPtr)(void *, int); void (**keepAwakePtr)(void *); -private: + private: std::vector targetPoints; std::list edges; std::vector tree; @@ -116,4 +118,4 @@ inline tf::ObjectPool pgb; EImage TokiMap2EImage(const TokiMap &); -#endif // PRIMGLASSBUILDER_H +#endif // PRIMGLASSBUILDER_H diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 54b7038d..7aff2c32 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -19,6 +19,7 @@ This file is part of SlopeCraft. github:https://github.com/SlopeCraft/SlopeCraft bilibili:https://space.bilibili.com/351429231 */ +#include #include "TokiSlopeCraft.h" @@ -441,8 +442,8 @@ void TokiSlopeCraft::makeBridge() { extension[0] = schem.x_range(); extension[1] = schem.z_range(); extension[2] = 1; - TokiMap targetMap = ySlice2TokiMap( - schem.tensor().slice(start, extension).cast()); + TokiMap targetMap = + ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); glassMap glass; cerr << "Construct glass bridge at y=" << y << endl; glass = glassBuilder->makeBridge(targetMap); @@ -460,11 +461,10 @@ void TokiSlopeCraft::makeBridge() { extension[0] = schem.x_range(); extension[1] = 1; extension[2] = schem.z_range(); - TokiMap yCur = ySlice2TokiMap( - schem.tensor().slice(start, extension).cast()); + TokiMap yCur = ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); start[1] = y - 1; - TokiMap yBelow = ySlice2TokiMap( - schem.tensor().slice(start, extension).cast()); + TokiMap yBelow = + ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); cerr << "Construct glass bridge between y=" << y << " and y=" << y - 1 << endl; glassMap glass = connectBetweenLayers(yCur, yBelow, nullptr); From 368538d6958b4bbf4aa4d068f9cc540c94d4d025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 00:44:24 +0800 Subject: [PATCH 0338/1123] make aicvter easier to use --- SlopeCraftL/AiCvterOpt.cpp | 33 -------------------------- SlopeCraftL/AiCvterOpt.h | 45 ------------------------------------ SlopeCraftL/CMakeLists.txt | 5 ++-- SlopeCraftL/SlopeCraftL.h | 35 +++++++++++++++++----------- SlopeCraftL/TokiSlopeCraft.h | 2 -- 5 files changed, 25 insertions(+), 95 deletions(-) delete mode 100644 SlopeCraftL/AiCvterOpt.cpp delete mode 100644 SlopeCraftL/AiCvterOpt.h diff --git a/SlopeCraftL/AiCvterOpt.cpp b/SlopeCraftL/AiCvterOpt.cpp deleted file mode 100644 index 1a08b9b9..00000000 --- a/SlopeCraftL/AiCvterOpt.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "AiCvterOpt.h" - -using namespace SlopeCraft; - -AiCvterOpt::AiCvterOpt() { - popSize = 50; - maxGeneration = 200; - maxFailTimes = 50; - crossoverProb = 0.8; - mutationProb = 0.01; -} diff --git a/SlopeCraftL/AiCvterOpt.h b/SlopeCraftL/AiCvterOpt.h deleted file mode 100644 index e126419a..00000000 --- a/SlopeCraftL/AiCvterOpt.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef AICVTEROPT_H -#define AICVTEROPT_H -#include "SCLDefines.h" -#include "SlopeCraftL.h" - -#ifndef SCL_CAPI -namespace SlopeCraft { -#endif - -struct AiCvterOpt { - AiCvterOpt(); - size_t popSize; - size_t maxGeneration; - size_t maxFailTimes; - double crossoverProb; - double mutationProb; -}; - -#ifndef SCL_CAPI -} // namespace SlopeCraft -#endif - -#endif // AICVTEROPT_H diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index f59c21c8..5d88994a 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -23,7 +23,8 @@ endif() set(SlopeCraft_SCL_sources ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h - AiCvterOpt.h + + # AiCvterOpt.h Colors.h HeightLine.h @@ -39,7 +40,7 @@ set(SlopeCraft_SCL_sources SlopeCraftL_global.h WriteStringDeliver.h - AiCvterOpt.cpp + # AiCvterOpt.cpp Colors.cpp ColorSource.cpp HeightLine.cpp diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 4c745758..3a426f5b 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -37,8 +37,8 @@ This file is part of SlopeCraft. // declare classes namespace SlopeCraft { class AbstractBlock; -struct AiCvterOpt; class Kernel; +struct AiCvterOpt; } // namespace SlopeCraft namespace SlopeCraft { @@ -55,6 +55,15 @@ using errorFlag = ::SCL_errorFlag; namespace SlopeCraft { +struct AiCvterOpt { + uint64_t version{SC_VERSION_U64}; + size_t popSize{50}; + size_t maxGeneration{200}; + size_t maxFailTimes{50}; + double crossoverProb{0.8}; + double mutationProb{0.01}; +}; + struct StringDeliver { StringDeliver() = default; StringDeliver(char *p, size_t cap) : data(p), capacity(cap) {} @@ -378,20 +387,20 @@ struct blockListOption { SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *); -[[nodiscard]] SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt(); -SCL_EXPORT void SCL_destroyAiCvterOpt(AiCvterOpt *); +[[deprecated]] [[nodiscard]] SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt(); +[[deprecated]] SCL_EXPORT void SCL_destroyAiCvterOpt(AiCvterOpt *); -SCL_EXPORT void SCL_setPopSize(AiCvterOpt *, uint32_t p); -SCL_EXPORT void SCL_setMaxGeneration(AiCvterOpt *, uint32_t p); -SCL_EXPORT void SCL_setMaxFailTimes(AiCvterOpt *, uint32_t p); -SCL_EXPORT void SCL_setCrossoverProb(AiCvterOpt *, double p); -SCL_EXPORT void SCL_setMutationProb(AiCvterOpt *, double p); +[[deprecated]] SCL_EXPORT void SCL_setPopSize(AiCvterOpt *, uint32_t p); +[[deprecated]] SCL_EXPORT void SCL_setMaxGeneration(AiCvterOpt *, uint32_t p); +[[deprecated]] SCL_EXPORT void SCL_setMaxFailTimes(AiCvterOpt *, uint32_t p); +[[deprecated]] SCL_EXPORT void SCL_setCrossoverProb(AiCvterOpt *, double p); +[[deprecated]] SCL_EXPORT void SCL_setMutationProb(AiCvterOpt *, double p); -SCL_EXPORT uint32_t SCL_getPopSize(const AiCvterOpt *); -SCL_EXPORT uint32_t SCL_getMaxGeneration(const AiCvterOpt *); -SCL_EXPORT uint32_t SCL_getMaxFailTimes(const AiCvterOpt *); -SCL_EXPORT double SCL_getCrossoverProb(const AiCvterOpt *); -SCL_EXPORT double SCL_getMutationProb(const AiCvterOpt *); +[[deprecated]] SCL_EXPORT uint32_t SCL_getPopSize(const AiCvterOpt *); +[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxGeneration(const AiCvterOpt *); +[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxFailTimes(const AiCvterOpt *); +[[deprecated]] SCL_EXPORT double SCL_getCrossoverProb(const AiCvterOpt *); +[[deprecated]] SCL_EXPORT double SCL_getMutationProb(const AiCvterOpt *); SCL_EXPORT void SCL_preprocessImage( uint32_t *ARGB32ptr, const uint64_t imageSize, diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 8db959fe..c8609ea0 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -46,8 +46,6 @@ This file is part of SlopeCraft. #include -#include "AiCvterOpt.h" - #include #include #include From dcfeedff6615c3ea35c786361a3fb1792243b082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 00:44:51 +0800 Subject: [PATCH 0339/1123] add AiCvterParameterDialog --- SlopeCraft/AiCvterParameterDialog.cpp | 63 ++++++++++ SlopeCraft/AiCvterParameterDialog.h | 58 +++++++++ SlopeCraft/AiCvterParameterDialog.ui | 171 ++++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 SlopeCraft/AiCvterParameterDialog.cpp create mode 100644 SlopeCraft/AiCvterParameterDialog.h create mode 100644 SlopeCraft/AiCvterParameterDialog.ui diff --git a/SlopeCraft/AiCvterParameterDialog.cpp b/SlopeCraft/AiCvterParameterDialog.cpp new file mode 100644 index 00000000..975582ae --- /dev/null +++ b/SlopeCraft/AiCvterParameterDialog.cpp @@ -0,0 +1,63 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include "AiCvterParameterDialog.h" +#include "ui_AiCvterParameterDialog.h" + +#include "SCWind.h" + +using namespace SlopeCraft; +AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent, + SlopeCraft::Kernel *kernelp) + : QDialog(parent), ui(new Ui::AiCvterParameterDialog), kernel(kernelp) { + this->ui->setupUi(this); + + SlopeCraft::AiCvterOpt opt = *this->kernel->aiCvterOpt(); + opt.version = SC_VERSION_U64; + + this->ui->sb_pop_size->setValue(opt.popSize); + this->ui->sb_max_gen->setValue(opt.maxGeneration); + this->ui->sb_max_early_stop->setValue(opt.maxFailTimes); + this->ui->dsb_crossover_prob->setValue(opt.crossoverProb); + this->ui->dsb_mutate_prob->setValue(opt.mutationProb); +} + +AiCvterParameterDialog::~AiCvterParameterDialog() { delete this->ui; } + +SlopeCraft::AiCvterOpt AiCvterParameterDialog::current_option() const noexcept { + SlopeCraft::AiCvterOpt ret; + ret.crossoverProb = this->ui->dsb_crossover_prob->value(); + ret.mutationProb = this->ui->dsb_mutate_prob->value(); + ret.maxFailTimes = this->ui->sb_max_early_stop->value(); + ret.maxGeneration = this->ui->sb_max_gen->value(); + ret.popSize = this->ui->sb_pop_size->value(); + return ret; +} + +void AiCvterParameterDialog::on_buttonBox_accepted() noexcept { + auto opt = this->current_option(); + this->kernel->setAiCvterOpt(&opt); +} + +void AiCvterParameterDialog::on_buttonBox_rejected() noexcept { + this->deleteLater(); +} diff --git a/SlopeCraft/AiCvterParameterDialog.h b/SlopeCraft/AiCvterParameterDialog.h new file mode 100644 index 00000000..9fd435af --- /dev/null +++ b/SlopeCraft/AiCvterParameterDialog.h @@ -0,0 +1,58 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#ifndef AICVTERPARAMETERDIALOG_H +#define AICVTERPARAMETERDIALOG_H + +#include +#include +#include + +class AiCvterParameterDialog; + +namespace Ui { +class AiCvterParameterDialog; +} + +class SCWind; + +class AiCvterParameterDialog : public QDialog { + Q_OBJECT + + public: + explicit AiCvterParameterDialog(SCWind *parent, SlopeCraft::Kernel *kernelp); + ~AiCvterParameterDialog(); + + SlopeCraft::AiCvterOpt current_option() const noexcept; + + private slots: + // void updateMaxFailTimes(); + void on_buttonBox_accepted() noexcept; + + void on_buttonBox_rejected() noexcept; + + private: + Ui::AiCvterParameterDialog *ui; + SlopeCraft::Kernel *const kernel; +}; + +#endif // AICVTERPARAMETERDIALOG_H diff --git a/SlopeCraft/AiCvterParameterDialog.ui b/SlopeCraft/AiCvterParameterDialog.ui new file mode 100644 index 00000000..74e2665f --- /dev/null +++ b/SlopeCraft/AiCvterParameterDialog.ui @@ -0,0 +1,171 @@ + + + AiCvterParameterDialog + + + + 0 + 0 + 325 + 120 + + + + Ai转化器参数 + + + + + + 最大提前收敛代数: + + + 10 + + + 3000 + + + 10 + + + + + + + 交叉概率: + + + + + + 1.000000000000000 + + + 0.010000000000000 + + + 0.800000000000000 + + + + + + + + 150 + 0 + + + + + + + 种群数量: + + + 30 + + + 500 + + + 10 + + + 50 + + + + + + + + 150 + 0 + + + + 最大进化代数: + + + 50 + + + 3000 + + + 10 + + + 200 + + + + + + + 变异概率: + + + 3 + + + 1.000000000000000 + + + 0.001000000000000 + + + 0.010000000000000 + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AiCvterParameterDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AiCvterParameterDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From 53ff27893c29581e2ef7a3fc238119bf383305b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 00:45:11 +0800 Subject: [PATCH 0340/1123] add cache dir functions --- SlopeCraft/CMakeLists.txt | 7 +++- SlopeCraft/SCWind.h | 6 +++ SlopeCraft/SCWind.ui | 29 ++++++++++++++ SlopeCraft/SCWind_slots.cpp | 76 ++++++++++++++++++++++++++++++++++++- 4 files changed, 115 insertions(+), 3 deletions(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index b20d7dc4..dc8f51f3 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -22,7 +22,8 @@ set(SlopeCraft_headers PoolModel.h AdaptiveListView.h PreviewWind.h - ExportTableModel.h) + ExportTableModel.h + AiCvterParameterDialog.h) set(SlopeCraft_sources SCWind.cpp @@ -32,13 +33,15 @@ set(SlopeCraft_sources AdaptiveListView.cpp PreviewWind.cpp ExportTableModel.cpp + AiCvterParameterDialog.cpp main.cpp ${SlopeCraft_rc_files}) set(SlopeCraft_uis SCWind.ui - PreviewWind.ui) + PreviewWind.ui + AiCvterParameterDialog.ui) set(SlopeCraft_project_files ${SlopeCraft_headers} diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 30a1d9f3..2acc3bd2 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -64,6 +64,12 @@ class SCWind : public QMainWindow { void on_pb_export_file_clicked() noexcept; + private slots: + void on_ac_GAcvter_options_triggered() noexcept; + + void on_ac_cache_dir_open_triggered() noexcept; + void on_ac_clear_cache_triggered() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index b0b0aed7..ef5c2e03 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1397,6 +1397,15 @@ 高级 + + + 缓存 + + + + + + @@ -1408,6 +1417,26 @@ + + + GA转化器参数 + + + + + open_cache_dir + + + + + 打开缓存文件夹 + + + + + 清除缓存 + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 6f1323fb..85a7fd6c 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -4,7 +4,9 @@ #include #include #include -#include +#include +#include "PreviewWind.h" +#include "AiCvterParameterDialog.h" void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 @@ -640,4 +642,76 @@ void SCWind::on_pb_export_file_clicked() noexcept { this->kernel->exportAsData(dir.toLocal8Bit().data(), cur_seq_beg, nullptr, nullptr); } +} + +void SCWind::on_ac_GAcvter_options_triggered() noexcept { + AiCvterParameterDialog *acpd = new AiCvterParameterDialog{this, this->kernel}; + + acpd->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); + acpd->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); + acpd->setWindowFlag(Qt::WindowType::Window, true); + // bb->setAttribute(Qt::WidgetAttribute::WA_NativeWindow, true); + acpd->show(); +} + +void SCWind::on_ac_cache_dir_open_triggered() noexcept { + auto cache_dir = QString::fromLocal8Bit(this->kernel->cacheDir()); + QDesktopServices::openUrl(QUrl::fromLocalFile(cache_dir)); +} + +void SCWind::on_ac_clear_cache_triggered() noexcept { + const auto cache_dir_name = QString::fromLocal8Bit(this->kernel->cacheDir()); + + QDir cache_dir{cache_dir_name}; + + if (!cache_dir.exists()) { + return; + } + + for (auto &task : this->tasks) { + task.set_unconverted(); + } + + emit this->image_changed(); + + const auto entries = cache_dir.entryList(); + + auto remove_cache_fun = [](QString filename) -> bool { + if (QFileInfo{filename}.isFile()) { + return QFile{filename}.remove(); + } else { + return QDir{filename}.removeRecursively(); + } + }; + + for (const auto &name : entries) { + if (name == "." || name == "..") { + continue; + } + + QString filename = QStringLiteral("%1/%2").arg(cache_dir_name).arg(name); + + while (true) { + if (remove_cache_fun(filename)) { + break; + } + + const auto ret = QMessageBox::warning( + this, tr("删除缓存失败"), + tr("无法删除文件或文件夹\"%1\"。\n点击 Ignore 以跳过,点击 Retry " + "以重试,点击 Cancel 以取消这次操作") + .arg(filename), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, + QMessageBox::StandardButton::Retry, + QMessageBox::StandardButton::Cancel}); + + if (ret == QMessageBox::StandardButton::Retry) { + continue; + } + if (ret == QMessageBox::StandardButton::Ignore) { + break; + } + return; // QMessageBox::StandardButton::Cancel and for closing the dialog + } + } } \ No newline at end of file From b08f0aac9f8f7822efe57afa86421ac341401ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 12:55:42 +0800 Subject: [PATCH 0341/1123] export table displays converted images only --- SlopeCraft/ExportTableModel.cpp | 7 ++--- SlopeCraft/PoolModel.h | 45 +++++---------------------------- SlopeCraft/cvt_task.cpp | 36 ++++++++++++++++++++++++++ SlopeCraft/cvt_task.h | 6 +++++ 4 files changed, 53 insertions(+), 41 deletions(-) diff --git a/SlopeCraft/ExportTableModel.cpp b/SlopeCraft/ExportTableModel.cpp index 64185411..8e350f51 100644 --- a/SlopeCraft/ExportTableModel.cpp +++ b/SlopeCraft/ExportTableModel.cpp @@ -49,7 +49,7 @@ void ExportTableModel::refresh() noexcept { } int ExportTableModel::rowCount(const QModelIndex&) const noexcept { - return this->pool->size(); + return ::converted_task_count(*this->pool); } int ExportTableModel::columnCount(const QModelIndex&) const noexcept { @@ -65,11 +65,12 @@ QVariant ExportTableModel::data(const QModelIndex& qmi, const int r = qmi.row(); const int c = qmi.column(); - if (r < 0 || r >= (int)this->pool->size()) { + if (r < 0 || r >= (int)this->rowCount({})) { return {}; } - const auto& task = this->pool->at(r); + const auto& task = + this->pool->at(::map_export_idx_to_full_idx(*this->pool, r)); if (role == Qt::ItemDataRole::DisplayRole) { const QSize map_size = map_size_of_images(task.original_image.size()); diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index 400c922a..bbcdff1e 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -90,54 +90,23 @@ class ExportPoolModel : public PoolModel { if (midx.isValid()) { return 0; } - int num = 0; - for (const auto& i : *this->pool) { - if (i.is_converted) { - num++; - } - } - return num; + return converted_task_count(*this->pool); } std::vector iteration_map() const noexcept { - std::vector ret; - ret.reserve(this->pool->size()); - for (int i = 0; i < (int)this->pool->size(); i++) { - if (this->pool->at(i).is_converted) { - ret.emplace_back(i); - } - } - return ret; + return ::iteration_map(*this->pool); } int export_idx_to_full_idx(int eidx) const noexcept { - assert(eidx >= 0); - for (int fidx = 0; fidx < (int)this->pool->size(); fidx++) { - if (pool->at(fidx).is_converted) { - eidx--; - } - if (eidx < 0) { - return fidx; - } - } - - assert(false); - return INT_MAX; + return ::map_export_idx_to_full_idx(*this->pool, eidx); } cvt_task* export_idx_to_task_ptr(int eidx) const noexcept { - assert(eidx >= 0); - for (int fidx = 0; fidx < (int)this->pool->size(); fidx++) { - if (pool->at(fidx).is_converted) { - eidx--; - } - if (eidx < 0) { - return &this->pool->at(fidx); - } + const int pidx = this->export_idx_to_full_idx(eidx); + if (pidx >= (int)this->pool->size()) { + return nullptr; } - - assert(false); - return nullptr; + return &this->pool->at(pidx); } QVariant data(const QModelIndex& idx, int role) const override; diff --git a/SlopeCraft/cvt_task.cpp b/SlopeCraft/cvt_task.cpp index c795e81c..bb7b6e3f 100644 --- a/SlopeCraft/cvt_task.cpp +++ b/SlopeCraft/cvt_task.cpp @@ -15,4 +15,40 @@ cvt_task cvt_task::load(QString filename, QString& err) noexcept { ret.original_image = temp.convertToFormat(QImage::Format_ARGB32); return ret; +} + +int converted_task_count(const task_pool_t& pool) noexcept { + int num = 0; + for (const auto& i : pool) { + if (i.is_converted) { + num++; + } + } + return num; +} + +int map_export_idx_to_full_idx(const task_pool_t& pool, int eidx) noexcept { + assert(eidx >= 0); + for (int fidx = 0; fidx < (int)pool.size(); fidx++) { + if (pool.at(fidx).is_converted) { + eidx--; + } + if (eidx < 0) { + return fidx; + } + } + + assert(false); + return INT_MAX; +} + +std::vector iteration_map(const task_pool_t& pool) noexcept { + std::vector ret; + ret.reserve(pool.size()); + for (int i = 0; i < (int)pool.size(); i++) { + if (pool.at(i).is_converted) { + ret.emplace_back(i); + } + } + return ret; } \ No newline at end of file diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 5716f5a9..45190123 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -49,4 +49,10 @@ Q_DECLARE_METATYPE(cvt_task); using task_pool_t = std::vector; +int converted_task_count(const task_pool_t&) noexcept; + +int map_export_idx_to_full_idx(const task_pool_t&, int eidx) noexcept; + +std::vector iteration_map(const task_pool_t& pool) noexcept; + #endif // SLOPECRAFT_SLOPECRAFT_CVT_TASK_H \ No newline at end of file From ef21dd26d459f0548551a7e1efb367d416f9130b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 13:11:43 +0800 Subject: [PATCH 0342/1123] try to fix macos-build --- .github/workflows/build-dev.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b683b45f..2d493c72 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -26,7 +26,9 @@ jobs: - name: Install Ninja build system run: brew install ninja - name: Install dependencies - run: brew install qt@6 + run: | + brew install libpng-dev + brew install qt@6 - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH From 477d0c0ef4e63acdb983c49d6959dc89be4623b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 13:34:54 +0800 Subject: [PATCH 0343/1123] try to fix macos-build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 2d493c72..b04143ad 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -27,7 +27,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng-dev + brew install libpng brew install qt@6 - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From b01c13f314475162e3769acb7903a848c3f93140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 20 May 2023 13:54:05 +0800 Subject: [PATCH 0344/1123] fix a bug in flat diagram --- utilities/FlatDiagram/FlatDiagram.cpp | 32 +++++++++++++++------------ utilities/FlatDiagram/FlatDiagram.h | 5 ++++- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/utilities/FlatDiagram/FlatDiagram.cpp b/utilities/FlatDiagram/FlatDiagram.cpp index c48d9a93..e0222be0 100644 --- a/utilities/FlatDiagram/FlatDiagram.cpp +++ b/utilities/FlatDiagram/FlatDiagram.cpp @@ -1,14 +1,11 @@ +#include #include "FlatDiagram.h" #include #include -#include #include #include -using EImgRowMajor_t = - Eigen::Array; - void libFlatDiagram::reverse_color(uint32_t *ptr, size_t num_pixels) noexcept { // this can be vertorized by compiler optimization for (uint32_t *p = ptr; p < ptr + num_pixels; p++) { @@ -25,12 +22,10 @@ void libFlatDiagram::ARGB_to_AGBR(uint32_t *ptr, size_t num_pixels) noexcept { } void libFlatDiagram::draw_flat_diagram_to_memory( - uint32_t *image_u8c3_rowmajor, const fd_option &opt, + Eigen::Map buffer, const fd_option &opt, const get_blk_image_callback_t &blk_image_at) { - Eigen::Map map{ - image_u8c3_rowmajor, (opt.row_end - opt.row_start) * 16, opt.cols * 16}; - - memset(image_u8c3_rowmajor, 0, map.size() * sizeof(uint32_t)); + assert(buffer.cols() == opt.cols * 16); + assert(buffer.rows() >= (opt.row_end - opt.row_start) * 16); // copy block images for (int64_t r = opt.row_start; r < opt.row_end; r++) { @@ -45,7 +40,7 @@ void libFlatDiagram::draw_flat_diagram_to_memory( const bool is_aligned = is_dst_aligned && is_src_aligned; */ - map.block<16, 16>(r_pixel_beg, c_pixel_beg) = blk_image_at(r, c); + buffer.block<16, 16>(r_pixel_beg, c_pixel_beg) = blk_image_at(r, c); } } @@ -54,7 +49,7 @@ void libFlatDiagram::draw_flat_diagram_to_memory( (br % opt.split_line_row_margin == 0)) { const int64_t pr = (br - opt.row_start) * 16; - reverse_color(&map(pr, 0), map.cols()); + reverse_color(&buffer(pr, 0), buffer.cols()); } } @@ -63,8 +58,8 @@ void libFlatDiagram::draw_flat_diagram_to_memory( (bc % opt.split_line_col_margin == 0)) { const int64_t pc = bc * 16; - for (int64_t pr = 0; pr < map.rows(); pr++) { - map(pr, pc) = reverse_color(map(pr, pc)); + for (int64_t pr = 0; pr < buffer.rows(); pr++) { + buffer(pr, pc) = reverse_color(buffer(pr, pc)); } } } @@ -138,12 +133,21 @@ std::string libFlatDiagram::export_flat_diagram( opt_temp.row_start = ridx; opt_temp.row_end = ridx + rows_this_time; - draw_flat_diagram_to_memory(buffer.data(), opt, blk_image_at); + draw_flat_diagram_to_memory({buffer.data(), buffer.rows(), buffer.cols()}, + opt_temp, blk_image_at); ARGB_to_AGBR(buffer.data(), rows_this_time * 16 * opt.cols * 16); for (int64_t pix_r = 0; pix_r < rows_this_time * 16; pix_r++) { + // The row pointer should only be converted to const uint8_t*, but there + // is a terrible bug on libpng from brew makes this code fail to compile: + // binary interface function png_write_row is trampered to + // `void png_write_row(png_structrp png_ptr, png_bytep row)`. + // This bug doesn't exist in windows and linux, but only with libpng + // installed with homebrew. png_write_row(png, reinterpret_cast(&buffer(pix_r, 0))); + // This is terrible because a const pointer have to be converted to + // non-constant } } diff --git a/utilities/FlatDiagram/FlatDiagram.h b/utilities/FlatDiagram/FlatDiagram.h index e9d841c0..0f6c66ed 100644 --- a/utilities/FlatDiagram/FlatDiagram.h +++ b/utilities/FlatDiagram/FlatDiagram.h @@ -10,6 +10,9 @@ namespace libFlatDiagram { +using EImgRowMajor_t = + Eigen::Array; + constexpr uint32_t reverse_color(uint32_t ARGB_src) noexcept { return ARGB32(255 - getR(ARGB_src), 255 - getG(ARGB_src), 255 - getB(ARGB_src), getA(ARGB_src)); @@ -49,7 +52,7 @@ using get_blk_image_callback_t = constexpr size_t callback_size = sizeof(get_blk_image_callback_t); -void draw_flat_diagram_to_memory(uint32_t *image_u8c3_rowmajor, +void draw_flat_diagram_to_memory(Eigen::Map buffer, const fd_option &opt, const get_blk_image_callback_t &blk_image_at); From 46437e59855aff52b7ee31e4137281120a263362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 21 May 2023 13:29:51 +0800 Subject: [PATCH 0345/1123] add report error for SCWind --- SlopeCraft/CMakeLists.txt | 3 +++ SlopeCraft/SCWind.cpp | 32 ++++++++++++++++++++++++++++++++ SlopeCraft/SCWind.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index dc8f51f3..b6025a16 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) +find_package(magic_enum REQUIRED) set(SlopeCraft_rc_files) @@ -58,6 +59,8 @@ target_link_libraries(SlopeCraft PRIVATE Qt6::Core Qt6::Widgets Qt6::Network + magic_enum::magic_enum + SlopeCraftL AdaptiveLabel VersionDialog diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 33f8c83c..716b6e49 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) @@ -41,6 +42,10 @@ SCWind::SCWind(QWidget *parent) }); this->kernel->setKeepAwake([](void *) { QApplication::processEvents(); }); + this->kernel->setReportError( + [](void *_this, ::SCL_errorFlag err, const char *msg) { + reinterpret_cast(_this)->report_error(err, msg); + }); } // initialize cvt pool model { @@ -858,4 +863,31 @@ SCWind::current_flatdiagram_option(QString &err) const noexcept { int SCWind::current_map_begin_seq_number() const noexcept { return this->ui->sb_file_start_idx->value(); +} + +void SCWind::report_error(::SCL_errorFlag flag, const char *msg) noexcept { + if (flag == SCL_errorFlag::NO_ERROR_OCCUR) { + return; + } + using sb = QMessageBox::StandardButton; + using sbs = QMessageBox::StandardButtons; + + auto flag_name = magic_enum::enum_name(flag); + + const QString errmsg = tr("错误类型:%1,错误码:%2。详细信息:\n%3") + .arg(flag_name.data()) + .arg(int(flag)) + .arg(msg); + + const auto ret = QMessageBox::critical( + this, tr("SlopeCraft 出现错误"), + tr("%1\n\n点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。") + .arg(errmsg), + sbs{sb::Ok, sb::Close}); + + if (ret == sb::Close) { + exit(0); + } + + return; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 2acc3bd2..eef8f779 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -181,6 +181,8 @@ class SCWind : public QMainWindow { void export_current_cvted_image(int idx, QString filename) noexcept; + void report_error(::SCL_errorFlag flag, const char* msg) noexcept; + signals: void image_changed(); }; From dcbffe4a7f72195d856459807395f88d9fd130f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 13:07:01 +0800 Subject: [PATCH 0346/1123] enable coping material list --- SlopeCraft/CMakeLists.txt | 4 ++- SlopeCraft/CopyableTableView.cpp | 57 ++++++++++++++++++++++++++++++++ SlopeCraft/CopyableTableView.h | 21 ++++++++++++ SlopeCraft/PreviewWind.cpp | 14 ++++++-- SlopeCraft/PreviewWind.ui | 35 ++++++++++++-------- 5 files changed, 113 insertions(+), 18 deletions(-) create mode 100644 SlopeCraft/CopyableTableView.cpp create mode 100644 SlopeCraft/CopyableTableView.h diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index b6025a16..f33fd099 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -24,7 +24,8 @@ set(SlopeCraft_headers AdaptiveListView.h PreviewWind.h ExportTableModel.h - AiCvterParameterDialog.h) + AiCvterParameterDialog.h + CopyableTableView.h) set(SlopeCraft_sources SCWind.cpp @@ -35,6 +36,7 @@ set(SlopeCraft_sources PreviewWind.cpp ExportTableModel.cpp AiCvterParameterDialog.cpp + CopyableTableView.cpp main.cpp ${SlopeCraft_rc_files}) diff --git a/SlopeCraft/CopyableTableView.cpp b/SlopeCraft/CopyableTableView.cpp new file mode 100644 index 00000000..e29c317a --- /dev/null +++ b/SlopeCraft/CopyableTableView.cpp @@ -0,0 +1,57 @@ +#include "CopyableTableView.h" +#include +#include +#include + +CopyableTableView::CopyableTableView(QWidget* parent) : QTableView(parent) {} + +CopyableTableView::~CopyableTableView() = default; + +bool CopyableTableView::event(QEvent* event) noexcept { + if (event->type() == QEvent::Type::KeyPress) { + QKeyEvent* const ke = dynamic_cast(event); + if (ke != nullptr) { + if (ke->matches(QKeySequence::StandardKey::Copy)) { + const auto sel = this->selectedIndexes(); + + QString text; + text.reserve(sel.size() * 64); + + int prev_row = -1; + + for (const auto& qmi : sel) { + if (!qmi.isValid()) { + continue; + } + const int r = qmi.row(); + const bool is_row_changed = (prev_row != r); + const bool is_prev_row_valid = (prev_row >= 0); + + prev_row = r; + + if (is_row_changed) { + if (is_prev_row_valid) { + text.push_back('\n'); + // another row + } + // the first element, do not append any char + + } else { + text.push_back('\t'); // same row, but different col + } + + text.append(qmi.data(Qt::ItemDataRole::DisplayRole).toString()); + } + + QApplication::clipboard()->setText(text); + + event->accept(); + emit this->copied(); + return true; + // do copy here + } + } + } + + return QTableView::event(event); +} \ No newline at end of file diff --git a/SlopeCraft/CopyableTableView.h b/SlopeCraft/CopyableTableView.h new file mode 100644 index 00000000..4b36e397 --- /dev/null +++ b/SlopeCraft/CopyableTableView.h @@ -0,0 +1,21 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_COPYABLETABLEVIEW_H +#define SLOPECRAFT_SLOPECRAFT_COPYABLETABLEVIEW_H + +#include +#include + +class CopyableTableView : public QTableView { + Q_OBJECT + private: + public: + explicit CopyableTableView(QWidget* parent = nullptr); + ~CopyableTableView(); + + protected: + bool event(QEvent* event) noexcept override; + + signals: + void copied(); +}; + +#endif // SLOPECRAFT_SLOPECRAFT_COPYABLETABLEVIEW_H \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 9f8b71c5..ccf0e670 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "CopyableTableView.h" PreviewWind::PreviewWind(QWidget* parent) : QDialog(parent), ui(new Ui::PreviewWind) { @@ -18,6 +19,12 @@ PreviewWind::PreviewWind(QWidget* parent) &MaterialModel::refresh); connect(this->ui->cb_sort_option, &QComboBox::currentIndexChanged, this->mmp, &MaterialModel::refresh); + this->ui->tv_mat->setModel(this->mmp); + + connect(this->ui->tv_mat, &CopyableTableView::copied, [this]() noexcept { + this->setWindowTitle( + tr("%1 -- 表格内容已复制到剪贴板").arg(tr("查看材料列表"))); + }); } PreviewWind::~PreviewWind() { delete this->ui; } @@ -64,9 +71,10 @@ void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { this->set_size(sz); } - this->ui->tv_mat->setModel(this->mmp); - this->mmp->refresh(); - this->ui->tv_mat->doItemsLayout(); + // this->ui->tv_mat->setModel(this->mmp); + emit this->mmp->layoutChanged(); + // this->mmp->refresh(); + // this->ui->tv_mat->doItemsLayout(); } bool PreviewWind::is_unit_stack() const noexcept { diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index 8a414521..e841a577 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -14,19 +14,6 @@ 查看材料列表 - - - - - - - QFrame::StyledPanel - - - - - - @@ -43,6 +30,19 @@ + + + + + + + QFrame::StyledPanel + + + + + + @@ -76,7 +76,7 @@ - + true @@ -121,6 +121,13 @@
+ + + CopyableTableView + QTableView +
CopyableTableView.h
+
+
From bf910a47dd6152dbf089d48e3e4c6b6f9c3099ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 13:18:01 +0800 Subject: [PATCH 0347/1123] add sorting function --- SlopeCraft/CopyableTableView.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/CopyableTableView.cpp b/SlopeCraft/CopyableTableView.cpp index e29c317a..9067888d 100644 --- a/SlopeCraft/CopyableTableView.cpp +++ b/SlopeCraft/CopyableTableView.cpp @@ -2,17 +2,28 @@ #include #include #include +#include CopyableTableView::CopyableTableView(QWidget* parent) : QTableView(parent) {} CopyableTableView::~CopyableTableView() = default; +bool qmi_sorter(const QModelIndex& a, const QModelIndex& b) noexcept { + if (a.row() != b.row()) { + return a.row() < b.row(); + } + + return a.column() < b.column(); +} + bool CopyableTableView::event(QEvent* event) noexcept { if (event->type() == QEvent::Type::KeyPress) { QKeyEvent* const ke = dynamic_cast(event); if (ke != nullptr) { if (ke->matches(QKeySequence::StandardKey::Copy)) { - const auto sel = this->selectedIndexes(); + auto sel = this->selectedIndexes(); + + std::sort(sel.begin(), sel.end(), qmi_sorter); QString text; text.reserve(sel.size() * 64); From a5b04673fc1ece58321e62d47eb62bb78e42bfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 15:00:24 +0800 Subject: [PATCH 0348/1123] add more actions to SC menu --- SlopeCraft/SCWind.ui | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index ef5c2e03..dcbd5572 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1392,6 +1392,8 @@ 语言 + +
@@ -1406,15 +1408,37 @@ + + 关于 + + + 联系作者 + + + + + + + + + + + + 帮助 + + + + + @@ -1437,6 +1461,78 @@ 清除缓存 + + + 简体中文 + + + + + English + + + + + 关于 SlopeCraft + + + + + Github + + + Github + + + Github + + + + + Bilibili + + + Bilibili + + + Bilibili + + + + + 反馈 bug + + + + + 检查更新 + + + + + 测试方块列表 + + + + + 输出当前颜色表 + + + + + 查看 SlopeCraft 文档 + + + + + 使用教程 + + + + + 常见问题 + + From f2139dddb677c23a647fa887a8ae66e297afc289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 15:37:42 +0800 Subject: [PATCH 0349/1123] update translations with qt_add_lupdate --- CMakeLists.txt | 5 +++++ MapViewer/CMakeLists.txt | 13 ++++++------- SlopeCraft/CMakeLists.txt | 11 +++++++++-- VisualCraft/CMakeLists.txt | 10 +++++----- imageCutter/CMakeLists.txt | 13 ++++++------- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c6c2d0d..67050e3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,6 +139,11 @@ if(${WIN32}) COMMENT "A interface target to run windeployqt for all targets") endif() +# # Language related variables +if(${SlopeCraft_update_ts_no_obsolete}) + list(APPEND SC_lupdate_flags "-no-obsolete") +endif() + # Sub dirss ------------------------------------------------------------------ add_subdirectory(utilities) add_subdirectory(imageCutter) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index 58e1491f..90db3ce0 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -38,13 +38,6 @@ endif() set(MapViewer_ts_files MapViewer_en_US.ts) -if(${SlopeCraft_update_ts_files}) - execute_process( - COMMAND ${SlopeCraft_Qt_lupdate_executable} MapViewerWind.ui ${MapViewer_header_files} ${MapViewer_source_files} "-ts" ${MapViewer_ts_files} ${SlopeCraft_ts_flags} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) -endif() - set(MapViewer_project_sources ${MapViewer_header_files} ${MapViewer_source_files} @@ -78,6 +71,12 @@ set_target_properties(MapViewer PROPERTIES WIN32_EXECUTABLE TRUE ) +qt_add_lupdate(MapViewer + TS_FILES ${MapViewer_ts_files} + SOURCES ${MapViewer_project_sources} + OPTIONS ${SC_lupdate_flags} +) + # translation qt_add_lrelease(MapViewer TS_FILES ${MapViewer_ts_files} QM_FILES_OUTPUT_VARIABLE MapViewer_qm_files) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index f33fd099..29509f64 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -46,10 +46,15 @@ set(SlopeCraft_uis PreviewWind.ui AiCvterParameterDialog.ui) +set(SlopeCraft_ts_files + others/SlopeCraft_en_US.ts +) + set(SlopeCraft_project_files ${SlopeCraft_headers} ${SlopeCraft_sources} - ${SlopeCraft_uis}) + ${SlopeCraft_uis} + ${SlopeCraft_ts_files}) qt_add_executable(SlopeCraft MANUAL_FINALIZATION @@ -88,7 +93,9 @@ qt_add_resources(SlopeCraft "SC_images" FILES ${SlopeCraft_qrc_images}) qt_add_lupdate(SlopeCraft - TS_FILES others/SlopeCraft_en_US.ts + TS_FILES ${SlopeCraft_ts_files} + SOURCES ${SlopeCraft_project_files} + OPTIONS ${SC_lupdate_flags} ) qt_finalize_executable(SlopeCraft) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index bf04faf2..613aa68d 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -77,11 +77,6 @@ set(VisualCraft_project_sources ${VisualCraft_win_files} ) -if(${SlopeCraft_update_ts_files}) - execute_process(COMMAND ${SlopeCraft_Qt_lupdate_executable} ${VisualCraft_header_files} ${VisualCraft_source_files} ${VisualCraft_ui_files} -ts others/VisualCraft_en_US.ts ${SlopeCraft_ts_flags} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND_ERROR_IS_FATAL ANY) -endif() - qt_add_executable(VisualCraft MANUAL_FINALIZATION ${VisualCraft_project_sources}) @@ -111,6 +106,11 @@ set_target_properties(VisualCraft PROPERTIES ) # translation +qt_add_lupdate(VisualCraft + TS_FILES ${VisualCraft_ts_files} + SOURCES ${VisualCraft_project_sources} + OPTIONS ${SC_lupdate_flags} +) qt_add_lrelease(VisualCraft TS_FILES ${VisualCraft_ts_files} QM_FILES_OUTPUT_VARIABLE VC_qm_files) qt_add_resources(VisualCraft "VC_translations" diff --git a/imageCutter/CMakeLists.txt b/imageCutter/CMakeLists.txt index 9901be0f..f97c3314 100644 --- a/imageCutter/CMakeLists.txt +++ b/imageCutter/CMakeLists.txt @@ -29,13 +29,6 @@ endif() set(imageCutter_ts_files imageCutter_en_US.ts) -if(${SlopeCraft_update_ts_files}) - # qt_add_lupdate(imageCutter TSFILES ${imageCutter_ts_files} CutterWind.ui SOURCES ${imageCutter_header_files} ${imageCutter_source_files}) - execute_process( - COMMAND ${SlopeCraft_Qt_lupdate_executable} CutterWind.ui ${imageCutter_header_files} ${imageCutter_source_files} "-ts" ${imageCutter_ts_files} ${SlopeCraft_ts_flags} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -endif() - set(imageCutter_project_sources CutterWind.h CutterWind.cpp @@ -50,6 +43,12 @@ qt_add_executable(imageCutter ${imageCutter_project_sources}) # translation +qt_add_lupdate(imageCutter + TS_FILES ${imageCutter_ts_files} + SOURCES ${imageCutter_project_sources} + OPTIONS ${SC_lupdate_flags} +) + qt_add_lrelease(imageCutter TS_FILES ${imageCutter_ts_files} QM_FILES_OUTPUT_VARIABLE imageCutter_qm_files) qt_add_resources(imageCutter "translations" From 31ab1e3b9a6b961a3b96885e45d4e09023a2d819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 18:01:30 +0800 Subject: [PATCH 0350/1123] add translations --- SlopeCraft/CMakeLists.txt | 8 ++++ SlopeCraft/PreviewWind.cpp | 9 ++++- SlopeCraft/SCWind.cpp | 39 +++++++++++++++++++ SlopeCraft/SCWind.h | 7 ++++ utilities/BlockListManager/CMakeLists.txt | 17 ++++---- .../BlockListManager_en_US.ts | 21 ++++++++++ utilities/VersionDialog/CMakeLists.txt | 10 ++--- 7 files changed, 96 insertions(+), 15 deletions(-) rename utilities/BlockListManager/{removed => others}/BlockListManager_en_US.ts (67%) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 29509f64..2c4b010c 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -98,6 +98,14 @@ qt_add_lupdate(SlopeCraft OPTIONS ${SC_lupdate_flags} ) +qt_add_lrelease(SlopeCraft TS_FILES ${SlopeCraft_ts_files} + QM_FILES_OUTPUT_VARIABLE SC_qm_files) + +qt_add_resources(SlopeCraft "SC_translations" + PREFIX "/i18n" + BASE ${CMAKE_CURRENT_BINARY_DIR} + FILES ${SC_qm_files}) + qt_finalize_executable(SlopeCraft) if(${WIN32}) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index ccf0e670..c87e6eaf 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "SCWind.h" #include "CopyableTableView.h" PreviewWind::PreviewWind(QWidget* parent) @@ -177,7 +178,13 @@ QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { if (role == Qt::ItemDataRole::DisplayRole) { if (c == 0) { - return QString::fromUtf8(mat.blk->getNameZH()); + const auto lang = + dynamic_cast(this->pwind->parent())->lang(); + if (lang == ::SCL_language::Chinese) { + return QString::fromUtf8(mat.blk->getNameZH()); + } else { + return QString::fromUtf8(mat.blk->getNameEN()); + } } if (c == 1) { diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 716b6e49..691d22c4 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -13,6 +13,32 @@ SCWind::SCWind(QWidget *parent) ui(new Ui::SCWind), kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); + { + // create translators + const char *const translator_filenames[] = { + ":/i18n/SlopeCraft_en_US.qm", ":/i18n/BlockListManager_en_US.qm", + ":/i18n/VersionDialog_en_US.qm"}; + /*this->translators.reserve(sizeof(translator_filenames) / + sizeof(const char *)); + */ + for (const char *tf : translator_filenames) { + QTranslator *t = new QTranslator{this}; + QString filename = QString::fromUtf8(tf); + const bool ok = t->load(filename); + if (!ok) { + QMessageBox::warning(this, "Failed to load translate file", + QStringLiteral("Failed to load %1").arg(filename)); + } + + this->translators.emplace_back(t); + } + + connect(this->ui->ac_lang_ZH, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::Chinese); }); + connect(this->ui->ac_lang_EN, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::English); }); + } + { const auto pid = QApplication::applicationPid(); @@ -890,4 +916,17 @@ void SCWind::report_error(::SCL_errorFlag flag, const char *msg) noexcept { } return; +} + +void SCWind::set_lang(::SCL_language lang) noexcept { + this->language = lang; + for (auto &trans : this->translators) { + if (this->language == ::SCL_language::Chinese) { + QApplication::removeTranslator(trans); + } else { + QApplication::installTranslator(trans); + } + } + + this->ui->blm->when_lang_updated(lang); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index eef8f779..683e11e0 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "cvt_task.h" #include "PoolModel.h" #include "ExportTableModel.h" @@ -81,6 +82,9 @@ class SCWind : public QMainWindow { std::array default_presets; + SCL_language language{SCL_language::Chinese}; + std::vector translators; + // QString fileonly_export_dir{""}; public: @@ -141,6 +145,9 @@ class SCWind : public QMainWindow { int current_map_begin_seq_number() const noexcept; + inline auto lang() const noexcept { return this->language; } + void set_lang(::SCL_language lang) noexcept; + private: // kernel related functions void kernel_set_type() noexcept; diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 1c08ec55..670a939a 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -29,18 +29,12 @@ set(BlockListManager_ui_files ) set(BlockListManager_ts_files + others/BlockListManager_en_US.ts # ${CMAKE_CURRENT_SOURCE_DIR}/BlockListManager_en_US.ts ) -if(${SlopeCraft_update_ts_files}) - execute_process( - COMMAND ${SlopeCraft_Qt_lupdate_executable} ${BlockListManager_header_files} ${BlockListManager_source_files} "-ts" ${BlockListManager_ts_files} ${SlopeCraft_ts_flags} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) -endif() - -set(BlockListManaer_project_sources +set(BlockListManager_project_sources ${BlockListManager_header_files} ${BlockListManager_source_files} ${BlockListManager_ui_files} @@ -48,11 +42,16 @@ set(BlockListManaer_project_sources ) # include_directories(../SlopeCraftL) -add_library(BlockListManager STATIC ${BlockListManaer_project_sources}) +add_library(BlockListManager STATIC ${BlockListManager_project_sources}) target_link_libraries(BlockListManager PUBLIC Qt6::Widgets SlopeCraftL) target_include_directories(BlockListManager INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir}) +qt_add_lupdate(BlockListManager + TS_FILES ${BlockListManager_ts_files} + SOURCES ${BlockListManager_project_sources} + OPTIONS ${SC_lupdate_flags} +) qt_add_lrelease(BlockListManager TS_FILES ${BlockListManager_ts_files} QM_FILES_OUTPUT_VARIABLE BlockListManager_qm_files) qt_add_resources(BlockListManager "BLM_translations" diff --git a/utilities/BlockListManager/removed/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts similarity index 67% rename from utilities/BlockListManager/removed/BlockListManager_en_US.ts rename to utilities/BlockListManager/others/BlockListManager_en_US.ts index 07c7129f..603c8d74 100644 --- a/utilities/BlockListManager/removed/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -1,27 +1,46 @@ + + BaseColorWidget + + + GroupBox + + + + + 启用 + + + BlockListManager + + 解析方块列表失败 Failed to parse block list + + 加载预设错误 Failed to load preset + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id @@ -30,11 +49,13 @@ QObject + 基色 %1 的预设被重复定义。一个基色只能被定义一次。 The preset of base color %1 is defined multiple time. A base color can be defined only once. + 解析预设 json 时发生异常:"%1" Exception occured when parsing preset json: "%1" diff --git a/utilities/VersionDialog/CMakeLists.txt b/utilities/VersionDialog/CMakeLists.txt index ed260b13..7ac24917 100644 --- a/utilities/VersionDialog/CMakeLists.txt +++ b/utilities/VersionDialog/CMakeLists.txt @@ -33,12 +33,12 @@ target_compile_features(VersionDialog PUBLIC cxx_std_20) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) target_include_directories(VersionDialog PRIVATE ${SlopeCraft_Nlohmann_json_include_dir}) -if(${SlopeCraft_update_ts_files}) - execute_process(COMMAND ${SlopeCraft_Qt_lupdate_executable} ${VersionDialog_header_files} ${VersionDialog_source_files} ${VersionDialog_ui_files} -ts others/VersionDialog_en_US.ts ${SlopeCraft_ts_flags} -no-obsolete - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND_ERROR_IS_FATAL ANY) -endif() - # translation +qt_add_lupdate(VersionDialog + TS_FILES ${BlockListManager_ts_files} + SOURCES ${VersionDialog_project_sources} + OPTIONS ${SC_lupdate_flags} +) qt_add_lrelease(VersionDialog TS_FILES ${VersionDialog_ts_files} QM_FILES_OUTPUT_VARIABLE VD_qm_files) qt_add_resources(VersionDialog "VersionDialog_translations" From cdff42ad72cf79e6c5ecd6566ce310f7d250dfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 18:48:16 +0800 Subject: [PATCH 0351/1123] fix translate function --- SlopeCraft/SCWind.cpp | 3 +- SlopeCraft/SCWind.ui | 39 ++++++++++++------- utilities/BlockListManager/BaseColorWidget.ui | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 691d22c4..68a9b6fa 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -920,13 +920,14 @@ void SCWind::report_error(::SCL_errorFlag flag, const char *msg) noexcept { void SCWind::set_lang(::SCL_language lang) noexcept { this->language = lang; - for (auto &trans : this->translators) { + for (auto trans : this->translators) { if (this->language == ::SCL_language::Chinese) { QApplication::removeTranslator(trans); } else { QApplication::installTranslator(trans); } } + this->ui->retranslateUi(this); this->ui->blm->when_lang_updated(lang); } \ No newline at end of file diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index dcbd5572..2282e6f5 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -73,21 +73,21 @@ - Vanilla + Vanilla - Cheap + Cheap - Elegant + Elegant true @@ -97,14 +97,14 @@ - Shiny + Shiny - Custom + Custom @@ -530,7 +530,7 @@ true - IconMode + 显示缩略图 true @@ -555,21 +555,21 @@ - Lab00 + Lab00 - Lab94 + Lab94 - RGB+ + RGB+ true @@ -579,21 +579,21 @@ - RGB + RGB - XYZ + XYZ - GACvter + GACvter @@ -749,7 +749,7 @@ - Litematica + Litematica true @@ -976,6 +976,9 @@ 用结构空位替代空气 + + true + @@ -1463,12 +1466,18 @@ - 简体中文 + 简体中文 + + + 简体中文 - English + English + + + English diff --git a/utilities/BlockListManager/BaseColorWidget.ui b/utilities/BlockListManager/BaseColorWidget.ui index 220da7cc..b1214e02 100644 --- a/utilities/BlockListManager/BaseColorWidget.ui +++ b/utilities/BlockListManager/BaseColorWidget.ui @@ -11,7 +11,7 @@ - GroupBox + From 6986046f6bb0f07650c02687155af16ec7c73af3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 18:58:45 +0800 Subject: [PATCH 0352/1123] update translations --- SlopeCraft/others/SlopeCraft_en_US.ts | 1486 ++++++++++++++++++++++++- 1 file changed, 1481 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 074bb811..bfab0866 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -4,6 +4,7 @@ AiCvterParameterDialog + Ai转化器参数 Set AiConverter parameters @@ -14,27 +15,32 @@ Enable fail times - + + 最大提前收敛代数: Max fail times : - + + 交叉概率: Crossover prob : - + + 种群数量: Population size : - + + 最大进化代数: Max generation : - + + 变异概率: Mutation prob : @@ -132,6 +138,69 @@ All tasks finished + + ExportTableModel + + + + + + + + 原图文件名 + Image file + + + + + + + + + 图像大小 + Image size + + + + + + + + + 地图大小 + Map size + + + + + + + + + 地图序号范围 + Map index range + + + + + + + + + 第一个地图文件名 + First map + + + + + + + + + 最后一个地图文件名 + Last map + + MainWindow @@ -1262,6 +1331,52 @@ Click "Yes" to continue and replace these files, or click "No&quo Failed to allocate memory for image + + MaterialModel + + + + + + + + %1 盒 + %2 组 + %3 个 + %1 shulker box(es) + %2 stack(s) + %3 + + + + + + + + + %1 组 + %2 个 + %1 stack(s) + %2 + + + + + + + + + %1 个 + %1 + + + + PoolModel + + + + + + + + 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 + The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. + + PreviewWind @@ -1316,6 +1431,77 @@ Click "Yes" to continue and replace these files, or click "No&quo 如果使用了有损压缩,上一步生成的地图画可能会被轻微的修改 The converted image might be slightly modified if lossy compression is enabled. + + + + + 查看材料列表 + Material List + + + + + 按组显示 + Display by stacks + + + + + 不排序 + Do not sort + + + + + 升序 + Acsending + + + + + 降序 + Decsending + + + + + + + + + %1 -- 表格内容已复制到剪贴板 + %1 -- Table content copied to clipboart + + + + + + + + + 大小:%1 × %2 × %3 + Size: %1 × %2 × %3 + + + + + + + + + 体积:%1 + Volume: %1 + + + + + + + + + 方块总数:%1 + Block count: %1 + QObject @@ -1334,6 +1520,1296 @@ Click "Yes" to continue and replace these files, or click "No&quo stacks + + + + + + + + 加载图片 %1 失败。 + Failed to load image %1. + + + + + + + + + 绘制图标时发现错误 + An error occurred when drawing icon + + + + SCWind + + + + 地图画配置 + Map configurations + + + + + 方块列表预设 + Blocklist preset + + + + + 加载预设 + Load preset + + + + + + 保存当前预设 + Save as preset + + + + + 可用方块数量: + Available block count: + + + + + Vanilla + + + + + + Cheap + + + + + + Elegant + + + + + + Shiny + + + + + + Custom + + + + + + 游戏版本 + Game Version + + + + + 地图画类型 + Map type + + + + + 立体地图画 + 3D Map + + + + + 平板地图画 + Flat Map + + + + + 纯文件地图画 + File-only Map + + + + + 优先彩色玻璃 + Use stained glass + + + + + 优先混凝土 + Use Concrete + + + + + 优先羊毛 + Use Wool + + + + + 优先木板 + Use planks + + + + + 优先原木 + Use logs + + + + + 导入图像并转化 + Load image and convert + + + + + 原图 + Original image + + + + + 转化后 + Converted image + + + + + 删除 + Delete + + + + + + 项目池 + Task pool + + + + + 添加 + Add + + + + + IconMode + + + + + + 转化算法 + Convert algorithm + + + + + 抖动 + Dithering + + + + + Lab00 + + + + + + Lab94 + + + + + + RGB+ + + + + + + RGB + + + + + + XYZ + + + + + + GACvter + GACvter + + + + + 转化当前图像 + Convert current image + + + + + + + 保存转化后图像 + Save converted image + + + + + 全部转化 + Convert all + + + + + + 导出 + Export + + + + + Litematica + + + + + + + 结构方块文件 + Vanilla structure + + + + + 显示缩略图 + + + + + + + WE原理图 + WE Schem + + + + + + 平面示意图 + Flat diagram + + + + + 地图文件 + Map data files + + + + + 其他选项 + Others + + + + + 防火 + Fire Proof + + + + + 防末影人 + Enderman Proof + + + + + 连接蘑菇块 + Connect mushroom blocks + + + + + 压缩高度 + Compress + + + + + 有损压缩 + Lossy Compression + + + + + 无损压缩 + Lossless Compress + + + + + 最大允许高度: + Max height: + + + + + 搭桥 + Glass Bridge + + + + + 允许搭桥 + Construct Glass Bridge + + + + + 层 + layer(s) + + + + + 搭桥间隔: + Glass bridge interval: + + + + + 投影区域名称 + Region name + + + + + 投影名称 + Litematic name + + + + + 用结构空位替代空气 + Replace air with structure void + + + + + offset + + + + + + WEOffset + + + + + + + + + + + 0 + + + + + + 原理图名称 + Name of schematic + + + + + 依赖 mod 名称 + Depend mods + + + + + 在这里输入依赖 mod 的名字。用换行符分割多个 mod + Input names of required mods here. To represent multiple mods, split them with a line break + + + + + + 方块 + block(s) + + + + + + 间距: + Line interval: + + + + + 垂直分割线 + Vertical split line + + + + + 水平分割线 + Horizontal split line + + + + + 大小与方块数量 + Size and block count + + + + + + 大小: + Size: + + + + + + 方块数量: + Block count: + + + + + 全部导出 + Export all + + + + + 预览 + Preview + + + + + 预览材料表 + Material list + + + + + 预览压缩效果 + Compress effect + + + + + 预构建三维结构 + Construct 3d structure + + + + + 地图画起始序号: + Map beginning index: + + + + + 语言 + Language + + + + + 高级 + Advanced + + + + + 缓存 + Cache + + + + + 关于 + About + + + + + 联系作者 + Contact with me + + + + + 帮助 + Help + + + + + GA转化器参数 + GACvter parameters + + + + + open_cache_dir + + + + + + 打开缓存文件夹 + Open cache directory + + + + + 清除缓存 + Clean caches + + + + + 简体中文 + + + + + + English + + + + + + 关于 SlopeCraft + About SlopeCraft + + + + + 反馈 bug + Report bugs + + + + + 检查更新 + Check updates + + + + + 测试方块列表 + Test block list + + + + + 输出当前颜色表 + Export current colorset + + + + + 查看 SlopeCraft 文档 + Documentation + + + + + 使用教程 + Tutorial + + + + + 常见问题 + FAQ + + + + + + + + + 加载默认预设失败 + Failed to load default presets + + + + + + + + + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 +具体报错信息: +%1 + One or more internal presets failed to be parsed. SlopeCraft may have been damaged, please reinstall it. +Detail information: +%1 + + + + + + + + + 设置方块列表失败 + Failed to setup blocklist + + + + + + + + + 您设置的方块列表可能存在错误 + There may be errors in your blocklist + + + + + + + + + 可用颜色数量:%1 + Avaliable colors: %1 + + + + + + + + + 应用预设失败 + Failed to apply preset + + + + + + + + + 转化图像失败 + Failed to convert image + + + + + + + + + + + + + + + 缓存失败 + Failed to save cache + + + + + + + + + + + + + + + 未能创建缓存文件,错误信息: +%1 + Failed to create cache directory, error info: +%1 + + + + + + + + + 无法保存第%1个转化后图像 + Failed to save the %1-th converted image + + + + + + + + + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 + This image is not converted, or you have changed the color palette/convert algo. Please convert it again. + + + + + + + + + 保存图像失败 + Failed to save image + + + + + + + + + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 + Failed when saving %1. This may because of a file path error, or the image format is not supported. + + + + + + + + + 构建三维结构失败 + Failed to build 3d structure + + + + + + + + + 构建三维结构时,出现错误。可能是因为尝试跳步。 + An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. + + + + + + + + + 大小: %1 × %2 × %3 + Size: %1 × %2 × %3 + + + + + + + + + 方块数量:%1 + Block count: %1 + + + + + + + + + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 + Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. + + + + + + + + + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 + Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. + + + + + + + + + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 + Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. + + + + + + + + + 错误类型:%1,错误码:%2。详细信息: +%3 + Error type: %1, error code: %2, details: +%3 + + + + + + + + + SlopeCraft 出现错误 + An error occurred to SlopeCraft + + + + + + + + + %1 + +点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 + %1 + +Click Ok to ignore, and click Close to exit SlopeCraft. + + + + + + + + + 选择图片 + Select Image + + + + + + + + + 打开图像失败 + Failed to open image + + + + + + + + + 无法打开图像 %1。常见原因:图像尺寸太大。 +详细信息: %2 + Failed to open image %1. Possible reason: the image is too large. +Detailed information: %2 + + + + + + + + + 选择预设文件 + Select a preset file + + + + + + + + + 解析预设文件失败 + Failed to parse thes preset file + + + + + + + + + 预设文件%1存在错误:%2 + The preset file "%1" is invalid. Detail: %2 + + + + + + + + + 保存预设文件失败 + Failed to save preset file + + + + + + + + + 无法生成预设文件%1,错误信息:%2 + Failed to generate preset file "%1", detail: %2 + + + + + + + + + + + + + + + + + + + + + + + + + + + 未选择图像 + No image selected + + + + + + + + + + + + + + + + + + + + + 请在左侧任务池选择一个图像 + Please select a image in the left + + + + + + + + + 请在左侧任务池选择一个或多个图像 + Please select one or more images in the left + + + + + + + + + 将要覆盖已存在的图像 + Existing file(s) will be replaced + + + + + + + + + %1将被覆盖,确认覆盖吗? + %1 will be replaced, are you sure to replace it? + + + + + + + + + + + + + + + + + + + + + 该图像尚未被转化 + The image is not converted + + + + + + + + + + + + + + + 必须先转化一个图像,然后再为它构建三维结构 + You must convert a image before building 3d structure for it + + + + + + + + + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 + You may have changed the convertion algorithm after the convertion finished. You must convert it again. + + + + + + + + + 尚未构建三维结构 + 3d structure not built + + + + + + + + + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 + You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. + + + + + + + + + 导出设置有错 + Error in export options + + + + + + + + + 导出设置存在如下错误: +%1 + There is an error in your export option: +%1 + + + + + + + + + 你点错按钮了 + Wrong button + + + + + + + + + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 + the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). + + + + + + + + + 无可导出的任务 + Nothing to export + + + + + + + + + 任务池为空,请先转化一个或一些图像 + The task pool is empty, please convert one or more images + + + + + + + + + 选择导出位置 + Select export directory + + + + + + + + + 将要覆盖已经存在的文件 + Existing files will be replaced + + + + + + + + + 确定要覆盖这些文件吗?以下文件将被覆盖: +%1 + Are you sure to replace these files: +%1 + + + + + + + + + 导出失败 + Failed to export + + + + + + + + + 导出%1时失败。原图像文件名为%2 +点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 + Failed when exporting %1. The corresponding image is %2 +Click Ignore to skip this image, and Cancel to cancel. + + + + + + + + + 设置导出位置 + Set export directory + + + + + + + + + %1 个文件将被替换 + %1 files will be replaced + + + + + + + + + 以下文件将被替换: +%1 +点击 Yes 将替换它们,点击 No 将取消这次导出。 + These files will be replaced: +%1 +Click Yes to replace them, or No to cancel. + + + + + + + + + 删除缓存失败 + Failed to clean cache + + + + + + + + + 无法删除文件或文件夹"%1"。 +点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 + Failed to remove file or directory named "%1". +Click Ignore to skip, Retry to retry and Cancel to cancel + TaskBox From a8417710813d2d832428a16fbbe9fdcf75e390a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 18:59:03 +0800 Subject: [PATCH 0353/1123] update translations --- CMakeLists.txt | 4 +- MapViewer/MapViewer_en_US.ts | 157 ++- VisualCraft/others/VisualCraft_en_US.ts | 1067 +++++++++++++++-- imageCutter/imageCutter_en_US.ts | 168 ++- .../others/BlockListManager_en_US.ts | 86 +- 5 files changed, 1314 insertions(+), 168 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67050e3c..b2001104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,8 @@ if(${WIN32}) endif() # # Language related variables +set(SC_lupdate_flags -no-ui-lines) + if(${SlopeCraft_update_ts_no_obsolete}) list(APPEND SC_lupdate_flags "-no-obsolete") endif() @@ -150,7 +152,7 @@ add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) # add_subdirectory(SlopeCraftMain) -add_subdirectory(SlopeCraft) +# add_subdirectory(SlopeCraft) add_subdirectory(MapViewer) add_subdirectory(tests) add_subdirectory(VisualCraftL) diff --git a/MapViewer/MapViewer_en_US.ts b/MapViewer/MapViewer_en_US.ts index bfbee63a..1ab79f9c 100644 --- a/MapViewer/MapViewer_en_US.ts +++ b/MapViewer/MapViewer_en_US.ts @@ -4,146 +4,261 @@ MapViewerWind - - + + 加载地图 Load maps - + + 清除 Clear - + + 列数: Cols: - + + 行数: Rows: - + + 矩阵存储序 Storage order - + + 列优先 Col-major - + + 行优先 Row-major - + + 请选择地图文件 Please select files - + + 查看图像 Browse map - + + 放大倍数: Scale: - + + 显示网格 Show grid - + + 显示像素信息 Show pixel infos - + + 仅颜色 Color-only - + + 地图色 Map color - + + 基色 Base color - + + 阴影 Shade - + + 保存当前图片 Save - + + 组合图像 Compose maps - + + 保存为图片 Save - + + 显示空隙 Show grid + + + + + + + + + + + + 地图数: Map count: + + + + + + + + + + + + There is/are + + + + + + + + + + + + 个像素点出现未知的基色,它们使用了Mojang未定义的基色。这可能是因为软件版本较旧而游戏版本太新,或者地图文件损坏。 其行、列坐标分别为: pixel(s) which have unknown base color, they are using basecolors out of Mojang's defination. This may be caused by damaged map data file, or the software version is too old. + + + + + + + + + + + + 地图中有Mojang未定义基色 Undefined basecolor in map data files (undefined by Mojang) + + + + + + + + + + + + 选择地图数据文件 Select map data files + + + + + + + + + + + + 加载地图文件失败 Failed to load map data file(s) + + + + + + + + + + + + 出错的文件: Map data file: + + + + + + + + + + + + 错误信息: diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index a7269473..b98411f0 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -4,46 +4,57 @@ BiomeBrowser - + + 查看生物群系 Browse biomes - + + 选择生物群系 Select a biome - + + 颜色代码 Color in hex - + + 放大倍率: Scale: - + + 显示颜色坐标 Show coordinate - + + 选择颜色表 Select a colormap - + + 温度: Temperature: - + + 降水: Downfall: + + + 当前颜色: Current color: @@ -52,17 +63,20 @@ BlockBrowser - + + 浏览方块 Block Browser - + + 可用方块 Avaliable blocks - + + 在“可用方块”页,可以浏览所有可用方块在每一个面的投影图像。在“所有方块”页,可以浏览任何方块(包括当前版本不可用的方块)的所有属性。 在“可用方块”页选择了一个方块后,“所有方块”页也会自动选中这个方块。但在”所有方块“页选择的方块不会影响到”可用方块“页,因为选中的方块不一定能在当前版本使用,不一定能计算出投影图像。 @@ -71,86 +85,105 @@ If you select a block in "Avaliable blocks" page, the other page will switch to this block automatically. But any selection on "All blocks" will not affect "Avaliable blocks", since your selected block may not be avaliable in current version, so the projection image is probably not able to be computed. - + + 保存当前图片 Save current image - + + 选择视角 Select direction - + + 放大倍率: Scale: - - - + + 方块id Block id - - + + 选择方块 Select block - + + 所有方块 All blocks - + + MC版本 MC version - + + 是否可用 Is avaliable - + + 英文名 Block name in English - + + 属性 Attribute - + + Value - + + 中文名 Block name in Chinese - + + 方块类别: Block class: + + + 致命逻辑错误 Impossible error + + + 保存图片失败 Failed to save image. + + + 不知道怎么回事,反正就是没存上。 I don't know why. @@ -159,21 +192,27 @@ If you select a block in "Avaliable blocks" page, the other page will BlockSelector - + + 自定义准则 Custom criteria - + + 启用匹配的方块 Enabled matched blocks - + + 禁用匹配的方块 Disable matched blocks + + + 匹配到%1个方块 %1 block(s) matched @@ -182,57 +221,83 @@ If you select a block in "Avaliable blocks" page, the other page will ColorBrowser - + + 查看颜色表 Browse colorset - + + 颜色序号 Color id - + + 颜色 Color - + + 色号 Hex - + + 方块图标 Block icons + + + 第%1个方块 block %1 + + + 获取颜色表失败 Failed to retrive colorset + + + 在尝试获取第%1个颜色(color_id = %2)时出现错误。函数VCL_get_basic_color_composition返回值为%3,正常情况下应当返回正数。 An error occurred when trying to get color %1 (color_id = %2). Function VCL_get_basic_color_composition returned %3, but a positive number is expected. + + + + + + 计算投影图像失败 Failed to compute projection image + + + 在尝试获取方块 "%1" 的方块模型时出现错误。 An error occurred when trying to get block model for block "%1" (color_id = %2) + + + 成功获取到方块 "%1" 的方块模型,但计算投影图像失败。 Managed to get a block model for block '%1", but subsequent computation of projection image failed. @@ -241,454 +306,581 @@ If you select a block in "Avaliable blocks" page, the other page will VCWind - + + VisualCraft Pre-release VisualCraft 预览版 - + + 基础属性 Baisc attributes - + + 游戏版本 MC version - + + 最大厚度: Max layers: - + + 资源包 Resource packs - - + + 添加 Add - - + + 删除 Remove - + + 方块id文件(json) Block state list files (json) - + + 像素画方向 Pixel art direction - + + 侧面(侧视) Side - + + 上面(俯视) Up - + + 下面(仰视) Down - + + 树叶透明 Transparent leaves - + + 方块列表 Blocks - + + 全部方块 All blocks - + + 快捷键 Hot keys - + + 全部启用 Select all - + + 全部禁用 Deselect all - + + 高级匹配 Advanced - + + 禁用罕见方块 Disable rare blocks - + + 禁用不可再生 Disable non-reproducible - + + 全部反选 Select reversely blockwise - + + 按类反选 Select reversely classwise - + + 选择图片 Select images - + + 显示原始尺寸 Original size - + + 调色算法 Convertion algorithm - + + 抖动 Dithering - + + 显示原图 Display original - + + 显示转化后图像 Display converted - - + + 导出 Export - + + 图像 Image - + + 大小(行,列) Size (rows, cols) - + + 生成litematica Litematica file - + + 生成结构方块文件 Structure file - + + 生成WE原理图 WE schem file - + + 生成转化后图像 Converted image - + + 生成平面示意图 Flat diagram - + + 进度 Progress - + + 导出类型 Export type - + + litematic投影 Litematica - + + 原版结构方块文件 Vanilla structure - + + WorldEdit原理图 WorldEdit schematic - + + 转化后图像 Converted image - + + 平面示意图 Flat diagram - + + 开始执行 Start - + + 设置导出位置 Set export directory - + + 平面示意图(*.png) Flat diagram(*.png) - + + png压缩级别: png compress level: - - + + 方块 blocks - - + + 间距: margin: - + + 垂直分隔线 Vertical split line - + + 水平分隔线 Horizontal split line - + + png压缩内存级别: png compress memory level: - + + 联系开发者 Contact developer - + + 关于VisualCraft About VisualCraft - + + 反馈bug Report bugs - - + + Github仓库 Github repository - + + bilibili ? bilibili - + + 生成测试投影 Generate testing litematic - + + 查看所有颜色 Browse all colors - + + 查看可用颜色 Browse avaliable colors - + + 检查更新 Check updates - + + 刷新警告信息 Flush warnings - + + 使用教程 Tutorial - + + 原版结构方块文件(*.nbt) Vanilla structure(*.nbt) - + + 用结构空位表示空气 Use structure void as air - + + Litematica投影(*.litematic) Litematica file (*.litematic) - + + 导出选项 Export options - + + 区域名称 Region name - + + 投影名称(非文件名) Schematic name(not file name) - + + WorldEdit原理图(*.schem) (仅1.13+) WorldEdit schematic(*schem) (1.13+ only) - + + 名称(非文件名) Name (not file name) - + + 需要的mod名(一行一个,默认为空) Required mods (one mod in one line) - + + 显卡设置 GPU settings - + + 计算设置 Computation settings - + + CPU线程数: CPU threads: - + + 选择计算设备 Select compute device - + + 测试 Test - + + 查看 Browse - + + 资源 Resources - + + 关于 About - + + 方块 Blocks - + + 加载资源 Load resources - + + 设置可用的方块 Set avaliable blocks - + + 生物群系 Biomes + + + + + + + + + + + + VisualCraftL 动态库版本不匹配 The version of VisualCraftL shared lib mismatch + + + + + + + + + + + + 界面程序编译时使用的 VisualCraftL 版本为%1,而 VisualCraftL 动态库的版本为%2。通常这是因为动态库版本过低。 The version of VisualCraftL at compile-time is %1, while that at runtime is %2. Usually it is because the version of VisualCraftL shared lib is too old. + + + + + + + + + + + + 加载配置文件失败。 Failed to load configuration file. + + + + + + + + + + + + 无法加载配置文件"./vc-config.json"。 %1 @@ -696,97 +888,337 @@ If you select a block in "Avaliable blocks" page, the other page will %1 + + + + + + + + + + + + 原版资源包 Vanilla + + + + + + + + + + + + 选择资源包 Select resource pack + + + + + + + + + + + + 资源包解析失败 Failed to parse resource pack + + + + + + + + + + + + + + + + + + + + + + + + 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. + + + + + + + + + + + + 原版 json Vanilla + + + + + + + + + + + + 选择方块 id json 文件 Select block id json file + + + + + + + + + + + + 方块状态列表 json 解析失败 Failed to parse block state json list + + + + + + + + + + + + 资源包/方块状态列表 json 解析失败 The resource pack or block list json failed to be parsed + + + + + + + + + + + + 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. + + + + + + + + + + + + 设置可用方块失败 Failed to set avaliable blocks + + + + + + + + + + + + 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. + + + + + + + + + + + + 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) + + + + + + + + + + + + 选择图片(可多选) Select images - 读取图片失败 - Failed to load image. - - + + + + + + + + + + + + + 读取图片失败 + Failed to load image. + + + + + + + + + + + + + + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. + + + + + + + + + + + + 设置图片失败 Failed to set image + + + + + + + + + + + + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. + + + + + + + + + + + + 关于 VisualCraft About VisualCraft + + + + + + + + + + + + VisualCraft 是一款全新的 Minecraft 像素画生成器,由 MC 玩家 TokiNoBug 开发,是 SlopeCraft 的子项目。与其他类似的软件不同,VisualCraft 旨在跟进最新的 MC 版本 (1.12~最新版)、支持最多的 MC 特性,提供最强大的功能。 @@ -796,6 +1228,18 @@ If you select a block in "Avaliable blocks" page, the other page will + + + + + + + + + + + + 目前 VisualCraft 能够解析许多第三方资源包,也允许自定义增加加新方块。与传统的思路不同,VisualCraft 以方块模型的方式来解析资源包,尽量贴近 Minecraft 的方式,因此支持各种自定义的方块模型。 @@ -805,6 +1249,18 @@ If you select a block in "Avaliable blocks" page, the other page will + + + + + + + + + + + + 在导出方面,VisualCraft 支持 Litematica mod 的投影 (*.litematic)、WorldEdit 原理图 (*.shem)(仅 1.13+可用)、原版结构方块文件 (*.nbt)、平面示意图 (*.png) 等方式。 @@ -814,6 +1270,18 @@ If you select a block in "Avaliable blocks" page, the other page will + + + + + + + + + + + + VisualCraft 支持用各种透明方块互相叠加,产生更多的颜色。软件最多支持不超过 65534 种颜色,受此限制,像素画的层数不超过3 层。 @@ -823,71 +1291,239 @@ If you select a block in "Avaliable blocks" page, the other page will + + + + + + + + + + + + 由于颜色数量很多,VisualCraft 使用了显卡加速。目前支持的 API 有 OpenCL。现在正在使用的 API 是%1 The great amount of colors makes GPU accleration necessary. Now OpenCL is supported, and %1 is what currently being used. + + + + + + + + + + + + 可用的计算设备(CPU + %1可用的显卡) Avaliable compute devices (CPU + %1-avaliable-GPUs) + + + + + + + + + + + + 无法获取platform信息. 请检查驱动. OpenCL错误码: %1. Failed to get platform information. Please check GPU driver(s). OpenCL error code : %1. + + + + + + + + + + + + 无法获取device信息. 请检查驱动. OpenCL错误码: %1 Failed to get device infomation. Please check the driver(s). OpenCL error code : %1 + + + + + + + + + + + + 设置计算设备失败 Failed to set compute device + + + + + + + + + + + + 创建GPU平台失败,平台序号为%1,设备序号为%2 Failed to create GPU platform, the index of platform is %1 and index of device is %2 + + + + + + + + + + + + 创建GPU设备失败,平台序号为%1,设备序号为%2 Failed to create GPU device, the index of platform is %1 and index of device is %2 + + + + + + + + + + + + 设置GPU设备失败。,平台序号为%1,设备序号为%2 Failed to set GPU device, the index of platform is %1 and index of device is %2 + + + + + + + + + + + + 选择输出位置 Select output directory + + + + + + + + + + + + %1, %2 %1 rows, %2 cols + + + + + + + + + + + + 错误操作 Invalid operation + + + + + + + + + + + + 设置任何一种导出类型的输出位置时,都需要在左侧的combo box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 When you set the output directory for any type of export, you should select the type of export with the combobox in the left. Please select a type first. + + + + + + + + + + + + 平面示意图输入错误 Invalid input for flatdiagram + + + + + + + + + + + + 应输入%1个以";"分隔的文件名,但实际上输入了%2个。 您输入的%2个文件名是: @@ -897,71 +1533,239 @@ The %2 filename(s) you give is: %3 + + + + + + + + + + + + 导出平面示意图失败 Failed to export flat diagram + + + + + + + + + + + + 尝试为原图生成第%1个平面示意图(%2)时出现了错误。 Error occurred when trying to generate the %1-th flat diagram(%2). + + + + + + + + + + + + 致命逻辑错误 Impossible error + + + + + + + + + + + + 导出页码表格中的图片"%1"不能在this->image_cache中找到对应的缓存。请将这个错误反馈给软件开发者。 Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. + + + + + + + + + + + + 保存转化后图像失败 Failed to save the converted image + + + + + + + + + + + + QImage未能生成"%1"。 QImage failed to generate "%1". + + + + + + + + + + + + 构建三维结构失败 Failed to build 3D structure + + + + + + + + + + + + VisualCraftL不能为图像"%1"构建三维结构。 VisualCraft failed to build 3D structure for image "%1". + + + + + + + + + + + + 导出litematica失败 Failed to export as litematic + + + + + + + + + + + + VisualCraftL不能为图像"%1"生成投影文件"%2"。 VisualCraft failed to generate litematic file "%2" for image "%1". + + + + + + + + + + + + 导出原版结构方块文件失败 Failed to export as vanilla structure + + + + + + + + + + + + VisualCraftL不能为图像"%1"生成结构方块文件"%2"。 VisualCraft failed to generate structure file "%2" for image "%1". + + + + + + + + + + + + 导出World Edit原理图失败 Failed to export as WE schematic + + + + + + + + + + + + VisualCraftL不能为图像"%1"生成World Edit原理图"%2"。 VisualCraft failed to generate WE schematic file "%2" for image "%1". @@ -970,7 +1774,8 @@ The %2 filename(s) you give is: VC_block_class - + + 启用 Enable diff --git a/imageCutter/imageCutter_en_US.ts b/imageCutter/imageCutter_en_US.ts index fa1243e5..8e758b72 100644 --- a/imageCutter/imageCutter_en_US.ts +++ b/imageCutter/imageCutter_en_US.ts @@ -4,94 +4,167 @@ CutterWind - + + 图片预处理 Preprocess image - + + cols - + + 缩放至: Scale to - + + 图片尺寸(方块): Image size (blocks) : - + + 请加载图片 Please load an image - + + rows - + + 开始 Start - + + 图片变换 Transform - + + 加载图片 Load image - + + 缩放 Scale image - + + 图片分块 Cut image - + + 保存图片 Save image + 不保持比例 IgnoreAspectRatio + + + + + + + + + + + + 保持比例缩小 KeepAspectRatio + + + + + + + + + + + + 保持比例扩张 KeepAspectRatioByExpanding + + + + + + + + + + + + 快速变换 FastTransformation + + + + + + + + + + + + 平滑变换 SmoothTransformation + + + + + + + + + + + + 选择图片 Select image @@ -99,28 +172,97 @@ - 图片(*.png *.bmp *.jpg *.tif) + + + + + + + + + + + + + + + 图片 (*.png *.bmp *.jpg *.tif) Images (*.png *.bmp *.jpg *.tif) + + + + + + + + + + + + 打开图片失败 Failed to load image + + + + + + + + + + + + 图片格式损坏,或者图片过于巨大。 The image might be damaged, or it's too huge. + + + + + + + + + + + + 行 , rows, + + + + + 选择输出文件夹 Select output directory + + + + + + + + + + + + 图片(*.png *.bmp *.jpg *.tif) + + diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index 603c8d74..6a1563b5 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -4,14 +4,16 @@ BaseColorWidget + GroupBox - + + 启用 - + Enable @@ -21,6 +23,26 @@ + + + + + + + + + + + + + + + + + + + + 解析方块列表失败 Failed to parse block list @@ -29,18 +51,58 @@ + + + + + + + + + + + + + + + + + + + + 加载预设错误 Failed to load preset + + + + + + + + + + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors + + + + + + + + + + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id @@ -50,12 +112,32 @@ + + + + + + + + + + 基色 %1 的预设被重复定义。一个基色只能被定义一次。 The preset of base color %1 is defined multiple time. A base color can be defined only once. + + + + + + + + + + 解析预设 json 时发生异常:"%1" Exception occured when parsing preset json: "%1" From 5b6cc77207c5b574d607fa329ea7e9f643f875a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 21:42:53 +0800 Subject: [PATCH 0354/1123] implement menus --- CMakeLists.txt | 4 ++-- SlopeCraft/SCWind.cpp | 46 ++++++++++++++++++++++++++++++++++++++----- SlopeCraft/SCWind.h | 12 +++++++++++ SlopeCraft/SCWind.ui | 5 ++--- SlopeCraft/main.cpp | 29 +++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2001104..7551c8d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.0.1) +set(SlopeCraft_version 5.1.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) @@ -152,7 +152,7 @@ add_subdirectory(imageCutter) add_subdirectory(SlopeCraftL) # add_subdirectory(SlopeCraftMain) -# add_subdirectory(SlopeCraft) +add_subdirectory(SlopeCraft) add_subdirectory(MapViewer) add_subdirectory(tests) add_subdirectory(VisualCraftL) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 68a9b6fa..ee90a522 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -6,6 +6,45 @@ #include #include #include +#include +#include "VersionDialog.h" + +const QString SCWind::update_url{ + "https://api.github.com/repos/SlopeCraft/SlopeCraft/releases"}; + +void SCWind::connect_slots() noexcept { + // ac_contact_Github + + connect(this->ui->ac_lang_ZH, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::Chinese); }); + connect(this->ui->ac_lang_EN, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::English); }); + + connect(this->ui->ac_contact_Github, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://github.com/SlopeCraft/SlopeCraft")); + }); + connect(this->ui->ac_contact_Bilibili, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://space.bilibili.com/351429231")); + }); + connect(this->ui->ac_report_bugs, &QAction::triggered, []() { + QDesktopServices::openUrl( + QUrl("https://github.com/SlopeCraft/SlopeCraft/issues/new/choose")); + }); + // ac_check_updates + + connect(this->ui->ac_tutorial, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/")); + }); + connect(this->ui->ac_faq, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/faq/")); + }); + + connect(this->ui->ac_check_updates, &QAction::triggered, [this]() { + VersionDialog::start_network_request(this, "SlopeCraft", + QUrl{SCWind::update_url}, + SCWind::network_manager(), true); + }); +} // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) @@ -13,6 +52,8 @@ SCWind::SCWind(QWidget *parent) ui(new Ui::SCWind), kernel(SlopeCraft::SCL_createKernel()) { this->ui->setupUi(this); + + this->connect_slots(); { // create translators const char *const translator_filenames[] = { @@ -32,11 +73,6 @@ SCWind::SCWind(QWidget *parent) this->translators.emplace_back(t); } - - connect(this->ui->ac_lang_ZH, &QAction::triggered, - [this]() { this->set_lang(::SCL_language::Chinese); }); - connect(this->ui->ac_lang_EN, &QAction::triggered, - [this]() { this->set_lang(::SCL_language::English); }); } { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 683e11e0..ef3845e5 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "cvt_task.h" #include "PoolModel.h" #include "ExportTableModel.h" @@ -21,9 +22,20 @@ class SCWind; class SCWind : public QMainWindow { Q_OBJECT + private: + void connect_slots() noexcept; + public: explicit SCWind(QWidget* parent = nullptr); ~SCWind(); + + inline static QNetworkAccessManager& network_manager() noexcept { + static QNetworkAccessManager manager; + return manager; + } + + const static QString update_url; + enum class export_type { litematica, vanilla_structure, diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 2282e6f5..20ac7f60 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1412,7 +1412,7 @@ - + @@ -1434,7 +1434,6 @@ 帮助 - @@ -1522,7 +1521,7 @@ 测试方块列表 - + 输出当前颜色表 diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index d4612c59..15bca620 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -1,5 +1,7 @@ #include #include "SCWind.h" +#include "VersionDialog.h" +#include int main(int argc, char** argv) { QApplication qapp(argc, argv); @@ -8,5 +10,32 @@ int main(int argc, char** argv) { wind.show(); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + + bool is_language_ZH = QLocale::system().uiLanguages().contains("zh"); + + // this line is used to test the translation + + for (int i = 0; i < argc; i++) { + if (std::string_view(argv[i]) == "--lang-force-to-en") { + is_language_ZH = false; + break; + } + if (std::string_view(argv[i]) == "--lang-force-to-zh") { + is_language_ZH = true; + break; + } + } + + if (is_language_ZH) { + wind.set_lang(::SCL_language::Chinese); + } else { + wind.set_lang(::SCL_language::English); + } + + VersionDialog::start_network_request(&wind, "SlopeCraft", + QUrl{SCWind::update_url}, + SCWind::network_manager(), false); + return qapp.exec(); } \ No newline at end of file From a2c5af0db18b66c0c6c810e3d7bad04c56d387eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 22 May 2023 22:00:13 +0800 Subject: [PATCH 0355/1123] update translations --- SlopeCraft/SCWind.cpp | 35 - SlopeCraft/SCWind.h | 2 + SlopeCraft/SCWind_slots.cpp | 54 ++ SlopeCraft/others/SlopeCraft_en_US.ts | 679 ++++++++++++------ .../others/BlockListManager_en_US.ts | 91 +-- 5 files changed, 531 insertions(+), 330 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index ee90a522..65d2019c 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -7,45 +7,10 @@ #include #include #include -#include "VersionDialog.h" const QString SCWind::update_url{ "https://api.github.com/repos/SlopeCraft/SlopeCraft/releases"}; -void SCWind::connect_slots() noexcept { - // ac_contact_Github - - connect(this->ui->ac_lang_ZH, &QAction::triggered, - [this]() { this->set_lang(::SCL_language::Chinese); }); - connect(this->ui->ac_lang_EN, &QAction::triggered, - [this]() { this->set_lang(::SCL_language::English); }); - - connect(this->ui->ac_contact_Github, &QAction::triggered, []() { - QDesktopServices::openUrl(QUrl("https://github.com/SlopeCraft/SlopeCraft")); - }); - connect(this->ui->ac_contact_Bilibili, &QAction::triggered, []() { - QDesktopServices::openUrl(QUrl("https://space.bilibili.com/351429231")); - }); - connect(this->ui->ac_report_bugs, &QAction::triggered, []() { - QDesktopServices::openUrl( - QUrl("https://github.com/SlopeCraft/SlopeCraft/issues/new/choose")); - }); - // ac_check_updates - - connect(this->ui->ac_tutorial, &QAction::triggered, []() { - QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/")); - }); - connect(this->ui->ac_faq, &QAction::triggered, []() { - QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/faq/")); - }); - - connect(this->ui->ac_check_updates, &QAction::triggered, [this]() { - VersionDialog::start_network_request(this, "SlopeCraft", - QUrl{SCWind::update_url}, - SCWind::network_manager(), true); - }); -} - // #include "PoolWidget.h" SCWind::SCWind(QWidget *parent) : QMainWindow(parent), diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index ef3845e5..832dfaa1 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -83,6 +83,8 @@ class SCWind : public QMainWindow { void on_ac_cache_dir_open_triggered() noexcept; void on_ac_clear_cache_triggered() noexcept; + void on_ac_about_triggered() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 85a7fd6c..51c96303 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -7,6 +7,7 @@ #include #include "PreviewWind.h" #include "AiCvterParameterDialog.h" +#include "VersionDialog.h" void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 @@ -714,4 +715,57 @@ void SCWind::on_ac_clear_cache_triggered() noexcept { return; // QMessageBox::StandardButton::Cancel and for closing the dialog } } +} + +void SCWind::connect_slots() noexcept { + // ac_contact_Github + + connect(this->ui->ac_lang_ZH, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::Chinese); }); + connect(this->ui->ac_lang_EN, &QAction::triggered, + [this]() { this->set_lang(::SCL_language::English); }); + + connect(this->ui->ac_contact_Github, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://github.com/SlopeCraft/SlopeCraft")); + }); + connect(this->ui->ac_contact_Bilibili, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://space.bilibili.com/351429231")); + }); + connect(this->ui->ac_report_bugs, &QAction::triggered, []() { + QDesktopServices::openUrl( + QUrl("https://github.com/SlopeCraft/SlopeCraft/issues/new/choose")); + }); + // ac_check_updates + + connect(this->ui->ac_tutorial, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/")); + }); + connect(this->ui->ac_faq, &QAction::triggered, []() { + QDesktopServices::openUrl(QUrl("https://slopecraft.readthedocs.io/faq/")); + }); + + connect(this->ui->ac_check_updates, &QAction::triggered, [this]() { + VersionDialog::start_network_request(this, "SlopeCraft", + QUrl{SCWind::update_url}, + SCWind::network_manager(), true); + }); +} + +void SCWind::on_ac_about_triggered() noexcept { + QString info; + info += + tr("感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft " + "是由我开发的一款立体地图画生成器,主要用于在 minecraft " + "中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地" + "图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 " + "SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen " + "等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 " + "minecraft 而设计的。AbrasiveBoar902 " + "为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS " + "的适配做出了贡献。"); + info += "\n\n"; + info += tr("本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。"); + info += "\n\n"; + info += tr("版权所有 © 2021-2023 SlopeCraft 开发者"); + QMessageBox::information(this, tr("关于 SlopeCraft"), info); } \ No newline at end of file diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index bfab0866..64374bc9 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -4,8 +4,8 @@ AiCvterParameterDialog - - + + Ai转化器参数 Set AiConverter parameters @@ -15,32 +15,32 @@ Enable fail times - - + + 最大提前收敛代数: Max fail times : - - + + 交叉概率: Crossover prob : - - + + 种群数量: Population size : - - + + 最大进化代数: Max generation : - - + + 变异概率: Mutation prob : @@ -147,6 +147,9 @@ + + + 原图文件名 Image file @@ -157,6 +160,9 @@ + + + 图像大小 Image size @@ -167,6 +173,9 @@ + + + 地图大小 Map size @@ -177,6 +186,9 @@ + + + 地图序号范围 Map index range @@ -187,6 +199,9 @@ + + + 第一个地图文件名 First map @@ -197,6 +212,9 @@ + + + 最后一个地图文件名 Last map @@ -1340,6 +1358,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + %1 盒 + %2 组 + %3 个 %1 shulker box(es) + %2 stack(s) + %3 @@ -1350,6 +1371,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + %1 组 + %2 个 %1 stack(s) + %2 @@ -1360,6 +1384,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + %1 个 %1 @@ -1373,6 +1400,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. @@ -1432,33 +1462,33 @@ Click "Yes" to continue and replace these files, or click "No&quo The converted image might be slightly modified if lossy compression is enabled. - - + + 查看材料列表 Material List - - + + 按组显示 Display by stacks - - + + 不排序 Do not sort - - + + 升序 Acsending - - + + 降序 Decsending @@ -1469,6 +1499,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + %1 -- 表格内容已复制到剪贴板 %1 -- Table content copied to clipboart @@ -1479,6 +1512,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 大小:%1 × %2 × %3 Size: %1 × %2 × %3 @@ -1489,6 +1525,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 体积:%1 Volume: %1 @@ -1499,6 +1538,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 方块总数:%1 Block count: %1 @@ -1527,6 +1569,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 加载图片 %1 失败。 Failed to load image %1. @@ -1537,6 +1582,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 绘制图标时发现错误 An error occurred when drawing icon @@ -1544,33 +1592,33 @@ Click "Yes" to continue and replace these files, or click "No&quo SCWind - - + + 地图画配置 Map configurations - - + + 方块列表预设 Blocklist preset - - + + 加载预设 Load preset - - - + + + 保存当前预设 Save as preset - - + + 可用方块数量: Available block count: @@ -1605,99 +1653,98 @@ Click "Yes" to continue and replace these files, or click "No&quo - - + + 游戏版本 Game Version - - + + 地图画类型 Map type - - + + 立体地图画 3D Map - - + + 平板地图画 Flat Map - - + + 纯文件地图画 File-only Map - - + + 优先彩色玻璃 Use stained glass - - + + 优先混凝土 Use Concrete - - + + 优先羊毛 Use Wool - - + + 优先木板 Use planks - - + + 优先原木 Use logs - - + + 导入图像并转化 Load image and convert - - + + 原图 Original image - - + + 转化后 Converted image - - + + 删除 Delete - - - + + 项目池 - Task pool + Task pool - - + + 添加 Add @@ -1708,14 +1755,14 @@ Click "Yes" to continue and replace these files, or click "No&quo - - + + 转化算法 Convert algorithm - - + + 抖动 Dithering @@ -1756,341 +1803,330 @@ Click "Yes" to continue and replace these files, or click "No&quo GACvter - - + + 转化当前图像 Convert current image - - - - + + + + 保存转化后图像 Save converted image - - + + 全部转化 Convert all - - - + + 导出 Export - - + + Litematica - - - + + 结构方块文件 Vanilla structure - - + + 显示缩略图 - - - + + WE原理图 WE Schem - - - + + 平面示意图 Flat diagram - - + + 地图文件 Map data files - - + + 其他选项 Others - - + + 防火 Fire Proof - - + + 防末影人 Enderman Proof - - + + 连接蘑菇块 Connect mushroom blocks - - + + 压缩高度 Compress - - + + 有损压缩 Lossy Compression - - + + 无损压缩 Lossless Compress - - + + 最大允许高度: Max height: - - + + 搭桥 Glass Bridge - - + + 允许搭桥 Construct Glass Bridge - - + + layer(s) - - + + 搭桥间隔: Glass bridge interval: - - + + 投影区域名称 Region name - - + + 投影名称 Litematic name - - + + 用结构空位替代空气 Replace air with structure void - - + + offset - - + + WEOffset - - - - - - - + + 0 - - + + 原理图名称 Name of schematic - - + + 依赖 mod 名称 Depend mods - - + + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - - + + 方块 block(s) - - - + + 间距: Line interval: - - + + 垂直分割线 Vertical split line - - + + 水平分割线 Horizontal split line - - + + 大小与方块数量 Size and block count - - - + + + 大小: Size: - - - + + + 方块数量: Block count: - - + + 全部导出 Export all - - + + 预览 Preview - - + + 预览材料表 Material list - - + + 预览压缩效果 Compress effect - - + + 预构建三维结构 Construct 3d structure - - + + 地图画起始序号: Map beginning index: - - + + 语言 Language - - + + 高级 Advanced - - + + 缓存 Cache - - + + 关于 About - - + + 联系作者 Contact with me - - + + 帮助 Help - - + + GA转化器参数 GACvter parameters - - + + open_cache_dir - - + + 打开缓存文件夹 Open cache directory - - + + 清除缓存 Clean caches @@ -2107,50 +2143,51 @@ Click "Yes" to continue and replace these files, or click "No&quo - - + + + 关于 SlopeCraft About SlopeCraft - - + + 反馈 bug Report bugs - - + + 检查更新 Check updates - - + + 测试方块列表 Test block list - - + + 输出当前颜色表 Export current colorset - - + + 查看 SlopeCraft 文档 Documentation - - + + 使用教程 Tutorial - - + + 常见问题 FAQ @@ -2161,6 +2198,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 加载默认预设失败 Failed to load default presets @@ -2171,6 +2211,9 @@ Click "Yes" to continue and replace these files, or click "No&quo + + + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -2185,6 +2228,9 @@ Detail information: + + + 设置方块列表失败 Failed to setup blocklist @@ -2195,6 +2241,9 @@ Detail information: + + + 您设置的方块列表可能存在错误 There may be errors in your blocklist @@ -2205,6 +2254,9 @@ Detail information: + + + 可用颜色数量:%1 Avaliable colors: %1 @@ -2215,6 +2267,9 @@ Detail information: + + + 应用预设失败 Failed to apply preset @@ -2225,6 +2280,9 @@ Detail information: + + + 转化图像失败 Failed to convert image @@ -2241,6 +2299,12 @@ Detail information: + + + + + + 缓存失败 Failed to save cache @@ -2257,6 +2321,12 @@ Detail information: + + + + + + 未能创建缓存文件,错误信息: %1 Failed to create cache directory, error info: @@ -2269,6 +2339,9 @@ Detail information: + + + 无法保存第%1个转化后图像 Failed to save the %1-th converted image @@ -2279,6 +2352,9 @@ Detail information: + + + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. @@ -2289,6 +2365,9 @@ Detail information: + + + 保存图像失败 Failed to save image @@ -2299,6 +2378,9 @@ Detail information: + + + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. @@ -2309,6 +2391,9 @@ Detail information: + + + 构建三维结构失败 Failed to build 3d structure @@ -2319,6 +2404,9 @@ Detail information: + + + 构建三维结构时,出现错误。可能是因为尝试跳步。 An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. @@ -2329,6 +2417,9 @@ Detail information: + + + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 @@ -2339,6 +2430,9 @@ Detail information: + + + 方块数量:%1 Block count: %1 @@ -2349,6 +2443,9 @@ Detail information: + + + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. @@ -2359,6 +2456,9 @@ Detail information: + + + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. @@ -2369,6 +2469,9 @@ Detail information: + + + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. @@ -2379,6 +2482,9 @@ Detail information: + + + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: @@ -2391,6 +2497,9 @@ Detail information: + + + SlopeCraft 出现错误 An error occurred to SlopeCraft @@ -2401,6 +2510,9 @@ Detail information: + + + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -2415,6 +2527,9 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + + + 选择图片 Select Image @@ -2425,6 +2540,9 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + + + 打开图像失败 Failed to open image @@ -2435,6 +2553,9 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + + + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. @@ -2447,6 +2568,9 @@ Detailed information: %2 + + + 选择预设文件 Select a preset file @@ -2457,6 +2581,9 @@ Detailed information: %2 + + + 解析预设文件失败 Failed to parse thes preset file @@ -2467,6 +2594,9 @@ Detailed information: %2 + + + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 @@ -2477,6 +2607,9 @@ Detailed information: %2 + + + 保存预设文件失败 Failed to save preset file @@ -2487,6 +2620,9 @@ Detailed information: %2 + + + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 @@ -2515,6 +2651,18 @@ Detailed information: %2 + + + + + + + + + + + + 未选择图像 No image selected @@ -2537,6 +2685,15 @@ Detailed information: %2 + + + + + + + + + 请在左侧任务池选择一个图像 Please select a image in the left @@ -2547,6 +2704,9 @@ Detailed information: %2 + + + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left @@ -2557,6 +2717,9 @@ Detailed information: %2 + + + 将要覆盖已存在的图像 Existing file(s) will be replaced @@ -2567,6 +2730,9 @@ Detailed information: %2 + + + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? @@ -2589,6 +2755,15 @@ Detailed information: %2 + + + + + + + + + 该图像尚未被转化 The image is not converted @@ -2605,6 +2780,12 @@ Detailed information: %2 + + + + + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it @@ -2615,6 +2796,9 @@ Detailed information: %2 + + + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. @@ -2625,6 +2809,9 @@ Detailed information: %2 + + + 尚未构建三维结构 3d structure not built @@ -2635,6 +2822,9 @@ Detailed information: %2 + + + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. @@ -2645,6 +2835,9 @@ Detailed information: %2 + + + 导出设置有错 Error in export options @@ -2655,6 +2848,9 @@ Detailed information: %2 + + + 导出设置存在如下错误: %1 There is an error in your export option: @@ -2667,6 +2863,9 @@ Detailed information: %2 + + + 你点错按钮了 Wrong button @@ -2677,6 +2876,9 @@ Detailed information: %2 + + + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). @@ -2687,6 +2889,9 @@ Detailed information: %2 + + + 无可导出的任务 Nothing to export @@ -2697,6 +2902,9 @@ Detailed information: %2 + + + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images @@ -2707,6 +2915,9 @@ Detailed information: %2 + + + 选择导出位置 Select export directory @@ -2717,6 +2928,9 @@ Detailed information: %2 + + + 将要覆盖已经存在的文件 Existing files will be replaced @@ -2727,6 +2941,9 @@ Detailed information: %2 + + + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: @@ -2739,6 +2956,9 @@ Detailed information: %2 + + + 导出失败 Failed to export @@ -2749,6 +2969,9 @@ Detailed information: %2 + + + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 @@ -2761,6 +2984,9 @@ Click Ignore to skip this image, and Cancel to cancel. + + + 设置导出位置 Set export directory @@ -2771,6 +2997,9 @@ Click Ignore to skip this image, and Cancel to cancel. + + + %1 个文件将被替换 %1 files will be replaced @@ -2781,6 +3010,9 @@ Click Ignore to skip this image, and Cancel to cancel. + + + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -2795,6 +3027,9 @@ Click Yes to replace them, or No to cancel. + + + 删除缓存失败 Failed to clean cache @@ -2805,11 +3040,35 @@ Click Yes to replace them, or No to cancel. + + + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel + + + + + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 + Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. + + + + + + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 + This program is released under license GPL-3.0 or later. + + + + + + 版权所有 © 2021-2023 SlopeCraft 开发者 + Copyright © 2021-2023 SlopeCraft deveploers + TaskBox diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index 6a1563b5..c82b5ffd 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -4,7 +4,6 @@ BaseColorWidget - GroupBox @@ -19,54 +18,13 @@ BlockListManager - - - - - - - - - - - - - - - - - - - - - 解析方块列表失败 Failed to parse block list - - - - - - - - - - - - - - - - - - - - @@ -75,67 +33,30 @@ Failed to load preset - - - - - - - - - - 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 - There 're %1 basecolors in the preset file, while actually there are %2 basecolors + There 're %1 basecolors in the preset file, while actually there are + %2 basecolors - - - - - - - - - - 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id - Block "%2" is assigned to base color %1, but failed to find a block with such id + Block "%2" is assigned to base color %1, but failed to find a + block with such id QObject - - - - - - - - - - 基色 %1 的预设被重复定义。一个基色只能被定义一次。 - The preset of base color %1 is defined multiple time. A base color can be defined only once. + The preset of base color %1 is defined multiple time. A base color can be + defined only once. - - - - - - - - - - 解析预设 json 时发生异常:"%1" From 518a3eaca1480c4de06b8f68d3696f989772e2e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 23 May 2023 12:29:24 +0800 Subject: [PATCH 0356/1123] update translation --- SlopeCraft/others/SlopeCraft_en_US.ts | 148 +++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 64374bc9..b10e8457 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -176,6 +176,7 @@ + 地图大小 Map size @@ -189,6 +190,7 @@ + 地图序号范围 Map index range @@ -202,6 +204,7 @@ + 第一个地图文件名 First map @@ -215,6 +218,7 @@ + 最后一个地图文件名 Last map @@ -1361,6 +1365,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + %1 盒 + %2 组 + %3 个 %1 shulker box(es) + %2 stack(s) + %3 @@ -1374,6 +1379,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + %1 组 + %2 个 %1 stack(s) + %2 @@ -1387,6 +1393,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + %1 个 %1 @@ -1403,6 +1410,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. @@ -1502,6 +1510,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + %1 -- 表格内容已复制到剪贴板 %1 -- Table content copied to clipboart @@ -1515,6 +1524,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 大小:%1 × %2 × %3 Size: %1 × %2 × %3 @@ -1528,6 +1538,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 体积:%1 Volume: %1 @@ -1541,6 +1552,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 方块总数:%1 Block count: %1 @@ -1572,6 +1584,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 加载图片 %1 失败。 Failed to load image %1. @@ -1585,6 +1598,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 绘制图标时发现错误 An error occurred when drawing icon @@ -2023,14 +2037,14 @@ Click "Yes" to continue and replace these files, or click "No&quo - + 大小: Size: - + 方块数量: Block count: @@ -2201,6 +2215,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 加载默认预设失败 Failed to load default presets @@ -2214,6 +2229,7 @@ Click "Yes" to continue and replace these files, or click "No&quo + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -2231,6 +2247,7 @@ Detail information: + 设置方块列表失败 Failed to setup blocklist @@ -2244,6 +2261,7 @@ Detail information: + 您设置的方块列表可能存在错误 There may be errors in your blocklist @@ -2257,6 +2275,7 @@ Detail information: + 可用颜色数量:%1 Avaliable colors: %1 @@ -2270,6 +2289,7 @@ Detail information: + 应用预设失败 Failed to apply preset @@ -2283,6 +2303,7 @@ Detail information: + 转化图像失败 Failed to convert image @@ -2305,6 +2326,8 @@ Detail information: + + 缓存失败 Failed to save cache @@ -2327,6 +2350,8 @@ Detail information: + + 未能创建缓存文件,错误信息: %1 Failed to create cache directory, error info: @@ -2342,6 +2367,7 @@ Detail information: + 无法保存第%1个转化后图像 Failed to save the %1-th converted image @@ -2355,6 +2381,7 @@ Detail information: + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. @@ -2368,6 +2395,7 @@ Detail information: + 保存图像失败 Failed to save image @@ -2381,6 +2409,7 @@ Detail information: + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. @@ -2394,6 +2423,7 @@ Detail information: + 构建三维结构失败 Failed to build 3d structure @@ -2407,6 +2437,7 @@ Detail information: + 构建三维结构时,出现错误。可能是因为尝试跳步。 An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. @@ -2420,6 +2451,7 @@ Detail information: + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 @@ -2433,6 +2465,7 @@ Detail information: + 方块数量:%1 Block count: %1 @@ -2446,6 +2479,7 @@ Detail information: + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. @@ -2459,6 +2493,7 @@ Detail information: + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. @@ -2472,6 +2507,7 @@ Detail information: + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. @@ -2485,6 +2521,7 @@ Detail information: + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: @@ -2500,6 +2537,7 @@ Detail information: + SlopeCraft 出现错误 An error occurred to SlopeCraft @@ -2513,6 +2551,7 @@ Detail information: + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -2530,6 +2569,7 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + 选择图片 Select Image @@ -2543,6 +2583,7 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + 打开图像失败 Failed to open image @@ -2556,6 +2597,7 @@ Click Ok to ignore, and click Close to exit SlopeCraft. + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. @@ -2571,6 +2613,7 @@ Detailed information: %2 + 选择预设文件 Select a preset file @@ -2584,6 +2627,7 @@ Detailed information: %2 + 解析预设文件失败 Failed to parse thes preset file @@ -2597,6 +2641,7 @@ Detailed information: %2 + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 @@ -2610,6 +2655,7 @@ Detailed information: %2 + 保存预设文件失败 Failed to save preset file @@ -2623,6 +2669,7 @@ Detailed information: %2 + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 @@ -2663,6 +2710,10 @@ Detailed information: %2 + + + + 未选择图像 No image selected @@ -2694,6 +2745,9 @@ Detailed information: %2 + + + 请在左侧任务池选择一个图像 Please select a image in the left @@ -2707,6 +2761,7 @@ Detailed information: %2 + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left @@ -2720,6 +2775,7 @@ Detailed information: %2 + 将要覆盖已存在的图像 Existing file(s) will be replaced @@ -2733,6 +2789,7 @@ Detailed information: %2 + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? @@ -2764,6 +2821,9 @@ Detailed information: %2 + + + 该图像尚未被转化 The image is not converted @@ -2786,6 +2846,8 @@ Detailed information: %2 + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it @@ -2799,6 +2861,7 @@ Detailed information: %2 + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. @@ -2812,6 +2875,7 @@ Detailed information: %2 + 尚未构建三维结构 3d structure not built @@ -2825,6 +2889,7 @@ Detailed information: %2 + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. @@ -2838,6 +2903,7 @@ Detailed information: %2 + 导出设置有错 Error in export options @@ -2851,6 +2917,7 @@ Detailed information: %2 + 导出设置存在如下错误: %1 There is an error in your export option: @@ -2866,6 +2933,7 @@ Detailed information: %2 + 你点错按钮了 Wrong button @@ -2879,6 +2947,7 @@ Detailed information: %2 + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). @@ -2892,6 +2961,7 @@ Detailed information: %2 + 无可导出的任务 Nothing to export @@ -2905,6 +2975,7 @@ Detailed information: %2 + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images @@ -2918,6 +2989,7 @@ Detailed information: %2 + 选择导出位置 Select export directory @@ -2931,6 +3003,7 @@ Detailed information: %2 + 将要覆盖已经存在的文件 Existing files will be replaced @@ -2944,6 +3017,7 @@ Detailed information: %2 + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: @@ -2959,6 +3033,7 @@ Detailed information: %2 + 导出失败 Failed to export @@ -2972,6 +3047,7 @@ Detailed information: %2 + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 @@ -2987,6 +3063,7 @@ Click Ignore to skip this image, and Cancel to cancel. + 设置导出位置 Set export directory @@ -3000,6 +3077,7 @@ Click Ignore to skip this image, and Cancel to cancel. + %1 个文件将被替换 %1 files will be replaced @@ -3013,6 +3091,7 @@ Click Ignore to skip this image, and Cancel to cancel. + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -3030,6 +3109,7 @@ Click Yes to replace them, or No to cancel. + 删除缓存失败 Failed to clean cache @@ -3043,6 +3123,7 @@ Click Yes to replace them, or No to cancel. + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". @@ -3052,6 +3133,7 @@ Click Ignore to skip, Retry to retry and Cancel to cancel + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. @@ -3059,6 +3141,7 @@ Click Ignore to skip, Retry to retry and Cancel to cancel + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. @@ -3066,9 +3149,70 @@ Click Ignore to skip, Retry to retry and Cancel to cancel + 版权所有 © 2021-2023 SlopeCraft 开发者 Copyright © 2021-2023 SlopeCraft deveploers + + + 正在构建高度矩阵 + Making height matrix + + + + 正在构建三维结构 + Building 3D structure + + + + 正在收集整张图片的颜色 + Collecting colors of the whole image + + + + 正在压缩立体地图画 + Compressing 3D map pixel arts + + + + 正在为立体地图画搭桥 + Constructing glass bridge + + + + 正在匹配颜色 + Matching colors + + + + 正在使用抖动仿色 + Dithering + + + + 正在将平板地图画变为墙面地图画 + Converting flat map art to wall map art + + + + 正在写入三维结构 + Writing 3D structure + + + + 正在写入方块列表 + Writing block palette + + + + 正在写入地图数据文件 + Writing map data + + + + 正在写入基础信息 + Writing meta data + TaskBox From 99c7a4e52f8681e33564887dd6dbcbe19d10f260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 23 May 2023 12:34:23 +0800 Subject: [PATCH 0357/1123] display window title --- SlopeCraft/SCWind.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++ SlopeCraft/SCWind.h | 4 +++ SlopeCraft/main.cpp | 1 + 3 files changed, 87 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 65d2019c..f2ee0f21 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -73,6 +73,19 @@ SCWind::SCWind(QWidget *parent) [](void *_this, ::SCL_errorFlag err, const char *msg) { reinterpret_cast(_this)->report_error(err, msg); }); + this->kernel->setReportWorkingStatue([](void *_this, ::SCL_workStatues ws) { + SCWind *const wind = reinterpret_cast(_this); + + const QString status_str = SCWind::workStatus_to_string(ws); + QString wind_title; + if (status_str.isEmpty()) { + wind_title = SCWind::default_wind_title(); + } else { + wind_title = QStringLiteral("%1 | %2") + .arg(SCWind::default_wind_title(), status_str); + } + wind->setWindowTitle(wind_title); + }); } // initialize cvt pool model { @@ -931,4 +944,73 @@ void SCWind::set_lang(::SCL_language lang) noexcept { this->ui->retranslateUi(this); this->ui->blm->when_lang_updated(lang); +} + +QString impl_default_title() noexcept { + QString newtitle = + QStringLiteral("SlopeCraft %1").arg(SlopeCraft::SCL_getSCLVersion()); + +#ifdef WIN32 + newtitle += + " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Mifan-T"; // windowsf +#elif defined(_MAC) || defined(__APPLE__) + newtitle += + " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Cubik65536, Mifan-T"; // macOs +#else + newtitle += + " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Mifan-T"; // unknown + // platform +#endif + + return newtitle; +} + +const QString &SCWind::default_wind_title() noexcept { + static const QString title = impl_default_title(); + return title; +} + +QString SCWind::workStatus_to_string(::SCL_workStatues status) noexcept { + switch (status) { + case SlopeCraft::workStatues::none: + break; + case SlopeCraft::workStatues::buidingHeighMap: + return tr("正在构建高度矩阵"); + break; + case SlopeCraft::workStatues::building3D: + return tr("正在构建三维结构"); + break; + case SlopeCraft::workStatues::collectingColors: + return tr("正在收集整张图片的颜色"); + break; + case SlopeCraft::workStatues::compressing: + return tr("正在压缩立体地图画"); + break; + case SlopeCraft::workStatues::constructingBridges: + return tr("正在为立体地图画搭桥"); + break; + case SlopeCraft::workStatues::converting: + return tr("正在匹配颜色"); + break; + case SlopeCraft::workStatues::dithering: + return tr("正在使用抖动仿色"); + break; + case SlopeCraft::workStatues::flippingToWall: + return tr("正在将平板地图画变为墙面地图画"); + break; + case SlopeCraft::workStatues::writing3D: + return tr("正在写入三维结构"); + break; + case SlopeCraft::workStatues::writingBlockPalette: + return tr("正在写入方块列表"); + break; + case SlopeCraft::workStatues::writingMapDataFiles: + return tr("正在写入地图数据文件"); + break; + case SlopeCraft::workStatues::writingMetaInfo: + return tr("正在写入基础信息"); + break; + } + + return {}; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 832dfaa1..0ffe0d5b 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -34,6 +34,10 @@ class SCWind : public QMainWindow { return manager; } + static const QString& default_wind_title() noexcept; + + static QString workStatus_to_string(::SCL_workStatues) noexcept; + const static QString update_url; enum class export_type { diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index 15bca620..73384a19 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -9,6 +9,7 @@ int main(int argc, char** argv) { SCWind wind; wind.show(); + wind.setWindowTitle(SCWind::default_wind_title()); QDir::setCurrent(QCoreApplication::applicationDirPath()); From 0198e7c2de0fdab202c2f91aba794ded8bb38361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 23 May 2023 13:57:18 +0800 Subject: [PATCH 0358/1123] implement test block list --- SlopeCraft/SCWind.h | 3 + SlopeCraft/SCWind_slots.cpp | 106 ++++++++++++++++++ SlopeCraftL/SlopeCraftL.h | 17 ++- SlopeCraftL/TokiSlopeCraft.h | 15 ++- SlopeCraftL/TokiSlopeCraft_build.cpp | 56 ++++----- utilities/BlockListManager/BaseColor.h | 2 + utilities/BlockListManager/BlockListManager.h | 4 + 7 files changed, 170 insertions(+), 33 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 0ffe0d5b..caebee5f 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -89,6 +89,9 @@ class SCWind : public QMainWindow { void on_ac_about_triggered() noexcept; + void on_ac_get_current_colorlist_triggered() noexcept; + void on_ac_test_blocklist_triggered() noexcept; + private: Ui::SCWind* ui; SlopeCraft::Kernel* kernel; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 51c96303..7db15292 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -768,4 +768,110 @@ void SCWind::on_ac_about_triggered() noexcept { info += "\n\n"; info += tr("版权所有 © 2021-2023 SlopeCraft 开发者"); QMessageBox::information(this, tr("关于 SlopeCraft"), info); +} + +void SCWind::on_ac_get_current_colorlist_triggered() noexcept { + if (this->kernel->queryStep() < SCL_step::wait4Image) { + this->kernel_set_type(); + } + constexpr int basecolors_per_row = 4; + constexpr int basecolors_per_col = 16; + + static_assert(basecolors_per_row * basecolors_per_col == 64); + + constexpr int row_pixels = basecolors_per_row * 4; + constexpr int col_pixels = basecolors_per_col * 1; + + static_assert(row_pixels * col_pixels == 256); + static QString prev_dir{""}; + const QString dest_file = + QFileDialog::getSaveFileName(this, tr("保存颜色表"), prev_dir, "*.png"); + + if (dest_file.isEmpty()) { + return; + } + + prev_dir = QFileInfo{dest_file}.dir().path(); + + QImage img(row_pixels, col_pixels, QImage::Format::Format_ARGB32); + + if (img.isNull()) { + QMessageBox::warning(this, tr("保存颜色表失败"), tr("分配内存失败")); + return; + } + + img.fill(0x00FFFFFFU); + + uint32_t *const img_data = reinterpret_cast(img.scanLine(0)); + /* + Eigen::Map< + Eigen::Array> + map(reinterpret_cast(img.scanLine(0)), row_pixels, + col_pixels); +*/ + uint32_t argb_colors[256]; + uint8_t map_colors[256]; + const int available_colors = kernel->getColorCount(); + kernel->getAvailableColors(argb_colors, map_colors); + + for (int cidx = 0; cidx < available_colors; cidx++) { + /* + const int basecolor = (map_colors[cidx] / 4); + const int shade = (map_colors[cidx] % 4); + const int pixel_row = basecolor / basecolors_per_col; + const int pixel_col = (basecolor % basecolors_per_col) * 4 + shade; + */ + img_data[map_colors[cidx]] = argb_colors[cidx]; + // map(map_colors[cidx]) = argb_colors[cidx]; + } + + if (!img.save(dest_file)) { + QMessageBox::warning(this, tr("保存颜色表失败"), + tr("无法生成文件 %1").arg(dest_file)); + } +} + +void SCWind::on_ac_test_blocklist_triggered() noexcept { + if (this->kernel->queryStep() < SCL_step::wait4Image) { + this->kernel_set_type(); + } + + static QString prev_dir; + QString filename = + QFileDialog::getSaveFileName(this, tr("保存测试文件"), prev_dir, "*.nbt"); + if (filename.isEmpty()) { + return; + } + prev_dir = QFileInfo{filename}.dir().path(); + + std::vector blks; + std::vector basecolors; + for (uint8_t basecolor = 0; basecolor <= SlopeCraft::SCL_maxBaseColor(); + basecolor++) { + const auto bcwp = this->ui->blm->basecolorwidget_at(basecolor); + for (const auto &bwp : bcwp->block_widgets()) { + blks.emplace_back(bwp->attachted_block()); + basecolors.emplace_back(basecolor); + } + } + + assert(blks.size() == basecolors.size()); + + std::string err; + err.resize(4096); + SlopeCraft::StringDeliver sd{err.data(), err.size()}; + + SlopeCraft::Kernel::test_blocklist_options opt; + opt.block_count = blks.size(); + opt.block_ptrs = blks.data(); + opt.basecolors = basecolors.data(); + opt.err = &sd; + + if (!this->kernel->makeTests(filename.toLocal8Bit().data(), opt)) { + QString qerr = QString::fromUtf8(err.data()); + QMessageBox::warning(this, tr("输出测试文件失败"), + tr("保存测试文件 %1 时出现错误。详细信息:\n%2") + .arg(filename) + .arg(qerr)); + } } \ No newline at end of file diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 3a426f5b..8bda02bf 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -205,8 +205,8 @@ class Kernel { uint8_t *const map_color_dest = nullptr, int *const num = nullptr) const = 0; /// make a structure that includes all accessible blocks - virtual bool makeTests(const AbstractBlock **, const uint8_t *, const char *, - char *) = 0; + [[deprecated]] virtual bool makeTests(const AbstractBlock **, const uint8_t *, + const char *, char *) = 0; // can do in convertionReady: /// convert original image to map @@ -347,7 +347,7 @@ class Kernel { const WE_schem_options &option) const noexcept = 0; struct flag_diagram_options { - uint64_t lib_version{SC_VERSION_U64}; + uint64_t version{SC_VERSION_U64}; // 0 or negative number means no split lines int32_t split_line_row_margin{0}; @@ -360,6 +360,17 @@ class Kernel { virtual bool exportAsFlatDiagram( const char *filename_local, const flag_diagram_options &option) const noexcept = 0; + + struct test_blocklist_options { + uint64_t version{SC_VERSION_U64}; + const AbstractBlock *const *block_ptrs{nullptr}; + const uint8_t *basecolors{nullptr}; + size_t block_count{0}; + StringDeliver *err{nullptr}; + }; + virtual bool makeTests( + const char *filename, + const test_blocklist_options &option) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index c8609ea0..37004ab2 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -128,8 +128,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void decreaseStep(step) override; bool makeTests(const AbstractBlock **, const unsigned char *, const char *, char *) override; - std::string makeTests(const AbstractBlock **, const uint8_t *, - const std::string &); void setAiCvterOpt(const AiCvterOpt *) override; const AiCvterOpt *aiCvterOpt() const override; @@ -391,6 +389,19 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { return this->load_build_cache(option); } + bool makeTests(const char *filename, + const test_blocklist_options &option) const noexcept override { + std::string err = this->impl_make_tests(filename, option); + if (option.err != nullptr) { + write(*option.err, err); + } + return err.empty(); + } + + std::string impl_make_tests( + std::string_view filename, + const test_blocklist_options &option) const noexcept; + private: // determined by mcver, map type and allowed colorest static std::vector type_hash() noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 7aff2c32..a30bee8d 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -20,7 +20,7 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ #include - +#include #include "TokiSlopeCraft.h" bool TokiSlopeCraft::makeTests(const AbstractBlock **src, @@ -35,20 +35,29 @@ bool TokiSlopeCraft::makeTests(const AbstractBlock **src, return false; } + size_t blk_count{0}; + for (;; blk_count++) { + if (src[blk_count] == nullptr) { + break; + } + } + test_blocklist_options opt; + opt.block_ptrs = src; + opt.basecolors = baseColor; + opt.block_count = blk_count; + std::string err = this->impl_make_tests(dst, opt); - std::string s = makeTests(src, baseColor, std::string(dst)); - if (_unFileName != nullptr) std::strcpy(_unFileName, s.data()); + if (_unFileName != nullptr) std::strcpy(_unFileName, err.data()); - return s.empty(); + return err.empty(); } -std::string TokiSlopeCraft::makeTests(const AbstractBlock **src, - const uint8_t *src_baseColor, - const std::string &fileName) { - if (!fileName.ends_with(".nbt")) { +std::string TokiSlopeCraft::impl_make_tests( + std::string_view filename, + const test_blocklist_options &option) const noexcept { + if (!filename.ends_with(".nbt")) { return "File name should ends with \".nbt\""; } - libSchem::Schem test; test.set_MC_major_version_number(::TokiSlopeCraft::mcVer); test.set_MC_version_number( @@ -58,24 +67,18 @@ std::string TokiSlopeCraft::makeTests(const AbstractBlock **src, std::vector realBaseColor; realSrc.clear(); realBaseColor.clear(); - for (uint32_t idx = 0; src[idx] != nullptr; idx++) { - if (src[idx]->getVersion() > (int)mcVer) { + for (size_t idx = 0; idx < option.block_count; idx++) { + if (option.block_ptrs[idx]->getVersion() > (int)mcVer) { continue; } - realSrc.emplace_back(static_cast(src[idx])); - realBaseColor.emplace_back(src_baseColor[idx]); + realSrc.emplace_back( + static_cast(option.block_ptrs[idx])); + realBaseColor.emplace_back(option.basecolors[idx]); } std::vector> blocks; blocks.resize(64); - for (auto &it : blocks) { - while (!it.empty()) { - it.clear(); - // it.reserve(16); - } - } - for (uint32_t idx = 0; idx < realSrc.size(); idx++) { blocks[realBaseColor[idx]].push_back(idx); } @@ -85,11 +88,7 @@ std::string TokiSlopeCraft::makeTests(const AbstractBlock **src, ids.reserve(realSrc.size() + 1); ids.emplace_back("minecraft:air"); for (auto i : realSrc) { - if (TokiSlopeCraft::mcVer == SCL_gameVersion::MC12) { - ids.emplace_back(i->getIdOld()); - } else { - ids.emplace_back(i->getId()); - } + ids.emplace_back(i->idForVersion(TokiSlopeCraft::mcVer)); } test.set_block_id(ids.data(), ids.size()); @@ -115,11 +114,12 @@ std::string TokiSlopeCraft::makeTests(const AbstractBlock **src, SCL_errorFlag err; std::string detail; - const bool success = test.export_structure(fileName, true, &err, &detail); + const bool success = test.export_structure(filename, true, &err, &detail); if (!success) { - return std::string("Failed to export structure file ") + fileName + - ", error code = " + std::to_string(int(err)) + ", detail: " + detail; + return fmt::format( + "Failed to export structure file {}, error code = {}, detail: {}", + filename, int(err), detail); } else { return {}; } diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index d91d5500..6d4cd35b 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -53,6 +53,8 @@ class BaseColorWidget : public QGroupBox { inline auto& block_widgets() noexcept { return this->blocks; } + inline const auto& block_widgets() const noexcept { return this->blocks; } + void select_by_callback(const select_callback_t& fun); signals: diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 51904c1f..0b535c88 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -78,6 +78,10 @@ class BlockListManager : public QWidget { blockListPreset to_preset() const noexcept; + const BaseColorWidget *basecolorwidget_at(size_t basecolor) const noexcept { + return this->basecolors[basecolor]; + } + signals: void changed(); From 66cd3476d9c5dd552fa84400a25b6cb1d82750c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 25 May 2023 12:17:48 +0800 Subject: [PATCH 0359/1123] add brew update to macos-build --- .github/workflows/build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b04143ad..522a71fa 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -19,6 +19,8 @@ jobs: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} steps: + - name: brew update + run: brew update - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE From d28a4912d2c9b00314aea17b17cbd5b4cc7f8b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 25 May 2023 13:27:23 +0800 Subject: [PATCH 0360/1123] add transparent strategy wind --- SlopeCraft/CMakeLists.txt | 7 +- SlopeCraft/TransparentStrategyWind.cpp | 59 +++++++ SlopeCraft/TransparentStrategyWind.h | 35 ++++ SlopeCraft/TransparentStrategyWind.ui | 223 +++++++++++++++++++++++++ 4 files changed, 322 insertions(+), 2 deletions(-) create mode 100644 SlopeCraft/TransparentStrategyWind.cpp create mode 100644 SlopeCraft/TransparentStrategyWind.h create mode 100644 SlopeCraft/TransparentStrategyWind.ui diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 2c4b010c..4946958a 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -25,7 +25,8 @@ set(SlopeCraft_headers PreviewWind.h ExportTableModel.h AiCvterParameterDialog.h - CopyableTableView.h) + CopyableTableView.h + TransparentStrategyWind.h) set(SlopeCraft_sources SCWind.cpp @@ -37,6 +38,7 @@ set(SlopeCraft_sources ExportTableModel.cpp AiCvterParameterDialog.cpp CopyableTableView.cpp + TransparentStrategyWind.cpp main.cpp ${SlopeCraft_rc_files}) @@ -44,7 +46,8 @@ set(SlopeCraft_sources set(SlopeCraft_uis SCWind.ui PreviewWind.ui - AiCvterParameterDialog.ui) + AiCvterParameterDialog.ui + TransparentStrategyWind.ui) set(SlopeCraft_ts_files others/SlopeCraft_en_US.ts diff --git a/SlopeCraft/TransparentStrategyWind.cpp b/SlopeCraft/TransparentStrategyWind.cpp new file mode 100644 index 00000000..1fe257d6 --- /dev/null +++ b/SlopeCraft/TransparentStrategyWind.cpp @@ -0,0 +1,59 @@ +#include "TransparentStrategyWind.h" +#include "ui_TransparentStrategyWind.h" + +TransparentStrategyWind::TransparentStrategyWind(QWidget* parent) + : QDialog{parent}, ui{new Ui::TransparentStrategyWind} { + this->ui->setupUi(this); + + QPalette pl; + pl.setColor(QPalette::ColorRole::Text, Qt::black); + pl.setColor(QPalette::ColorRole::Window, QColor(Qt::GlobalColor::white)); + + this->ui->lb_show_custom_color->setPalette(pl); +} + +TransparentStrategyWind::~TransparentStrategyWind() { delete this->ui; } + +SCL_PureTpPixelSt TransparentStrategyWind::pure_strategy() const noexcept { + if (this->ui->cb_pure_air->isChecked()) { + return SCL_PureTpPixelSt::ReserveAsAir; + } + return SCL_PureTpPixelSt::ReplaceWithBackGround; +} + +SCL_HalfTpPixelSt TransparentStrategyWind::half_strategy() const noexcept { + if (this->ui->cb_half_background->isChecked()) { + return SCL_HalfTpPixelSt::ReplaceWithBackGround; + } + if (this->ui->cb_half_compose->isChecked()) { + return SCL_HalfTpPixelSt::ComposeWithBackGround; + } + return SCL_HalfTpPixelSt::IgnoreAlpha; +} + +uint32_t TransparentStrategyWind::background_color() const noexcept { + auto pl = this->ui->lb_show_custom_color->palette(); + auto color = pl.color(QPalette::ColorRole::Window).toRgb(); + + return qRgb(color.red(), color.green(), color.blue()); +} + +TransparentStrategyWind::strategy TransparentStrategyWind::current_strategy() + const noexcept { + return {this->pure_strategy(), this->half_strategy(), + this->background_color()}; +} + +std::optional +TransparentStrategyWind::ask_for_strategy(QWidget* parent) noexcept { + TransparentStrategyWind tpswind{parent}; + + const auto dialog_code = tpswind.exec(); + + if (dialog_code == QDialog::DialogCode::Rejected) { + return std::nullopt; + } + + const auto ret = tpswind.current_strategy(); + return ret; +} \ No newline at end of file diff --git a/SlopeCraft/TransparentStrategyWind.h b/SlopeCraft/TransparentStrategyWind.h new file mode 100644 index 00000000..9c6ca602 --- /dev/null +++ b/SlopeCraft/TransparentStrategyWind.h @@ -0,0 +1,35 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_TRANSPARENCYSTRATEGYWIND_H +#define SLOPECRAFT_SLOPECRAFT_TRANSPARENCYSTRATEGYWIND_H +#include +#include +#include + +class TransparentStrategyWind; +namespace Ui { +class TransparentStrategyWind; +} + +class TransparentStrategyWind : public QDialog { + Q_OBJECT + private: + Ui::TransparentStrategyWind *const ui; + + public: + explicit TransparentStrategyWind(QWidget *parent = nullptr); + ~TransparentStrategyWind(); + + struct strategy { + SCL_PureTpPixelSt pure_transparent; + SCL_HalfTpPixelSt half_transparent; + uint32_t background_color; + }; + + SCL_PureTpPixelSt pure_strategy() const noexcept; + SCL_HalfTpPixelSt half_strategy() const noexcept; + uint32_t background_color() const noexcept; + + strategy current_strategy() const noexcept; + + static std::optional ask_for_strategy(QWidget *parent) noexcept; +}; +#endif // SLOPECRAFT_SLOPECRAFT_TRANSPARENCYSTRATEGYWIND_H \ No newline at end of file diff --git a/SlopeCraft/TransparentStrategyWind.ui b/SlopeCraft/TransparentStrategyWind.ui new file mode 100644 index 00000000..d84a6e3c --- /dev/null +++ b/SlopeCraft/TransparentStrategyWind.ui @@ -0,0 +1,223 @@ + + + TransparentStrategyWind + + + + 0 + 0 + 480 + 320 + + + + 透明像素处理策略 + + + true + + + + + + 背景色 + + + + + + 高级灰(#DCDCDC) + + + true + + + + + + + + 20 + 20 + + + + + 20 + 16777215 + + + + background-color: rgb(255, 255, 255); + + + QFrame::StyledPanel + + + + + + + + + + 自定义 + + + + + + + QFrame::StyledPanel + + + + + + + + + + background-color: rgb(220, 220, 220); + + + QFrame::StyledPanel + + + + + + + + + + 纯白(#FFFFFF) + + + + + + + + + + + 0 + 0 + + + + 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 +”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 +”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 +完成设置后,需重新导入图片。 + + + true + + + 4 + + + + + + + 纯透明像素 + + + + + + 替换为空气 + + + + + + + 替换为背景色 + + + true + + + + + + + + + + 半透明像素 + + + + + + 保留颜色 + + + + + + + 与背景色叠加 + + + true + + + + + + + 替换为背景色 + + + + + + + + + + 12 + + + 6 + + + 6 + + + 0 + + + + + 确定 + + + + + + + 取消 + + + + + + + 恢复默认设定 + + + + + + + + + + From 042246e8296bdb278e794d659f50deaf677c98f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 25 May 2023 13:53:05 +0800 Subject: [PATCH 0361/1123] let user input tps --- SlopeCraft/SCWind_slots.cpp | 21 ++++++++++ SlopeCraft/TransparentStrategyWind.cpp | 14 +++++++ SlopeCraft/TransparentStrategyWind.h | 3 ++ SlopeCraftL/SlopeCraftL.h | 3 ++ SlopeCraftL/imagePreprocess.cpp | 53 ++++++++++++++++---------- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 7db15292..1d351373 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -8,6 +8,7 @@ #include "PreviewWind.h" #include "AiCvterParameterDialog.h" #include "VersionDialog.h" +#include "TransparentStrategyWind.h" void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 @@ -21,6 +22,8 @@ void SCWind::on_pb_add_image_clicked() noexcept { return; } + std::optional strategy_opt{std::nullopt}; + QString err; for (const auto &filename : files) { auto task = cvt_task::load(filename, err); @@ -41,6 +44,24 @@ void SCWind::on_pb_add_image_clicked() noexcept { } } + // have transparent pixels + if (SlopeCraft::SCL_haveTransparentPixel( + (const uint32_t *)task.original_image.scanLine(0), + task.original_image.sizeInBytes() / sizeof(uint32_t))) { + if (!strategy_opt.has_value()) { + strategy_opt = TransparentStrategyWind::ask_for_strategy(this); + } + + if (!strategy_opt.has_value()) { + continue; + } + const auto &st = strategy_opt.value(); + SlopeCraft::SCL_preprocessImage( + (uint32_t *)task.original_image.scanLine(0), + task.original_image.sizeInBytes() / sizeof(uint32_t), + st.pure_transparent, st.half_transparent, st.background_color); + } + this->tasks.emplace_back(task); } diff --git a/SlopeCraft/TransparentStrategyWind.cpp b/SlopeCraft/TransparentStrategyWind.cpp index 1fe257d6..212f6294 100644 --- a/SlopeCraft/TransparentStrategyWind.cpp +++ b/SlopeCraft/TransparentStrategyWind.cpp @@ -32,6 +32,12 @@ SCL_HalfTpPixelSt TransparentStrategyWind::half_strategy() const noexcept { } uint32_t TransparentStrategyWind::background_color() const noexcept { + if (this->ui->cb_background_white->isChecked()) { + return 0xFFFFFFFF; + } + if (this->ui->cb_background_gray->isChecked()) { + return 0xFFDCDCDC; + } auto pl = this->ui->lb_show_custom_color->palette(); auto color = pl.color(QPalette::ColorRole::Window).toRgb(); @@ -44,6 +50,14 @@ TransparentStrategyWind::strategy TransparentStrategyWind::current_strategy() this->background_color()}; } +void TransparentStrategyWind::on_pb_confirm_clicked() noexcept { + emit this->accept(); +} + +void TransparentStrategyWind::on_pb_cancel_clicked() noexcept { + emit this->reject(); +} + std::optional TransparentStrategyWind::ask_for_strategy(QWidget* parent) noexcept { TransparentStrategyWind tpswind{parent}; diff --git a/SlopeCraft/TransparentStrategyWind.h b/SlopeCraft/TransparentStrategyWind.h index 9c6ca602..6803bbb2 100644 --- a/SlopeCraft/TransparentStrategyWind.h +++ b/SlopeCraft/TransparentStrategyWind.h @@ -13,6 +13,9 @@ class TransparentStrategyWind : public QDialog { Q_OBJECT private: Ui::TransparentStrategyWind *const ui; + private slots: + void on_pb_confirm_clicked() noexcept; + void on_pb_cancel_clicked() noexcept; public: explicit TransparentStrategyWind(QWidget *parent = nullptr); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 8bda02bf..2debeaec 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -419,6 +419,9 @@ SCL_EXPORT void SCL_preprocessImage( const SCL_HalfTpPixelSt = SCL_HalfTpPixelSt::ComposeWithBackGround, uint32_t backGround = 0xFFFFFFFF); +SCL_EXPORT bool SCL_haveTransparentPixel(const uint32_t *ARGB32, + const uint64_t imageSize); + SCL_EXPORT uint8_t SCL_maxAvailableVersion(); SCL_EXPORT const char *SCL_getSCLVersion(); diff --git a/SlopeCraftL/imagePreprocess.cpp b/SlopeCraftL/imagePreprocess.cpp index 329e9764..56504fd7 100644 --- a/SlopeCraftL/imagePreprocess.cpp +++ b/SlopeCraftL/imagePreprocess.cpp @@ -48,40 +48,51 @@ void SCL_EXPORT SCL_preprocessImage(ARGB *data, const uint64_t imageSize, ARGB backGround) { backGround |= 0xFF000000; - if (data == nullptr) - return; - if (imageSize <= 0) - return; + if (data == nullptr) return; + if (imageSize <= 0) return; for (uint64_t i = 0; i < imageSize; i++) { - if (getA(data[i]) == 0) { // pure transparent + if (getA(data[i]) == 0) { // pure transparent switch (pSt) { - case SCL_PureTpPixelSt::ReplaceWithBackGround: - data[i] = backGround; - break; - default: - break; + case SCL_PureTpPixelSt::ReplaceWithBackGround: + data[i] = backGround; + break; + default: + break; } } - if (getA(data[i]) < 255) { // half transparent + if (getA(data[i]) < 255) { // half transparent switch (hSt) { - case SCL_HalfTpPixelSt::ReplaceWithBackGround: - data[i] = backGround; - break; - case SCL_HalfTpPixelSt::ComposeWithBackGround: - data[i] = composeColor(data[i], backGround); - break; - default: - data[i] |= 0xFF000000; - break; + case SCL_HalfTpPixelSt::ReplaceWithBackGround: + data[i] = backGround; + break; + case SCL_HalfTpPixelSt::ComposeWithBackGround: + data[i] = composeColor(data[i], backGround); + break; + default: + data[i] |= 0xFF000000; + break; } } } } +SCL_EXPORT bool SCL_haveTransparentPixel(const uint32_t *ARGB32, + const uint64_t imageSize) { + for (uint64_t i = 0; i < imageSize; i++) { + const uint32_t argb = ARGB32[i]; + + if (getA(argb) != 255) { + return true; + } + } + + return false; +} + unsigned char SCL_EXPORT SCL_maxAvailableVersion() { return 19; } #ifndef SCL_CAPI -} // namespace SlopeCraft +} // namespace SlopeCraft #endif From c237f3ae907aef945c9bc5afaf957ad9c5853a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 25 May 2023 14:07:23 +0800 Subject: [PATCH 0362/1123] implement custom background color for tpswind --- SlopeCraft/TransparentStrategyWind.cpp | 15 ++++++++++++++- SlopeCraft/TransparentStrategyWind.h | 2 ++ SlopeCraft/TransparentStrategyWind.ui | 9 ++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/SlopeCraft/TransparentStrategyWind.cpp b/SlopeCraft/TransparentStrategyWind.cpp index 212f6294..6a1e6d06 100644 --- a/SlopeCraft/TransparentStrategyWind.cpp +++ b/SlopeCraft/TransparentStrategyWind.cpp @@ -1,12 +1,12 @@ #include "TransparentStrategyWind.h" #include "ui_TransparentStrategyWind.h" +#include TransparentStrategyWind::TransparentStrategyWind(QWidget* parent) : QDialog{parent}, ui{new Ui::TransparentStrategyWind} { this->ui->setupUi(this); QPalette pl; - pl.setColor(QPalette::ColorRole::Text, Qt::black); pl.setColor(QPalette::ColorRole::Window, QColor(Qt::GlobalColor::white)); this->ui->lb_show_custom_color->setPalette(pl); @@ -58,6 +58,19 @@ void TransparentStrategyWind::on_pb_cancel_clicked() noexcept { emit this->reject(); } +void TransparentStrategyWind::on_cb_background_custom_clicked() noexcept { + auto color = + QColorDialog::getColor(Qt::GlobalColor::white, this, tr("设置背景色")); + if (!color.isValid()) { + this->ui->cb_background_gray->setChecked(true); + } + + QPalette pl; + pl.setColor(QPalette::ColorRole::Window, color); + + this->ui->lb_show_custom_color->setPalette(pl); +} + std::optional TransparentStrategyWind::ask_for_strategy(QWidget* parent) noexcept { TransparentStrategyWind tpswind{parent}; diff --git a/SlopeCraft/TransparentStrategyWind.h b/SlopeCraft/TransparentStrategyWind.h index 6803bbb2..eb57d057 100644 --- a/SlopeCraft/TransparentStrategyWind.h +++ b/SlopeCraft/TransparentStrategyWind.h @@ -17,6 +17,8 @@ class TransparentStrategyWind : public QDialog { void on_pb_confirm_clicked() noexcept; void on_pb_cancel_clicked() noexcept; + void on_cb_background_custom_clicked() noexcept; + public: explicit TransparentStrategyWind(QWidget *parent = nullptr); ~TransparentStrategyWind(); diff --git a/SlopeCraft/TransparentStrategyWind.ui b/SlopeCraft/TransparentStrategyWind.ui index d84a6e3c..7086145b 100644 --- a/SlopeCraft/TransparentStrategyWind.ui +++ b/SlopeCraft/TransparentStrategyWind.ui @@ -51,7 +51,7 @@ background-color: rgb(255, 255, 255); - QFrame::StyledPanel + QFrame::Box @@ -67,8 +67,11 @@ + + true + - QFrame::StyledPanel + QFrame::Box @@ -81,7 +84,7 @@ background-color: rgb(220, 220, 220); - QFrame::StyledPanel + QFrame::Box From 04169b30fada11c452d18a9b35fc6a4b9d0b9107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 25 May 2023 14:10:36 +0800 Subject: [PATCH 0363/1123] implement reset for tpswind --- SlopeCraft/TransparentStrategyWind.cpp | 15 +++++++++++---- SlopeCraft/TransparentStrategyWind.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/SlopeCraft/TransparentStrategyWind.cpp b/SlopeCraft/TransparentStrategyWind.cpp index 6a1e6d06..3a1b9aad 100644 --- a/SlopeCraft/TransparentStrategyWind.cpp +++ b/SlopeCraft/TransparentStrategyWind.cpp @@ -6,10 +6,7 @@ TransparentStrategyWind::TransparentStrategyWind(QWidget* parent) : QDialog{parent}, ui{new Ui::TransparentStrategyWind} { this->ui->setupUi(this); - QPalette pl; - pl.setColor(QPalette::ColorRole::Window, QColor(Qt::GlobalColor::white)); - - this->ui->lb_show_custom_color->setPalette(pl); + this->on_pb_reset_clicked(); } TransparentStrategyWind::~TransparentStrategyWind() { delete this->ui; } @@ -71,6 +68,16 @@ void TransparentStrategyWind::on_cb_background_custom_clicked() noexcept { this->ui->lb_show_custom_color->setPalette(pl); } +void TransparentStrategyWind::on_pb_reset_clicked() noexcept { + this->ui->cb_pure_background->setChecked(true); + this->ui->cb_half_compose->setChecked(true); + this->ui->cb_background_gray->setChecked(true); + QPalette pl; + pl.setColor(QPalette::ColorRole::Window, QColor(Qt::GlobalColor::white)); + + this->ui->lb_show_custom_color->setPalette(pl); +} + std::optional TransparentStrategyWind::ask_for_strategy(QWidget* parent) noexcept { TransparentStrategyWind tpswind{parent}; diff --git a/SlopeCraft/TransparentStrategyWind.h b/SlopeCraft/TransparentStrategyWind.h index eb57d057..51d4e5e0 100644 --- a/SlopeCraft/TransparentStrategyWind.h +++ b/SlopeCraft/TransparentStrategyWind.h @@ -19,6 +19,8 @@ class TransparentStrategyWind : public QDialog { void on_cb_background_custom_clicked() noexcept; + void on_pb_reset_clicked() noexcept; + public: explicit TransparentStrategyWind(QWidget *parent = nullptr); ~TransparentStrategyWind(); From f8b8b4c4d8b641f5518eea329e1e01ea0bf4a94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:14:09 +0800 Subject: [PATCH 0364/1123] fix lupdate and update translations --- CMakeLists.txt | 3 +- MapViewer/CMakeLists.txt | 3 +- MapViewer/MapViewer_en_US.ts | 157 +- SlopeCraft/CMakeLists.txt | 4 +- SlopeCraft/others/SlopeCraft_en_US.ts | 2289 +++++------------ VisualCraft/CMakeLists.txt | 3 +- VisualCraft/others/VisualCraft_en_US.ts | 1059 +------- imageCutter/CMakeLists.txt | 3 +- imageCutter/imageCutter_en_US.ts | 164 +- utilities/BlockListManager/CMakeLists.txt | 3 +- .../others/BlockListManager_en_US.ts | 15 +- 11 files changed, 754 insertions(+), 2949 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7551c8d8..7a27871d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,7 +140,8 @@ if(${WIN32}) endif() # # Language related variables -set(SC_lupdate_flags -no-ui-lines) +# set(SC_lupdate_flags -no-ui-lines) +set(SC_lupdate_flags) if(${SlopeCraft_update_ts_no_obsolete}) list(APPEND SC_lupdate_flags "-no-obsolete") diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index 90db3ce0..a4509c20 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -42,7 +42,8 @@ set(MapViewer_project_sources ${MapViewer_header_files} ${MapViewer_source_files} MapViewerWind.ui - ${MapViewer_ts_files} + + # ${MapViewer_ts_files} ${MapViewer_windows_rc_files} ) diff --git a/MapViewer/MapViewer_en_US.ts b/MapViewer/MapViewer_en_US.ts index 1ab79f9c..bfbee63a 100644 --- a/MapViewer/MapViewer_en_US.ts +++ b/MapViewer/MapViewer_en_US.ts @@ -4,261 +4,146 @@ MapViewerWind - - + + 加载地图 Load maps - - + 清除 Clear - - + 列数: Cols: - - + 行数: Rows: - - + 矩阵存储序 Storage order - - + 列优先 Col-major - - + 行优先 Row-major - - + 请选择地图文件 Please select files - - + 查看图像 Browse map - - + 放大倍数: Scale: - - + 显示网格 Show grid - - + 显示像素信息 Show pixel infos - - + 仅颜色 Color-only - - + 地图色 Map color - - + 基色 Base color - - + 阴影 Shade - - + 保存当前图片 Save - - + 组合图像 Compose maps - - + 保存为图片 Save - - + 显示空隙 Show grid - - - - - - - - - - - - 地图数: Map count: - - - - - - - - - - - - There is/are - - - - - - - - - - - - 个像素点出现未知的基色,它们使用了Mojang未定义的基色。这可能是因为软件版本较旧而游戏版本太新,或者地图文件损坏。 其行、列坐标分别为: pixel(s) which have unknown base color, they are using basecolors out of Mojang's defination. This may be caused by damaged map data file, or the software version is too old. - - - - - - - - - - - - 地图中有Mojang未定义基色 Undefined basecolor in map data files (undefined by Mojang) - - - - - - - - - - - - 选择地图数据文件 Select map data files - - - - - - - - - - - - 加载地图文件失败 Failed to load map data file(s) - - - - - - - - - - - - 出错的文件: Map data file: - - - - - - - - - - - - 错误信息: diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 4946958a..7ca1f2fe 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -57,7 +57,9 @@ set(SlopeCraft_project_files ${SlopeCraft_headers} ${SlopeCraft_sources} ${SlopeCraft_uis} - ${SlopeCraft_ts_files}) + + # ${SlopeCraft_ts_files} +) qt_add_executable(SlopeCraft MANUAL_FINALIZATION diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index b10e8457..4ad4e552 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -4,43 +4,36 @@ AiCvterParameterDialog - - + Ai转化器参数 Set AiConverter parameters - 允许提前收敛 - Enable fail times + Enable fail times - - + 最大提前收敛代数: Max fail times : - - + 交叉概率: Crossover prob : - - + 种群数量: Population size : - - + 最大进化代数: Max generation : - - + 变异概率: Mutation prob : @@ -48,176 +41,106 @@ BatchUi - SlopeCraft批量操作 - SlopeCraft batch operation + SlopeCraft batch operation - 开始执行 - Start + Start - 导出格式 - Export format + Export format - Litematica投影文件 - Litematica + Litematica - 原版结构方块文件 - Vanilla structure + Vanilla structure - 地图文件 - Map data files + Map data files - 地图文件输出位置 - Map data files directory + Map data files directory - 浏览 - Browse + Browse - 选择输出文件夹 - Select a directory + Select a directory - 目标文件夹不可用 - Invalid directory + Invalid directory - 主窗体中选择了纯文件地图画,冲突 - Confilction : you assigned file-only maps in main window + Confilction : you assigned file-only maps in main window - 就绪 - Ready + Ready - 批量处理中: - Batch operation working ...... + Batch operation working ...... - 正在转化为地图画 - Converting image to map + Converting image to map - 正在构建三维结构 - Building 3D structure + Building 3D structure - 正在导出三维结构 - Exporting 3D structure + Exporting 3D structure - 正在导出地图文件 - Exporting map data files + Exporting map data files - 批量处理完成 - All tasks finished + All tasks finished ExportTableModel - - - - - - - - 原图文件名 Image file - - - - - - - - 图像大小 Image size - - - - - - - - - 地图大小 Map size - - - - - - - - - 地图序号范围 Map index range - - - - - - - - - 第一个地图文件名 First map - - - - - - - - - 最后一个地图文件名 Last map @@ -226,1173 +149,881 @@ MainWindow - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">地图画</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">Map Arts</span></p></body></html> - - - 开始 - Start + Start - - - - 导入图片 - Import image + Import image - - - 地图画类型 - Type of map + Type of map - - 方块列表 - Block List + Block List - - - 调整颜色 - Convert to Map + Convert to Map - - 导出为 - Export + Export - - 投影文件 - Litematic + Litematic - - 地图文件 - Map data files + Map data files - - 结构文件 - Structure + Structure - - - 完成 - Finish + Finish - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">联系作者</span></p></body></html> - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">Contact Us</span></p></body></html> + <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">Contact Us</span></p></body></html> - - 反馈Bug - Report bugs + Report bugs - 创建平板地图画 - Create Flat Map + Create Flat Map - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">传统的地图画样式</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Traditional 2D map pixel art</span></p></body></html> + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Traditional 2D map pixel art</span></p></body></html> - 创建立体地图画 - Create 3D Map + Create 3D Map - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">原版生存的最高画质</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Best quality in vanilla survival</span></p></body></html> + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Best quality in vanilla survival</span></p></body></html> - 创建纯文件地图画 - Create File-only Map + Create File-only Map - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Highest quality, but requires to edit saves.</span></p></body></html> + <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Highest quality, but requires to edit saves.</span></p></body></html> - 设置 - Settings + Settings - - - 下一步 - Next + Next - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - <html><head/><body><p>Step 1,click the load Image button, choose the image you want to make into map.</p><p>The size of image should be multiple of 128 pixels.</p><p></p><p></p><p>Provided that you want to build it, don't choose a large image. 128×128 is enough.</p></body></html> + <html><head/><body><p>Step 1,click the load Image button, choose the image you want to make into map.</p><p>The size of image should be multiple of 128 pixels.</p><p></p><p></p><p>Provided that you want to build it, don't choose a large image. 128×128 is enough.</p></body></html> - <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> - <html><head/><body><p align="justify">Step 2</p><p align="justify">Set the type and gameversion of your map.</p><p align="justify">3D means 3D map paintings built in survival.</p><p align="justify">Flat is like a floor which is easiest to build.</p><p align="justify">File-only Maps has most colors but can't be built.</p></body></html> + <html><head/><body><p align="justify">Step 2</p><p align="justify">Set the type and gameversion of your map.</p><p align="justify">3D means 3D map paintings built in survival.</p><p align="justify">Flat is like a floor which is easiest to build.</p><p align="justify">File-only Maps has most colors but can't be built.</p></body></html> - 游戏版本 - Game Version + Game Version - - 1.18 - - - - - 1.19 - - - - 立体地图画 - 3D Map + 3D Map - 平板地图画 - Flat Map + Flat Map - 纯文件地图画 - File-only Map + File-only Map - 预设方块列表 - Presets + Presets - <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> - <html><head/><body><p align="justify">Step 3</p><p align="justify">Select a block for each colors. </p><p align="justify">Here we have 4 presets above, You can also set your custom block list in the scroll area.</p></body></html> + <html><head/><body><p align="justify">Step 3</p><p align="justify">Select a block for each colors. </p><p align="justify">Here we have 4 presets above, You can also set your custom block list in the scroll area.</p></body></html> - 优先混凝土 - Use Concrete + Use Concrete - 优先羊毛 - Use Wool + Use Wool - 优先染色玻璃 - Use Glass + Use Glass - 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 调整颜色可能会比较慢,下面的进度条指示了进度。 - Step 4, Convert image to map. Your map should only consist of map colors. + Step 4, Convert image to map. Your map should only consist of map colors. 6 Algorithms correspond to different method to adjust pixel colors, you can try each. If "Dithering" is turned on,SlopeCraft will try to fit image better through mixing similar colors. It might be laggy, the progressbar shows the progress. - 导出为 地图文件 - Export + Export map files - 显示原图 - Show image + Show image - 显示地图画 - Show Map + Show Map - 转换为地图画 - Convert to map + Convert to map - 算法 - Algothrims + Algothrims - 抖动仿色 - Dithering + Dithering - 无损压缩 - Lossless Compress + Lossless Compress - 最大允许高度: - Max height: + Max height: - 智能有损压缩 - Intelligent Lossy Compress + Intelligent Lossy Compress - 投影名称 - Litematic name + Litematic name - 总方块数 - Total count + Total count - 压缩高度 - Compressing + Compressing - 防火 - Fire Proof + Fire Proof - 层 - layers + layers - 搭桥间隔: - Construct interval: + Construct interval: - 投影尺寸 - Size + Size - 允许搭桥 - Construct Glass Bridge + Construct Glass Bridge - 防末影人 - Enderman Proof + Enderman Proof - 投影区域名称 - Region name + Region name - 其他选项 - Others + Others - 搭桥 - Glass Bridge + Glass Bridge - <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> - <html><head/><body><p align="justify"> + <html><head/><body><p align="justify"> The last step is to make your map into a litematic file, to make it easier to be built.</p><p align="justify">3 blanks on the left side are some properties of your litematic file. </p><p align="justify">If you turn on "Compress height(lossless)", SlopeCraft will try to compress the height of 3d map according to rule of maps, in order to prevent it from surpassing 256(not always effective on all kinds of images).</p><p align="justify">Two bars below exhibit some information of your map. </p><p align="justify">This process might be quite slow, see the progress bar.</p></body></html> - - 结束 - Finish + Finish - - 导出 - Export + Export - 预览 - Preview + Preview - 平面示意图 - Flat diagram + Flat diagram - 透明度相关设置 - About transparency + About transparency - 适合创造 - Suitable for creative mod + Suitable for creative mod - 适合生存早期 - Suitable for survival mod(undeveloped) - - - - 适合生存后期 - + Suitable for survival mod(undeveloped) - 适合光影 - Suitable for shaders + Suitable for shaders - 自定义 - Custom + Custom - RGB欧式距离 - RGB Euclidean Distance + RGB Euclidean Distance - 更好的RGB色差公式 - A better RGB color difference formula + A better RGB color difference formula - 不是简单的欧式距离 - Not simple Euclidean distance + Not simple Euclidean distance - Lab1994公式 - The Lab1994 color difference formula + The Lab1994 color difference formula - Lab2000公式 - The Lab2000 color difference formula + The Lab2000 color difference formula - XYZ欧式距离 - XYZ Euclidean Distance + XYZ Euclidean Distance - 遗传算法 - Genetic algorithm + Genetic algorithm - GACvter - GACvter + GACvter - 用分辨率换颜色 - Trade colors with resolution + Trade colors with resolution - 方便建造,耗费玻璃 - Easy to build but cost many glass blocks + Easy to build but cost many glass blocks - 降低总高度,破坏连续性 - Lower the total height and break the continousness + Lower the total height and break the continousness - 用玻璃包围防火方块 - Cover burnable blocks with glass + Cover burnable blocks with glass - 用玻璃包围可偷方块 - Cover stealable blocks with glasses + Cover stealable blocks with glasses - 降低总高度,微调颜色 - Lower the total height and modify colors slightly + Lower the total height and modify colors slightly - 节省大量存储空间 - Save disk space greatly + Save disk space greatly - 用结构空位代替 - Replace with structure void + Replace with structure void - 空气处理方式 - Air processing method + Air processing method - 原理图名称 - Name of schematic + Name of schematic - 依赖mod名称 - Dependent mods + Dependent mods - 导出平面示意图 - Export flat diagram + Export flat diagram - 导出三维结构 - Export 3D + Export 3D - - - GACvter参数 - GACvter parameters + GACvter parameters - 构建三维结构 - Build 3D + Build 3D - - WE原理图 - WE Schem + WE Schem - 保存当前图片 - Save current Image + Save current Image - 导出为 原版结构文件 - Export + Export Vanilla structure - 导出为 WorldEdit原理图 - Export + Export WE Schem - 导出为 Litematica投影 - Export + Export Litematic - <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> - <html><head/><body><p align="justify">The last step is to generate map data files.</p><p align="justify">The name of map data files is like<span style=" font-weight:700;"> map_3.dat</span>, it's used to storage content of maps. In it's file name, 3 refers to the sequence number of map data files. Sequence number starts with 0.</p><p align="justify">Located in<span style=" font-weight:700;"> data</span> folder in your saves, map data files can only be manipulated with enough authority. If you are neither single-player nor op in a server, you should export it as litematic instead of map data files.</p><p align="justify">Each map can only show a 128×128 frame, a large image results to multiple map data files. Thus, a continuous series of sequence numbers will be occupied.</p><p align="justify">For ex, run <span style=" font-weight:700;">/give @s filled_map{map:3}</span> will give you the map of <span style=" font-weight:700;">map_3.dat </span><p align="justify">1.12Command: /give @p filled_map 1 3</p><span style=" font-style:italic;">.</span></p><p align="justify">This is suitable for large images, but not for servers.</p></body></html> + <html><head/><body><p align="justify">The last step is to generate map data files.</p><p align="justify">The name of map data files is like<span style=" font-weight:700;"> map_3.dat</span>, it's used to storage content of maps. In it's file name, 3 refers to the sequence number of map data files. Sequence number starts with 0.</p><p align="justify">Located in<span style=" font-weight:700;"> data</span> folder in your saves, map data files can only be manipulated with enough authority. If you are neither single-player nor op in a server, you should export it as litematic instead of map data files.</p><p align="justify">Each map can only show a 128×128 frame, a large image results to multiple map data files. Thus, a continuous series of sequence numbers will be occupied.</p><p align="justify">For ex, run <span style=" font-weight:700;">/give @s filled_map{map:3}</span> will give you the map of <span style=" font-weight:700;">map_3.dat </span><p align="justify">1.12Command: /give @p filled_map 1 3</p><span style=" font-style:italic;">.</span></p><p align="justify">This is suitable for large images, but not for servers.</p></body></html> - 导出的文件名 - Map data files + Map data files - 地图文件起始序号 - Beginning + Beginning sequence number - 地图画行数 - Map rows + Map rows - 地图画列数 - Map cols + Map cols - 地图文件数量 - Map counts + Map counts - 查看导出的文件 - See exported file + See exported file - - 联系作者 - Contact with me + Contact with me - 退出 - Exit + Exit - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021 TokiNoBug</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">Your map is finished!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">About SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">You are currently using the 3rd generation of SlopeCraft, based on Qt, Eigen and zlib. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono) made great effort to the designing and optimization, and also developed a brand-new interface based on SlopeCraft's kernel. Besides, Cubik65536 and 67au made contribution to the adaption on MacOS and Linux platforms respectively.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Contact with me:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft on github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">My homepage on GitHub</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">This program is released under license GPL-3.0 or later.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> + <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">Your map is finished!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">About SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">You are currently using the 3rd generation of SlopeCraft, based on Qt, Eigen and zlib. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono) made great effort to the designing and optimization, and also developed a brand-new interface based on SlopeCraft's kernel. Besides, Cubik65536 and 67au made contribution to the adaption on MacOS and Linux platforms respectively.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Contact with me:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft on github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">My homepage on GitHub</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">This program is released under license GPL-3.0 or later.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - 关于 - About + About - 地图画 - Map + Map - 高级 - Advanced + Advanced - 批量操作 - Batch operation + Batch operation - 方块列表预设 - Blocklist preset + Blocklist preset - - - - - - - 转到页面 - Goto this page + Goto this page - - - - 导出为投影文件 - Export as litematic + Export as litematic - - 导出为mcfunction - Export as mcfunction + Export as mcfunction - - 导出为地图文件 - Export as map files + Export as map files - 关于SlopeCraft - About SlopeCraft + About SlopeCraft - 测试方块列表 - Test block list + Test block list - 设置导出参数 - Set exporting parameters + Set exporting parameters - - 保存预设 - Save preset + Save preset - 加载预设 - Load preset + Load preset - 输出当前颜色表 - Export current colorset + Export current colorset - 使用教程 - Tutorial + Tutorial - - - - 检查更新 - Check updates + Check updates - 设置地图画类型 - Set map type + Set map type - 设置方块列表 - Set BlockList + Set BlockList - 选择图片 - Select Image + Select Image - 打开图片失败 - Failed to read image + Failed to read image - SlopeCraft 无法加载必需方块列表 - SlopeCraft failed to load fixed block list + SlopeCraft failed to load fixed block list - SlopeCraft 必须退出 - SlopeCraft must exit + SlopeCraft must exit - SlopeCraft 无法加载可选方块列表 - SlopeCraft failed to load custom block list + SlopeCraft failed to load custom block list - 此错误可以忽略 - This error can be ignored + This error can be ignored - 加载默认预设失败 - Failed to load default presets + Failed to load default presets - 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 - One or more internal presets failed to be parsed. SlopeCraft may have been damaged, please reinstall it. + One or more internal presets failed to be parsed. SlopeCraft may have been damaged, please reinstall it. Detail information: %1 - 要不试试换一张图片吧! - Why not try another one? + Why not try another one? - 图片尺寸: - Image size: + Image size: - 像素 - Pixels + Pixels - 图片中存在透明/半透明像素,已处理,您可以点击“设置”重新选择处理透明/半透明像素的方式。 重新设置处理方式后,需要重新导入一次。 - There's transparent pixels in your image, SlopeCraft has processed it. You can click "Settings" to reset the strategy of processing transparent pixels. + There's transparent pixels in your image, SlopeCraft has processed it. You can click "Settings" to reset the strategy of processing transparent pixels. After you reset the strategy, load the image again. - 导出为投影/结构方块文件 - Export as litematic or structure + Export as litematic or structure - 投影文件导出失败 - Failed to export as litematic. + Failed to export as litematic. - 这可能是汉字编码错误造成的。请检查路径中是否有汉字 - There might be sth wrong with characters' encoding, check if the filepath includes non-English characters. + There might be sth wrong with characters' encoding, check if the filepath includes non-English characters. - 错误信息: - Error details : + Error details : - 你输入的起始序号不可用 - Invalid sequence number. + Invalid sequence number. - 请选择导出的文件夹 - Please select a folder for exporting. + Please select a folder for exporting. - 你选择的文件夹不存在! - Folder dosen't exist! + Folder dosen't exist! - 请稍等 - Please wait + Please wait - 具体信息: - Detail: + Detail: - 未知游戏版本 - Unknown game version + Unknown game version - - - - 导出原理图失败 - Failed to export. + Failed to export. - 方块种类超出上限。 - The types of blocks overflow. + The types of blocks overflow. - 错误的文件扩展名 - Invalid file extension name + Invalid file extension name - 三维结构中存在错误的方块 - Wrong block in 3D structure. + Wrong block in 3D structure. - 无法创建/打开文件 - Failed to create/open file + Failed to create/open file - 导出原版结构方块文件失败 - Failed to export vanilla structure file. + Failed to export vanilla structure file. - 导出时指定不使用结构空位表示空气,但方块列表中不包含空气。 - When exporting as structure, you assigned not to replace air with structure void, but there is no air in the block palette. + When exporting as structure, you assigned not to replace air with structure void, but there is no air in the block palette. - 转化原图为地图画时出错 - Error occurred when converting image to map + Error occurred when converting image to map - 原图为空!你可能没有导入原图! - Your source image is empty! You might have forgot to import source image! + Your source image is empty! You might have forgot to import source image! - 构建高度矩阵时出现错误 - Error occurred when making height martix + Error occurred when making height martix - 原版地图画不允许出现第三个阴影(不存在的几何关系不可能生存实装!) 请检查你的地图画类型,纯文件地图画不可以导出为投影! - The third shadow shouldn't apper in vanilla map! + The third shadow shouldn't apper in vanilla map! Check your map type, remember that file-only map can't be exported as litematic! - 跳步操作 - You skipped a step + You skipped a step - 有损压缩失败 - Inteligent lossy compression failed + Inteligent lossy compression failed - 最大允许高度太小了 - The maxmium allowed height is too low + The maxmium allowed height is too low - 允许使用的颜色过少 - Too few colors allowed! + Too few colors allowed! - 你应该勾选启用尽可能多的基色,颜色太少是不行的! - You should enable as much base colors as possible. + You should enable as much base colors as possible. - - 这可能是因为路径中含有中文字符! - This might because of non-English characters in filename of path. + This might because of non-English characters in filename of path. - 删除临时文件失败 - Failed to remove temporary file + Failed to remove temporary file - 在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 这可能是因为地图画行数过大。 尝试启用无损压缩,或者提高最大允许高度 - Lossy compression failed to compress the maximun height down to max allowed hehight when computing height map. This may be caused by a too large image. Try enabling lossless compression, or enlarge max allowed height. + Lossy compression failed to compress the maximun height down to max allowed hehight when computing height map. This may be caused by a too large image. Try enabling lossless compression, or enlarge max allowed height. - 导出为 mcfunction - Export as mcfunction + Export as mcfunction - 图片 (*.png *.bmp *.jpg *.tif *.GIF ) - Image (*.png *.bmp *.jpg *.tif *.GIF ) + Image (*.png *.bmp *.jpg *.tif *.GIF ) - 投影文件 (*.litematic) - Litematic file (*.litematic) + Litematic file (*.litematic) - 结构方块文件 (*.nbt) - Structure file(*.nbt) + Structure file(*.nbt) - WorldEdit 原理图 (*.schem) - WorldEdit schematic (*.schem) + WorldEdit schematic (*.schem) - (xz 坐标=-65±128×整数) - (xz coordinate = -65±128×<any integer>) + (xz coordinate = -65±128×<any integer>) - 你输入的起始序号不可用,请输入大于等于 0 的整数! - The initial sequence number is invalid, expected non-negative number! + The initial sequence number is invalid, expected non-negative number! - 请输入大于等于 0 的整数! - Please input a non negative number! + Please input a non negative number! - 你可以选择存档中的 data 文件夹 - You can select the "data" dir in the saves of MC. + You can select the "data" dir in the saves of MC. - 导出时将会覆盖部分地图文件 - Some files will be replaced + Some files will be replaced - %1 个文件将被覆盖: %2 点击"Yes"将继续并覆盖这些文件,点击"No"将撤销本次操作。 - %1 file(s) will be replaced: + %1 file(s) will be replaced: %2 Click "Yes" to continue and replace these files, or click "No" to cancel this operation. - 导出 WorldEdit 原理图失败 - Failed to export WorldEdit schem + Failed to export WorldEdit schem - 不支持导出 1.12 WorldEdit 原理图(.schematic 格式),仅支持.schem 格式 - Exporting as WE schematic is not supported in MC 12(*.schematic), only *.schem is supported + Exporting as WE schematic is not supported in MC 12(*.schematic), only *.schem is supported - SlopeCraft 不允许你跳步操作,请按照左侧竖边栏的顺序操作! - Skipping any step is not allowed by SlopeCraft + Skipping any step is not allowed by SlopeCraft - 有损压缩的最大允许不要低于 14,否则很容易压缩失败 - The maximum height of lossy compression should not be less than 14 + The maximum height of lossy compression should not be less than 14 - 导出时 Gzip 压缩文件失败 - Failed to compress a exported file + Failed to compress a exported file - 正在构建高度矩阵 - Making height matrix + Making height matrix - 正在构建三维结构 - Building 3D structure + Building 3D structure - 正在收集整张图片的颜色 - Collecting colors of the whole image + Collecting colors of the whole image - 正在压缩立体地图画 - Compressing 3D map pixel arts + Compressing 3D map pixel arts - 正在为立体地图画搭桥 - Constructing glass bridge + Constructing glass bridge - 正在匹配颜色 - Matching colors + Matching colors - 正在使用抖动仿色 - Dithering + Dithering - 正在将平板地图画变为墙面地图画 - Converting flat map art to wall map art + Converting flat map art to wall map art - 正在写入三维结构 - Writing 3D structure + Writing 3D structure - 正在写入方块列表 - Writing block palette + Writing block palette - 正在写入地图数据文件 - Writing map data + Writing map data - 正在写入基础信息 - Writing meta data + Writing meta data - 可用 - + - 种颜色 - colors available. + colors available. - 保存截屏 - Save screenshot + Save screenshot - 图片 (*.jpg *.jpeg *.tif *.bmp *.png) - Image (*.jpg *.jpeg *.tif *.bmp *.png) + Image (*.jpg *.jpeg *.tif *.bmp *.png) - 保存当前显示图片 - Save current image + Save current image - 图片 (*.png) - Image (*.png) + Image (*.png) - 保存预设文件失败 - Failed to save preset file + Failed to save preset file - 无法创建文件"%1" - Failed to create file "%1" + Failed to create file "%1" - 选择预设文件 - Select a preset file + Select a preset file - 加载预设失败 - Failed to load preset + Failed to load preset - 测试方块列表的结构文件 - Svae structure file for blocklist testing + Svae structure file for blocklist testing - 测试方块列表失败 - Failed to test the block list. + Failed to test the block list. - 具体信息: - Detailed information: + Detailed information: - 保存颜色表 - Save palette + Save palette - 保存颜色表失败 - Failed to save colormap image + Failed to save colormap image - 分配内存失败 - Failed to allocate memory for image + Failed to allocate memory for image MaterialModel - - - - - - - - - %1 盒 + %2 组 + %3 个 %1 shulker box(es) + %2 stack(s) + %3 - - - - - - - - - %1 组 + %2 个 %1 stack(s) + %2 - - - - - - - - - %1 个 %1 @@ -1401,15 +1032,6 @@ Click "Yes" to continue and replace these files, or click "No&quo PoolModel - - - - - - - - - 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. @@ -1418,140 +1040,87 @@ Click "Yes" to continue and replace these files, or click "No&quo PreviewWind - 预览投影文件 - Preview Schematic + Preview Schematic - 材料表 - Material List + Material List - - 方块 - Blocks + Blocks - 投影尺寸 - Size + Size - - 数量 - Count + Count - 总方块数 - Total count + Total count - 总体积 - Volume + Volume - 切换单位 - Switch Unit + Switch Unit - 预览地图画 - Preview map + Preview map - 如果使用了有损压缩,上一步生成的地图画可能会被轻微的修改 - The converted image might be slightly modified if lossy compression is enabled. + The converted image might be slightly modified if lossy compression is enabled. - - + 查看材料列表 Material List - - + 按组显示 Display by stacks - - + 不排序 Do not sort - - + 升序 Acsending - - + 降序 Decsending - - - - - - - - - %1 -- 表格内容已复制到剪贴板 %1 -- Table content copied to clipboart - - - - - - - - - 大小:%1 × %2 × %3 Size: %1 × %2 × %3 - - - - - - - - - 体积:%1 Volume: %1 - - - - - - - - - 方块总数:%1 Block count: %1 @@ -1560,44 +1129,23 @@ Click "Yes" to continue and replace these files, or click "No&quo QObject - 个 - block(s) + block(s) - 盒 - SB + SB - 组 - stacks + stacks - - - - - - - - - 加载图片 %1 失败。 Failed to load image %1. - - - - - - - - - 绘制图标时发现错误 An error occurred when drawing icon @@ -1606,630 +1154,459 @@ Click "Yes" to continue and replace these files, or click "No&quo SCWind - - + 地图画配置 Map configurations - - + 方块列表预设 Blocklist preset - - + 加载预设 Load preset - - - + + 保存当前预设 Save as preset - - + 可用方块数量: Available block count: - - - Vanilla - - - - - - Cheap - - - - - - Elegant - - - - - - Shiny - - - - - - Custom - - - - - + 游戏版本 Game Version - - + 地图画类型 Map type - - + 立体地图画 3D Map - - + 平板地图画 Flat Map - - + 纯文件地图画 File-only Map - - + 优先彩色玻璃 Use stained glass - - + 优先混凝土 Use Concrete - - + 优先羊毛 Use Wool - - + 优先木板 Use planks - - + 优先原木 Use logs - - + 导入图像并转化 Load image and convert - - + 原图 Original image - - + 转化后 Converted image - - + 删除 Delete - - + + 项目池 Task pool - - + 添加 Add - - - IconMode - - - - - + 转化算法 Convert algorithm - - + 抖动 Dithering - - - Lab00 - - - - - - Lab94 - - - - - - RGB+ - - - - - - RGB - - - - - - XYZ - - - - - GACvter - GACvter + GACvter - - + 转化当前图像 Convert current image - - - - + + + 保存转化后图像 Save converted image - - + 全部转化 Convert all - - + + 导出 Export - - + Litematica - - + + 结构方块文件 Vanilla structure - - + 显示缩略图 - - + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - - + 地图文件 Map data files - - + 其他选项 Others - - + 防火 Fire Proof - - + 防末影人 Enderman Proof - - + 连接蘑菇块 Connect mushroom blocks - - + 压缩高度 Compress - - + 有损压缩 Lossy Compression - - + 无损压缩 Lossless Compress - - + 最大允许高度: Max height: - - + 搭桥 Glass Bridge - - + 允许搭桥 Construct Glass Bridge - - + layer(s) - - + 搭桥间隔: Glass bridge interval: - - + 投影区域名称 Region name - - + 投影名称 Litematic name - - + 用结构空位替代空气 Replace air with structure void - - + offset - - + WEOffset - - + + + + + + 0 - - + 原理图名称 Name of schematic - - + 依赖 mod 名称 Depend mods - - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - - + 垂直分割线 Vertical split line - - + 水平分割线 Horizontal split line - - + 大小与方块数量 Size and block count - - - + + 大小: Size: - - - + + 方块数量: Block count: - - + 全部导出 Export all - - + 预览 Preview - - + 预览材料表 Material list - - + 预览压缩效果 Compress effect - - + 预构建三维结构 Construct 3d structure - - + 地图画起始序号: Map beginning index: - - + 语言 Language - - + 高级 Advanced - - + 缓存 Cache - - + 关于 About - - + 联系作者 Contact with me - - + 帮助 Help - - + GA转化器参数 GACvter parameters - - + open_cache_dir - - + 打开缓存文件夹 Open cache directory - - + 清除缓存 Clean caches - - - 简体中文 - - - - - - English - - - - - - + + 关于 SlopeCraft About SlopeCraft - - + 反馈 bug Report bugs - - + 检查更新 Check updates - - + 测试方块列表 Test block list - - + 输出当前颜色表 Export current colorset - - + 查看 SlopeCraft 文档 Documentation - - + 使用教程 Tutorial - - + 常见问题 FAQ - - - - - - - - - - + 加载默认预设失败 Failed to load default presets - - - - - - - - - - + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -2238,320 +1615,113 @@ Detail information: %1 - - - - - - - - - - + 设置方块列表失败 Failed to setup blocklist - - - - - - - - - - + 您设置的方块列表可能存在错误 There may be errors in your blocklist - - - - - - - - - - + 可用颜色数量:%1 Avaliable colors: %1 - - - - - - - - - - + 应用预设失败 Failed to apply preset - - - - - - - - - - + 转化图像失败 Failed to convert image - - - - - - - - - - - - - - - - - - - - + + 缓存失败 Failed to save cache - - - - - - - - - - - - - - - - - - - - + + 未能创建缓存文件,错误信息: %1 Failed to create cache directory, error info: %1 - - - - - - - - - - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - - - - - - - - - - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - - - - - - - - - - + 保存图像失败 Failed to save image - - - - - - - - - - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - - - - - - - - - - + 构建三维结构失败 Failed to build 3d structure - - - - - - - - - - + 构建三维结构时,出现错误。可能是因为尝试跳步。 An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. - - - - - - - - - - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - - - - - - - - - - + 方块数量:%1 Block count: %1 - - - - - - - - - - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - - - - - - - - - - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - - - - - - - - - - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - - - - - - - - - - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - - - - - - - - - - + SlopeCraft 出现错误 An error occurred to SlopeCraft - - - - - - - - - - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -2560,538 +1730,178 @@ Detail information: Click Ok to ignore, and click Close to exit SlopeCraft. - - - - - - - - - - + 选择图片 Select Image - - - - - - - - - - + 打开图像失败 Failed to open image - - - - - - - - - - + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. Detailed information: %2 - - - - - - - - - - + 选择预设文件 Select a preset file - - - - - - - - - - + 解析预设文件失败 Failed to parse thes preset file - - - - - - - - - - + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 - - - - - - - - - - + 保存预设文件失败 Failed to save preset file - - - - - - - - - - + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + 未选择图像 No image selected - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 请在左侧任务池选择一个图像 Please select a image in the left - - - - - - - - - - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - - - - - - - - - - + 将要覆盖已存在的图像 Existing file(s) will be replaced - - - - - - - - - - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 该图像尚未被转化 The image is not converted - - - - - - - - - - - - - - - - - - - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - - - - - - - - - - + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - - - - - - - - - - + 尚未构建三维结构 3d structure not built - - - - - - - - - - + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - - - - - - - - - - + 导出设置有错 Error in export options - - - - - - - - - - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - - - - - - - - - - + 你点错按钮了 Wrong button - - - - - - - - - - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - - - - - - - - - - + 无可导出的任务 Nothing to export - - - - - - - - - - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - - - - - - - - - - + 选择导出位置 Select export directory - - - - - - - - - - + 将要覆盖已经存在的文件 Existing files will be replaced - - - - - - - - - - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - - - - - - - - - - + 导出失败 Failed to export - - - - - - - - - - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - - - - - - - - - - + 设置导出位置 Set export directory - - - - - - - - - - + %1 个文件将被替换 %1 files will be replaced - - - - - - - - - - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -3100,256 +1910,315 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - - - - - - - - - - + 删除缓存失败 Failed to clean cache - - - - - - - - - - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - - - - + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. - - - - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - - - - + 版权所有 © 2021-2023 SlopeCraft 开发者 Copyright © 2021-2023 SlopeCraft deveploers - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - - - TaskBox - - Form - + + 保存颜色表 + Save palette - - 浏览 - Browse + + + 保存颜色表失败 + Failed to save colormap image - - 投影/结构文件名 - Schematic name + + 分配内存失败 + Failed to allocate memory for image - - × - + + 无法生成文件 %1 + Failed to generate %1 - - ~ - + + 保存测试文件 + Save testing file - - 占用的地图序号: - Map sequence number : + + 输出测试文件失败 + Failed to save testing file - - FileName - + + 保存测试文件 %1 时出现错误。详细信息: +%2 + An error occured when saving test file %1. Details: +%2 + + + + TaskBox + + 浏览 + Browse + + + 投影/结构文件名 + Schematic name + + + 占用的地图序号: + Map sequence number : - 选择图片 - Select Image + Select Image - 图片(*.png *.bmp *.jpg *.tif *.GIF ) - Images(*.png *.bmp *.jpg *.tif *.GIF ) + Images(*.png *.bmp *.jpg *.tif *.GIF ) - 图片格式损坏 - Damaged image + Damaged image - tpStrategyWind + TransparentStrategyWind - + 透明像素处理策略 Transparent pixels processing strategy - + + 背景色 + Background color + + + + 高级灰(#DCDCDC) + Silver gray(#DCDCDC) + + + + 自定义 + Custom + + + + 纯白(#FFFFFF) + Pure white(#FFFFFF) + + + + 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 +”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 +”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 +完成设置后,需重新导入图片。 + Transparency is hardly supported in map paintings. 3d maps and flat maps cannot implement transparent pixels. Although transparent pixels do exist in file-only maps, they just let the background of map/item go through. Thus it's necessary to deal with full/semi trasnparent pixels. +"Replace with background" replace pixels with background color, while "Replace with air" with air. +"Compose with backgroundcolor" compose pixel's color with background color accroding to alpha value, and "Reserve color" simply ignore the alpha value, using its RGB directly. +You should load the image again after you confirmed these settings. + + + + 纯透明像素 + Full transparent + + + + 替换为空气 + Replace with air + + + + + 替换为背景色 + Replace with background + + + + 半透明像素 + Semi-transparent + + + + 保留颜色 + Reserve color + + + + 与背景色叠加 + Compose with backgroundcolor + + + 确定 OK - + 取消 Cancel - + 恢复默认设定 Restore to default - + + 设置背景色 + Set background color + + + + tpStrategyWind + + 透明像素处理策略 + Transparent pixels processing strategy + + + 确定 + OK + + + 取消 + Cancel + + + 恢复默认设定 + Restore to default + + 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 ”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 ”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 完成设置后,需重新导入图片。 - Transparency is hardly supported in map paintings. 3d maps and flat maps cannot implement transparent pixels. Although transparent pixels do exist in file-only maps, they just let the background of map/item go through. Thus it's necessary to deal with full/semi trasnparent pixels. + Transparency is hardly supported in map paintings. 3d maps and flat maps cannot implement transparent pixels. Although transparent pixels do exist in file-only maps, they just let the background of map/item go through. Thus it's necessary to deal with full/semi trasnparent pixels. "Replace with background" replace pixels with background color, while "Replace with air" with air. "Compose with backgroundcolor" compose pixel's color with background color accroding to alpha value, and "Reserve color" simply ignore the alpha value, using its RGB directly. You should load the image again after you confirmed these settings. - 纯透明像素 - Full transparent + Full transparent - 替换为空气 - Replace with air + Replace with air - - 替换为背景色 - Replace with background + Replace with background - 背景色 - Background color + Background color - 高级灰(#DCDCDC) - Silver gray(#DCDCDC) + Silver gray(#DCDCDC) - 自定义 - Custom + Custom - 纯白(#FFFFFF) - Pure white(#FFFFFF) + Pure white(#FFFFFF) - 半透明像素 - Semi-transparent + Semi-transparent - 保留颜色 - Reserve color + Reserve color - 与背景色叠加 - Compose with backgroundcolor + Compose with backgroundcolor diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index 613aa68d..daa8dc8b 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -73,7 +73,8 @@ set(VisualCraft_project_sources ${VisualCraft_header_files} ${VisualCraft_source_files} ${VisualCraft_ui_files} - ${VisualCraft_ts_files} + + # ${VisualCraft_ts_files} ${VisualCraft_win_files} ) diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index b98411f0..a7269473 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -4,57 +4,46 @@ BiomeBrowser - - + 查看生物群系 Browse biomes - - + 选择生物群系 Select a biome - - + 颜色代码 Color in hex - - + 放大倍率: Scale: - - + 显示颜色坐标 Show coordinate - - + 选择颜色表 Select a colormap - - + 温度: Temperature: - - + 降水: Downfall: - - - 当前颜色: Current color: @@ -63,20 +52,17 @@ BlockBrowser - - + 浏览方块 Block Browser - - + 可用方块 Avaliable blocks - - + 在“可用方块”页,可以浏览所有可用方块在每一个面的投影图像。在“所有方块”页,可以浏览任何方块(包括当前版本不可用的方块)的所有属性。 在“可用方块”页选择了一个方块后,“所有方块”页也会自动选中这个方块。但在”所有方块“页选择的方块不会影响到”可用方块“页,因为选中的方块不一定能在当前版本使用,不一定能计算出投影图像。 @@ -85,105 +71,86 @@ If you select a block in "Avaliable blocks" page, the other page will switch to this block automatically. But any selection on "All blocks" will not affect "Avaliable blocks", since your selected block may not be avaliable in current version, so the projection image is probably not able to be computed. - - + 保存当前图片 Save current image - - + 选择视角 Select direction - - + 放大倍率: Scale: - - + + + 方块id Block id - - + + 选择方块 Select block - - + 所有方块 All blocks - - + MC版本 MC version - - + 是否可用 Is avaliable - - + 英文名 Block name in English - - + 属性 Attribute - - + Value - - + 中文名 Block name in Chinese - - + 方块类别: Block class: - - - 致命逻辑错误 Impossible error - - - 保存图片失败 Failed to save image. - - - 不知道怎么回事,反正就是没存上。 I don't know why. @@ -192,27 +159,21 @@ If you select a block in "Avaliable blocks" page, the other page will BlockSelector - - + 自定义准则 Custom criteria - - + 启用匹配的方块 Enabled matched blocks - - + 禁用匹配的方块 Disable matched blocks - - - 匹配到%1个方块 %1 block(s) matched @@ -221,83 +182,57 @@ If you select a block in "Avaliable blocks" page, the other page will ColorBrowser - - + 查看颜色表 Browse colorset - - + 颜色序号 Color id - - + 颜色 Color - - + 色号 Hex - - + 方块图标 Block icons - - - 第%1个方块 block %1 - - - 获取颜色表失败 Failed to retrive colorset - - - 在尝试获取第%1个颜色(color_id = %2)时出现错误。函数VCL_get_basic_color_composition返回值为%3,正常情况下应当返回正数。 An error occurred when trying to get color %1 (color_id = %2). Function VCL_get_basic_color_composition returned %3, but a positive number is expected. - - - - - - 计算投影图像失败 Failed to compute projection image - - - 在尝试获取方块 "%1" 的方块模型时出现错误。 An error occurred when trying to get block model for block "%1" (color_id = %2) - - - 成功获取到方块 "%1" 的方块模型,但计算投影图像失败。 Managed to get a block model for block '%1", but subsequent computation of projection image failed. @@ -306,581 +241,454 @@ If you select a block in "Avaliable blocks" page, the other page will VCWind - - + VisualCraft Pre-release VisualCraft 预览版 - - + 基础属性 Baisc attributes - - + 游戏版本 MC version - - + 最大厚度: Max layers: - - + 资源包 Resource packs - - + + 添加 Add - - + + 删除 Remove - - + 方块id文件(json) Block state list files (json) - - + 像素画方向 Pixel art direction - - + 侧面(侧视) Side - - + 上面(俯视) Up - - + 下面(仰视) Down - - + 树叶透明 Transparent leaves - - + 方块列表 Blocks - - + 全部方块 All blocks - - + 快捷键 Hot keys - - + 全部启用 Select all - - + 全部禁用 Deselect all - - + 高级匹配 Advanced - - + 禁用罕见方块 Disable rare blocks - - + 禁用不可再生 Disable non-reproducible - - + 全部反选 Select reversely blockwise - - + 按类反选 Select reversely classwise - - + 选择图片 Select images - - + 显示原始尺寸 Original size - - + 调色算法 Convertion algorithm - - + 抖动 Dithering - - + 显示原图 Display original - - + 显示转化后图像 Display converted - - + + 导出 Export - - + 图像 Image - - + 大小(行,列) Size (rows, cols) - - + 生成litematica Litematica file - - + 生成结构方块文件 Structure file - - + 生成WE原理图 WE schem file - - + 生成转化后图像 Converted image - - + 生成平面示意图 Flat diagram - - + 进度 Progress - - + 导出类型 Export type - - + litematic投影 Litematica - - + 原版结构方块文件 Vanilla structure - - + WorldEdit原理图 WorldEdit schematic - - + 转化后图像 Converted image - - + 平面示意图 Flat diagram - - + 开始执行 Start - - + 设置导出位置 Set export directory - - + 平面示意图(*.png) Flat diagram(*.png) - - + png压缩级别: png compress level: - - + + 方块 blocks - - + + 间距: margin: - - + 垂直分隔线 Vertical split line - - + 水平分隔线 Horizontal split line - - + png压缩内存级别: png compress memory level: - - + 联系开发者 Contact developer - - + 关于VisualCraft About VisualCraft - - + 反馈bug Report bugs - - + + Github仓库 Github repository - - + bilibili ? bilibili - - + 生成测试投影 Generate testing litematic - - + 查看所有颜色 Browse all colors - - + 查看可用颜色 Browse avaliable colors - - + 检查更新 Check updates - - + 刷新警告信息 Flush warnings - - + 使用教程 Tutorial - - + 原版结构方块文件(*.nbt) Vanilla structure(*.nbt) - - + 用结构空位表示空气 Use structure void as air - - + Litematica投影(*.litematic) Litematica file (*.litematic) - - + 导出选项 Export options - - + 区域名称 Region name - - + 投影名称(非文件名) Schematic name(not file name) - - + WorldEdit原理图(*.schem) (仅1.13+) WorldEdit schematic(*schem) (1.13+ only) - - + 名称(非文件名) Name (not file name) - - + 需要的mod名(一行一个,默认为空) Required mods (one mod in one line) - - + 显卡设置 GPU settings - - + 计算设置 Computation settings - - + CPU线程数: CPU threads: - - + 选择计算设备 Select compute device - - + 测试 Test - - + 查看 Browse - - + 资源 Resources - - + 关于 About - - + 方块 Blocks - - + 加载资源 Load resources - - + 设置可用的方块 Set avaliable blocks - - + 生物群系 Biomes - - - - - - - - - - - - VisualCraftL 动态库版本不匹配 The version of VisualCraftL shared lib mismatch - - - - - - - - - - - - 界面程序编译时使用的 VisualCraftL 版本为%1,而 VisualCraftL 动态库的版本为%2。通常这是因为动态库版本过低。 The version of VisualCraftL at compile-time is %1, while that at runtime is %2. Usually it is because the version of VisualCraftL shared lib is too old. - - - - - - - - - - - - 加载配置文件失败。 Failed to load configuration file. - - - - - - - - - - - - 无法加载配置文件"./vc-config.json"。 %1 @@ -888,337 +696,97 @@ If you select a block in "Avaliable blocks" page, the other page will %1 - - - - - - - - - - - - 原版资源包 Vanilla - - - - - - - - - - - - 选择资源包 Select resource pack - - - - - - - - - - - - 资源包解析失败 Failed to parse resource pack - - - - - - - - - - - - - - - - - - - - - - - - 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. - - - - - - - - - - - - 原版 json Vanilla - - - - - - - - - - - - 选择方块 id json 文件 Select block id json file - - - - - - - - - - - - 方块状态列表 json 解析失败 Failed to parse block state json list - - - - - - - - - - - - 资源包/方块状态列表 json 解析失败 The resource pack or block list json failed to be parsed - - - - - - - - - - - - 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. - - - - - - - - - - - - 设置可用方块失败 Failed to set avaliable blocks - - - - - - - - - - - - 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. - - - - - - - - - - - - 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) - - - - - - - - - - - - 选择图片(可多选) Select images - - - - - - - - - - - - 读取图片失败 Failed to load image. - - - - - - - - - - - - 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. - - - - - - - - - - - - 设置图片失败 Failed to set image - - - - - - - - - - - - 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. - - - - - - - - - - - - 关于 VisualCraft About VisualCraft - - - - - - - - - - - - VisualCraft 是一款全新的 Minecraft 像素画生成器,由 MC 玩家 TokiNoBug 开发,是 SlopeCraft 的子项目。与其他类似的软件不同,VisualCraft 旨在跟进最新的 MC 版本 (1.12~最新版)、支持最多的 MC 特性,提供最强大的功能。 @@ -1228,18 +796,6 @@ If you select a block in "Avaliable blocks" page, the other page will - - - - - - - - - - - - 目前 VisualCraft 能够解析许多第三方资源包,也允许自定义增加加新方块。与传统的思路不同,VisualCraft 以方块模型的方式来解析资源包,尽量贴近 Minecraft 的方式,因此支持各种自定义的方块模型。 @@ -1249,18 +805,6 @@ If you select a block in "Avaliable blocks" page, the other page will - - - - - - - - - - - - 在导出方面,VisualCraft 支持 Litematica mod 的投影 (*.litematic)、WorldEdit 原理图 (*.shem)(仅 1.13+可用)、原版结构方块文件 (*.nbt)、平面示意图 (*.png) 等方式。 @@ -1270,18 +814,6 @@ If you select a block in "Avaliable blocks" page, the other page will - - - - - - - - - - - - VisualCraft 支持用各种透明方块互相叠加,产生更多的颜色。软件最多支持不超过 65534 种颜色,受此限制,像素画的层数不超过3 层。 @@ -1291,239 +823,71 @@ If you select a block in "Avaliable blocks" page, the other page will - - - - - - - - - - - - 由于颜色数量很多,VisualCraft 使用了显卡加速。目前支持的 API 有 OpenCL。现在正在使用的 API 是%1 The great amount of colors makes GPU accleration necessary. Now OpenCL is supported, and %1 is what currently being used. - - - - - - - - - - - - 可用的计算设备(CPU + %1可用的显卡) Avaliable compute devices (CPU + %1-avaliable-GPUs) - - - - - - - - - - - - 无法获取platform信息. 请检查驱动. OpenCL错误码: %1. Failed to get platform information. Please check GPU driver(s). OpenCL error code : %1. - - - - - - - - - - - - 无法获取device信息. 请检查驱动. OpenCL错误码: %1 Failed to get device infomation. Please check the driver(s). OpenCL error code : %1 - - - - - - - - - - - - 设置计算设备失败 Failed to set compute device - - - - - - - - - - - - 创建GPU平台失败,平台序号为%1,设备序号为%2 Failed to create GPU platform, the index of platform is %1 and index of device is %2 - - - - - - - - - - - - 创建GPU设备失败,平台序号为%1,设备序号为%2 Failed to create GPU device, the index of platform is %1 and index of device is %2 - - - - - - - - - - - - 设置GPU设备失败。,平台序号为%1,设备序号为%2 Failed to set GPU device, the index of platform is %1 and index of device is %2 - - - - - - - - - - - - 选择输出位置 Select output directory - - - - - - - - - - - - %1, %2 %1 rows, %2 cols - - - - - - - - - - - - 错误操作 Invalid operation - - - - - - - - - - - - 设置任何一种导出类型的输出位置时,都需要在左侧的combo box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 When you set the output directory for any type of export, you should select the type of export with the combobox in the left. Please select a type first. - - - - - - - - - - - - 平面示意图输入错误 Invalid input for flatdiagram - - - - - - - - - - - - 应输入%1个以";"分隔的文件名,但实际上输入了%2个。 您输入的%2个文件名是: @@ -1533,239 +897,71 @@ The %2 filename(s) you give is: %3 - - - - - - - - - - - - 导出平面示意图失败 Failed to export flat diagram - - - - - - - - - - - - 尝试为原图生成第%1个平面示意图(%2)时出现了错误。 Error occurred when trying to generate the %1-th flat diagram(%2). - - - - - - - - - - - - 致命逻辑错误 Impossible error - - - - - - - - - - - - 导出页码表格中的图片"%1"不能在this->image_cache中找到对应的缓存。请将这个错误反馈给软件开发者。 Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. - - - - - - - - - - - - 保存转化后图像失败 Failed to save the converted image - - - - - - - - - - - - QImage未能生成"%1"。 QImage failed to generate "%1". - - - - - - - - - - - - 构建三维结构失败 Failed to build 3D structure - - - - - - - - - - - - VisualCraftL不能为图像"%1"构建三维结构。 VisualCraft failed to build 3D structure for image "%1". - - - - - - - - - - - - 导出litematica失败 Failed to export as litematic - - - - - - - - - - - - VisualCraftL不能为图像"%1"生成投影文件"%2"。 VisualCraft failed to generate litematic file "%2" for image "%1". - - - - - - - - - - - - 导出原版结构方块文件失败 Failed to export as vanilla structure - - - - - - - - - - - - VisualCraftL不能为图像"%1"生成结构方块文件"%2"。 VisualCraft failed to generate structure file "%2" for image "%1". - - - - - - - - - - - - 导出World Edit原理图失败 Failed to export as WE schematic - - - - - - - - - - - - VisualCraftL不能为图像"%1"生成World Edit原理图"%2"。 VisualCraft failed to generate WE schematic file "%2" for image "%1". @@ -1774,8 +970,7 @@ The %2 filename(s) you give is: VC_block_class - - + 启用 Enable diff --git a/imageCutter/CMakeLists.txt b/imageCutter/CMakeLists.txt index f97c3314..16ede52a 100644 --- a/imageCutter/CMakeLists.txt +++ b/imageCutter/CMakeLists.txt @@ -34,7 +34,8 @@ set(imageCutter_project_sources CutterWind.cpp main.cpp CutterWind.ui - ${imageCutter_ts_files} + + # ${imageCutter_ts_files} ${imageCutter_windows_rc_files} ) diff --git a/imageCutter/imageCutter_en_US.ts b/imageCutter/imageCutter_en_US.ts index 8e758b72..812b1b85 100644 --- a/imageCutter/imageCutter_en_US.ts +++ b/imageCutter/imageCutter_en_US.ts @@ -4,261 +4,123 @@ CutterWind - - + 图片预处理 Preprocess image - - + cols - - + 缩放至: Scale to - - + 图片尺寸(方块): Image size (blocks) : - - + 请加载图片 Please load an image - - + rows - - + 开始 Start - - + 图片变换 Transform - - + 加载图片 Load image - - + 缩放 Scale image - - + 图片分块 Cut image - - + 保存图片 Save image - 不保持比例 IgnoreAspectRatio - - - - - - - - - - - - 保持比例缩小 KeepAspectRatio - - - - - - - - - - - - 保持比例扩张 KeepAspectRatioByExpanding - - - - - - - - - - - - 快速变换 FastTransformation - - - - - - - - - - - - 平滑变换 SmoothTransformation - - - - - - - - - - - - 选择图片 Select image - - - - - - - - - - - - - - - - 图片 (*.png *.bmp *.jpg *.tif) - Images (*.png *.bmp *.jpg *.tif) + Images (*.png *.bmp *.jpg *.tif) - - - - - - - - - - - - 打开图片失败 Failed to load image - - - - - - - - - - - - 图片格式损坏,或者图片过于巨大。 The image might be damaged, or it's too huge. - - - - - - - - - - - - 行 , rows, - - - - - 选择输出文件夹 Select output directory - - - - - - - - 图片(*.png *.bmp *.jpg *.tif) diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 670a939a..a57505bd 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -38,7 +38,8 @@ set(BlockListManager_project_sources ${BlockListManager_header_files} ${BlockListManager_source_files} ${BlockListManager_ui_files} - ${BlockListManager_ts_files} + + # ${BlockListManager_ts_files} ) # include_directories(../SlopeCraftL) diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index c82b5ffd..2f72ecc8 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -4,13 +4,7 @@ BaseColorWidget - - GroupBox - - - - - + 启用 Enable @@ -18,29 +12,24 @@ BlockListManager - 解析方块列表失败 Failed to parse block list - - 加载预设错误 Failed to load preset - 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors - 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a @@ -50,14 +39,12 @@ QObject - 基色 %1 的预设被重复定义。一个基色只能被定义一次。 The preset of base color %1 is defined multiple time. A base color can be defined only once. - 解析预设 json 时发生异常:"%1" Exception occured when parsing preset json: "%1" From 70ee492eb7353f2ad5240b47a1345327a0360ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:21:20 +0800 Subject: [PATCH 0365/1123] try to check libpng on macos --- .github/workflows/build-dev.yml | 14 +++++++++++++- .github/workflows/check-libpng-macos.yml | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/check-libpng-macos.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 522a71fa..bfd97a24 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -5,10 +5,22 @@ on: branches: - main - dev - - update-sc-ui + #- update-sc-ui jobs: + macos-check-libpng: + runs-on: macos-latest + steps: + - name: brew update + run: | + brew update-reset + brew update + - name: install libpng + run: brew install libpng + - name: find png.h + run: find . -name png.h + macos-build: runs-on: macos-latest strategy: diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml new file mode 100644 index 00000000..1a03a0a2 --- /dev/null +++ b/.github/workflows/check-libpng-macos.yml @@ -0,0 +1,18 @@ +name: Build dev version artifacts +on: + pull_request: + push: + branches: + - update-sc-ui + +jobs: + + macos-check-libpng: + runs-on: macos-latest + steps: + - name: brew update + run: brew update + - name: install libpng + run: brew install libpng + - name: find png.h + run: find . -name png.h From 771f9ab748af0dcd1a77986d89cb866b39f0750f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:24:48 +0800 Subject: [PATCH 0366/1123] try to check libpng on macos --- .github/workflows/build-dev.yml | 13 ------------- .github/workflows/check-libpng-macos.yml | 6 ++++-- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index bfd97a24..3bfafb93 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -8,19 +8,6 @@ on: #- update-sc-ui jobs: - - macos-check-libpng: - runs-on: macos-latest - steps: - - name: brew update - run: | - brew update-reset - brew update - - name: install libpng - run: brew install libpng - - name: find png.h - run: find . -name png.h - macos-build: runs-on: macos-latest strategy: diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index 1a03a0a2..921316b2 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -11,8 +11,10 @@ jobs: runs-on: macos-latest steps: - name: brew update - run: brew update + run: | + brew update-reset + brew update - name: install libpng run: brew install libpng - name: find png.h - run: find . -name png.h + run: find / -name png.h -print From d6adccab0393d8046a2554303e43c6a51077ff81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:29:15 +0800 Subject: [PATCH 0367/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index 921316b2..79cec5ae 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -17,4 +17,8 @@ jobs: - name: install libpng run: brew install libpng - name: find png.h - run: find / -name png.h -print + run: find /System/Volumes/Data/usr/local -name png.h -print + - name: cat png.h + run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h + - name: cat png.h with grep + run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h | grep png_write_row From d9e2b4994428fdb75e660e13aa5abfa52b2c789f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:33:08 +0800 Subject: [PATCH 0368/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index 79cec5ae..35c9b74c 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -22,3 +22,10 @@ jobs: run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h - name: cat png.h with grep run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h | grep png_write_row + + - name: Upload png.h and png_conf.h + uses: actions/upload-artifact@v3 + with: + name: libpng headers on macos from brew + path: /System/Volumes/Data/usr/local/Cellar/libpng/* + if-no-files-found: error \ No newline at end of file From 561d4001149c3c4024f708c7c3c997258d691d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:39:24 +0800 Subject: [PATCH 0369/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index 35c9b74c..a5ca556b 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -17,15 +17,15 @@ jobs: - name: install libpng run: brew install libpng - name: find png.h - run: find /System/Volumes/Data/usr/local -name png.h -print + run: find /Library -name png.h -print - name: cat png.h - run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h + run: cat /Library/Frameworks/Mono.framework/Headers/png.h - name: cat png.h with grep - run: cat /System/Volumes/Data/usr/local/Cellar/libpng/1.6.39/include/libpng16/png.h | grep png_write_row + run: cat /Library/Frameworks/Mono.framework/Headers/png.h | grep png_write_row - name: Upload png.h and png_conf.h uses: actions/upload-artifact@v3 with: name: libpng headers on macos from brew - path: /System/Volumes/Data/usr/local/Cellar/libpng/* + path: /Library/Frameworks/Mono.framework/Headers/png.h if-no-files-found: error \ No newline at end of file From bbe0e96e44b565146683c3e9cc9b908fc3ac5225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:40:54 +0800 Subject: [PATCH 0370/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index a5ca556b..fced07aa 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -10,12 +10,6 @@ jobs: macos-check-libpng: runs-on: macos-latest steps: - - name: brew update - run: | - brew update-reset - brew update - - name: install libpng - run: brew install libpng - name: find png.h run: find /Library -name png.h -print - name: cat png.h @@ -27,5 +21,5 @@ jobs: uses: actions/upload-artifact@v3 with: name: libpng headers on macos from brew - path: /Library/Frameworks/Mono.framework/Headers/png.h + path: /Library/Frameworks/Mono.framework/Headers/png* if-no-files-found: error \ No newline at end of file From 73efb51e81e98f44a78d32b081356ed3048a1d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:41:36 +0800 Subject: [PATCH 0371/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index fced07aa..e87e0055 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -10,8 +10,6 @@ jobs: macos-check-libpng: runs-on: macos-latest steps: - - name: find png.h - run: find /Library -name png.h -print - name: cat png.h run: cat /Library/Frameworks/Mono.framework/Headers/png.h - name: cat png.h with grep From a1a7ed0feeee5874e28873bde09e71574d71038a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:45:07 +0800 Subject: [PATCH 0372/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index e87e0055..fce9478d 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -19,5 +19,5 @@ jobs: uses: actions/upload-artifact@v3 with: name: libpng headers on macos from brew - path: /Library/Frameworks/Mono.framework/Headers/png* + path: /Library/Frameworks/Mono.framework/Headers/png.h if-no-files-found: error \ No newline at end of file From e7eac62ba8385eb1836025653d5a801e3eaff606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:48:14 +0800 Subject: [PATCH 0373/1123] try to check libpng on macos --- .github/workflows/check-libpng-macos.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml index fce9478d..60952b72 100644 --- a/.github/workflows/check-libpng-macos.yml +++ b/.github/workflows/check-libpng-macos.yml @@ -15,9 +15,12 @@ jobs: - name: cat png.h with grep run: cat /Library/Frameworks/Mono.framework/Headers/png.h | grep png_write_row + - name: copy png.j + run: cp /Library/Frameworks/Mono.framework/Headers/png.h . + - name: Upload png.h and png_conf.h uses: actions/upload-artifact@v3 with: name: libpng headers on macos from brew - path: /Library/Frameworks/Mono.framework/Headers/png.h + path: ./png.h if-no-files-found: error \ No newline at end of file From 887e58413d402eb1bf6f5214efdb5a8676a7a1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 20:52:03 +0800 Subject: [PATCH 0374/1123] fix macos build --- .github/workflows/build-dev.yml | 2 +- .github/workflows/check-libpng-macos.yml | 26 ------------------------ VisualCraftL/CMakeLists.txt | 2 +- utilities/FlatDiagram/CMakeLists.txt | 2 +- 4 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 .github/workflows/check-libpng-macos.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3bfafb93..b256687f 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -5,7 +5,7 @@ on: branches: - main - dev - #- update-sc-ui + - update-sc-ui jobs: macos-build: diff --git a/.github/workflows/check-libpng-macos.yml b/.github/workflows/check-libpng-macos.yml deleted file mode 100644 index 60952b72..00000000 --- a/.github/workflows/check-libpng-macos.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Build dev version artifacts -on: - pull_request: - push: - branches: - - update-sc-ui - -jobs: - - macos-check-libpng: - runs-on: macos-latest - steps: - - name: cat png.h - run: cat /Library/Frameworks/Mono.framework/Headers/png.h - - name: cat png.h with grep - run: cat /Library/Frameworks/Mono.framework/Headers/png.h | grep png_write_row - - - name: copy png.j - run: cp /Library/Frameworks/Mono.framework/Headers/png.h . - - - name: Upload png.h and png_conf.h - uses: actions/upload-artifact@v3 - with: - name: libpng headers on macos from brew - path: ./png.h - if-no-files-found: error \ No newline at end of file diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 64963f14..344d446e 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -76,7 +76,7 @@ add_library(VisualCraftL_static STATIC ${VCL_source_files}) find_package(ZLIB 1.2.11 REQUIRED) -find_package(PNG 1.4.12 REQUIRED) +find_package(PNG 1.6 REQUIRED) find_package(libzip 1.7.0 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index 61a83fa8..fd68f7a1 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -1,6 +1,6 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) -find_package(PNG REQUIRED) +find_package(PNG 1.6 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) find_package(Eigen3 REQUIRED) From 2ed23b3c864f3a8e243b2148e06b07b85856ee45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 21:09:34 +0800 Subject: [PATCH 0375/1123] fix macos build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index b256687f..f03498b1 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -37,7 +37,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build From b30d0b0d081f558e49efcb2e01d468afbb93876f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 21:34:05 +0800 Subject: [PATCH 0376/1123] fix macos and linux build --- .github/workflows/build-dev.yml | 3 +++ VisualCraftL/CMakeLists.txt | 2 +- utilities/FlatDiagram/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index f03498b1..e5ca57e7 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -77,6 +77,9 @@ jobs: run: | echo $BUILD_TYPE echo $GPU_API + - name: apt update + run: sudo apt update + - name: Make directories run: mkdir build install pack diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 344d446e..ee01516c 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -76,7 +76,7 @@ add_library(VisualCraftL_static STATIC ${VCL_source_files}) find_package(ZLIB 1.2.11 REQUIRED) -find_package(PNG 1.6 REQUIRED) +find_package(PNG 1.6 REQUIRED PATHS ${CMAKE_PREFIX_PATH}) find_package(libzip 1.7.0 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index fd68f7a1..0cbd3d2f 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -1,6 +1,6 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) -find_package(PNG 1.6 REQUIRED) +find_package(PNG 1.6 REQUIRED PATHS ${CMAKE_PREFIX_PATH}) include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) find_package(Eigen3 REQUIRED) From 6acec978b3f875ffa44a318fe677ef15ecbf6b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 21:46:38 +0800 Subject: [PATCH 0377/1123] fix win, macos and linux build --- CMakeLists.txt | 7 +++++++ VisualCraftL/CMakeLists.txt | 1 - utilities/FlatDiagram/CMakeLists.txt | 2 -- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a27871d..82eb88fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,13 @@ if(${WIN32}) include(cmake/install_if_is_shared.cmake) endif() +# Find libpng +if(${APPLE}) + find_package(PNG 1.6 REQUIRED CONFIG PATHS ${CMAKE_PREFIX_PATH} NO_CMAKE_SYSTEM_PATH) +else() + find_package(PNG 1.6 REQUIRED) +endif() + # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index ee01516c..b822ac0e 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -76,7 +76,6 @@ add_library(VisualCraftL_static STATIC ${VCL_source_files}) find_package(ZLIB 1.2.11 REQUIRED) -find_package(PNG 1.6 REQUIRED PATHS ${CMAKE_PREFIX_PATH}) find_package(libzip 1.7.0 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index 0cbd3d2f..2d738e80 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -1,7 +1,5 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) -find_package(PNG 1.6 REQUIRED PATHS ${CMAKE_PREFIX_PATH}) - include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) find_package(Eigen3 REQUIRED) From 97924878aeabfcb87903caed28d7811ca2598042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 22:08:48 +0800 Subject: [PATCH 0378/1123] fix macos build --- CMakeLists.txt | 10 +++++----- cmake/add_compiler_path_to_prefix.cmake | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82eb88fb..00673d26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,17 +64,17 @@ include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -if(${WIN32}) - include(cmake/install_if_is_shared.cmake) -endif() - # Find libpng if(${APPLE}) - find_package(PNG 1.6 REQUIRED CONFIG PATHS ${CMAKE_PREFIX_PATH} NO_CMAKE_SYSTEM_PATH) + find_package(PNG 1.6 REQUIRED NO_CMAKE_SYSTEM_PATH) else() find_package(PNG 1.6 REQUIRED) endif() +if(${WIN32}) + include(cmake/install_if_is_shared.cmake) +endif() + # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) diff --git a/cmake/add_compiler_path_to_prefix.cmake b/cmake/add_compiler_path_to_prefix.cmake index fa8d0c05..17b958e7 100644 --- a/cmake/add_compiler_path_to_prefix.cmake +++ b/cmake/add_compiler_path_to_prefix.cmake @@ -9,9 +9,10 @@ cmake_path(GET temp PARENT_PATH temp) list(FIND CMAKE_PREFIX_PATH temp out_temp) if(${out_temp} LESS 0) - message(STATUS "Added the root directory of compiler to CMAKE_PREFIX_PATH") + message(STATUS "Added the installation prefix of compiler to CMAKE_PREFIX_PATH") list(APPEND CMAKE_PREFIX_PATH ${temp}) - #set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${temp}) + + # set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${temp}) message("CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") endif() From 5141dbef3bd99f20396886174f9ee7cd45291dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 22:23:41 +0800 Subject: [PATCH 0379/1123] fix macos build --- .github/workflows/build-dev.yml | 2 +- CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index e5ca57e7..3a4dc875 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -37,7 +37,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar;/System/Volumes/Data/usr/local/Cellar/libpng -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index 00673d26..54dc3b76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,9 @@ include(cmake/find_qt6.cmake) # Find libpng if(${APPLE}) - find_package(PNG 1.6 REQUIRED NO_CMAKE_SYSTEM_PATH) + find_package(PNG 1.6 REQUIRED + NO_CMAKE_SYSTEM_PATH + PATHS ${CMAKE_PREFIX_PATH}) else() find_package(PNG 1.6 REQUIRED) endif() From 8fc0c4055a8defac3f20710cce6a65269ea0ce49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 26 May 2023 22:43:30 +0800 Subject: [PATCH 0380/1123] fix macos build --- .github/workflows/build-dev.yml | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 3a4dc875..4271f925 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -37,7 +37,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar;/System/Volumes/Data/usr/local/Cellar/libpng -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar;/System/Volumes/Data/usr/local/Cellar/libpng/1.6.39 -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build and Install run: | cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index 54dc3b76..05e7891e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ include(cmake/find_qt6.cmake) if(${APPLE}) find_package(PNG 1.6 REQUIRED NO_CMAKE_SYSTEM_PATH - PATHS ${CMAKE_PREFIX_PATH}) + ) else() find_package(PNG 1.6 REQUIRED) endif() From 77e7d9bcbb64c95abf690b019fca98d95e688078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 11:48:00 +0800 Subject: [PATCH 0381/1123] configure libpng automatically --- CMakeLists.txt | 12 +++--------- cmake/configure_libpng.cmake | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 cmake/configure_libpng.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 05e7891e..9b908667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,21 +58,15 @@ if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() # configure global dependencies ---------------------------------------------- +include(cmake/configure_libpng.cmake) +find_package(PNG 1.6 REQUIRED) + include(cmake/add_compiler_path_to_prefix.cmake) include(cmake/find_nlohmann_json.cmake) include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -# Find libpng -if(${APPLE}) - find_package(PNG 1.6 REQUIRED - NO_CMAKE_SYSTEM_PATH - ) -else() - find_package(PNG 1.6 REQUIRED) -endif() - if(${WIN32}) include(cmake/install_if_is_shared.cmake) endif() diff --git a/cmake/configure_libpng.cmake b/cmake/configure_libpng.cmake new file mode 100644 index 00000000..90a7fb3e --- /dev/null +++ b/cmake/configure_libpng.cmake @@ -0,0 +1,15 @@ + +find_package(PNG 1.6) + +if(${PNG_FOUND}) + return() +endif() + +include(FetchContent) + +FetchContent_Declare(libpng + GIT_REPOSITORY https://github.com/glennrp/libpng.git + GIT_TAG v1.6.39 + OVERRIDE_FIND_PACKAGE) + +FetchContent_MakeAvailable(libpng) \ No newline at end of file From ae2d08255c331924eec4a60df4d03bb494a5b38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 12:40:37 +0800 Subject: [PATCH 0382/1123] fix macos build --- .github/workflows/build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 4271f925..1f937b6c 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -37,7 +37,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar;/System/Volumes/Data/usr/local/Cellar/libpng/1.6.39 -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - name: Build and Install run: | cd build From 911fbc473a5cf5bbc13d9fde7cc1701994a45643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 13:11:37 +0800 Subject: [PATCH 0383/1123] fix macos find png --- CMakeLists.txt | 2 +- cmake/configure_libpng.cmake | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b908667..3d81749a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,8 @@ endif() # configure global dependencies ---------------------------------------------- include(cmake/configure_libpng.cmake) -find_package(PNG 1.6 REQUIRED) +# find_package(PNG 1.6 REQUIRED) include(cmake/add_compiler_path_to_prefix.cmake) include(cmake/find_nlohmann_json.cmake) include(cmake/find_Eigen3.cmake) diff --git a/cmake/configure_libpng.cmake b/cmake/configure_libpng.cmake index 90a7fb3e..68d999c0 100644 --- a/cmake/configure_libpng.cmake +++ b/cmake/configure_libpng.cmake @@ -1,5 +1,9 @@ -find_package(PNG 1.6) +if(${APPLE}) + set(CMAKE_FIND_FRAMEWORK LAST) +endif() + +find_package(PNG 1.6 REQUIRED) if(${PNG_FOUND}) return() @@ -7,9 +11,11 @@ endif() include(FetchContent) -FetchContent_Declare(libpng - GIT_REPOSITORY https://github.com/glennrp/libpng.git +FetchContent_Declare(PNG + GIT_REPOSITORY https://github.com/glennrp/libpng GIT_TAG v1.6.39 OVERRIDE_FIND_PACKAGE) -FetchContent_MakeAvailable(libpng) \ No newline at end of file +FetchContent_MakeAvailable(PNG) + +find_package(PNG 1.6 REQUIRED CONFIG) \ No newline at end of file From 7e50c81ba076414a602f5d659db1b594a785885e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 13:22:44 +0800 Subject: [PATCH 0384/1123] fix macos find png --- CMakeLists.txt | 2 -- cmake/configure_libpng.cmake | 17 +---------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d81749a..465c35dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,6 @@ endif() # configure global dependencies ---------------------------------------------- include(cmake/configure_libpng.cmake) - -# find_package(PNG 1.6 REQUIRED) include(cmake/add_compiler_path_to_prefix.cmake) include(cmake/find_nlohmann_json.cmake) include(cmake/find_Eigen3.cmake) diff --git a/cmake/configure_libpng.cmake b/cmake/configure_libpng.cmake index 68d999c0..46ae2f95 100644 --- a/cmake/configure_libpng.cmake +++ b/cmake/configure_libpng.cmake @@ -3,19 +3,4 @@ if(${APPLE}) set(CMAKE_FIND_FRAMEWORK LAST) endif() -find_package(PNG 1.6 REQUIRED) - -if(${PNG_FOUND}) - return() -endif() - -include(FetchContent) - -FetchContent_Declare(PNG - GIT_REPOSITORY https://github.com/glennrp/libpng - GIT_TAG v1.6.39 - OVERRIDE_FIND_PACKAGE) - -FetchContent_MakeAvailable(PNG) - -find_package(PNG 1.6 REQUIRED CONFIG) \ No newline at end of file +find_package(PNG 1.6 REQUIRED) \ No newline at end of file From 1e7c6dc1a7c50d4e34be65cb4b2f958182ee1b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 13:24:32 +0800 Subject: [PATCH 0385/1123] remove unused --- .../BlockListManager/removed/BLM_preset.cpp | 100 ----- .../removed/BlockListManager.cpp | 385 ------------------ .../removed/BlockListManager.h | 132 ------ .../removed/BlockListManager_global.h | 34 -- .../removed/TokiBaseColor.cpp | 186 --------- .../BlockListManager/removed/TokiBaseColor.h | 80 ---- .../BlockListManager/removed/TokiBlock.cpp | 68 ---- .../BlockListManager/removed/TokiBlock.h | 71 ---- 8 files changed, 1056 deletions(-) delete mode 100644 utilities/BlockListManager/removed/BLM_preset.cpp delete mode 100644 utilities/BlockListManager/removed/BlockListManager.cpp delete mode 100644 utilities/BlockListManager/removed/BlockListManager.h delete mode 100644 utilities/BlockListManager/removed/BlockListManager_global.h delete mode 100644 utilities/BlockListManager/removed/TokiBaseColor.cpp delete mode 100644 utilities/BlockListManager/removed/TokiBaseColor.h delete mode 100644 utilities/BlockListManager/removed/TokiBlock.cpp delete mode 100644 utilities/BlockListManager/removed/TokiBlock.h diff --git a/utilities/BlockListManager/removed/BLM_preset.cpp b/utilities/BlockListManager/removed/BLM_preset.cpp deleted file mode 100644 index 78c81d9a..00000000 --- a/utilities/BlockListManager/removed/BLM_preset.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "BlockListManager.h" -#include - -using njson = nlohmann::json; - -basecolorOption parse_single(const njson& jo) noexcept(false); - -blockListPreset load_preset(QString filename, QString& err) noexcept { - err.clear(); - - blockListPreset ret; - - try { - QFile file(filename); - file.open(QFile::OpenMode::enum_type::ReadOnly); - auto qba = file.readAll(); - - njson jo = njson::parse(qba.begin(), qba.end(), nullptr, true, true); - - ret.values.resize(jo.size()); - - for (size_t idx = 0; idx < jo.size(); idx++) { - basecolorOption opt = parse_single(jo[idx]); - - if (!ret.values[opt.baseColor].second.isEmpty()) { - err = QObject::tr("基色 %1 的预设被重复定义。一个基色只能被定义一次。") - .arg(int(opt.baseColor)); - return {}; - } - - ret.values[opt.baseColor] = {opt.enabled, opt.blockId}; - } - - } catch (std::exception& e) { - err = QObject::tr("解析预设 json 时发生异常:\"%1\"").arg(e.what()); - return {}; - } - - return ret; -} - -basecolorOption parse_single(const njson& jo) noexcept(false) { - basecolorOption ret; - ret.baseColor = jo.at("baseColor"); - std::string id = jo.at("blockId"); - ret.blockId = QString::fromUtf8(id.data()); - ret.enabled = jo.at("enabled"); - return ret; -} - -QString serialize_preset(const blockListPreset& preset) noexcept { - njson::array_t arr; - arr.resize(preset.values.size()); - - for (size_t idx = 0; idx < preset.values.size(); idx++) { - njson obj; - obj["baseColor"] = idx; - obj["blockId"] = preset.values[idx].second.toUtf8(); - obj["enabled"] = preset.values[idx].first; - - arr[idx] = obj; - } - - std::string str = njson(arr).dump(2); - - return QString::fromUtf8(str); -} - -blockListPreset load_preset(QString filename) noexcept(false) { - QString err; - auto temp = load_preset(filename, err); - - if (!err.isEmpty()) { - throw std::runtime_error{err.toUtf8()}; - } - - return temp; -} \ No newline at end of file diff --git a/utilities/BlockListManager/removed/BlockListManager.cpp b/utilities/BlockListManager/removed/BlockListManager.cpp deleted file mode 100644 index 18bb154a..00000000 --- a/utilities/BlockListManager/removed/BlockListManager.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "BlockListManager.h" -#include "TokiBaseColor.h" -#include "TokiBlock.h" -#include -#include -#include -#include - -BlockListManager::BlockListManager(QHBoxLayout *_area, QObject *parent) - : QObject(parent) { - isApplyingPreset = false; - area = _area; - qDebug() << ((area == nullptr) ? " 错误!_area 为空指针" : ""); - QGroupBox *qgb = nullptr; - QGridLayout *qgl = nullptr; - TokiBaseColor *tbc = nullptr; - tbcs.clear(); - // qDebug("方块列表管理者开始创建 QGroupBox"); - for (uchar baseColor = 0; baseColor < 64; baseColor++) { - if (baseColorNames[baseColor].isEmpty()) break; - qgb = new QGroupBox(baseColorNames[baseColor]); - // qDebug("create QGroupBox"); - qgl = new QGridLayout; - qgb->setLayout(qgl); - // qDebug("create Layout"); - tbc = new TokiBaseColor(baseColor, qgl); - // qDebug("create TokiBaseColor"); - area->addWidget(qgb); - // qDebug("add QGroupBox to layout"); - tbcs.push_back(tbc); - - connect(this, &BlockListManager::translate, tbc, &TokiBaseColor::translate); - connect(tbc, &TokiBaseColor::userClicked, this, - &BlockListManager::receiveClicked); - } - // qDebug("Manager 构造函数完毕"); -} - -BlockListManager::~BlockListManager() { - for (uchar i = 0; i < tbcs.size(); i++) delete tbcs[i]; -} - -void BlockListManager::setVersion(uchar _ver) { - if (_ver < 12 || _ver > SlopeCraft::SCL_maxAvailableVersion()) return; - TokiBaseColor::mcVer = _ver; - for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->versionCheck(); -} - -bool callback_load_image(const char *filename, uint32_t *dst_row_major) { - QImage img(QString::fromLocal8Bit(filename)); - - if (img.isNull()) { - return false; - } - - QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); - - memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); - return true; -} - -bool BlockListManager::setupFixedBlockList(const QString &filename, - const QString &imgdir) noexcept { - return this->impl_setupBlockList(filename, imgdir, this->BL_fixed); -} -bool BlockListManager::setupCustomBlockList(const QString &filename, - const QString &imgdir) noexcept { - return this->impl_setupBlockList(filename, imgdir, this->BL_custom); -} - -bool BlockListManager::impl_setupBlockList( - const QString &filename, const QString &dirname, - std::unique_ptr - &dst) noexcept { - std::string errmsg; - errmsg.resize(4096); - SlopeCraft::blockListOption opt; - opt.errmsg = errmsg.data(); - opt.errmsg_capacity = errmsg.size(); - size_t msg_len{0}; - opt.errmsg_len_dest = &msg_len; - - auto img_dir_local8bit = dirname.toLocal8Bit(); - opt.image_dir = img_dir_local8bit.data(); - - opt.callback_load_image = callback_load_image; - - SlopeCraft::BlockListInterface *bli = - SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), opt); - - errmsg.resize(msg_len); - - if (!errmsg.empty()) { - if (bli == nullptr) { - QMessageBox::critical(dynamic_cast(this->parent()), - tr("解析方块列表失败"), - QString::fromUtf8(errmsg.data())); - return false; - } else { - QMessageBox::warning(dynamic_cast(this->parent()), - tr("解析方块列表失败"), - QString::fromUtf8(errmsg.data())); - } - } - dst.reset(bli); - - std::vector blockps; - std::vector basecolors; - basecolors.resize(dst->size()); - blockps.resize(dst->size()); - - dst->get_blocks(blockps.data(), basecolors.data(), blockps.size()); - - for (size_t idx = 0; idx < dst->size(); idx++) { - this->tbcs[basecolors[idx]]->addTokiBlock(blockps[idx]); - } - return true; -} - -void BlockListManager::setSelected(uchar baseColor, ushort blockSeq) { - isApplyingPreset = true; - tbcs[baseColor]->setSelected(blockSeq); - isApplyingPreset = false; -} - -void BlockListManager::setEnabled(uchar baseColor, bool isEnable) { - isApplyingPreset = true; - tbcs[baseColor]->checkBox->setChecked(isEnable); - isApplyingPreset = false; -} - -void BlockListManager::receiveClicked() const { - if (isApplyingPreset) return; - emit switchToCustom(); - emit blockListChanged(); -} - -void BlockListManager::setLabelColors(const QRgb *colors) { - for (uchar i = 0; i < tbcs.size(); i++) tbcs[i]->makeLabel(colors[i]); -} - -void BlockListManager::getEnableList(bool *dest) const { - for (uchar i = 0; i < tbcs.size(); i++) dest[i] = tbcs[i]->getEnabled(); -} - -void BlockListManager::getSimpleBlockList( - const SlopeCraft::AbstractBlock **SBL) const { - // qDebug("void BlockListManager::getSimpleBlockList(simpleBlock * SBL) - // const"); - - for (uchar i = 0; i < 64; i++) { - SBL[i] = nullptr; - } - for (uchar i = 0; i < tbcs.size(); i++) { - SBL[i] = (tbcs[i]->getTokiBlock()->getSimpleBlock()); - } -} -std::vector -BlockListManager::getSimpleBlockList() const { - std::vector SBL(64); - const SlopeCraft::AbstractBlock *p; - for (uchar i = 0; i < tbcs.size(); i++) { - p = tbcs[i]->getTokiBlock()->getSimpleBlock(); - SBL[i] = p; - } - return SBL; -} -std::vector BlockListManager::getTokiBlockList() const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getTokiBlock(); - else - TBL[i] = nullptr; - } - return TBL; -} - -std::vector BlockListManager::getQRadioButtonList() - const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getTokiBlock()->getTarget(); - else - TBL[i] = nullptr; - } - return TBL; -} - -std::vector BlockListManager::toPreset() const { - std::vector TBL(64); - for (uchar i = 0; i < 64; i++) { - if (i < tbcs.size()) - TBL[i] = tbcs[i]->getSelected(); - else - TBL[i] = 0; - } - return TBL; -} - -bool isValidBlockInfo(const QJsonObject &json) { - return (json.contains("id") && json.contains("nameZH") && - json.contains("nameEN") && json.contains("baseColor")); -} - -void BlockListManager::getTokiBaseColors( - std::vector *dest) const { - dest->clear(); - dest->reserve(tbcs.size()); - for (const auto it : tbcs) { - dest->emplace_back(it); - } -} - -int BlockListManager::getBlockNum() const { - int result = 0; - for (auto it : tbcs) { - result += it->tbs.size(); - } - return result; -} - -void BlockListManager::getBlockPtrs(const SlopeCraft::AbstractBlock **dest, - uint8_t *baseColor) const { - int idx = 0; - for (auto it : tbcs) { - for (auto jt : it->tbs) { - baseColor[idx] = it->baseColor; - dest[idx] = jt->getSimpleBlock(); - idx++; - } - } - dest[idx] = nullptr; -} - -bool BlockListManager::loadPreset(const blockListPreset &preset) { - if (preset.values.size() != this->tbcs.size()) { - QMessageBox::warning(dynamic_cast(this->parent()), - tr("加载预设错误"), - tr("预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符") - .arg(preset.values.size()) - .arg(this->tbcs.size())); - return false; - } - - std::vector blocks_arr; - - for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { - auto tbc = this->tbcs[basecolor]; - const auto &pre = preset.values[basecolor]; - - this->setEnabled(basecolor, pre.first); - - // find block - int matched_block_idx = -1; - blocks_arr.clear(); - tbc->getTokiBlockList(blocks_arr); - for (int bidx = 0; bidx < (int)blocks_arr.size(); bidx++) { - const char *const blkid = blocks_arr[bidx]->getSimpleBlock()->getId(); - if (QString::fromUtf8(blkid) == pre.second) { - matched_block_idx = bidx; - break; - } - } - - if (matched_block_idx < 0) { - QMessageBox::warning( - dynamic_cast(this->parent()), tr("加载预设错误"), - tr("预设中为基色%1指定的方块 id 是\"%2\",没有找到这个方块 id") - .arg(basecolor) - .arg(pre.second)); - return false; - } - - this->setSelected(basecolor, matched_block_idx); - } - - emit blockListChanged(); - - return true; -} - -bool BlockListManager::loadInternalPreset( - const blockListPreset &preset) noexcept { - return this->loadPreset(preset); -} - -blockListPreset BlockListManager::currentPreset() const noexcept { - blockListPreset ret; - ret.values.resize(this->tbcs.size()); - for (size_t basecolor = 0; basecolor < this->tbcs.size(); basecolor++) { - ret.values[basecolor].first = this->tbcs[basecolor]->getEnabled(); - ret.values[basecolor].second = QString::fromUtf8( - this->tbcs[basecolor]->getTokiBlock()->getSimpleBlock()->getId()); - } - return ret; -} - -const QString BlockListManager::baseColorNames[64] = {"00 None", - "01 Grass", - "02 Sand", - "03 Wool", - "04 Fire", - "05 Ice", - "06 Metal", - "07 Plant", - "08 Snow", - "09 Clay", - "10 Dirt", - "11 Stone", - "12 Water", - "13 Wood", - "14 Quartz", - "15 ColorOrange", - "16 ColorMagenta", - "17 ColorLightBlue", - "18 ColorYellow", - "19 ColorLime", - "20 ColorPink", - "21 ColorGray", - "22 ColorLightGray", - "23 ColorCyan", - "24 ColorPurple", - "25 ColorBlue", - "26 ColorBrown", - "27 ColorGreen", - "28 ColorRed", - "29 ColorBlack", - "30 Gold", - "31 Diamond", - "32 Lapis", - "33 Emerald", - "34 Podzol", - "35 Nether", - "36 TerracottaWhite", - "37 TerracottaOrange", - "38 TerracottaMagenta", - "39 TerracottaLightBlue", - "40 TerracottaYellow", - "41 TerracottaLime", - "42 TerracottaPink", - "43 TerracottaGray", - "44 TerracottaLightGray", - "45 TerracottaCyan", - "46 TerracottaPurple", - "47 TerracottaBlue", - "48 TerracottaBrown", - "49 TerracottaGreen", - "50 TerracottaRed", - "51 TerracottaBlack", - "52 CrimsonNylium", - "53 CrimsonStem", - "54 CrimsonHyphae", - "55 WarpedNylium", - "56 WarpedStem", - "57 WarpedHyphae", - "58 WarpedWartBlock", - "59 Deepslate", - "60 RawIron", - "61 GlowLichen", - "", - ""}; diff --git a/utilities/BlockListManager/removed/BlockListManager.h b/utilities/BlockListManager/removed/BlockListManager.h deleted file mode 100644 index dd066cf2..00000000 --- a/utilities/BlockListManager/removed/BlockListManager.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef BLOCKLISTMANAGER_H -#define BLOCKLISTMANAGER_H - -#include -#include -#include -#include -#include -#include - -#include "../../SlopeCraftL/SlopeCraftL.h" - -#include "TokiBaseColor.h" -#include "TokiBlock.h" - -#define DispLine qDebug() << "File = " << __FILE__ << " , Line = " << __LINE__; - -struct basecolorOption { - uint8_t baseColor{0xFF}; - bool enabled{false}; - QString blockId{""}; -}; - -struct blockListPreset { - std::vector> values; -}; - -blockListPreset load_preset(QString filename) noexcept(false); -blockListPreset load_preset(QString filename, QString &err) noexcept; - -QString serialize_preset(const blockListPreset &preset) noexcept; - -class BlockListDeleter { - public: - void operator()(SlopeCraft::BlockListInterface *ptr) noexcept { - SlopeCraft::SCL_destroyBlockList(ptr); - } -}; - -class BlockListManager : public QObject { - Q_OBJECT - - public: - explicit BlockListManager(QHBoxLayout *_area, QObject *parent = nullptr); - - ~BlockListManager(); - - bool setupFixedBlockList(const QString &filename, - const QString &imgdir) noexcept; - bool setupCustomBlockList(const QString &filename, - const QString &imgdir) noexcept; - - private: - bool impl_setupBlockList(const QString &filename, const QString &dirname, - std::unique_ptr &dst) noexcept; - - public: - void setSelected(uchar baseColor, ushort blockSeq); - - void setEnabled(uchar baseColor, bool isEnable); - - void setLabelColors(const QRgb *); - - void setVersion(uchar); - - void getEnableList(bool *) const; - void getSimpleBlockList(const SlopeCraft::AbstractBlock **) const; - std::vector getSimpleBlockList() const; - std::vector getTokiBlockList() const; - std::vector getQRadioButtonList() const; - std::vector toPreset() const; - - void getTokiBaseColors(std::vector *) const; - - int getBlockNum() const; - void getBlockPtrs(const SlopeCraft::AbstractBlock **, uint8_t *) const; - - bool loadPreset(const blockListPreset &preset); - - bool loadInternalPreset(const blockListPreset &preset) noexcept; - - blockListPreset currentPreset() const noexcept; - - public slots: - - signals: - void translate(Language); - void switchToCustom() const; - void blockListChanged() const; - - private: - bool isApplyingPreset; - QHBoxLayout *area; - std::vector tbcs; - - std::unique_ptr BL_fixed{ - nullptr}; - std::unique_ptr BL_custom{ - nullptr}; - - static const QString baseColorNames[64]; - - private slots: - void receiveClicked() const; -}; - -bool isValidBlockInfo(const QJsonObject &); - -#endif // BLOCKLISTMANAGER_H diff --git a/utilities/BlockListManager/removed/BlockListManager_global.h b/utilities/BlockListManager/removed/BlockListManager_global.h deleted file mode 100644 index 832d3d00..00000000 --- a/utilities/BlockListManager/removed/BlockListManager_global.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef BLOCKLISTMANAGER_GLOBAL_H -#define BLOCKLISTMANAGER_GLOBAL_H - -#include - -#if defined(BLOCKLISTMANAGER_LIBRARY) -#define BLOCKLISTMANAGER_EXPORT Q_DECL_EXPORT -#else -#define BLOCKLISTMANAGER_EXPORT Q_DECL_IMPORT -#endif - -#endif // BLOCKLISTMANAGER_GLOBAL_H diff --git a/utilities/BlockListManager/removed/TokiBaseColor.cpp b/utilities/BlockListManager/removed/TokiBaseColor.cpp deleted file mode 100644 index fc595ef3..00000000 --- a/utilities/BlockListManager/removed/TokiBaseColor.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TokiBaseColor.h" - -uchar TokiBaseColor::mcVer = 17; - -TokiBaseColor::TokiBaseColor(uchar _baseColor, QGridLayout *_layout, - QObject *parent) - : QObject(parent) { - layout = _layout; - baseColor = _baseColor; - // 负责创建 QCheckBox 和对应的弹簧 - - layout->addWidget(checkBox = new QCheckBox("启用"), 0, 1); - checkBox->setChecked(false); - checkBox->setSizePolicy(QSizePolicy(QSizePolicy::Policy::Expanding, - QSizePolicy::Policy::Preferred)); - checkBox->setEnabled(baseColor != 0); - - connect(checkBox, &QCheckBox::toggled, this, &TokiBaseColor::updateEnabled); - connect(checkBox, &QCheckBox::toggled, this, &TokiBaseColor::userClicked); - connect(this, &TokiBaseColor::translate, this, - &TokiBaseColor::translateCheckBox); - // 创建弹簧 - QSpacerItem *si = new QSpacerItem(40, 20, QSizePolicy::Policy::Expanding, - QSizePolicy::Policy::Preferred); - layout->addItem(si, 0, 2); - - isEnabled = true; - tbs.clear(); - selected = 65535; - versionCheck(); -} - -TokiBaseColor::~TokiBaseColor() { - for (ushort i = 0; i < tbs.size(); i++) delete tbs[i]; -} - -void TokiBaseColor::addTokiBlock(SlopeCraft::AbstractBlock *blkp) noexcept { - QRadioButton *qrb = new QRadioButton; - int rows = 1 + tbs.size() / 2; - int cols = 1 + tbs.size() % 2; - layout->addWidget(qrb, rows, cols); - - TokiBlock *tb = new TokiBlock(qrb, blkp, tbs.size(), this); - tbs.push_back(tb); - - if (tb->getSimpleBlock()->getVersion() > mcVer) { - tb->getNCTarget()->setEnabled(false); - tb->getNCTarget()->setChecked(false); - } - - connect(tb, &TokiBlock::radioBtnClicked, this, - &TokiBaseColor::receiveClicked); - connect(this, &TokiBaseColor::translate, tb, &TokiBlock::translate); - connect(tb, &TokiBlock::radioBtnClicked, this, &TokiBaseColor::userClicked); -} - -void TokiBaseColor::makeLabel(QRgb color) { - QLabel *qL = new QLabel(""); - layout->addWidget(qL, 0, 0, ceil(1 + tbs.size() / 2.0), 1); - QPalette pl; - pl.setColor(QPalette::ColorRole::Text, Qt::black); - pl.setColor( - QPalette::ColorRole::Window, - QColor(qRed(color), qGreen(color), qBlue(color), 255 * bool(baseColor))); - - qL->setPalette(pl); - qL->setSizePolicy(QSizePolicy::Policy::Preferred, - QSizePolicy::Policy::Preferred); - qL->setMinimumWidth(30); - qL->setFrameShape(QFrame::Shape::StyledPanel); - qL->setFrameShadow(QFrame::Shadow::Plain); - qL->setLineWidth(1); - qL->setAutoFillBackground(true); -} - -void TokiBaseColor::receiveClicked(ushort _selected) { - selected = _selected % tbs.size(); - versionCheck(); -} - -bool TokiBaseColor::isAllOverVersion() const { // 判断是否所有方块都超版本了 - bool isAllOver = true; - for (auto it = tbs.cbegin(); it != tbs.cend(); it++) { - isAllOver &= ((*it)->block->getVersion() > mcVer); - } - return isAllOver; -} - -void TokiBaseColor::versionCheck() { - checkBox->setEnabled(baseColor != 0 && !isAllOverVersion()); - if (!checkBox->isEnabled()) { - checkBox->setChecked(false || baseColor == 0); - } - isEnabled = checkBox->isChecked(); - - if (tbs.size() <= 0) { - selected = 65535; - return; - } - if (tbs.size() == 1) { - selected = 0; - tbs[0]->getNCTarget()->setChecked(true); - tbs[0]->getNCTarget()->setEnabled(false); - return; - } - std::vector scores(tbs.size()); - for (ushort idx = 0; idx < tbs.size(); idx++) { - if (tbs[idx]->getSimpleBlock()->getVersion() <= mcVer) { - scores[idx] = (tbs[idx]->getTarget()->isChecked()) ? 100 : 51; - tbs[idx]->getNCTarget()->setEnabled(true); - } else { - scores[idx] = (idx <= 0); - tbs[idx]->getNCTarget()->setEnabled(false); - } - } - ushort maxIndex = 0; - for (ushort idx = 0; idx < scores.size(); idx++) { - if (scores[idx] > scores[maxIndex]) maxIndex = idx; - } - selected = maxIndex; - if (!tbs[selected]->getTarget()->isChecked()) { - tbs[selected]->getNCTarget()->setChecked(true); - } -} - -void TokiBaseColor::setSelected(ushort sel) { - tbs[sel]->getNCTarget()->setChecked(true); - versionCheck(); -} - -void TokiBaseColor::updateEnabled(bool isChecked) { - isEnabled = isChecked; - versionCheck(); -} - -void TokiBaseColor::translateCheckBox(Language lang) { - switch (lang) { - case Language::ZH: - checkBox->setText("启用"); - break; - case Language::EN: - checkBox->setText("Enable"); - break; - } -} - -const TokiBlock *TokiBaseColor::getTokiBlock() const { - // qDebug("getTokiBlock"); - // qDebug()< &dest) const { - dest.clear(); - dest.reserve(tbs.size()); - for (const auto it : tbs) { - dest.emplace_back(it); - } -} diff --git a/utilities/BlockListManager/removed/TokiBaseColor.h b/utilities/BlockListManager/removed/TokiBaseColor.h deleted file mode 100644 index ebae60ed..00000000 --- a/utilities/BlockListManager/removed/TokiBaseColor.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TOKIBASECOLOR_H -#define TOKIBASECOLOR_H - -#include -#include -#include -#include -#include -#include -#include - -#include "TokiBlock.h" - -class BlockListManager; - -class TokiBaseColor : public QObject { - Q_OBJECT - friend class BlockListManager; - - public: - explicit TokiBaseColor(uchar, QGridLayout *, QObject *parent = nullptr); - ~TokiBaseColor(); - - const TokiBlock *getTokiBlock() const; - - bool getEnabled() const; - - ushort getSelected() const; - - void addTokiBlock(SlopeCraft::AbstractBlock *blkp) noexcept; - - void makeLabel(QRgb); - - void getTokiBlockList(std::vector &) const; - - static uchar mcVer; - - signals: - void userClicked(); - void translate(Language); - - private: - uchar baseColor; - bool isEnabled; - ushort selected; - QGridLayout *layout; - QCheckBox *checkBox; - std::vector tbs; - bool isAllOverVersion() const; - void setSelected(ushort); - private slots: - void receiveClicked(ushort); - void updateEnabled(bool); - void versionCheck(); - void translateCheckBox(Language); -}; - -#endif // TOKIBASECOLOR_H diff --git a/utilities/BlockListManager/removed/TokiBlock.cpp b/utilities/BlockListManager/removed/TokiBlock.cpp deleted file mode 100644 index 9c0a09af..00000000 --- a/utilities/BlockListManager/removed/TokiBlock.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TokiBlock.h" - -using namespace SlopeCraft; - -TokiBlock::TokiBlock(QRadioButton *_target, SlopeCraft::AbstractBlock *blkp, - uint16_t _self, QObject *parent) - : QObject(parent) { - this->self = _self; - this->target = _target; - this->block = blkp; - - target->setText(nameZH()); - target->setChecked(true); - - connect(target, &QRadioButton::clicked, this, &TokiBlock::onTargetClicked); - - QImage img(16, 16, QImage::Format_ARGB32); - - this->block->getImage((uint32_t *)img.scanLine(0), true); - - this->target->setIcon(QIcon(QPixmap::fromImage(img))); -} - -void TokiBlock::translate(Language lang) { - switch (lang) { - case Language::ZH: - target->setText(nameZH()); - break; - case Language::EN: - target->setText(nameEN()); - break; - } - return; -} - -TokiBlock::~TokiBlock() {} - -void TokiBlock::onTargetClicked(bool isChecked) { - if (isChecked) emit radioBtnClicked(self); -} - -const QRadioButton *TokiBlock::getTarget() const { return target; } - -const AbstractBlock *TokiBlock::getSimpleBlock() const { return block; } - -QRadioButton *TokiBlock::getNCTarget() const { return target; } diff --git a/utilities/BlockListManager/removed/TokiBlock.h b/utilities/BlockListManager/removed/TokiBlock.h deleted file mode 100644 index 581a299d..00000000 --- a/utilities/BlockListManager/removed/TokiBlock.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TOKIBLOCK_H -#define TOKIBLOCK_H - -#include -#include -#include -#include -#include -#include - -#include "../../SlopeCraftL/SlopeCraftL.h" - -class TokiBaseColor; - -enum class Language { ZH, EN }; - -class TokiBlock : public QObject { - Q_OBJECT - friend class TokiBaseColor; - - public: - explicit TokiBlock(QRadioButton *_target, SlopeCraft::AbstractBlock *blkp, - uint16_t _self, QObject *parent); - - ~TokiBlock(); - const QRadioButton *getTarget() const; - const SlopeCraft::AbstractBlock *getSimpleBlock() const; - - QString nameZH() const noexcept { - return QString::fromUtf8(this->block->getNameZH()); - } - QString nameEN() const noexcept { - return QString::fromUtf8(this->block->getNameEN()); - } - - signals: - void radioBtnClicked(ushort); - - private: - ushort self; // 指明自己是所属基色的第 i 个方块 - QRadioButton *target; - SlopeCraft::AbstractBlock *block; - QRadioButton *getNCTarget() const; - private slots: - void translate(Language); - void onTargetClicked(bool); -}; - -#endif // TOKIBLOCK_H From 39d66a5519a0727ff51098c1963c5333fc151650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 13:29:24 +0800 Subject: [PATCH 0386/1123] fix BLM translation --- utilities/BlockListManager/BaseColor.cpp | 7 +++++++ utilities/BlockListManager/BaseColor.h | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index a5b54d1a..c03ddaa8 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -209,4 +209,11 @@ void BaseColorWidget::select_by_callback(const select_callback_t& fun) { } this->select_block_soft(output); +} + +void BaseColorWidget::update_lang(SCL_language lang) noexcept { + this->ui->retranslateUi(this); + for (auto bw : this->blocks) { + bw->update_lang(lang); + } } \ No newline at end of file diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index 6d4cd35b..19f4b3de 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -43,11 +43,7 @@ class BaseColorWidget : public QGroupBox { return this->blocks[this->selected_idx()]->attachted_block(); } - void update_lang(SCL_language lang) noexcept { - for (auto bw : this->blocks) { - bw->update_lang(lang); - } - } + void update_lang(SCL_language lang) noexcept; void set_enabled(bool enabled) noexcept; From 77034c7622ab8727231030ab209f77baafa42dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 14:36:25 +0800 Subject: [PATCH 0387/1123] add getCompressedImage to SCL --- SlopeCraftL/SlopeCraftL.h | 3 +++ SlopeCraftL/TokiSlopeCraft.cpp | 26 +++++++++++-------- SlopeCraftL/TokiSlopeCraft.h | 5 ++++ SlopeCraftL/TokiSlopeCraft_build.cpp | 38 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 2debeaec..69c9ee5e 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -300,6 +300,9 @@ class Kernel { bool connect_mushrooms{false}; }; virtual bool build(const build_options &option) noexcept = 0; + + virtual void getCompressedImage(int *row, int *cols, uint32_t *dest, + bool expected_col_major) const noexcept = 0; // requires step >= wait4image // virtual bool checkColorsetHash() const noexcept = 0; // requires step >= converted diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index b916fbb1..57ce37a4 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -418,7 +418,7 @@ TokiSlopeCraft::ColorSpace TokiSlopeCraft::getColorSpace() const { void TokiSlopeCraft::getConvertedImage(int *rows, int *cols, ARGB *dest, bool expected_col_major) const { - EImage result = getConovertedImage(); + EImage result = this->getConovertedImage(); if (rows != nullptr) *rows = result.rows(); if (cols != nullptr) *cols = result.cols(); if (!expected_col_major) { @@ -439,22 +439,16 @@ EImage TokiSlopeCraft::getConovertedImage() const { return cvtedImg; } - Eigen::Array argbLUT; - for (int idx = 0; idx < 256; idx++) { - argbLUT[idx] = - RGB2ARGB(Basic.RGB(idx, 0), Basic.RGB(idx, 1), Basic.RGB(idx, 2)); - } + const auto argbLUT = this->LUT_mapcolor_to_argb(); - // RGBint =(RGBint > 255).select(Eigen::ArrayXXi::Constant(256, 3, 255), - // RGBint); - // short Index; for (short r = 0; r < sizePic(0); r++) { for (short c = 0; c < sizePic(1); c++) { - if (mapColor2baseColor(this->mapPic(r, c)) == 0) { // if base ==0 + const auto map_color = this->image_cvter.color_id(r, c); + if (mapColor2baseColor(map_color) == 0) { // if base ==0 cvtedImg(r, c) = ARGB32(0, 0, 0, 0); continue; } - const int Index = mapColor2Index(this->mapPic(r, c)); + const int Index = mapColor2Index(map_color); cvtedImg(r, c) = argbLUT[Index]; } @@ -462,6 +456,16 @@ EImage TokiSlopeCraft::getConovertedImage() const { return cvtedImg; } +std::array TokiSlopeCraft::LUT_mapcolor_to_argb() + const noexcept { + std::array argbLUT; + for (int idx = 0; idx < 256; idx++) { + argbLUT[idx] = + RGB2ARGB(Basic.RGB(idx, 0), Basic.RGB(idx, 1), Basic.RGB(idx, 2)); + } + return argbLUT; +} + void TokiSlopeCraft::getConvertedMap(int *rows, int *cols, unsigned char *dst) const { if (rows != nullptr) { diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 37004ab2..b93d23ea 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -398,6 +398,9 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { return err.empty(); } + void getCompressedImage(int *row, int *cols, uint32_t *dest, + bool expected_col_major) const noexcept override; + std::string impl_make_tests( std::string_view filename, const test_blocklist_options &option) const noexcept; @@ -464,6 +467,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { static const simpleBlock *find_block_for_idx(int idx, std::string_view blkid) noexcept; + std::array LUT_mapcolor_to_argb() const noexcept; + public: static int getBlockPalette(const AbstractBlock **blkpp, size_t capacity) noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index a30bee8d..a6ffce12 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -708,4 +708,42 @@ std::string TokiSlopeCraft::export_flat_diagram( } return fmt::format("Failed to export flat diagram. Details: {}", err); +} + +void TokiSlopeCraft::getCompressedImage( + int *rows, int *cols, uint32_t *dest_ptr, + bool expected_col_major) const noexcept { + if (kernelStep < SCL_step::builded) { + reportError(wind, errorFlag::HASTY_MANIPULATION, + "You can only export a map to structure after you build the 3D " + "structure."); + return; + } + + if (rows != nullptr) { + *rows = this->image_cvter.rows(); + } + if (cols != nullptr) { + *cols = this->image_cvter.cols(); + } + + if (dest_ptr == nullptr) { + return; + } + + Eigen::Map dest{dest_ptr, this->image_cvter.rows(), + this->image_cvter.cols()}; + dest.fill(0xFF000000); + + const auto LUT = this->LUT_mapcolor_to_argb(); + + for (int r = 0; r < this->image_cvter.rows(); r++) { + for (int c = 0; c < this->image_cvter.cols(); c++) { + dest(r, c) = LUT[this->mapPic(r, c)]; + } + } + + if (!expected_col_major) { + dest.transposeInPlace(); + } } \ No newline at end of file From 38e78df4f14da59f110f420a06bf77007abb9f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 15:34:09 +0800 Subject: [PATCH 0388/1123] fix getCompressedImage --- SlopeCraft/SCWind.h | 3 ++ SlopeCraft/SCWind_slots.cpp | 43 ++++++++++++++++++++++++++++ SlopeCraftL/TokiSlopeCraft_build.cpp | 31 +++++++++++++------- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index caebee5f..34aab473 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -77,6 +77,7 @@ class SCWind : public QMainWindow { void on_pb_build3d_clicked() noexcept; void on_pb_preview_materials_clicked() noexcept; + void on_pb_preview_compress_effect_clicked() noexcept; void on_pb_export_all_clicked() noexcept; void on_pb_export_file_clicked() noexcept; @@ -109,6 +110,8 @@ class SCWind : public QMainWindow { // QString fileonly_export_dir{""}; public: + const SlopeCraft::Kernel* kernel_ptr() const noexcept { return this->kernel; } + std::array version_buttons() noexcept; std::array version_buttons() const noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 1d351373..dfe0bdb0 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -9,6 +9,7 @@ #include "AiCvterParameterDialog.h" #include "VersionDialog.h" #include "TransparentStrategyWind.h" +#include "CompressEffectViewer.h" void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 @@ -414,6 +415,48 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { pw->setup_data(this->kernel); } +void SCWind::on_pb_preview_compress_effect_clicked() noexcept { + auto sel_opt = this->selected_export_task(); + if (!sel_opt.has_value()) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return; + } + const auto sel = sel_opt.value(); + QString errtitle{""}, errmsg{""}; + if (!sel->is_built) { + errtitle = tr("尚未构建三维结构"); + errmsg = + tr("在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" + "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + } + if (!this->kernel->loadConvertCache(this->selected_algo(), + this->is_dither_selected())) { + errtitle = tr("该图像尚未被转化"); + errmsg = + tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" + "新转化该图像。"); + } + if (!this->kernel->loadBuildCache(this->current_build_option())) { + errtitle = tr("尚未构建三维结构"); + errmsg = + tr("在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" + "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + } + if (!errtitle.isEmpty()) { + QMessageBox::warning(this, errtitle, errmsg); + return; + } + + CompressEffectViewer *cev = new CompressEffectViewer{this}; + + cev->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); + cev->setWindowFlag(Qt::WindowType::Window, true); + // cev->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); + // bb->setAttribute(Qt::WidgetAttribute::WA_NativeWindow, true); + cev->show(); +} + #define SC_PRIVATE_MACRO_PROCESS_IF_ERR_on_pb_export_all_clicked \ if (!temp.has_value()) { \ process_err(err); \ diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index a6ffce12..d97b1f9e 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -731,19 +731,30 @@ void TokiSlopeCraft::getCompressedImage( return; } - Eigen::Map dest{dest_ptr, this->image_cvter.rows(), - this->image_cvter.cols()}; - dest.fill(0xFF000000); - const auto LUT = this->LUT_mapcolor_to_argb(); - for (int r = 0; r < this->image_cvter.rows(); r++) { - for (int c = 0; c < this->image_cvter.cols(); c++) { - dest(r, c) = LUT[this->mapPic(r, c)]; + auto fun = [this, &LUT](auto &dst) { + for (int r = 0; r < this->image_cvter.rows(); r++) { + for (int c = 0; c < this->image_cvter.cols(); c++) { + const auto map_color = this->mapPic(r, c); + if (mapColor2baseColor(map_color) == 0) { // if base ==0 + dst(r, c) = ARGB32(0, 0, 0, 0); + continue; + } + const int index = mapColor2Index(map_color); + dst(r, c) = LUT[index]; + } } - } + }; - if (!expected_col_major) { - dest.transposeInPlace(); + if (expected_col_major) { + Eigen::Map dest{dest_ptr, this->image_cvter.rows(), + this->image_cvter.cols()}; + fun(dest); + } else { + Eigen::Map< + Eigen::Array> + dest{dest_ptr, this->image_cvter.rows(), this->image_cvter.cols()}; + fun(dest); } } \ No newline at end of file From 24ef8e14ad80efa3ee5fd8b33be6766497500c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 27 May 2023 15:34:25 +0800 Subject: [PATCH 0389/1123] add CompressEffectViewer to SC --- SlopeCraft/CMakeLists.txt | 9 +++- SlopeCraft/CompressEffectViewer.cpp | 41 ++++++++++++++++ SlopeCraft/CompressEffectViewer.h | 25 ++++++++++ SlopeCraft/CompressEffectViewer.ui | 60 +++++++++++++++++++++++ utilities/AdaptiveLabel/AdaptiveLabel.cpp | 4 +- utilities/AdaptiveLabel/AdaptiveLabel.h | 7 ++- 6 files changed, 141 insertions(+), 5 deletions(-) create mode 100644 SlopeCraft/CompressEffectViewer.cpp create mode 100644 SlopeCraft/CompressEffectViewer.h create mode 100644 SlopeCraft/CompressEffectViewer.ui diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 7ca1f2fe..7a90d91a 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -26,7 +26,9 @@ set(SlopeCraft_headers ExportTableModel.h AiCvterParameterDialog.h CopyableTableView.h - TransparentStrategyWind.h) + TransparentStrategyWind.h + CompressEffectViewer.h +) set(SlopeCraft_sources SCWind.cpp @@ -39,6 +41,7 @@ set(SlopeCraft_sources AiCvterParameterDialog.cpp CopyableTableView.cpp TransparentStrategyWind.cpp + CompressEffectViewer.cpp main.cpp ${SlopeCraft_rc_files}) @@ -47,7 +50,9 @@ set(SlopeCraft_uis SCWind.ui PreviewWind.ui AiCvterParameterDialog.ui - TransparentStrategyWind.ui) + TransparentStrategyWind.ui + CompressEffectViewer.ui +) set(SlopeCraft_ts_files others/SlopeCraft_en_US.ts diff --git a/SlopeCraft/CompressEffectViewer.cpp b/SlopeCraft/CompressEffectViewer.cpp new file mode 100644 index 00000000..18954c29 --- /dev/null +++ b/SlopeCraft/CompressEffectViewer.cpp @@ -0,0 +1,41 @@ +#include +#include "CompressEffectViewer.h" +#include "ui_CompressEffectViewer.h" + +#include "SCWind.h" +#include +#include + +CompressEffectViewer::CompressEffectViewer(SCWind* parent) + : QDialog{parent}, ui{new Ui::CompressEffectViewer} { + this->ui->setupUi(this); + + auto kernel = parent->kernel_ptr(); + const int rows = kernel->getImageRows(); + const int cols = kernel->getImageCols(); + QImage img{rows, cols, QImage::Format_ARGB32}; + + kernel->getCompressedImage( + nullptr, nullptr, reinterpret_cast(img.scanLine(0)), false); + + this->ui->lb_display->setPixmap(QPixmap::fromImage(img)); +} + +CompressEffectViewer::~CompressEffectViewer() { delete this->ui; } + +void CompressEffectViewer::on_pb_save_image_clicked() noexcept { + static QString prev_dir; + const QString filename = QFileDialog::getSaveFileName( + this, tr("保存压缩后图片"), prev_dir, "*.png"); + if (filename.isEmpty()) { + return; + } + + prev_dir = QFileInfo{filename}.dir().path(); + + auto pixmap = this->ui->lb_display->pixmap(); + if (!pixmap.save(filename)) { + QMessageBox::warning(this, tr("保存图像失败"), + tr("无法保存图像 %1").arg(filename)); + } +} \ No newline at end of file diff --git a/SlopeCraft/CompressEffectViewer.h b/SlopeCraft/CompressEffectViewer.h new file mode 100644 index 00000000..5a21762b --- /dev/null +++ b/SlopeCraft/CompressEffectViewer.h @@ -0,0 +1,25 @@ +#ifndef SLOPECRAFT_SLOPECRAFT_COMPRESSEFFECTVIEWER_H +#define SLOPECRAFT_SLOPECRAFT_COMPRESSEFFECTVIEWER_H + +#include +class SCWind; + +class CompressEffectViewer; + +namespace Ui { +class CompressEffectViewer; +} + +class CompressEffectViewer : public QDialog { + Q_OBJECT + private: + Ui::CompressEffectViewer* const ui; + + public: + explicit CompressEffectViewer(SCWind* parent); + ~CompressEffectViewer(); + private slots: + void on_pb_save_image_clicked() noexcept; +}; + +#endif // SLOPECRAFT_SLOPECRAFT_COMPRESSEFFECTVIEWER_H \ No newline at end of file diff --git a/SlopeCraft/CompressEffectViewer.ui b/SlopeCraft/CompressEffectViewer.ui new file mode 100644 index 00000000..c6010e8b --- /dev/null +++ b/SlopeCraft/CompressEffectViewer.ui @@ -0,0 +1,60 @@ + + + CompressEffectViewer + + + + 0 + 0 + 555 + 460 + + + + + 0 + 0 + + + + 预览压缩效果 + + + + + + 保存图像 + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + + + + Qt::AlignCenter + + + + + + + + AdaptiveLabel + QLabel +
AdaptiveLabel.h
+
+
+ + +
diff --git a/utilities/AdaptiveLabel/AdaptiveLabel.cpp b/utilities/AdaptiveLabel/AdaptiveLabel.cpp index 58c9787c..3773969b 100644 --- a/utilities/AdaptiveLabel/AdaptiveLabel.cpp +++ b/utilities/AdaptiveLabel/AdaptiveLabel.cpp @@ -24,8 +24,8 @@ void AdaptiveLabel::refresh_image() noexcept { } auto label_size = this->size(); - label_size.setHeight(std::max(label_size.height(), 1)); - label_size.setWidth(std::max(label_size.width(), 1)); + label_size.setHeight(std::max(label_size.height() - 2, 1)); + label_size.setWidth(std::max(label_size.width() - 2, 1)); QPixmap scaled = this->real_image.scaled(label_size, Qt::AspectRatioMode::KeepAspectRatio, diff --git a/utilities/AdaptiveLabel/AdaptiveLabel.h b/utilities/AdaptiveLabel/AdaptiveLabel.h index 7f808d8e..ed9d93b1 100644 --- a/utilities/AdaptiveLabel/AdaptiveLabel.h +++ b/utilities/AdaptiveLabel/AdaptiveLabel.h @@ -1,3 +1,6 @@ +#ifndef SLOPECRAFT_UTILITIES_ADAPTIVELABEL_ADAPTIVELABEL_H +#define SLOPECRAFT_UTILITIES_ADAPTIVELABEL_ADAPTIVELABEL_H + #include #include #include @@ -32,4 +35,6 @@ class AdaptiveLabel : public QLabel { using QLabel::setStyleSheet; using QLabel::setText; using QLabel::sizePolicy; -}; \ No newline at end of file +}; + +#endif // SLOPECRAFT_UTILITIES_ADAPTIVELABEL_ADAPTIVELABEL_H \ No newline at end of file From 4047de819a90d391926aee3e20d781da96f02041 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 May 2023 13:11:40 +0800 Subject: [PATCH 0390/1123] fixed a bug about setting up allowed blocks in VC --- VisualCraft/VCWind.cpp | 22 +++++++++++++++------- VisualCraft/VCWind.h | 6 ++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 4fb307d9..4d80000e 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -443,15 +443,18 @@ void VCWind::setup_block_widgets() noexcept { } bool VCWind::is_basical_colorset_changed() const noexcept { - static QByteArray hash_prev{""}; + // static QByteArray hash_prev{""}; auto curr_opt = this->current_basic_option(); QByteArray curr_hash = this->checksum_basic_colorset_option(curr_opt); - const bool ret = hash_prev != curr_hash; - hash_prev = curr_hash; + const bool ret = this->basical_option_hash_prev != curr_hash; return ret; } +void VCWind::update_hash_basic(const basic_colorset_option &opt) noexcept { + this->basical_option_hash_prev = this->checksum_basic_colorset_option(opt); +} + void VCWind::setup_basical_colorset() noexcept { if (VCL_is_basic_colorset_ok() && !this->is_basical_colorset_changed()) { return; @@ -507,6 +510,7 @@ void VCWind::setup_basical_colorset() noexcept { } } + this->update_hash_basic(current_option); this->setup_block_widgets(); this->ui->ac_browse_basic_colors->setEnabled(true); } @@ -525,17 +529,21 @@ QByteArray VCWind::checksum_allowed_colorset_option( bool VCWind::is_allowed_colorset_changed( allowed_colorset_option *opt) const noexcept { - static QByteArray prev_hash{""}; + // static QByteArray prev_hash{""}; this->selected_blocks(&opt->blocks); QByteArray cur_hash = VCWind::checksum_allowed_colorset_option(*opt); - const bool ret = prev_hash != cur_hash; + const bool ret = this->allowed_option_hash_prev != cur_hash; - prev_hash = cur_hash; + // prev_hash = cur_hash; return ret; } +void VCWind::update_hash_allowed(const allowed_colorset_option &opt) noexcept { + this->allowed_option_hash_prev = this->checksum_allowed_colorset_option(opt); +} + void VCWind::setup_allowed_colorset() noexcept { this->setup_basical_colorset(); @@ -568,10 +576,10 @@ void VCWind::setup_allowed_colorset() noexcept { } } + this->update_hash_allowed(cur_option); this->ui->gb_convert_algo->setTitle( VCWind::tr("调色算法 (共%1种颜色)") .arg(VCL_get_allowed_colors(nullptr, 0))); - this->clear_convert_cache(); this->ui->ac_browse_allowed_colors->setEnabled(true); } diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index 74c0d5bc..49d745c9 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -78,10 +78,13 @@ class VCWind : public QMainWindow { // for all pages Ui::VCWind *ui; VCL_Kernel *const kernel{nullptr}; + // for page 0 // VCL_resource_pack *rp{nullptr}; // VCL_block_state_list *bsl{nullptr}; // bool is_basical_colorset_changed{true}; + QByteArray basical_option_hash_prev{""}; + QByteArray allowed_option_hash_prev{""}; // for page 1 std::map map_VC_block_class{}; @@ -129,6 +132,9 @@ class VCWind : public QMainWindow { [[nodiscard]] static VCL_block_state_list *create_block_state_list( const basic_colorset_option &opt) noexcept; + void update_hash_basic(const basic_colorset_option &opt) noexcept; + void update_hash_allowed(const allowed_colorset_option &opt) noexcept; + // receive current selected version from ui SCL_gameVersion current_selected_version() const noexcept; VCL_face_t current_selected_face() const noexcept; From 5688886ccbf18ac43b86bdfeb6f01ccc2df4760d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 30 May 2023 13:05:09 +0800 Subject: [PATCH 0391/1123] Fixed a bug in VCL_set_allowed (composed colors are allowed even though some block is not allowed) --- VisualCraft/BlockBrowser.cpp | 7 ++- VisualCraft/BlockBrowser.h | 12 ++--- VisualCraft/CallbackFunctions.cpp | 57 ++++++++++++--------- VisualCraft/VCWind.cpp | 3 ++ VisualCraft/VCWind_export.cpp | 74 +++++++++++++-------------- VisualCraftL/BlockStateList.cpp | 17 +++---- VisualCraftL/BlockStateList.h | 45 ++++++++--------- VisualCraftL/TokiVC.cpp | 83 +++++++++++++++++-------------- VisualCraftL/TokiVC.h | 20 ++++---- VisualCraftL/TokiVC_build.cpp | 49 ++++++++---------- VisualCraftL/VisualCraftL.cpp | 7 +-- 11 files changed, 193 insertions(+), 181 deletions(-) diff --git a/VisualCraft/BlockBrowser.cpp b/VisualCraft/BlockBrowser.cpp index 073494cc..57a843ae 100644 --- a/VisualCraft/BlockBrowser.cpp +++ b/VisualCraft/BlockBrowser.cpp @@ -33,7 +33,7 @@ BlockBrowser::BlockBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::BlockBrowser) { ui->setupUi(this); - this->fecth_content(); + this->fetch_content(); connect(this->ui->combobox_select_blk, &QComboBox::currentIndexChanged, this, &BlockBrowser::update_display); @@ -52,8 +52,8 @@ const VCWind *BlockBrowser::parent() const noexcept { return dynamic_cast(QWidget::parentWidget()); } -void BlockBrowser::fecth_content() noexcept { - // fecth content for avaliable blocks +void BlockBrowser::fetch_content() noexcept { + // fetch content for available blocks this->ui->combobox_select_blk->clear(); this->ui->combobox_select_face->clear(); @@ -141,7 +141,6 @@ void BlockBrowser::fecth_content() noexcept { } void BlockBrowser::update_display() noexcept { - if (this->ui->combobox_select_blk->currentIndex() < 0) { return; } diff --git a/VisualCraft/BlockBrowser.h b/VisualCraft/BlockBrowser.h index 3217ef7b..7677ea3b 100644 --- a/VisualCraft/BlockBrowser.h +++ b/VisualCraft/BlockBrowser.h @@ -37,20 +37,20 @@ class VCWind; class BlockBrowser : public QWidget { Q_OBJECT -private: + private: Ui::BlockBrowser *ui; - void fecth_content() noexcept; + void fetch_content() noexcept; -private slots: - // manuually connected + private slots: + // manually connected void update_display() noexcept; // auto connected void on_pb_save_current_image_clicked() noexcept; void on_combobox_select_blk_all_currentIndexChanged(int idx) noexcept; -public: + public: explicit BlockBrowser(QWidget *parent); ~BlockBrowser(); @@ -58,4 +58,4 @@ private slots: const VCWind *parent() const noexcept; }; -#endif // SLOPECRAFT_VISUALCRAFT_BLOCKBROWSER_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_BLOCKBROWSER_H \ No newline at end of file diff --git a/VisualCraft/CallbackFunctions.cpp b/VisualCraft/CallbackFunctions.cpp index 614f22a7..0435a282 100644 --- a/VisualCraft/CallbackFunctions.cpp +++ b/VisualCraft/CallbackFunctions.cpp @@ -23,6 +23,7 @@ This file is part of SlopeCraft. #include "CallbackFunctions.h" #include #include +#include QWidget *VC_callback::wind{nullptr}; @@ -31,37 +32,45 @@ void VC_callback::callback_receive_report(VCL_report_type_t type, bool flush) noexcept { static std::stringstream ss_warning; - switch (type) { - case VCL_report_type_t::information: { - QMessageBox::information(wind, "Information", QString::fromLocal8Bit(msg)); - return; + QWidget *wind_ptr{nullptr}; + if (wind != nullptr && QThread::currentThread() == wind->thread()) { + wind_ptr == wind; } - case VCL_report_type_t::warning: { - ss_warning << msg; - if (flush) { - std::string res; - ss_warning >> res; + switch (type) { + case VCL_report_type_t::information: { + QMessageBox::information(wind_ptr, "Information", + QString::fromLocal8Bit(msg)); + return; + } + case VCL_report_type_t::warning: { + ss_warning << msg; + + if (flush) { + std::string res; + ss_warning >> res; - if (res.empty()) { - return; + if (res.empty()) { + return; + } + QMessageBox::warning(wind_ptr, "Warning", QString::fromLocal8Bit(res)); } - QMessageBox::warning(wind, "Warning", QString::fromLocal8Bit(res)); + return; } - return; - } - case VCL_report_type_t::error: { - auto ret = QMessageBox::critical( - wind, "Fatal error", QString::fromLocal8Bit(msg), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); + case VCL_report_type_t::error: { + QString text = QString::fromLocal8Bit(msg); + + auto ret = QMessageBox::critical( + wind_ptr, "Fatal error", text, + QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, + QMessageBox::StandardButton::Ignore}, + QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Close) { - exit(1919810); + if (ret == QMessageBox::StandardButton::Close) { + exit(1919810); + } + return; } - return; - } } abort(); } \ No newline at end of file diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 4d80000e..b21e6543 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -498,6 +498,9 @@ void VCWind::setup_basical_colorset() noexcept { const bool success = VCL_set_resource_move(&rp, &bsl, option); + VCL_destroy_block_state_list(bsl); + VCL_destroy_resource_pack(rp); + if (!success) { const auto ret = QMessageBox::critical( this, VCWind::tr("资源包/方块状态列表 json 解析失败"), diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 842359ac..1b92b66b 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -90,13 +90,12 @@ void VCWind::flush_export_tabel() noexcept { } void VCWind::on_pb_select_export_dir_clicked() noexcept { - if (this->ui->combobox_export_type->currentIndex() < 0) { QMessageBox::warning( this, VCWind::tr("错误操作"), VCWind::tr( - "设置任何一种导出类型的输出位置时,都需要在左侧的combo " - "box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。"), + "设置任何一种导出类型的输出位置时,都需要在左侧的 combo " + "box 中选择一个导出类型。请先选择一种导出类型,再设置导出位置。"), QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok}); return; } @@ -111,30 +110,30 @@ void VCWind::on_pb_select_export_dir_clicked() noexcept { bool strip_image_extension = true; int dest_col = -1; switch (this->ui->combobox_export_type->currentIndex()) { - case 0: - suffix = ".litematic"; - dest_col = VCWind::export_col_lite; - break; - case 1: - suffix = ".nbt"; - dest_col = VCWind::export_col_structure; - break; - case 2: - suffix = ".schem"; - dest_col = VCWind::export_col_schem; - break; - case 3: - suffix = ""; - dest_col = VCWind::export_col_converted; - strip_image_extension = false; - break; - case 4: - suffix = ".png"; - dest_col = VCWind::export_col_flagdiagram; - break; - default: - abort(); - return; + case 0: + suffix = ".litematic"; + dest_col = VCWind::export_col_lite; + break; + case 1: + suffix = ".nbt"; + dest_col = VCWind::export_col_structure; + break; + case 2: + suffix = ".schem"; + dest_col = VCWind::export_col_schem; + break; + case 3: + suffix = ""; + dest_col = VCWind::export_col_converted; + strip_image_extension = false; + break; + case 4: + suffix = ".png"; + dest_col = VCWind::export_col_flagdiagram; + break; + default: + abort(); + return; } const int c = dest_col; @@ -173,8 +172,8 @@ bool VCWind::export_lite(const QString &lite_dest, this->ui->pte_lite_regionname->toPlainText().toUtf8().data()); if (!success) { const auto ret = QMessageBox::critical( - this, VCWind::tr("导出litematica失败"), - VCWind::tr("VisualCraftL不能为图像\"%1\"生成投影文件\"%2\"。") + this, VCWind::tr("导出 litematica 失败"), + VCWind::tr("VisualCraftL 不能为图像\"%1\"生成投影文件\"%2\"。") .arg(image_filename) .arg(lite_dest), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, @@ -198,7 +197,7 @@ bool VCWind::export_structure(const QString &nbt_dest, if (!success) { const auto ret = QMessageBox::critical( this, VCWind::tr("导出原版结构方块文件失败"), - VCWind::tr("VisualCraftL不能为图像\"%1\"生成结构方块文件\"%2\"。") + VCWind::tr("VisualCraftL 不能为图像\"%1\"生成结构方块文件\"%2\"。") .arg(image_filename) .arg(nbt_dest), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, @@ -239,8 +238,9 @@ bool VCWind::export_schem(const QString &schem_dest, mods_charp.data(), mods_charp.size()); if (!success) { const auto ret = QMessageBox::critical( - this, VCWind::tr("导出World Edit原理图失败"), - VCWind::tr("VisualCraftL不能为图像\"%1\"生成World Edit原理图\"%2\"。") + this, VCWind::tr("导出 World Edit 原理图失败"), + VCWind::tr( + "VisualCraftL 不能为图像\"%1\"生成 World Edit 原理图\"%2\"。") .arg(image_filename) .arg(schem_dest), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, @@ -262,7 +262,7 @@ bool VCWind::export_converted(const QString &converted_image_dest_path, if (!success) { const auto ret = QMessageBox::critical( this, VCWind::tr("保存转化后图像失败"), - VCWind::tr("QImage未能生成\"%1\"。").arg(converted_image_dest_path), + VCWind::tr("QImage 未能生成\"%1\"。").arg(converted_image_dest_path), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}, QMessageBox::StandardButton::Close); @@ -282,7 +282,7 @@ bool VCWind::export_flatdiagram(const QString &diagram_dest) noexcept { const auto ret = QMessageBox::critical( this, VCWind::tr("平面示意图输入错误"), VCWind::tr("应输入%1个以\";\"分隔的文件名,但实际上输入了%" - "2个。\n您输入的%2个文件名是:\n%3") + "2 个。\n您输入的%2个文件名是:\n%3") .arg(VCL_get_max_block_layers()) .arg(qsl.size()) .arg(diagram_dest), @@ -351,8 +351,8 @@ void VCWind::on_pb_execute_clicked() noexcept { if (it == this->image_cache.end()) { QMessageBox::critical( this, VCWind::tr("致命逻辑错误"), - VCWind::tr("导出页码表格中的图片\"%1\"不能在this->image_" - "cache中找到对应的缓存。请将这个错误反馈给软件开发者。") + VCWind::tr("导出页码表格中的图片\"%1\"不能在 this->image_" + "cache 中找到对应的缓存。请将这个错误反馈给软件开发者。") .arg(image_filename)); abort(); } @@ -433,7 +433,7 @@ void VCWind::on_pb_execute_clicked() noexcept { if (!success) { const auto ret = QMessageBox::critical( this, VCWind::tr("构建三维结构失败"), - VCWind::tr("VisualCraftL不能为图像\"%1\"构建三维结构。") + VCWind::tr("VisualCraftL 不能为图像\"%1\"构建三维结构。") .arg(image_filename), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}, diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index 404f14a1..ef035f96 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -97,14 +97,14 @@ version_set parse_version_set(const nlohmann::json &jo, return {}; } -#define VCL_PRIVATE_MACRO_PARSE_ATTRIBUTE(key_str, key_enum) \ - if (jo.contains(#key_str)) { \ - if (!jo.at(#key_str).is_boolean()) { \ - *ok = false; \ - return {}; \ - } \ - \ - ret.set_attribute(VCL_block::attribute::key_enum, jo.at(#key_str)); \ +#define VCL_PRIVATE_MACRO_PARSE_ATTRIBUTE(key_str, key_enum) \ + if (jo.contains(#key_str)) { \ + if (!jo.at(#key_str).is_boolean()) { \ + *ok = false; \ + return {}; \ + } \ + \ + ret.set_attribute(VCL_block::attribute::key_enum, jo.at(#key_str)); \ } VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { @@ -319,7 +319,6 @@ void VCL_block_state_list::update_foliages( VCL_block_class_t string_to_block_class(std::string_view str, bool *ok) noexcept { - auto ret = magic_enum::enum_cast(str); if (ok != nullptr) { *ok = ret.has_value(); diff --git a/VisualCraftL/BlockStateList.h b/VisualCraftL/BlockStateList.h index f01b050f..ba00aec2 100644 --- a/VisualCraftL/BlockStateList.h +++ b/VisualCraftL/BlockStateList.h @@ -28,29 +28,29 @@ This file is part of SlopeCraft. #include #include #include - +#include #include #include "VisualCraftL.h" constexpr inline size_t major_version_to_idx(SCL_gameVersion v) noexcept { switch (v) { - case SCL_gameVersion::FUTURE: - return 31; + case SCL_gameVersion::FUTURE: + return 31; - default: - return size_t(v); + default: + return size_t(v); } } class version_set { -private: + private: std::bitset<32> set{0}; -public: + public: version_set() = default; - version_set(uint32_t val) : set(val) {} + explicit version_set(uint32_t val) : set(val) {} static version_set all() noexcept { version_set ret(~uint32_t(0)); @@ -88,10 +88,9 @@ class version_set { class VCL_block_state_list; class VCL_block { - friend class VCL_block_state_list; -public: + public: VCL_block(); VCL_block(const std::string *full_id_ptr); @@ -181,7 +180,6 @@ class VCL_block { } inline const std::string &id_for_schem(SCL_gameVersion v) const noexcept { - for (const auto &pair : this->id_replace_list) { if (pair.first == v) { return pair.second; @@ -190,22 +188,22 @@ class VCL_block { return *this->full_id_p; } -private: + private: void initialize_attributes() noexcept; // members -public: + public: version_set version_info; -private: + private: std::bitset<32> attributes; -public: + public: VCL_block_class_t block_class{VCL_block_class_t::others}; -private: + private: const std::string *full_id_p{nullptr}; -public: + public: Eigen::Array project_image_on_exposed_face{0, 0}; std::string name_ZH{""}; @@ -214,15 +212,16 @@ class VCL_block { }; class VCL_block_state_list { -private: + private: std::unordered_map states; -public: + public: + using is_allowed_callback_t = std::function; bool add(std::string_view filename) noexcept; - void - available_block_states(SCL_gameVersion v, VCL_face_t f, - std::vector *const str_list) noexcept; + void available_block_states( + SCL_gameVersion v, VCL_face_t f, + std::vector *const str_list) noexcept; void avaliable_block_states_by_transparency( SCL_gameVersion v, VCL_face_t f, @@ -248,4 +247,4 @@ class VCL_block_state_list { VCL_block_class_t string_to_block_class(std::string_view str, bool *ok = nullptr) noexcept; -#endif // SLOPECRAFT_VISUALCRAFT_BLOCKSTATELIST_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_BLOCKSTATELIST_H \ No newline at end of file diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index df901a54..877d75d3 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -80,7 +80,7 @@ bool is_basic_color_set_ready = false; bool is_allowed_color_set_ready = false; std::set TokiVC_register; -} // namespace TokiVC_internal +} // namespace TokiVC_internal TokiVC::TokiVC() { TokiVC_internal::global_lock.lock(); @@ -342,7 +342,6 @@ bool compare_blocks_variant( const std::variant> &a, const std::variant> &b) noexcept { - if (blocks_count(a) != blocks_count(b)) { return blocks_count(a) < blocks_count(b); } @@ -364,7 +363,6 @@ void convert_blocks_and_colors_from_hash_vector( std::vector> &colors_temp, std::vector>> &LUT_bcitb) noexcept { - std::vector selected_variants; selected_variants.reserve(src.size()); @@ -411,15 +409,15 @@ void convert_blocks_and_colors_from_hash_vector( bool TokiVC::set_resource_no_lock() noexcept { switch (TokiVC::version) { - case SCL_gameVersion::ANCIENT: - case SCL_gameVersion::FUTURE: { - std::string msg = - fmt::format("Invalid MC version : {}\n", int(TokiVC::version)); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - default: - break; + case SCL_gameVersion::ANCIENT: + case SCL_gameVersion::FUTURE: { + std::string msg = + fmt::format("Invalid MC version : {}\n", int(TokiVC::version)); + VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + default: + break; } TokiVC::pack.set_is_MC12(TokiVC::version == SCL_gameVersion::MC12); @@ -551,26 +549,45 @@ bool TokiVC::set_resource_no_lock() noexcept { return true; } -bool TokiVC::set_allowed_no_lock(const VCL_block *const *const blocks_allowed, - size_t num_block_allowed) noexcept { +bool is_color_allowed( + const std::variant> + &variant, + const std::unordered_map + &blks_allowed) noexcept { + if (variant.index() == 0) { + return blks_allowed.contains(std::get<0>(variant)); + } else { + const auto &blocks = std::get<1>(variant); + for (const VCL_block *blkp : blocks) { + if (!blks_allowed.contains(blkp)) { + return false; + // here continue only skips one for loop! + } + } + return true; + } +} + +bool TokiVC::set_allowed_no_lock( + std::span blocks_ptr_allowed) noexcept { if (!TokiVC_internal::is_basic_color_set_ready) { - VCL_report( - VCL_report_type_t::error, - "You can not set the allowed blocks before basic color set is ready."); + VCL_report(VCL_report_type_t::error, + "You can not set the allowed blocks before basic color set is " + "ready."); return false; } TokiVC::blocks_allowed.clear(); - TokiVC::blocks_allowed.reserve(num_block_allowed); + TokiVC::blocks_allowed.reserve(blocks_ptr_allowed.size()); - for (size_t i = 0; i < num_block_allowed; i++) { - if (blocks_allowed[i] == nullptr || - blocks_allowed[i]->full_id_ptr() == nullptr) { + for (size_t i = 0; i < blocks_ptr_allowed.size(); i++) { + if (blocks_ptr_allowed[i] == nullptr || + blocks_ptr_allowed[i]->full_id_ptr() == nullptr) { VCL_report(VCL_report_type_t::error, "Invalid VCL_block pointer."); return false; } - TokiVC::blocks_allowed.emplace(blocks_allowed[i], 0xFFFF); + TokiVC::blocks_allowed.emplace(blocks_ptr_allowed[i], 0xFFFF); } { @@ -589,7 +606,7 @@ bool TokiVC::set_allowed_no_lock(const VCL_block *const *const blocks_allowed, if (counter_air != 1) { std::string msg = - fmt::format("Types of air block is {}, expected 1.", counter_air); + fmt::format("Types of air block is {}, but expected 1.", counter_air); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -597,7 +614,7 @@ bool TokiVC::set_allowed_no_lock(const VCL_block *const *const blocks_allowed, std::vector allowed_list; allowed_list.resize(TokiVC::LUT_basic_color_idx_to_blocks.size()); - memset(allowed_list.data(), 0, allowed_list.size()); + std::fill(allowed_list.begin(), allowed_list.end(), 0); if constexpr (false) { std::string msg = fmt::format("TokiVC::colorset_basic.color_count() = {}.", @@ -608,24 +625,14 @@ bool TokiVC::set_allowed_no_lock(const VCL_block *const *const blocks_allowed, for (size_t idx = 0; idx < TokiVC::LUT_basic_color_idx_to_blocks.size(); idx++) { const auto &variant = LUT_basic_color_idx_to_blocks[idx]; - // allowed_list[idx] = false; - if (variant.index() == 0) { - if (!TokiVC::blocks_allowed.contains(std::get<0>(variant))) { - continue; - } - } else { - for (const VCL_block *blkp : std::get<1>(variant)) { - if (!TokiVC::blocks_allowed.contains(blkp)) { - continue; - } - } + if (is_color_allowed(variant, TokiVC::blocks_allowed)) { + allowed_list[idx] = 1; } - - allowed_list[idx] = true; } + if (!TokiVC::colorset_allowed.apply_allowed( TokiVC::colorset_basic, - reinterpret_cast(allowed_list.data()))) { + reinterpret_cast(allowed_list.data()))) { VCL_report(VCL_report_type_t::error, "Function \"TokiVC::colorset_allowed.apply_allowed\" failed."); return false; diff --git a/VisualCraftL/TokiVC.h b/VisualCraftL/TokiVC.h index dcd4c134..a8e3a671 100644 --- a/VisualCraftL/TokiVC.h +++ b/VisualCraftL/TokiVC.h @@ -37,19 +37,19 @@ This file is part of SlopeCraft. #include class VCL_GPU_Platform { -public: + public: ~VCL_GPU_Platform() { gpu_wrapper::platform_wrapper::destroy(this->pw); } gpu_wrapper::platform_wrapper *pw{nullptr}; }; class VCL_GPU_Device { -public: + public: ~VCL_GPU_Device() { gpu_wrapper::device_wrapper::destroy(this->dw); } gpu_wrapper::device_wrapper *dw{nullptr}; }; class TokiVC : public VCL_Kernel { -public: + public: TokiVC(); virtual ~TokiVC(); void set_ui(void *uiptr, void (*progressRangeSet)(void *, int, int, int), @@ -138,7 +138,7 @@ class TokiVC : public VCL_Kernel { const char *const *const utf8_requiredMods = nullptr, const int requiredModsCount = 0) const noexcept override; -public: + public: static libImageCvt::template ImageCvter::basic_colorset_t colorset_basic; static libImageCvt::template ImageCvter::allowed_colorset_t @@ -153,8 +153,8 @@ class TokiVC : public VCL_Kernel { static VCL_biome_t biome; static bool set_resource_no_lock() noexcept; - static bool set_allowed_no_lock(const VCL_block *const *const blocks_allowed, - size_t num_block_allowed) noexcept; + static bool set_allowed_no_lock( + std::span blocks_ptr_allowed) noexcept; static bool export_test_litematic_no_lock(const char *filename) noexcept; @@ -162,14 +162,14 @@ class TokiVC : public VCL_Kernel { return TokiVC::LUT_basic_color_idx_to_blocks; } -private: + private: static std::vector< std::variant>> LUT_basic_color_idx_to_blocks; static std::unordered_map blocks_allowed; -private: + private: VCL_Kernel_step _step{VCL_Kernel_step::VCL_wait_for_resource}; bool imgcvter_prefer_gpu{false}; @@ -187,6 +187,6 @@ namespace TokiVC_internal { extern std::shared_mutex global_lock; extern bool is_basic_color_set_ready; extern bool is_allowed_color_set_ready; -} // namespace TokiVC_internal +} // namespace TokiVC_internal -#endif // SLOPECRAFT_VISUALCRAFTL_TOKIVC_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFTL_TOKIVC_H \ No newline at end of file diff --git a/VisualCraftL/TokiVC_build.cpp b/VisualCraftL/TokiVC_build.cpp index 6b7202dc..c28880aa 100644 --- a/VisualCraftL/TokiVC_build.cpp +++ b/VisualCraftL/TokiVC_build.cpp @@ -49,12 +49,9 @@ int64_t TokiVC::xyz_size(int64_t *x, int64_t *y, int64_t *z) const noexcept { return -1; } - if (x != nullptr) - *x = this->schem.x_range(); - if (y != nullptr) - *y = this->schem.y_range(); - if (z != nullptr) - *z = this->schem.z_range(); + if (x != nullptr) *x = this->schem.x_range(); + if (y != nullptr) *y = this->schem.y_range(); + if (z != nullptr) *z = this->schem.z_range(); return this->schem.size(); } @@ -80,10 +77,10 @@ bool TokiVC::build() noexcept { std::atomic_bool ret = true; const Eigen::ArrayXX color_id_mat = this->img_cvter.color_id(); -#pragma omp parallel for schedule(static) +#warning resume omp here + // #pragma omp parallel for schedule(static) for (int64_t r = 0; r < this->img_cvter.rows(); r++) { for (int64_t c = 0; c < this->img_cvter.cols(); c++) { - const auto &variant = TokiVC::LUT_basic_color_idx_to_blocks[color_id_mat(r, c)]; @@ -106,7 +103,7 @@ bool TokiVC::build() noexcept { for (size_t di = 0; di < 3; di++) { if (coord[di] < 0 || coord[di] >= range[di]) { std::string msg = - fmt::format("coordiante out of range : {}, {}, {}.\n", coord[0], + fmt::format("coordinate out of range : {}, {}, {}.\n", coord[0], coord[1], coord[2]); VCL_report(VCL_report_type_t::error, msg.c_str()); } @@ -116,10 +113,10 @@ bool TokiVC::build() noexcept { auto it = TokiVC::blocks_allowed.find(blkp); if (it == TokiVC::blocks_allowed.end()) { - std::string msg = - fmt::format("Failed to find VCL_block at address {} named {} in " - "allowed blocks. This is an internal error.", - (const void *)blkp, blkp->full_id_ptr()->c_str()); + std::string msg = fmt::format( + "Failed to find VCL_block at address {} named {} in " + "allowed blocks. This is an internal error.", + (const void *)blkp, blkp->full_id_ptr()->c_str()); VCL_report(VCL_report_type_t::error, msg.c_str()); ret = false; } @@ -143,7 +140,6 @@ bool TokiVC::build() noexcept { bool TokiVC::export_litematic(const char *localEncoding_filename, const char *utf8_litename, const char *utf8_regionname) const noexcept { - std::shared_lock lkgd(TokiVC_internal::global_lock); if (this->_step < VCL_Kernel_step::VCL_built) { @@ -171,10 +167,10 @@ bool TokiVC::export_litematic(const char *localEncoding_filename, &flag, &detail); if (!ok) { - std::string err = - fmt::format("VisualCraftL failed to export a litematic. Error " - "number(SCSL_errorFlag) = {}, detail : {}", - int(flag), detail); + std::string err = fmt::format( + "VisualCraftL failed to export a litematic. Error " + "number(SCSL_errorFlag) = {}, detail : {}", + int(flag), detail); VCL_report(VCL_report_type_t::error, err.c_str()); return false; } @@ -183,7 +179,6 @@ bool TokiVC::export_litematic(const char *localEncoding_filename, bool TokiVC::export_structure(const char *localEncoding_TargetName, bool is_air_structure_void) const noexcept { - std::shared_lock lkgd(TokiVC_internal::global_lock); if (this->_step < VCL_Kernel_step::VCL_built) { @@ -198,10 +193,10 @@ bool TokiVC::export_structure(const char *localEncoding_TargetName, localEncoding_TargetName, is_air_structure_void, &flag, &detail); if (!ok) { - std::string err = - fmt::format("VisualCraftL failed to export a structure. Error " - "number(SCSL_errorFlag) = {}, detail : {}", - int(flag), detail); + std::string err = fmt::format( + "VisualCraftL failed to export a structure. Error " + "number(SCSL_errorFlag) = {}, detail : {}", + int(flag), detail); VCL_report(VCL_report_type_t::error, err.c_str()); return false; } @@ -239,10 +234,10 @@ bool TokiVC::export_WESchem(const char *localEncoding_fileName, const bool ok = this->schem.export_WESchem(localEncoding_fileName, info, &flag, &detail); if (!ok) { - std::string err = - fmt::format("VisualCraftL failed to export a WorldEdit schem. Error " - "number(SCSL_errorFlag) = {}, detail : {}", - int(flag), detail); + std::string err = fmt::format( + "VisualCraftL failed to export a WorldEdit schem. Error " + "number(SCSL_errorFlag) = {}, detail : {}", + int(flag), detail); VCL_report(VCL_report_type_t::error, err.c_str()); return false; } diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 52f76cee..c15923ca 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -26,6 +26,7 @@ This file is part of SlopeCraft. #include #include +#include #include "BlockStateList.h" #include "ParseResourcePack.h" @@ -511,7 +512,7 @@ VCL_EXPORT_FUN bool VCL_set_allowed_blocks( const VCL_block *const *const blocks_allowed, size_t num_block_allowed) { std::unique_lock lkgd(TokiVC_internal::global_lock); - return TokiVC::set_allowed_no_lock(blocks_allowed, num_block_allowed); + return TokiVC::set_allowed_no_lock({blocks_allowed, num_block_allowed}); } VCL_EXPORT_FUN void VCL_discard_allowed_blocks() { std::unique_lock lkgd(TokiVC_internal::global_lock); @@ -560,7 +561,7 @@ VCL_EXPORT_FUN size_t VCL_get_allowed_color_id( std::shared_lock lkgd(TokiVC_internal::global_lock); if (!TokiVC_internal::is_basic_color_set_ready || - !TokiVC_internal::is_basic_color_set_ready) { + !TokiVC_internal::is_allowed_color_set_ready) { return 0; } @@ -785,7 +786,7 @@ VCL_EXPORT_FUN bool VCL_compare_block(const VCL_block *b1, } } - return std::less()(*b1->full_id_ptr(), *b2->full_id_ptr()); + return std::less()(*b1->full_id_ptr(), *b2->full_id_ptr()); } VCL_EXPORT_FUN VCL_block_class_t VCL_string_to_block_class(const char *str, From ec199b27746a07eea15115b746fb1b42ecfbcf26 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 30 May 2023 13:36:26 +0800 Subject: [PATCH 0392/1123] update translation --- SlopeCraft/SCWind.ui | 35 ++++- SlopeCraft/others/SlopeCraft_en_US.ts | 195 +++++++++++++++--------- VisualCraft/others/VisualCraft_en_US.ts | 124 ++++++++++----- 3 files changed, 234 insertions(+), 120 deletions(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 20ac7f60..9a3a0dbb 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -7,7 +7,7 @@ 0 0 920 - 740 + 865
@@ -18,7 +18,7 @@ - 0 + 2 @@ -305,8 +305,8 @@ 0 0 - 753 - 539 + 731 + 619 @@ -1372,6 +1372,31 @@
+ + + + + + + others/images/map_icon.png + + + + + + + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 + +在下面的表格里可以看到每个图像对应的文件名。 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + @@ -1388,7 +1413,7 @@ 0 0 920 - 22 + 27
diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 4ad4e552..14b35a27 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -113,6 +113,34 @@ All tasks finished
+ + CompressEffectViewer + + + 预览压缩效果 + Compress effect + + + + 保存图像 + + + + + 保存压缩后图片 + + + + + 保存图像失败 + Failed to save image + + + + 无法保存图像 %1 + + + ExportTableModel @@ -1170,7 +1198,7 @@ Click "Yes" to continue and replace these files, or click "No&quo - + 保存当前预设 Save as preset @@ -1281,8 +1309,8 @@ Click "Yes" to continue and replace these files, or click "No&quo - - + + 保存转化后图像 Save converted image @@ -1510,93 +1538,102 @@ Click "Yes" to continue and replace these files, or click "No&quo Map beginning index: - + + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 + +在下面的表格里可以看到每个图像对应的文件名。 + 💡tips: Set the beginning index and then click "Export", then select the directory to export map data files. + +Filenames of each image can be seen in the table below. + + + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ @@ -1730,178 +1767,186 @@ Detail information: Click Ok to ignore, and click Close to exit SlopeCraft. - + 选择图片 Select Image - + 打开图像失败 Failed to open image - + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. Detailed information: %2 - + 选择预设文件 Select a preset file - + 解析预设文件失败 Failed to parse thes preset file - + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 - + 保存预设文件失败 Failed to save preset file - + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 - - - - + + + + + 未选择图像 No image selected - - - + + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - + + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - + + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - + + + 尚未构建三维结构 3d structure not built - + + + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -1910,29 +1955,29 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + 版权所有 © 2021-2023 SlopeCraft 开发者 Copyright © 2021-2023 SlopeCraft deveploers @@ -1997,38 +2042,38 @@ Click Ignore to skip, Retry to retry and Cancel to cancel Writing meta data - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index a7269473..3a2dd9ab 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -72,7 +72,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 保存当前图片 Save current image @@ -136,7 +136,7 @@ If you select a block in "Avaliable blocks" page, the other page will - + 方块类别: Block class: @@ -146,12 +146,12 @@ If you select a block in "Avaliable blocks" page, the other page will Impossible error - + 保存图片失败 Failed to save image. - + 不知道怎么回事,反正就是没存上。 I don't know why. @@ -706,13 +706,13 @@ If you select a block in "Avaliable blocks" page, the other page will Select resource pack - + 资源包解析失败 Failed to parse resource pack - - + + 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. @@ -727,57 +727,57 @@ If you select a block in "Avaliable blocks" page, the other page will Select block id json file - + 方块状态列表 json 解析失败 Failed to parse block state json list - + 资源包/方块状态列表 json 解析失败 The resource pack or block list json failed to be parsed - + 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. - + 设置可用方块失败 Failed to set avaliable blocks - + 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. - + 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) - + 选择图片(可多选) Select images - + 读取图片失败 Failed to load image. - + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. - + 设置图片失败 Failed to set image - + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. @@ -873,26 +873,78 @@ If you select a block in "Avaliable blocks" page, the other page will %1 rows, %2 cols - + 错误操作 Invalid operation - - 设置任何一种导出类型的输出位置时,都需要在左侧的combo box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 + + 设置任何一种导出类型的输出位置时,都需要在左侧的 combo box 中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 When you set the output directory for any type of export, you should select the type of export with the combobox in the left. Please select a type first. + + + 导出 litematica 失败 + Failed to export as litematic + + + + VisualCraftL 不能为图像"%1"生成投影文件"%2"。 + VisualCraft failed to generate litematic file "%2" for image "%1". + + + + VisualCraftL 不能为图像"%1"生成结构方块文件"%2"。 + VisualCraft failed to generate structure file "%2" for image "%1". + + + + 导出 World Edit 原理图失败 + Failed to export as WE schematic + + + + VisualCraftL 不能为图像"%1"生成 World Edit 原理图"%2"。 + VisualCraft failed to generate WE schematic file "%2" for image "%1". + + + + QImage 未能生成"%1"。 + QImage failed to generate "%1". + + + + 应输入%1个以";"分隔的文件名,但实际上输入了%2 个。 +您输入的%2个文件名是: +%3 + You should input %1 filenames separeted by ";", but %2 is(are) given infact. +The %2 filename(s) you give is: +%3 + + + + 导出页码表格中的图片"%1"不能在 this->image_cache 中找到对应的缓存。请将这个错误反馈给软件开发者。 + Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. + + + + VisualCraftL 不能为图像"%1"构建三维结构。 + VisualCraft failed to build 3D structure for image "%1". + + + 设置任何一种导出类型的输出位置时,都需要在左侧的combo box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 + When you set the output directory for any type of export, you should select the type of export with the combobox in the left. Please select a type first. + 平面示意图输入错误 Invalid input for flatdiagram - 应输入%1个以";"分隔的文件名,但实际上输入了%2个。 您输入的%2个文件名是: %3 - You should input %1 filenames separeted by ";", but %2 is(are) given infact. + You should input %1 filenames separeted by ";", but %2 is(are) given infact. The %2 filename(s) you give is: %3 @@ -912,9 +964,8 @@ The %2 filename(s) you give is: Impossible error - 导出页码表格中的图片"%1"不能在this->image_cache中找到对应的缓存。请将这个错误反馈给软件开发者。 - Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. + Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. @@ -922,9 +973,8 @@ The %2 filename(s) you give is: Failed to save the converted image - QImage未能生成"%1"。 - QImage failed to generate "%1". + QImage failed to generate "%1". @@ -932,39 +982,33 @@ The %2 filename(s) you give is: Failed to build 3D structure - VisualCraftL不能为图像"%1"构建三维结构。 - VisualCraft failed to build 3D structure for image "%1". + VisualCraft failed to build 3D structure for image "%1". - 导出litematica失败 - Failed to export as litematic + Failed to export as litematic - VisualCraftL不能为图像"%1"生成投影文件"%2"。 - VisualCraft failed to generate litematic file "%2" for image "%1". + VisualCraft failed to generate litematic file "%2" for image "%1". - + 导出原版结构方块文件失败 Failed to export as vanilla structure - VisualCraftL不能为图像"%1"生成结构方块文件"%2"。 - VisualCraft failed to generate structure file "%2" for image "%1". + VisualCraft failed to generate structure file "%2" for image "%1". - 导出World Edit原理图失败 - Failed to export as WE schematic + Failed to export as WE schematic - VisualCraftL不能为图像"%1"生成World Edit原理图"%2"。 - VisualCraft failed to generate WE schematic file "%2" for image "%1". + VisualCraft failed to generate WE schematic file "%2" for image "%1". From cccd14fbf0f7ddd1e0adc9c43c53a680cd02833d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 31 May 2023 19:41:26 +0800 Subject: [PATCH 0393/1123] add map icon --- SlopeCraft/others/images/map_icon.png | Bin 0 -> 5546 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 SlopeCraft/others/images/map_icon.png diff --git a/SlopeCraft/others/images/map_icon.png b/SlopeCraft/others/images/map_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9cb5e28d225bce46d64bc7cce20cd3f0a2c3787e GIT binary patch literal 5546 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 literal 0 HcmV?d00001 From 8032df492c67ab72e9d87f5cf1be74200b669289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 31 May 2023 19:41:43 +0800 Subject: [PATCH 0394/1123] rewrite ySlice2TokiMap_u16 --- SlopeCraftL/PrimGlassBuilder.cpp | 18 ++++++++++++++++++ SlopeCraftL/PrimGlassBuilder.h | 10 ++++++++-- SlopeCraftL/TokiSlopeCraft_build.cpp | 25 ++----------------------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/PrimGlassBuilder.cpp index 3630c728..d6d0c60e 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/PrimGlassBuilder.cpp @@ -479,4 +479,22 @@ TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { return impl_ySlice2TokiMap(raw); +} + +TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, + std::span start_xzy, + std::span extension_xzy) noexcept { + // assert(raw.dimension(2) == 1); + assert(extension_xzy[2] == 1); + + TokiMap result; + + result.setZero(extension_xzy[0], extension_xzy[1]); + for (int x = 0; x < result.rows(); x++) { + for (int z = 0; z < result.cols(); z++) { + if (xzy(x + start_xzy[0], z + start_xzy[1], start_xzy[2]) > 1) + result(x, z) = PrimGlassBuilder::target; + } + } + return result; } \ No newline at end of file diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/PrimGlassBuilder.h index 7049b81f..49f19b14 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/PrimGlassBuilder.h @@ -35,6 +35,7 @@ This file is part of SlopeCraft. #include #include #include +#include // using namespace Eigen; @@ -77,8 +78,13 @@ class pairedEdge : public std::pair { void drawEdge(glassMap &, bool drawHead = false) const; }; -TokiMap ySlice2TokiMap(const Eigen::Tensor &) noexcept; -TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &) noexcept; +[[deprecated]] TokiMap ySlice2TokiMap( + const Eigen::Tensor &) noexcept; +[[deprecated]] TokiMap ySlice2TokiMap_u16( + const Eigen::Tensor &) noexcept; +TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, + std::span start_xzy, + std::span extension_xzy) noexcept; glassMap connectBetweenLayers(const TokiMap &, const TokiMap &, walkableMap *walkable); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index d97b1f9e..9213e396 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -442,10 +442,9 @@ void TokiSlopeCraft::makeBridge() { extension[0] = schem.x_range(); extension[1] = schem.z_range(); extension[2] = 1; - TokiMap targetMap = - ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); + TokiMap targetMap = ySlice2TokiMap_u16(schem.tensor(), start, extension); glassMap glass; - cerr << "Construct glass bridge at y=" << y << endl; + // cerr << "Construct glass bridge at y=" << y << endl; glass = glassBuilder->makeBridge(targetMap); for (int r = 0; r < glass.rows(); r++) for (int c = 0; c < glass.cols(); c++) @@ -454,26 +453,6 @@ void TokiSlopeCraft::makeBridge() { schem(r, y, c) = PrimGlassBuilder::glass; } else { continue; - std::array start, extension; - start[0] = 0; - start[1] = y; - start[2] = 0; - extension[0] = schem.x_range(); - extension[1] = 1; - extension[2] = schem.z_range(); - TokiMap yCur = ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); - start[1] = y - 1; - TokiMap yBelow = - ySlice2TokiMap_u16(schem.tensor().slice(start, extension)); - cerr << "Construct glass bridge between y=" << y << " and y=" << y - 1 - << endl; - glassMap glass = connectBetweenLayers(yCur, yBelow, nullptr); - - for (int r = 0; r < glass.rows(); r++) - for (int c = 0; c < glass.cols(); c++) - if (schem(r, y, c) == PrimGlassBuilder::air && - glass(r, c) == PrimGlassBuilder::glass) - schem(r, y, c) = PrimGlassBuilder::glass; } } algoProgressRangeSet(wind, 0, 100, 100); From dc8ad32e2c134b8961cbeb07709a8c7e08b4a354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 31 May 2023 21:08:59 +0800 Subject: [PATCH 0395/1123] fixed fmtlib compiling with clang --- cmake/configure_fmtlib.cmake | 39 +++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/cmake/configure_fmtlib.cmake b/cmake/configure_fmtlib.cmake index f62a8536..6916dad1 100644 --- a/cmake/configure_fmtlib.cmake +++ b/cmake/configure_fmtlib.cmake @@ -1,29 +1,40 @@ cmake_minimum_required(VERSION 3.14) -include(FetchContent) - set(SC_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -set(CMAKE_CXX_FLAGS "-fPIC") +set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + +find_package(fmt) -FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG "9.1.0" - OVERRIDE_FIND_PACKAGE +if(NOT ${fmt_FOUND}) + include(FetchContent) + FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG "9.1.0" + OVERRIDE_FIND_PACKAGE - # QUIET false - # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty - # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args -) + # QUIET false + # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty + # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args + ) -message(STATUS "Downaloding and building fmtlib......") + message(STATUS "Downaloding and building fmtlib......") -FetchContent_MakeAvailable(fmt) + FetchContent_MakeAvailable(fmt) + find_package(fmt REQUIRED) +endif() set(CMAKE_CXX_FLAGS ${SC_CMAKE_CXX_FLAGS}) unset(SC_CMAKE_CXX_FLAGS) +if(${MSVC}) + # enable c++ exceptions + add_compile_options("/EHsc") + + # target_compile_options(fmt::fmt INTERFACE "/EHsc") +endif() + # message(STATUS "fmt_POPULATED = " ) # message(STATUS "find_fmt_args = " ${find_fmt_args}) From 92f6bb6026bfd04aad6fdd5052a13acd73e77bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 31 May 2023 21:09:17 +0800 Subject: [PATCH 0396/1123] fixed oclwrapper compiling with clang --- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 19 +++++++++++-------- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 2 ++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index ee8dfaf1..2b097ab0 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -5,31 +5,35 @@ message(STATUS "Configuring OpenCL") include(${CMAKE_SOURCE_DIR}/cmake/find_ResourceCreator.cmake) include(${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/ResourceCreator.cmake) -add_library(OCLWrapper STATIC +target_sources(GPUInterface PRIVATE OCLWrapper.h OCLWrapper.cpp GPU_interface.cpp) if(CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(OCLWrapper PROPERTIES POSITION_INDEPENDENT_CODE TRUE) + set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) endif() # convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) add_resource_config_time(ColorManip_cl_rc ColorDiff.cl) -target_include_directories(OCLWrapper PUBLIC ${CMAKE_SOURCE_DIR}) -target_include_directories(OCLWrapper INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_features(OCLWrapper PUBLIC cxx_std_20) +target_include_directories(GPUInterface PUBLIC ${CMAKE_SOURCE_DIR}) +target_include_directories(GPUInterface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_features(GPUInterface PUBLIC cxx_std_20) find_package(Eigen3 REQUIRED) -target_link_libraries(OCLWrapper PUBLIC OpenCL::OpenCL ColorManip_cl_rc Eigen3::Eigen) +target_link_libraries(GPUInterface + PUBLIC + OpenCL::OpenCL + ColorManip_cl_rc + Eigen3::Eigen) message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) - target_compile_definitions(OCLWrapper PRIVATE SLOPECRAFT_NO_CL_HPP) + target_compile_definitions(GPUInterface PRIVATE SLOPECRAFT_NO_CL_HPP) message(STATUS "Failed to find cl.hpp. This file doesn't exists in opencl include dir. SlopeCraft assumes that opencl.hpp exists, and will try to include it.") @@ -46,7 +50,6 @@ else() message(STATUS "Found opencl C++ header: ${OpenCL_INCLUDE_DIR}/CL/cl.hpp") endif() -target_link_libraries(GPUInterface PUBLIC OCLWrapper) target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) if(${LINUX}) diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 3e371377..cee110f9 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -27,8 +27,10 @@ This file is part of SlopeCraft. #include #include +extern "C" { extern const unsigned char ColorManip_cl_rc[]; extern const unsigned int ColorManip_cl_rc_length; +} size_t ocl_warpper::platform_num() noexcept { cl_uint ret; From c049eaa7d5f15370fb1dfeac63d97bb1aeb24733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 02:04:59 +0800 Subject: [PATCH 0397/1123] fix windeployqt with clang-msvc --- CMakeLists.txt | 5 +++++ MapViewer/install.cmake | 3 ++- SlopeCraft/install.cmake | 3 ++- VisualCraft/install.cmake | 3 ++- cmake/deploy_qt.cmake.in | 2 +- cmake/find_qt6.cmake | 2 +- imageCutter/install.cmake | 3 ++- vccl/install.cmake | 3 ++- 8 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 465c35dc..bfcea1a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,11 @@ option(SlopeCraft_sanitize "Build with sanitizer" OFF) set(SlopeCraft_vccl_test_gpu_platform_idx 0 CACHE STRING "The opencl platform index used to test vccl") set(SlopeCraft_vccl_test_gpu_device_idx 0 CACHE STRING "The opencl device index used to test vccl") +if(${WIN32}) + set(SlopeCraft_windeployqt_flags_install "--no-translations;--force" CACHE STRING "Flags to run windeployqt during installation") + set(SlopeCraft_windeployqt_flags_build ${SlopeCraft_windeployqt_flags_install} CACHE STRING "Flags to run windeployqt in build dir") +endif() + # manage the install prefix -------------------------------------------------- if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 97705a9d..fcf5887d 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -11,7 +11,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at build time add_custom_target(Windeployqt-MapViewer - COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations MapViewer.exe + COMMAND ${SlopeCraft_Qt_windeployqt_executable} MapViewer.exe ${SlopeCraft_windeployqt_flags_build} + COMMAND_EXPAND_LISTS WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MapViewer) add_dependencies(SC_deploy_all Windeployqt-MapViewer) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 4d3f800b..fb4f94e4 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -65,7 +65,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at build time add_custom_target(Windeployqt-SlopeCraft - COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations SlopeCraft.exe + COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe ${SlopeCraft_windeployqt_flags_build} + COMMAND_EXPAND_LISTS WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS SlopeCraft) add_dependencies(SC_deploy_all Windeployqt-SlopeCraft) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 5038d0a6..e3686769 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -14,7 +14,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at build time add_custom_target(Windeployqt-VisualCraft - COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations VisualCraft.exe + COMMAND ${SlopeCraft_Qt_windeployqt_executable} VisualCraft.exe ${SlopeCraft_windeployqt_flags_build} + COMMAND_EXPAND_LISTS WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS VisualCraft) add_dependencies(SC_deploy_all Windeployqt-VisualCraft) diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in index 29692553..11455ec6 100644 --- a/cmake/deploy_qt.cmake.in +++ b/cmake/deploy_qt.cmake.in @@ -3,7 +3,7 @@ if(${WIN32}) message(STATUS "Running windeployqt for @AppName@ ...") execute_process( - COMMAND "@SlopeCraft_Qt_windeployqt_executable@" --no-translations "@AppName@.exe" + COMMAND "@SlopeCraft_Qt_windeployqt_executable@" "@AppName@.exe" @SlopeCraft_windeployqt_flags_install@ WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) diff --git a/cmake/find_qt6.cmake b/cmake/find_qt6.cmake index 9adfec63..1e834b73 100644 --- a/cmake/find_qt6.cmake +++ b/cmake/find_qt6.cmake @@ -46,4 +46,4 @@ endif() if(${APPLE}) find_program(SlopeCraft_Qt_macdeployqt_executable macdeployqt PATHS ${CMAKE_PREFIX_PATH}) -endif() \ No newline at end of file +endif() diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 4a2c823d..92b4aed1 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -11,7 +11,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at build time add_custom_target(Windeployqt-imageCutter - COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations imageCutter.exe + COMMAND ${SlopeCraft_Qt_windeployqt_executable} imageCutter.exe ${SlopeCraft_windeployqt_flags_build} + COMMAND_EXPAND_LISTS WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS imageCutter) add_dependencies(SC_deploy_all Windeployqt-imageCutter) diff --git a/vccl/install.cmake b/vccl/install.cmake index 93aa5710..18cd54c3 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -12,7 +12,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # Run windeployqt at build time add_custom_target(Windeployqt-vccl - COMMAND ${SlopeCraft_Qt_windeployqt_executable} --force --no-translations vccl.exe + COMMAND ${SlopeCraft_Qt_windeployqt_executable} vccl.exe ${SlopeCraft_windeployqt_flags_build} + COMMAND_EXPAND_LISTS WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS vccl) add_dependencies(SC_deploy_all Windeployqt-vccl) From 0d94c19d1516f74115cc25b33eb6351a652f2f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 02:05:10 +0800 Subject: [PATCH 0398/1123] small bugs fix --- VisualCraft/CallbackFunctions.cpp | 2 +- VisualCraft/VCWind_gpu.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/VisualCraft/CallbackFunctions.cpp b/VisualCraft/CallbackFunctions.cpp index 0435a282..29e45dab 100644 --- a/VisualCraft/CallbackFunctions.cpp +++ b/VisualCraft/CallbackFunctions.cpp @@ -34,7 +34,7 @@ void VC_callback::callback_receive_report(VCL_report_type_t type, QWidget *wind_ptr{nullptr}; if (wind != nullptr && QThread::currentThread() == wind->thread()) { - wind_ptr == wind; + wind_ptr = wind; } switch (type) { diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index 20375888..a9d9085e 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -20,16 +20,18 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include #include -#include #include #include +#include + #include "VCWind.h" #include "ui_VCWind.h" +#include + std::string get_cpu_name(bool &error) noexcept { int buffer[5]; uint8_t *const buffer_cptr = reinterpret_cast(buffer); @@ -93,7 +95,7 @@ void VCWind::refresh_gpu_info() noexcept { QString platname{}; if (plat == nullptr) { platname = - VCWind::tr("无法获取platform信息. 请检查驱动. OpenCL错误码: %1.") + VCWind::tr("无法获取 platform 信息。请检查驱动。OpenCL 错误码:%1.") .arg(errcode); } else { platname = QString::fromLocal8Bit(VCL_get_platform_name(plat)); @@ -116,7 +118,7 @@ void VCWind::refresh_gpu_info() noexcept { QString devicename{}; if (dev == nullptr) { devicename = - VCWind::tr("无法获取device信息. 请检查驱动. OpenCL错误码: %1") + VCWind::tr("无法获取 device 信息。请检查驱动。OpenCL 错误码:%1") .arg(errcode); } else { devicename = QString::fromLocal8Bit(VCL_get_device_name(dev)); @@ -197,20 +199,20 @@ QString VCWind::update_gpu_device(QPoint current_choice) noexcept { VCL_GPU_Platform *plat = VCL_get_platform(current_choice.x()); if (plat == nullptr) { - return VCWind::tr("创建GPU平台失败,平台序号为%1,设备序号为%2") + return VCWind::tr("创建 GPU 平台失败,平台序号为%1,设备序号为%2") .arg(current_choice.x()) .arg(current_choice.y()); } VCL_GPU_Device *dev = VCL_get_device(plat, current_choice.y()); if (dev == nullptr) { - return VCWind::tr("创建GPU设备失败,平台序号为%1,设备序号为%2") + return VCWind::tr("创建 GPU 设备失败,平台序号为%1,设备序号为%2") .arg(current_choice.x()) .arg(current_choice.y()); } if (!this->kernel->set_gpu_resource(plat, dev)) { - return VCWind::tr("设置GPU设备失败。,平台序号为%1,设备序号为%2") + return VCWind::tr("设置 GPU 设备失败。,平台序号为%1,设备序号为%2") .arg(current_choice.x()) .arg(current_choice.y()); } From a3d94f5cabd2232c9e396cf54405150fe135d1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 02:36:05 +0800 Subject: [PATCH 0399/1123] make installation of libpng and zlib required --- CMakeLists.txt | 3 --- SlopeCraftL/install.cmake | 1 + cmake/install.cmake | 19 +++++++++++++++---- cmake/install_if_is_shared.cmake | 5 ++++- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bfcea1a6..54ce4015 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,9 +125,6 @@ if(${MSVC}) add_compile_options("/Zc:__cplusplus") add_compile_options("/wd4819") add_compile_options("/utf-8") - -# add_compile_definitions("ZLIB_WINAPI") -# 1add_compile_definitions("Z_HAVE_UNISTD_H") else() add_compile_options(-Wall -Wreturn-type -Wsign-compare -Wextra) add_link_options(-flto) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index ffaac535..e0217687 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -40,6 +40,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ./../install_SlopeCraftL/C/include) SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) + SlopeCraft_install_if_is_shared(PNG::PNG .) return() endif() diff --git a/cmake/install.cmake b/cmake/install.cmake index 72c2266d..c6d9c6bf 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -6,6 +6,8 @@ set(SlopeCraft_readme_and_license_files license-translations/LICENSE-zh.md ) +include(${CMAKE_SOURCE_DIR}/cmake/add_compiler_path_to_prefix.cmake) + if(${WIN32}) install(FILES ${SlopeCraft_readme_and_license_files} DESTINATION .) @@ -14,26 +16,35 @@ if(${WIN32}) function(SlopeCraft_install_dll dllname dest is_required) find_library(dll_file - NAMES ${dllname} + NAMES ${dllname} + PATHS ${CMAKE_PREFIX_PATH} + NO_CMAKE_INSTALL_PREFIX + NO_CACHE) + + if(NOT dll_file) + find_file(dll_file + NAMES "lib${dllname}.dll" PATHS ${CMAKE_PREFIX_PATH} NO_CMAKE_INSTALL_PREFIX NO_CACHE) + endif() if(NOT dll_file) if(${is_required}) - message(WARNING "Failed to find ${dllname} dll.") + message(FATAL_ERROR "Failed to find ${dllname} dll.") else() - message(STATUS "Failed to find ${dllname} dll.") + message(WARNING "Failed to find ${dllname} dll.") endif() return() endif() message(STATUS "Install ${dll_file} to ${dest}") install(FILES ${dll_file} - DESTINATION ${dest}) + DESTINATION ${dest}) endfunction(SlopeCraft_install_dll) if(${MSVC}) + SlopeCraft_install_dll(omp . true) else() SlopeCraft_install_dll(gomp-1 . true) SlopeCraft_install_dll(stdc++-6 . true) diff --git a/cmake/install_if_is_shared.cmake b/cmake/install_if_is_shared.cmake index d6740f18..a9ee153a 100644 --- a/cmake/install_if_is_shared.cmake +++ b/cmake/install_if_is_shared.cmake @@ -33,7 +33,7 @@ function(SlopeCraft_install_lib lib_location dest) list(LENGTH dll_location len) if(len LESS_EQUAL 0) - message(WARNING "Trying to install dll of ${lib_location}, but failed to find ${dll_name}. + message(FATAL_ERROR "Trying to install dll of ${lib_location}, but failed to find ${dll_name}. The released package may failed to find this dll.") return() endif() @@ -52,8 +52,11 @@ function(SlopeCraft_install_lib lib_location dest) endif() if((extension MATCHES ".a") OR(extension MATCHES ".lib")) + message(STATUS "\"${lib_location}\" is a static library, skip installation of it.") return() endif() + + message(FATAL_ERROR "Unknown library extension: ${extension}") endfunction(SlopeCraft_install_lib) function(SlopeCraft_install_if_is_shared target dest) From c3eb9168e8117064803eebd16e55c6365f66dee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 02:36:14 +0800 Subject: [PATCH 0400/1123] restore omp --- VisualCraftL/TokiVC_build.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualCraftL/TokiVC_build.cpp b/VisualCraftL/TokiVC_build.cpp index c28880aa..c849dae3 100644 --- a/VisualCraftL/TokiVC_build.cpp +++ b/VisualCraftL/TokiVC_build.cpp @@ -77,8 +77,8 @@ bool TokiVC::build() noexcept { std::atomic_bool ret = true; const Eigen::ArrayXX color_id_mat = this->img_cvter.color_id(); -#warning resume omp here - // #pragma omp parallel for schedule(static) + // #warning resume omp here +#pragma omp parallel for schedule(static) for (int64_t r = 0; r < this->img_cvter.rows(); r++) { for (int64_t c = 0; c < this->img_cvter.cols(); c++) { const auto &variant = From 530a93576dbd7e9481aa740ebc1afc353eda279e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 02:37:50 +0800 Subject: [PATCH 0401/1123] fix windows-build --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54ce4015..998da8e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ set(SlopeCraft_vccl_test_gpu_platform_idx 0 CACHE STRING "The opencl platform in set(SlopeCraft_vccl_test_gpu_device_idx 0 CACHE STRING "The opencl device index used to test vccl") if(${WIN32}) - set(SlopeCraft_windeployqt_flags_install "--no-translations;--force" CACHE STRING "Flags to run windeployqt during installation") - set(SlopeCraft_windeployqt_flags_build ${SlopeCraft_windeployqt_flags_install} CACHE STRING "Flags to run windeployqt in build dir") + set(SlopeCraft_windeployqt_flags_install "--no-translations" CACHE STRING "Flags to run windeployqt during installation") + set(SlopeCraft_windeployqt_flags_build "${SlopeCraft_windeployqt_flags_install};--force" CACHE STRING "Flags to run windeployqt in build dir") endif() # manage the install prefix -------------------------------------------------- From 4145d7474f2b0329ce12e3568dace7b52c0cb138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:10:27 +0800 Subject: [PATCH 0402/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 184 ++++++++++++++++++++++++++ .github/workflows/build-dev.yml | 2 +- 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-dev-clang.yml diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml new file mode 100644 index 00000000..a6a701bb --- /dev/null +++ b/.github/workflows/build-dev-clang.yml @@ -0,0 +1,184 @@ +name: Build dev version artifacts +on: + pull_request: + push: + branches: + #- main + #- dev + - update-sc-ui + +jobs: + + windows-build: + runs-on: windows-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None] + vectorize: [true, false] + exclude: + - gpu_api: OpenCL + vectorize: false + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + VECTORIZE: ${{ matrix.vectorize }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo "env:BUILD_TYPE = $env:BUILD_TYPE" + echo "env:GPU_API = $env:GPU_API" + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: check clang + run: | + clang -v + clang-cl + + - name: Get short SHA + run: | + echo "GITHUB_SHA = $env:GITHUB_SHA" + $short_sha=$env:GITHUB_SHA.substring(0,7) + echo "short_sha = $short_sha" + echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV + + - name: Filter perl-related pathes from env:path + run: | + $basedir=(pwd).path.replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + echo "New path : $env:path.split(';')" + echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV + + run: | + mkdir bin + mkdir bin/Qt6.5.0-msvc-shared + mkdir 3rdParty + + - name: Build and install zlib + run: | + $basedir=(pwd).path.replace("\\","/") + echo "basedir = $basedir" + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/madler/zlib.git + cd zlib + git checkout v1.2.13 + cd $basedir + mkdir bin/build-zlib + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX=clang++ + cmake --build bin/build-zlib --parallel + cmake --install bin/build-zlib + + - name: Build and install libzip + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/nih-at/libzip.git + cd libzip + git checkout v1.9.2 + cd $basedir + mkdir bin/build-libzip + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + cmake --build bin/build-libzip --parallel + cmake --install bin/build-libzip + + - name: Build and install libpng + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/glennrp/libpng.git + cd libpng + git checkout v1.6.39 + cd $basedir + mkdir bin/build-libpng + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake --build bin/build-libpng --parallel + cmake --install bin/build-libpng + + - name: Download Qt6.5.0-msvc-shared and extract + run: | + cmd + curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared-native.7z" + 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z + exit + tree /f bin/Qt6.5.0-msvc-shared + # Qt installation dir: bin/Qt6.5.0-msvc-shared + - name: CMake configure + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + $GPU_API=$env:GPU_API + $env:path=$env:NEW_PATH + echo "env:path = $env:path" + mkdir build + mkdir install + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + + - name: CMake build + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + echo "Number of processors = $env:NUMBER_OF_PROCESSORS" + cmake --build ./build --parallel 10 + + - name: CMake install + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + cmake --install ./build + + #- name: Run CTest + # if: matrix.build_type == 'Release' + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $env:path=$env:NEW_PATH + # cd ./build + # ctest -j10 --output-on-failure --stop-on-failure + + - name: Make zip and 7z packs with CPack + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + cd ./build + cpack -G ZIP -B "$basedir/pack" + cpack -G 7Z -B "$basedir/pack" + + - name: Upload zip pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip + path: pack/SlopeCraft*.zip + if-no-files-found: error + + - name: Upload 7z pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z + path: pack/SlopeCraft*.7z + if-no-files-found: error + + + #- name: Tree /f + # run: tree /f D:/ > bin/all_files_on_D.txt + #- name: Upload all_files_on_D.txt + # uses: actions/upload-artifact@v3 + # with: + # name: all_files_on_D.txt + # path: bin/all_files_on_D.txt + # if-no-files-found: error + + + + #- name: Upload gcc + # uses: actions/upload-artifact@v3 + # with: + # name: gcc12-with-zlib,libzip,libpng + # path: bin/mingw64 + # if-no-files-found: error \ No newline at end of file diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 1f937b6c..b6ac5332 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -5,7 +5,7 @@ on: branches: - main - dev - - update-sc-ui + #- update-sc-ui jobs: macos-build: From 3e1ddb1c7ae5bd378c3b31e880186a70cfbfb9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:13:01 +0800 Subject: [PATCH 0403/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index a6a701bb..9db1710d 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -52,7 +52,8 @@ jobs: foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - + + - name: make dirs run: | mkdir bin mkdir bin/Qt6.5.0-msvc-shared From d4a8394c0846c1b601ef9495157b11a57a36fbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:16:16 +0800 Subject: [PATCH 0404/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 9db1710d..c69e41f4 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -29,13 +29,15 @@ jobs: echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" - - name: Checkout repository - uses: actions/checkout@v2 - - name: check clang run: | - clang -v - clang-cl + where clang + where clang-cl + clang --version + + + - name: Checkout repository + uses: actions/checkout@v2 - name: Get short SHA run: | @@ -52,7 +54,7 @@ jobs: foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - + - name: make dirs run: | mkdir bin From 75f3dfb104be4567fd97e907ac0cc7c8ea3db1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:22:36 +0800 Subject: [PATCH 0405/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 41 ++++++--------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index c69e41f4..77d6492b 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -60,6 +60,7 @@ jobs: mkdir bin mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty + mkdir bin/dependencies - name: Build and install zlib run: | @@ -73,7 +74,7 @@ jobs: cd $basedir mkdir bin/build-zlib "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX=clang++ + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -87,7 +88,8 @@ jobs: git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -101,7 +103,8 @@ jobs: git checkout v1.6.39 cd $basedir mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -122,7 +125,8 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - name: CMake build run: | @@ -137,14 +141,6 @@ jobs: $env:path=$env:NEW_PATH cmake --install ./build - #- name: Run CTest - # if: matrix.build_type == 'Release' - # run: | - # $basedir=(pwd).path.replace("\\","/") - # $env:path=$env:NEW_PATH - # cd ./build - # ctest -j10 --output-on-failure --stop-on-failure - - name: Make zip and 7z packs with CPack run: | $basedir=(pwd).path.replace("\\","/") @@ -165,23 +161,4 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z path: pack/SlopeCraft*.7z - if-no-files-found: error - - - #- name: Tree /f - # run: tree /f D:/ > bin/all_files_on_D.txt - #- name: Upload all_files_on_D.txt - # uses: actions/upload-artifact@v3 - # with: - # name: all_files_on_D.txt - # path: bin/all_files_on_D.txt - # if-no-files-found: error - - - - #- name: Upload gcc - # uses: actions/upload-artifact@v3 - # with: - # name: gcc12-with-zlib,libzip,libpng - # path: bin/mingw64 - # if-no-files-found: error \ No newline at end of file + if-no-files-found: error \ No newline at end of file From 6bd44bd90ede50445859703de72cb3e842763d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:26:28 +0800 Subject: [PATCH 0406/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 77d6492b..83016885 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -89,7 +89,7 @@ jobs: cd $basedir mkdir bin/build-libzip "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -104,7 +104,7 @@ jobs: cd $basedir mkdir bin/build-libpng "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -121,12 +121,12 @@ jobs: $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API - $env:path=$env:NEW_PATH + $env:path=$env:NEW_PATHs echo "env:path = $env:path" mkdir build mkdir install "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_C_COMPILER:FILEPATH=clang++ -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - name: CMake build run: | From 1be153460e9a0f5145ab110e2f186ff484fe2258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:35:31 +0800 Subject: [PATCH 0407/1123] add windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 83016885..2569d9bb 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -74,7 +74,7 @@ jobs: cd $basedir mkdir bin/build-zlib "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -89,7 +89,7 @@ jobs: cd $basedir mkdir bin/build-libzip "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -104,7 +104,7 @@ jobs: cd $basedir mkdir bin/build-libpng "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng From ea8419d1b07e9b99cbf25065c143152faefcc773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:41:36 +0800 Subject: [PATCH 0408/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 2569d9bb..68421c06 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -104,7 +104,7 @@ jobs: cd $basedir mkdir bin/build-libpng "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng From 356f98c376c391c00f05076c5ca7b716719c28ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:43:06 +0800 Subject: [PATCH 0409/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 68421c06..7c35c53a 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -104,7 +104,7 @@ jobs: cd $basedir mkdir bin/build-libpng "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng From e59f7b5aed0bb6e730c2732d20b71ee09384132c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:43:23 +0800 Subject: [PATCH 0410/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 7c35c53a..467e6477 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -104,7 +104,7 @@ jobs: cd $basedir mkdir bin/build-libpng "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng From ba1dac8ed601dbae9f00758ce0c484e1f188bebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 13:52:26 +0800 Subject: [PATCH 0411/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 467e6477..6d4317e3 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -121,12 +121,11 @@ jobs: $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API - $env:path=$env:NEW_PATHs echo "env:path = $env:path" mkdir build mkdir install "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" - name: CMake build run: | From 44523a4661f8ad90e76ea5c24f3a53e8e1bff745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 14:05:50 +0800 Subject: [PATCH 0412/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 6d4317e3..38e7bc1b 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -118,17 +118,18 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API echo "env:path = $env:path" mkdir build mkdir install - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" - name: CMake build run: | + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH echo "Number of processors = $env:NUMBER_OF_PROCESSORS" @@ -136,12 +137,14 @@ jobs: - name: CMake install run: | + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cmake --install ./build - name: Make zip and 7z packs with CPack run: | + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cd ./build From f420fd50f073c174a949c7cd8880860484a03a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 14:22:26 +0800 Subject: [PATCH 0413/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 38e7bc1b..257bb038 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -73,7 +73,7 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -88,7 +88,7 @@ jobs: git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -103,7 +103,7 @@ jobs: git checkout v1.6.39 cd $basedir mkdir bin/build-libpng - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -118,13 +118,13 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API echo "env:path = $env:path" mkdir build mkdir install + & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" - name: CMake build From 6156afcecfc31dd887f35b1a52ec8e1b8a0251a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 14:30:37 +0800 Subject: [PATCH 0414/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 257bb038..d15febf6 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -73,7 +73,6 @@ jobs: git checkout v1.2.13 cd $basedir mkdir bin/build-zlib - & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib @@ -88,7 +87,6 @@ jobs: git checkout v1.9.2 cd $basedir mkdir bin/build-libzip - & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false cmake --build bin/build-libzip --parallel cmake --install bin/build-libzip @@ -103,7 +101,6 @@ jobs: git checkout v1.6.39 cd $basedir mkdir bin/build-libpng - & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng @@ -118,13 +115,13 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | + & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API echo "env:path = $env:path" mkdir build mkdir install - & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" - name: CMake build From d9166c34078e5b551301d90ed9a2b43ce4a2b50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 14:36:57 +0800 Subject: [PATCH 0415/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index d15febf6..b51e19fd 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -115,7 +115,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - & "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API @@ -126,7 +126,7 @@ jobs: - name: CMake build run: | - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH echo "Number of processors = $env:NUMBER_OF_PROCESSORS" @@ -134,14 +134,14 @@ jobs: - name: CMake install run: | - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cmake --install ./build - name: Make zip and 7z packs with CPack run: | - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cd ./build From 86bb9515f248fe14a20a7244097a0f4471573080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 14:54:41 +0800 Subject: [PATCH 0416/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index b51e19fd..dd8f74bd 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -115,7 +115,8 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" + $env:path="$env:path;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build" + vcvars64.bat $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API @@ -126,7 +127,6 @@ jobs: - name: CMake build run: | - powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH echo "Number of processors = $env:NUMBER_OF_PROCESSORS" @@ -134,14 +134,12 @@ jobs: - name: CMake install run: | - powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cmake --install ./build - name: Make zip and 7z packs with CPack run: | - powershell.exe -c "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cd ./build From 403b3090792e7bd9d3c1dccfc1f071ddea962a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:08:01 +0800 Subject: [PATCH 0417/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index dd8f74bd..11e8985d 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,6 +34,8 @@ jobs: where clang where clang-cl clang --version + $env:path="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build;$env:path" + vcvars64.bat - name: Checkout repository @@ -115,7 +117,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - $env:path="$env:path;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build" + $env:path="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build;$env:path" vcvars64.bat $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE From 5ad5b79c9990fd72aa16ecb1daedf7603d5ba041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:18:26 +0800 Subject: [PATCH 0418/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 11e8985d..3251688f 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,7 +34,7 @@ jobs: where clang where clang-cl clang --version - $env:path="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build;$env:path" + $env:path="'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build';$env:path" vcvars64.bat From 28dee428cd0a875cad649c6d4c67bef6e6421c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:27:28 +0800 Subject: [PATCH 0419/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 3251688f..a7dfa5d3 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,8 +34,7 @@ jobs: where clang where clang-cl clang --version - $env:path="'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build';$env:path" - vcvars64.bat + Invoke-Expression 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat' - name: Checkout repository @@ -117,8 +116,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - $env:path="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build;$env:path" - vcvars64.bat + Invoke-Expression 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat' $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API From 67b18300e0f816f80444b7dbdffaba81289a476e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:35:46 +0800 Subject: [PATCH 0420/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index a7dfa5d3..ab9b2628 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,7 +34,7 @@ jobs: where clang where clang-cl clang --version - Invoke-Expression 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat' + Invoke-Expression -Command "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - name: Checkout repository @@ -116,7 +116,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - Invoke-Expression 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat' + Invoke-Expression -Command "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API From b32be4b5be5c92c0da342172653a82048c001027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:39:07 +0800 Subject: [PATCH 0421/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index ab9b2628..a71a340f 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,7 +34,7 @@ jobs: where clang where clang-cl clang --version - Invoke-Expression -Command "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + Invoke-Expression -Command "'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" - name: Checkout repository @@ -116,7 +116,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - Invoke-Expression -Command "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + Invoke-Expression -Command "'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API From 6303ec91a9b59927b13af73292ee39b6be7ea4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 15:54:12 +0800 Subject: [PATCH 0422/1123] fix windows build with clang-msvc --- .github/workflows/build-dev-clang.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index a71a340f..cf3bb275 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,7 +34,7 @@ jobs: where clang where clang-cl clang --version - Invoke-Expression -Command "'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" + Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" - name: Checkout repository @@ -116,7 +116,7 @@ jobs: # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure run: | - Invoke-Expression -Command "'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" + Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API From f8cf864e8f6e3a7598bc6d0d355b23b109c4ca56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 16:02:50 +0800 Subject: [PATCH 0423/1123] call vcvars64.bat in fucking powershell --- .github/workflows/build-dev-clang.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index cf3bb275..86e3cd74 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,7 +34,8 @@ jobs: where clang where clang-cl clang --version - Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" + + # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" - name: Checkout repository @@ -63,6 +64,10 @@ jobs: mkdir 3rdParty mkdir bin/dependencies + - name: make a symlink for vcvars64.bat to avoid space containing path for fucking powershell, holy shit, I can not even call vcvars64.bat due in pwsh because & can not be used in github actions!!!! + shell: cmd + run: mklink bin\vcvars64.bat "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + - name: Build and install zlib run: | $basedir=(pwd).path.replace("\\","/") @@ -115,8 +120,9 @@ jobs: tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure + shell: cmd run: | - Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" + .\bin\vcvars64.bat $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API From a7175538671d59f2b539c2ef7dfba9bf931441bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 16:09:31 +0800 Subject: [PATCH 0424/1123] call vcvars64.bat in fucking powershell --- .github/workflows/build-dev-clang.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 86e3cd74..21968d2c 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -64,9 +64,9 @@ jobs: mkdir 3rdParty mkdir bin/dependencies - - name: make a symlink for vcvars64.bat to avoid space containing path for fucking powershell, holy shit, I can not even call vcvars64.bat due in pwsh because & can not be used in github actions!!!! + - name: make a symlink for vcvars64.bat to avoid space containing path for fucking powershell, holy shit, I can not even call vcvars64.bat in pwsh because & can not be used in github actions!!!! shell: cmd - run: mklink bin\vcvars64.bat "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + run: mklink .\bin\vcvars64.bat "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - name: Build and install zlib run: | @@ -122,13 +122,13 @@ jobs: - name: CMake configure shell: cmd run: | - .\bin\vcvars64.bat $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API echo "env:path = $env:path" mkdir build mkdir install + Invoke-Expression -Command "$basedir\bin\vcvars64.bat" cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" - name: CMake build From 55430998d6d317239e4a757604ce2202ba048d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 16:26:50 +0800 Subject: [PATCH 0425/1123] call vcvars64.bat in fucking powershell --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 21968d2c..ea8bf3d3 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -120,7 +120,7 @@ jobs: tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure - shell: cmd + shell: pwsh run: | $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE From ad0495e75784c278e744d817b9b459cc9b4a25de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 17:42:43 +0800 Subject: [PATCH 0426/1123] call vcvars64.bat in fucking powershell --- .github/workflows/build-dev-clang.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index ea8bf3d3..32939867 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -128,8 +128,11 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - Invoke-Expression -Command "$basedir\bin\vcvars64.bat" - cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-msvc-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING="--no-translation;-release" + echo "cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=\"$basedir/bin/Qt6.5.0-msvc-shared\" -DCMAKE_INSTALL_PREFIX:PATH=\"$basedir/install\" -DCMAKE_BUILD_TYPE=\"$BUILD_TYPE\" -DSlopeCraft_GPU_API:STRING=\"$GPU_API\" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=\"--no-translation;-release\"" > run-cmake-configure.bat + cmd + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + .\run-cmake-configure.bat + - name: CMake build run: | From dacb73df83a8c26bef8fd953198b786ac1975ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 17:51:28 +0800 Subject: [PATCH 0427/1123] call vcvars64.bat in fucking powershell --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 32939867..eab3f9f1 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -128,7 +128,7 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - echo "cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=\"$basedir/bin/Qt6.5.0-msvc-shared\" -DCMAKE_INSTALL_PREFIX:PATH=\"$basedir/install\" -DCMAKE_BUILD_TYPE=\"$BUILD_TYPE\" -DSlopeCraft_GPU_API:STRING=\"$GPU_API\" -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=\"--no-translation;-release\"" > run-cmake-configure.bat + echo "cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release" > run-cmake-configure.bat cmd "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" .\run-cmake-configure.bat From 323de5648ac4bcef7d950eff1472c97cf4e32566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 17:59:23 +0800 Subject: [PATCH 0428/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index eab3f9f1..fc419cb5 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -119,7 +119,7 @@ jobs: exit tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - - name: CMake configure + - name: Prepare for CMake configure shell: pwsh run: | $basedir=(pwd).path.replace("\\","/") @@ -128,12 +128,17 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - echo "cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release" > run-cmake-configure.bat + echo 'cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat cmd "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" .\run-cmake-configure.bat - + - name: CMake configure + shell: cmd + run: | + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + .\run-cmake-configure.bat + - name: CMake build run: | $basedir=(pwd).path.replace("\\","/") From 98cadf1400f41787055cd2a2ea12f0eb8768db2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:00:51 +0800 Subject: [PATCH 0429/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index fc419cb5..fe9e177f 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -129,9 +129,7 @@ jobs: mkdir build mkdir install echo 'cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat - cmd - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - .\run-cmake-configure.bat + - name: CMake configure shell: cmd From d9ced412581214f30fd49e0b0aa5ecec2b931779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:03:49 +0800 Subject: [PATCH 0430/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index fe9e177f..d2c2ab36 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -134,7 +134,7 @@ jobs: - name: CMake configure shell: cmd run: | - "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" .\run-cmake-configure.bat - name: CMake build From 94e7f31fbb487c51950110152eb0e19948a2e378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:15:36 +0800 Subject: [PATCH 0431/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index d2c2ab36..6e275bef 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -128,7 +128,7 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - echo 'cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat + echo 'cmake -S . -B $basedir/build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat - name: CMake configure @@ -136,6 +136,7 @@ jobs: run: | "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" .\run-cmake-configure.bat + #cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build run: | From 32a4ea1fff0c03cfbaf225ad85716e76684e037a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:20:07 +0800 Subject: [PATCH 0432/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 6e275bef..bfd69941 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -135,6 +135,7 @@ jobs: shell: cmd run: | "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + type .\run-cmake-configure.bat .\run-cmake-configure.bat #cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release From 30771f966153de9920c91812ff05edb06d216547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:25:40 +0800 Subject: [PATCH 0433/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index bfd69941..f3db97ae 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -128,34 +128,28 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - echo 'cmake -S . -B $basedir/build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat + #echo 'cmake -S . -B $basedir/build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat - name: CMake configure shell: cmd run: | "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - type .\run-cmake-configure.bat - .\run-cmake-configure.bat - #cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build + shell: cmd run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - echo "Number of processors = $env:NUMBER_OF_PROCESSORS" cmake --build ./build --parallel 10 - name: CMake install + shell: cmd run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH cmake --install ./build - name: Make zip and 7z packs with CPack run: | $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH cd ./build cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" From 46268386bedd43008550924b6263314ac3a243c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:34:17 +0800 Subject: [PATCH 0434/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index f3db97ae..aa9dd505 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -140,6 +140,7 @@ jobs: - name: CMake build shell: cmd run: | + tree ./build cmake --build ./build --parallel 10 - name: CMake install From d657080106af4eb7717a766173ec5d6f9a81b03b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:35:24 +0800 Subject: [PATCH 0435/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index aa9dd505..0ca15a41 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -141,6 +141,7 @@ jobs: shell: cmd run: | tree ./build + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cmake --build ./build --parallel 10 - name: CMake install From 8c7bf04120ea42775e6cdb8592bed679f495a99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:39:17 +0800 Subject: [PATCH 0436/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 0ca15a41..3d0e9dc2 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -134,14 +134,12 @@ jobs: - name: CMake configure shell: cmd run: | - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build shell: cmd run: | tree ./build - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cmake --build ./build --parallel 10 - name: CMake install From bc347f1e935e40d5d1f2a8e64fab3ec87c126ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:45:51 +0800 Subject: [PATCH 0437/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 3d0e9dc2..ceec434c 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -134,7 +134,7 @@ jobs: - name: CMake configure shell: cmd run: | - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared;./bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build shell: cmd From c501a439af43dce10cc659c719341e9cedc05653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 18:59:40 +0800 Subject: [PATCH 0438/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 29 ++++----------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index ceec434c..b14df5bb 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -48,26 +48,13 @@ jobs: echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - name: Filter perl-related pathes from env:path - run: | - $basedir=(pwd).path.replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - echo "New path : $env:path.split(';')" - echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - - name: make dirs run: | mkdir bin mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty mkdir bin/dependencies - - - name: make a symlink for vcvars64.bat to avoid space containing path for fucking powershell, holy shit, I can not even call vcvars64.bat in pwsh because & can not be used in github actions!!!! - shell: cmd - run: mklink .\bin\vcvars64.bat "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" - + - name: Build and install zlib run: | $basedir=(pwd).path.replace("\\","/") @@ -119,21 +106,13 @@ jobs: exit tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - - name: Prepare for CMake configure - shell: pwsh - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - $GPU_API=$env:GPU_API - echo "env:path = $env:path" - mkdir build - mkdir install - #echo 'cmake -S . -B $basedir/build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=$basedir/bin/Qt6.5.0-msvc-shared -DCMAKE_INSTALL_PREFIX:PATH=$basedir/install -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSlopeCraft_GPU_API:STRING=$GPU_API -DSlopeCraft_vectorize:BOOL=$VECTORIZE -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release' > run-cmake-configure.bat - - name: CMake configure shell: cmd run: | + mkdir build + mkdir install + set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\cabal\bin;C:\\ghcup\bin;C:\Program Files\dotnet;C:\mysql\bin;C:\Program Files\R\R-4.3.0\bin\x64;C:\SeleniumWebDrivers\GeckoDriver;C:\Program Files (x86)\sbt\bin;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files (x86)\pipx_bin;C:\npm\prefix;C:\hostedtoolcache\windows\go\1.20.4\x64\bin;C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts;C:\hostedtoolcache\windows\Python\3.9.13\x64;C:\hostedtoolcache\windows\Ruby\3.0.6\x64\bin;C:\Program Files\OpenSSL\bin;C:\hostedtoolcache\windows\Java_Temurin-Hotspot_jdk\8.0.372-7\x64\bin;C:\Program Files\ImageMagick-7.1.1-Q16-HDRI;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\ProgramData\kind;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\ProgramData\Chocolatey\bin;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\ProgramData\chocolatey\lib\pulumi\tools\Pulumi\bin;C:\Program Files\TortoiseSVN\bin;C:\Program Files\CMake\bin;C:\ProgramData\chocolatey\lib\maven\apache-maven-3.8.7\bin;C:\Program Files\Microsoft Service Fabric\bin\Fabric\Fabric.Code;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\nodejs\;C:\Program Files\Git\cmd;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Program Files\GitHub CLI\;c:\tools\php;C:\Program Files (x86)\sbt\bin;C:\SeleniumWebDrivers\ChromeDriver\;C:\SeleniumWebDrivers\EdgeDriver\;C:\Program Files\Amazon\AWSCLIV2\;C:\Program Files\Amazon\SessionManagerPlugin\bin\;C:\Program Files\Amazon\AWSSAMCLI\bin\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared;./bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build From b4da98f98ac72c3225627cec7620980f8d948228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 19:09:44 +0800 Subject: [PATCH 0439/1123] clean the path --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index b14df5bb..66ed6a6f 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -112,7 +112,7 @@ jobs: run: | mkdir build mkdir install - set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\cabal\bin;C:\\ghcup\bin;C:\Program Files\dotnet;C:\mysql\bin;C:\Program Files\R\R-4.3.0\bin\x64;C:\SeleniumWebDrivers\GeckoDriver;C:\Program Files (x86)\sbt\bin;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files (x86)\pipx_bin;C:\npm\prefix;C:\hostedtoolcache\windows\go\1.20.4\x64\bin;C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts;C:\hostedtoolcache\windows\Python\3.9.13\x64;C:\hostedtoolcache\windows\Ruby\3.0.6\x64\bin;C:\Program Files\OpenSSL\bin;C:\hostedtoolcache\windows\Java_Temurin-Hotspot_jdk\8.0.372-7\x64\bin;C:\Program Files\ImageMagick-7.1.1-Q16-HDRI;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\ProgramData\kind;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\ProgramData\Chocolatey\bin;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\ProgramData\chocolatey\lib\pulumi\tools\Pulumi\bin;C:\Program Files\TortoiseSVN\bin;C:\Program Files\CMake\bin;C:\ProgramData\chocolatey\lib\maven\apache-maven-3.8.7\bin;C:\Program Files\Microsoft Service Fabric\bin\Fabric\Fabric.Code;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\nodejs\;C:\Program Files\Git\cmd;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Program Files\GitHub CLI\;c:\tools\php;C:\Program Files (x86)\sbt\bin;C:\SeleniumWebDrivers\ChromeDriver\;C:\SeleniumWebDrivers\EdgeDriver\;C:\Program Files\Amazon\AWSCLIV2\;C:\Program Files\Amazon\SessionManagerPlugin\bin\;C:\Program Files\Amazon\AWSSAMCLI\bin\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps + set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared;./bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build From 73c9c173bff269a396bf55fb878e16772d0d5450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 19:27:00 +0800 Subject: [PATCH 0440/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 66ed6a6f..c1dd7a6a 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -101,7 +101,7 @@ jobs: - name: Download Qt6.5.0-msvc-shared and extract run: | cmd - curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared-native.7z" + curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared.7z" 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z exit tree /f bin/Qt6.5.0-msvc-shared From 6a6133687f40ebe518b88167d1cbdf0ab5e83d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 19:36:58 +0800 Subject: [PATCH 0441/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index c1dd7a6a..9c203bce 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -113,7 +113,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=./bin/Qt6.5.0-msvc-shared;./bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=./install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build shell: cmd From 7b766dd5a025c01d5ce53d4f746c5955aeba76f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 19:56:02 +0800 Subject: [PATCH 0442/1123] fix windows-clang-msvc build --- .github/workflows/build-dev-clang.yml | 2 +- SlopeCraft/others/SlopeCraft.rc.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 9c203bce..8b29be1f 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -113,7 +113,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release - name: CMake build shell: cmd diff --git a/SlopeCraft/others/SlopeCraft.rc.in b/SlopeCraft/others/SlopeCraft.rc.in index ae9a1a84..d6ba2ea6 100644 --- a/SlopeCraft/others/SlopeCraft.rc.in +++ b/SlopeCraft/others/SlopeCraft.rc.in @@ -44,7 +44,7 @@ VS_VERSION_INFO VERSIONINFO VALUE "CompanyName", "\0" VALUE "FileDescription", "Minecraft Map Pixel Art Tool\0" VALUE "FileVersion", "@PROJECT_VERSION@.0\0" - VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2022\0" + VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2023\0" VALUE "OriginalFilename", "SlopeCraft.exe\0" VALUE "ProductName", "SlopeCraft\0" VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" From ab7bff674396bd5c0ed33fdddf0567eac9ee1f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 20:22:38 +0800 Subject: [PATCH 0443/1123] install eigen3 for win-clang-msvc build --- .github/workflows/build-dev-clang.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 8b29be1f..d5e686dd 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -97,6 +97,9 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng + + - name: Install Eigen3 + run: vcpkg install --triplet=x64-windows eigen3 - name: Download Qt6.5.0-msvc-shared and extract run: | @@ -113,7 +116,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=--no-translation;-release + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build shell: cmd From 1aeadc88a03b3c9181b8998dfd19525690bcc4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 20:39:23 +0800 Subject: [PATCH 0444/1123] avoid eigen installation --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index d5e686dd..df796989 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -116,7 +116,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies;C:/vcpkg/packages/vcpkg-cmake_x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build shell: cmd From cd213a1ce356e21f33a5e84d9432a2b0e3c3f0c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 1 Jun 2023 20:54:42 +0800 Subject: [PATCH 0445/1123] avoid eigen installation --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index df796989..8b6d0af3 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -116,7 +116,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies;C:/vcpkg/packages/vcpkg-cmake_x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build shell: cmd From 63ce7e60cbbf41fae82ad56bbe118c5a6065ae61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 12:50:25 +0800 Subject: [PATCH 0446/1123] add macos-clang build --- .github/workflows/build-dev-clang.yml | 58 ++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 8b6d0af3..df570259 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -148,4 +148,60 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z path: pack/SlopeCraft*.7z - if-no-files-found: error \ No newline at end of file + if-no-files-found: error + + + macos-build: + runs-on: macos-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: brew update + run: brew update + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng + brew install qt@6 + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build and Install + run: | + cd build + cmake --build . --parallel + cmake --install . + cd install + chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + chmod +x MapViewer.app/Contents/MacOS/MapViewer + chmod +x imageCutter.app/Contents/MacOS/imageCutter + chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd ./build/install + zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos + path: build/install/SlopeCraft-5.0.0-macos.zip \ No newline at end of file From 13ce2f0ba7fe1226bc02774e913752b7137ea6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 13:08:14 +0800 Subject: [PATCH 0447/1123] fix macos-clang build --- .github/workflows/build-dev-clang.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index df570259..99956414 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -172,6 +172,7 @@ jobs: - name: Install dependencies run: | brew install libpng + brew install libomp brew install qt@6 - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From 07d98f8afe0afbb3eb32ea4828e7f47542c62695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 13:24:03 +0800 Subject: [PATCH 0448/1123] remove warnings about non-gcc compilers --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 998da8e1..07f5589d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,13 +55,6 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) endif() -# warn if not gcc ------------------------------------------------------------ -if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - message(WARNING "MSVC or Clang are not fully supported. - You MAY meet werid errors if you continue to build. - Please use gcc.") -endif() - # configure global dependencies ---------------------------------------------- include(cmake/configure_libpng.cmake) include(cmake/add_compiler_path_to_prefix.cmake) From a36db6c6ffe1be729b27db809284a0cbd503ce36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 13:33:30 +0800 Subject: [PATCH 0449/1123] fix macos-clang build --- .github/workflows/build-dev-clang.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 99956414..b3271750 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -171,9 +171,8 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng - brew install libomp - brew install qt@6 + brew install libpng qt@6 eigen3 + brew reinstall libomp - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH From 47b39b45ef002464ec8355643fbbdb029ad88f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 13:50:53 +0800 Subject: [PATCH 0450/1123] support msvc --- .github/workflows/build-dev.yml | 366 -------------------------------- VisualCraft/VCWind_gpu.cpp | 9 + 2 files changed, 9 insertions(+), 366 deletions(-) delete mode 100644 .github/workflows/build-dev.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml deleted file mode 100644 index b6ac5332..00000000 --- a/.github/workflows/build-dev.yml +++ /dev/null @@ -1,366 +0,0 @@ -name: Build dev version artifacts -on: - pull_request: - push: - branches: - - main - - dev - #- update-sc-ui - -jobs: - macos-build: - runs-on: macos-latest - strategy: - matrix: - build_type: [Debug, Release] - gpu_api: [None] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: brew update - run: brew update - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: | - brew install libpng - brew install qt@6 - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build and Install - run: | - cd build - cmake --build . --parallel - cmake --install . - cd install - chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - chmod +x MapViewer.app/Contents/MacOS/MapViewer - chmod +x imageCutter.app/Contents/MacOS/imageCutter - chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl - # chmod +x vccl.app/Contents/MacOS/vccl - - name: Compress as zip - run: | - cd ./build/install - zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos - path: build/install/SlopeCraft-5.0.0-macos.zip - - linux-build: - runs-on: ubuntu-latest - strategy: - matrix: - build_type: [Debug, Release] - gpu_api: [None, OpenCL] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: apt update - run: sudo apt update - - - name: Make directories - run: mkdir build install pack - - #- name: List installed - # run: apt list --installed - - - name: Install cmake, ninja - run: sudo apt install cmake ninja-build - - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev - - - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - - name: Install additional qt-related packages - run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev - # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install OpenCL sdk - if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo - - - name: See clinfo - if: matrix.gpu_api == 'OpenCL' - run: clinfo - - - name: Install xz (Release as tar.xz) - run: sudo apt install xz-utils - - - name: Checkout repository - uses: actions/checkout@v2 - - - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - - - name: CMake build - run: cmake --build ./build --parallel - - - name: CMake install - run: cmake --install ./build - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - - name: Make deb and tar.xz packs with cpack - run: | - cd build - cpack -G DEB -B ../pack - cpack -G TXZ -B ../pack - cd .. - - - name: Upload deb pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - path: pack/SlopeCraft*.deb - if-no-files-found: error - - - name: Upload tar.xz pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz - path: pack/SlopeCraft*.tar.xz - if-no-files-found: error - - - name: Run CTest - if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') - run: | - cd ./build - ctest -j20 --output-on-failure --stop-on-failure - - name: Test deb pack - run: sudo dpkg -i ./pack/*.deb - - # linux-test-deb: - # runs-on: ubunut-latest - # needs: linux-build - # strategy: - # matrix: - # build_type: [Debug, Release] - # gpu_api: [None, OpenCL] - # steps: - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - # - name: Download deb - # uses: actions/download-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - # - # - name: ls - # run: ls . - # - # - name: Try installing deb - # run: sudo dpkg -i ./*.deb - - windows-build: - runs-on: windows-latest - strategy: - matrix: - build_type: [Debug, Release] - gpu_api: [None] - vectorize: [true, false] - exclude: - - gpu_api: OpenCL - vectorize: false - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - VECTORIZE: ${{ matrix.vectorize }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo "env:BUILD_TYPE = $env:BUILD_TYPE" - echo "env:GPU_API = $env:GPU_API" - - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Get short SHA - run: | - echo "GITHUB_SHA = $env:GITHUB_SHA" - $short_sha=$env:GITHUB_SHA.substring(0,7) - echo "short_sha = $short_sha" - echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - - name: Filter perl-related pathes from env:path, and append directory of gcc12 to path - run: | - $basedir=(pwd).path.replace("\\","/") - $exclude_key_words="perl","Strawberry" - $new_path="" - foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$basedir/bin/mingw64/bin;$new_path" - echo "New path : $env:path.split(';')" - echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - - #- name: See environment - # run: where.exe cmake ninja 7z clang gcc vcpkg - #- name: See versions - # run: | - # cmake --version - # ninja --version - # clang --version - # gcc --version - #- name: See Path - # run: $env:path -split ';' - - name: Make dirs - run: | - mkdir bin - mkdir bin/mingw64 - mkdir bin/Qt6.4.0-gcc12-shared - mkdir 3rdParty - - - name: Download mingw64 and extract - run: | - cmd - curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" - 7z x -obin bin/gcc12.7z - exit - # gcc installation dir: bin/mingw64 - # gcc.exe: bin/mingw64/bin/gcc.exe - # g++.exe: bin/mingw64/bin/g++.exe - - name: Build and install zlib - run: | - $basedir=(pwd).path.replace("\\","/") - echo "basedir = $basedir" - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/madler/zlib.git - cd zlib - git checkout v1.2.13 - cd $basedir - mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" - cmake --build bin/build-zlib --parallel - cmake --install bin/build-zlib - - - name: Build and install libzip - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/nih-at/libzip.git - cd libzip - git checkout v1.9.2 - cd $basedir - mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false - cmake --build bin/build-libzip --parallel - cmake --install bin/build-libzip - - - name: Build and install libpng - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/glennrp/libpng.git - cd libpng - git checkout v1.6.39 - cd $basedir - mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" - cmake --build bin/build-libpng --parallel - cmake --install bin/build-libpng - - - name: Download Qt6.4.0-gcc12-shared and extract - run: | - cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" - 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z - exit - tree /f bin/Qt6.4.0-gcc12-shared - # Qt installation dir: bin/Qt6.4.0-gcc12-shared - - name: CMake configure - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - $GPU_API=$env:GPU_API - $env:path=$env:NEW_PATH - echo "env:path = $env:path" - mkdir build - mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - - - name: CMake build - run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - echo "Number of processors = $env:NUMBER_OF_PROCESSORS" - cmake --build ./build --parallel 10 - - - name: CMake install - run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - cmake --install ./build - - #- name: Run CTest - # if: matrix.build_type == 'Release' - # run: | - # $basedir=(pwd).path.replace("\\","/") - # $env:path=$env:NEW_PATH - # cd ./build - # ctest -j10 --output-on-failure --stop-on-failure - - - name: Make zip and 7z packs with CPack - run: | - $basedir=(pwd).path.replace("\\","/") - $env:path=$env:NEW_PATH - cd ./build - cpack -G ZIP -B "$basedir/pack" - cpack -G 7Z -B "$basedir/pack" - - - name: Upload zip pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip - path: pack/SlopeCraft*.zip - if-no-files-found: error - - - name: Upload 7z pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z - path: pack/SlopeCraft*.7z - if-no-files-found: error - - - #- name: Tree /f - # run: tree /f D:/ > bin/all_files_on_D.txt - #- name: Upload all_files_on_D.txt - # uses: actions/upload-artifact@v3 - # with: - # name: all_files_on_D.txt - # path: bin/all_files_on_D.txt - # if-no-files-found: error - - - - #- name: Upload gcc - # uses: actions/upload-artifact@v3 - # with: - # name: gcc12-with-zlib,libzip,libpng - # path: bin/mingw64 - # if-no-files-found: error \ No newline at end of file diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index a9d9085e..2dd5898b 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -30,7 +30,11 @@ This file is part of SlopeCraft. #include "VCWind.h" #include "ui_VCWind.h" +#ifdef _MSC_VER +#include +#else #include +#endif std::string get_cpu_name(bool &error) noexcept { int buffer[5]; @@ -43,7 +47,12 @@ std::string get_cpu_name(bool &error) noexcept { for (auto i : input) { memset(buffer, 0, sizeof(buffer)); try { +#ifdef _MSC_VER + __cpuid(buffer, i); +#else __cpuid(i, buffer[0], buffer[1], buffer[2], buffer[3]); +#endif + } catch (std::exception &e) { strcpy(str, "Instruction cpuid failed. Detail : "); strcpy(str, e.what()); From c9c46da286f573bf01f975bc9cfb8c851a18c73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 13:51:08 +0800 Subject: [PATCH 0451/1123] rename build-dev to build-dev-gcc --- .github/workflows/build-dev-gcc.yml | 366 ++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 .github/workflows/build-dev-gcc.yml diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml new file mode 100644 index 00000000..b6ac5332 --- /dev/null +++ b/.github/workflows/build-dev-gcc.yml @@ -0,0 +1,366 @@ +name: Build dev version artifacts +on: + pull_request: + push: + branches: + - main + - dev + #- update-sc-ui + +jobs: + macos-build: + runs-on: macos-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: brew update + run: brew update + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng + brew install qt@6 + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build and Install + run: | + cd build + cmake --build . --parallel + cmake --install . + cd install + chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + chmod +x MapViewer.app/Contents/MacOS/MapViewer + chmod +x imageCutter.app/Contents/MacOS/imageCutter + chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd ./build/install + zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos + path: build/install/SlopeCraft-5.0.0-macos.zip + + linux-build: + runs-on: ubuntu-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None, OpenCL] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: apt update + run: sudo apt update + + - name: Make directories + run: mkdir build install pack + + #- name: List installed + # run: apt list --installed + + - name: Install cmake, ninja + run: sudo apt install cmake ninja-build + + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install qt6 + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + + - name: Install additional qt-related packages + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install OpenCL sdk + if: matrix.gpu_api == 'OpenCL' + run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + + - name: See clinfo + if: matrix.gpu_api == 'OpenCL' + run: clinfo + + - name: Install xz (Release as tar.xz) + run: sudo apt install xz-utils + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + + - name: CMake build + run: cmake --build ./build --parallel + + - name: CMake install + run: cmake --install ./build + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + + - name: Make deb and tar.xz packs with cpack + run: | + cd build + cpack -G DEB -B ../pack + cpack -G TXZ -B ../pack + cd .. + + - name: Upload deb pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + path: pack/SlopeCraft*.deb + if-no-files-found: error + + - name: Upload tar.xz pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz + path: pack/SlopeCraft*.tar.xz + if-no-files-found: error + + - name: Run CTest + if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure + - name: Test deb pack + run: sudo dpkg -i ./pack/*.deb + + # linux-test-deb: + # runs-on: ubunut-latest + # needs: linux-build + # strategy: + # matrix: + # build_type: [Debug, Release] + # gpu_api: [None, OpenCL] + # steps: + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Download deb + # uses: actions/download-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + # + # - name: ls + # run: ls . + # + # - name: Try installing deb + # run: sudo dpkg -i ./*.deb + + windows-build: + runs-on: windows-latest + strategy: + matrix: + build_type: [Debug, Release] + gpu_api: [None] + vectorize: [true, false] + exclude: + - gpu_api: OpenCL + vectorize: false + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + VECTORIZE: ${{ matrix.vectorize }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo "env:BUILD_TYPE = $env:BUILD_TYPE" + echo "env:GPU_API = $env:GPU_API" + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Get short SHA + run: | + echo "GITHUB_SHA = $env:GITHUB_SHA" + $short_sha=$env:GITHUB_SHA.substring(0,7) + echo "short_sha = $short_sha" + echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV + + - name: Filter perl-related pathes from env:path, and append directory of gcc12 to path + run: | + $basedir=(pwd).path.replace("\\","/") + $exclude_key_words="perl","Strawberry" + $new_path="" + foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} + $env:path="$basedir/bin/mingw64/bin;$new_path" + echo "New path : $env:path.split(';')" + echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV + + #- name: See environment + # run: where.exe cmake ninja 7z clang gcc vcpkg + #- name: See versions + # run: | + # cmake --version + # ninja --version + # clang --version + # gcc --version + #- name: See Path + # run: $env:path -split ';' + - name: Make dirs + run: | + mkdir bin + mkdir bin/mingw64 + mkdir bin/Qt6.4.0-gcc12-shared + mkdir 3rdParty + + - name: Download mingw64 and extract + run: | + cmd + curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" + 7z x -obin bin/gcc12.7z + exit + # gcc installation dir: bin/mingw64 + # gcc.exe: bin/mingw64/bin/gcc.exe + # g++.exe: bin/mingw64/bin/g++.exe + - name: Build and install zlib + run: | + $basedir=(pwd).path.replace("\\","/") + echo "basedir = $basedir" + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/madler/zlib.git + cd zlib + git checkout v1.2.13 + cd $basedir + mkdir bin/build-zlib + cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" + cmake --build bin/build-zlib --parallel + cmake --install bin/build-zlib + + - name: Build and install libzip + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/nih-at/libzip.git + cd libzip + git checkout v1.9.2 + cd $basedir + mkdir bin/build-libzip + cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + cmake --build bin/build-libzip --parallel + cmake --install bin/build-libzip + + - name: Build and install libpng + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + cd 3rdParty + git clone https://github.com/glennrp/libpng.git + cd libpng + git checkout v1.6.39 + cd $basedir + mkdir bin/build-libpng + cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" + cmake --build bin/build-libpng --parallel + cmake --install bin/build-libpng + + - name: Download Qt6.4.0-gcc12-shared and extract + run: | + cmd + curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" + 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z + exit + tree /f bin/Qt6.4.0-gcc12-shared + # Qt installation dir: bin/Qt6.4.0-gcc12-shared + - name: CMake configure + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + $GPU_API=$env:GPU_API + $env:path=$env:NEW_PATH + echo "env:path = $env:path" + mkdir build + mkdir install + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + + - name: CMake build + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + echo "Number of processors = $env:NUMBER_OF_PROCESSORS" + cmake --build ./build --parallel 10 + + - name: CMake install + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + cmake --install ./build + + #- name: Run CTest + # if: matrix.build_type == 'Release' + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $env:path=$env:NEW_PATH + # cd ./build + # ctest -j10 --output-on-failure --stop-on-failure + + - name: Make zip and 7z packs with CPack + run: | + $basedir=(pwd).path.replace("\\","/") + $env:path=$env:NEW_PATH + cd ./build + cpack -G ZIP -B "$basedir/pack" + cpack -G 7Z -B "$basedir/pack" + + - name: Upload zip pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip + path: pack/SlopeCraft*.zip + if-no-files-found: error + + - name: Upload 7z pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z + path: pack/SlopeCraft*.7z + if-no-files-found: error + + + #- name: Tree /f + # run: tree /f D:/ > bin/all_files_on_D.txt + #- name: Upload all_files_on_D.txt + # uses: actions/upload-artifact@v3 + # with: + # name: all_files_on_D.txt + # path: bin/all_files_on_D.txt + # if-no-files-found: error + + + + #- name: Upload gcc + # uses: actions/upload-artifact@v3 + # with: + # name: gcc12-with-zlib,libzip,libpng + # path: bin/mingw64 + # if-no-files-found: error \ No newline at end of file From f3efbf1a616f80e7e60b49f95d4a1c9c6c194a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 4 Jun 2023 14:08:12 +0800 Subject: [PATCH 0452/1123] add compiler id to artifacts --- .github/workflows/build-dev-clang.yml | 22 +++++++++++----------- .github/workflows/build-dev-gcc.yml | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index b3271750..3ba32ea3 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -136,17 +136,17 @@ jobs: cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" - - name: Upload zip pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip - path: pack/SlopeCraft*.zip - if-no-files-found: error + #- name: Upload zip pack + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-zip + # path: pack/SlopeCraft*.zip + # if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z path: pack/SlopeCraft*.7z if-no-files-found: error @@ -167,11 +167,11 @@ jobs: run: | echo $BUILD_TYPE echo $GPU_API - - name: Install Ninja build system - run: brew install ninja + - name: Install build system + run: brew install ninja cmake - name: Install dependencies run: | - brew install libpng qt@6 eigen3 + brew install libpng qt@6 eigen brew reinstall libomp - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH @@ -203,5 +203,5 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v2 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang path: build/install/SlopeCraft-5.0.0-macos.zip \ No newline at end of file diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index b6ac5332..79559a0b 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -60,7 +60,7 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v2 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc path: build/install/SlopeCraft-5.0.0-macos.zip linux-build: @@ -134,14 +134,14 @@ jobs: - name: Upload deb pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-deb path: pack/SlopeCraft*.deb if-no-files-found: error - name: Upload tar.xz pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-tar-xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-tar-xz path: pack/SlopeCraft*.tar.xz if-no-files-found: error @@ -332,17 +332,17 @@ jobs: cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" - - name: Upload zip pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip - path: pack/SlopeCraft*.zip - if-no-files-found: error + #- name: Upload zip pack + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip + # path: pack/SlopeCraft*.zip + # if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-7z + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-gcc-7z path: pack/SlopeCraft*.7z if-no-files-found: error From 208716899477de5e923178a6ec7f9479ecd63814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 30 Jun 2023 23:40:53 +0800 Subject: [PATCH 0453/1123] fix clang-msvc build --- CMakeLists.txt | 69 +++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07f5589d..da708d73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,13 +9,13 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) -if(${LINUX}) +if (${LINUX}) message(STATUS "setting runpath for linux") set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") # set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) # set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) -endif() +endif () enable_testing() @@ -35,25 +35,25 @@ option(SlopeCraft_sanitize "Build with sanitizer" OFF) set(SlopeCraft_vccl_test_gpu_platform_idx 0 CACHE STRING "The opencl platform index used to test vccl") set(SlopeCraft_vccl_test_gpu_device_idx 0 CACHE STRING "The opencl device index used to test vccl") -if(${WIN32}) +if (${WIN32}) set(SlopeCraft_windeployqt_flags_install "--no-translations" CACHE STRING "Flags to run windeployqt during installation") set(SlopeCraft_windeployqt_flags_build "${SlopeCraft_windeployqt_flags_install};--force" CACHE STRING "Flags to run windeployqt in build dir") -endif() +endif () # manage the install prefix -------------------------------------------------- -if(NOT DEFINED CMAKE_INSTALL_PREFIX) +if (NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) -endif() +endif () # convert relative path to absolute ------------------------------------------ cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX OUTPUT_VARIABLE CMAKE_INSTALL_PREFIX) message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") # Remove old compilation database -------------------------------------------- -if(EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) +if (EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) # delete files here file(REMOVE ${CMAKE_SOURCE_DIR}/compile_commands.json) -endif() +endif () # configure global dependencies ---------------------------------------------- include(cmake/configure_libpng.cmake) @@ -63,50 +63,50 @@ include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -if(${WIN32}) +if (${WIN32}) include(cmake/install_if_is_shared.cmake) -endif() +endif () # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty set(SlopeCraft_vectorize_flags) -if(NOT ${SlopeCraft_vectorize}) - if(NOT ${SlopeCraft_GPU_API} STREQUAL "None") +if (NOT ${SlopeCraft_vectorize}) + if (NOT ${SlopeCraft_GPU_API} STREQUAL "None") message(STATUS "You enabled GPU boosting, but disabled vectorization") - endif() -endif() + endif () +endif () -if(${SlopeCraft_vectorize}) +if (${SlopeCraft_vectorize}) include(CheckCXXCompilerFlag) add_definitions("-DSC_VECTORIZE_AVX2") - if(${MSVC}) + if (${MSVC}) set(SlopeCraft_vectorize_flags "/arch:AVX2") - else() + else () set(SlopeCraft_vectorize_flags -mavx -mavx2 -mfma) - endif() + endif () message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) add_compile_options(${SlopeCraft_vectorize_flags}) # list(APPEND SlopeCraft_vectorize_flags "-O3") -endif() +endif () -if(${WIN32}) +if (${WIN32}) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) -endif() +endif () # Add global compile options ------------------------------------------------- # profile with gprof -if(${SlopeCraft_gprof}) +if (${SlopeCraft_gprof}) add_compile_options("-pg") add_link_options("-pg") -endif() +endif () -if(${SlopeCraft_sanitize}) +if (${SlopeCraft_sanitize}) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fsanitize=address") -endif() +endif () add_compile_definitions(_USE_MATH_DEFINES) add_compile_definitions(SCL_FIND_GlobalEnums_BY_PATH) @@ -114,34 +114,35 @@ add_compile_definitions(SLOPECRAFTL_NOT_INSTALLED) add_compile_definitions(VISUALCRAFTL_NOT_INSTALLED) # Add compile options for different compilers -if(${MSVC}) +if (${MSVC}) add_compile_options("/Zc:__cplusplus") add_compile_options("/wd4819") add_compile_options("/utf-8") -else() + add_compile_options("/EHsc") +else () add_compile_options(-Wall -Wreturn-type -Wsign-compare -Wextra) add_link_options(-flto) -endif() +endif () # Add global include dirs ---------------------------------------------------- include_directories(${CMAKE_BINARY_DIR}/utilities) # Add global custom targets on windows --------------------------------------- -if(${WIN32}) +if (${WIN32}) add_custom_target(SC_create_all_symlinks - COMMENT "A interface target to create all symlinks on windows") + COMMENT "A interface target to create all symlinks on windows") add_custom_target(SC_deploy_all - COMMENT "A interface target to run windeployqt for all targets") -endif() + COMMENT "A interface target to run windeployqt for all targets") +endif () # # Language related variables # set(SC_lupdate_flags -no-ui-lines) set(SC_lupdate_flags) -if(${SlopeCraft_update_ts_no_obsolete}) +if (${SlopeCraft_update_ts_no_obsolete}) list(APPEND SC_lupdate_flags "-no-obsolete") -endif() +endif () # Sub dirss ------------------------------------------------------------------ add_subdirectory(utilities) From 233d191e9a2aedb3068cade48f3af7dc85b184b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 30 Jun 2023 23:41:26 +0800 Subject: [PATCH 0454/1123] restore github actions --- .github/workflows/build-dev-clang.yml | 4 ++-- .github/workflows/build-dev-gcc.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 3ba32ea3..7a354938 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -3,8 +3,8 @@ on: pull_request: push: branches: - #- main - #- dev + - main + - dev - update-sc-ui jobs: diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 79559a0b..e0567320 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -5,7 +5,7 @@ on: branches: - main - dev - #- update-sc-ui + - update-sc-ui jobs: macos-build: From a65f77b980bb9429880872fef97cf3d750f00288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 00:58:34 +0800 Subject: [PATCH 0455/1123] adapt to mc 1.20 for SC --- SlopeCraft/SCWind.ui | 10 +-- SlopeCraftL/TokiSlopeCraft_convert.cpp | 2 + SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 10 +-- SlopeCraftMain/MainWindow.cpp | 10 +-- utilities/MCDataVersion/MCDataVersion.cpp | 96 +++++++++++----------- utilities/MCDataVersion/MCDataVersion.h | 29 ++++++- utilities/SC_GlobalEnums.h | 4 +- utilities/Schem/Schem.cpp | 2 + 8 files changed, 96 insertions(+), 67 deletions(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 9a3a0dbb..85906428 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -18,7 +18,7 @@ - 2 + 0 @@ -143,7 +143,7 @@ - false + true 1.20 @@ -305,8 +305,8 @@ 0 0 - 731 - 619 + 753 + 664 @@ -1413,7 +1413,7 @@ 0 0 920 - 27 + 22 diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp index 4bb9cf37..81d66734 100644 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ b/SlopeCraftL/TokiSlopeCraft_convert.cpp @@ -190,6 +190,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, case SCL_gameVersion::MC17: case SCL_gameVersion::MC18: case SCL_gameVersion::MC19: + case SCL_gameVersion::MC20: MapFile.writeInt("DataVersion", mcVersion2VersionNumber(mcVer)); break; default: @@ -235,6 +236,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, case SCL_gameVersion::MC17: case SCL_gameVersion::MC18: case SCL_gameVersion::MC19: + case SCL_gameVersion::MC20: MapFile.writeListHead("banners", NBT::Compound, 0); MapFile.writeListHead("frames", NBT::Compound, 0); MapFile.writeString("dimension", "minecraft:overworld"); diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index c63e6faf..e5097f74 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -46,21 +46,15 @@ uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { case SCL_gameVersion::ANCIENT: return 114514; case SCL_gameVersion::MC12: - return 1631; case SCL_gameVersion::MC13: - return 1976; case SCL_gameVersion::MC14: - return 2230; case SCL_gameVersion::MC15: - return 2230; case SCL_gameVersion::MC16: - return 2586; case SCL_gameVersion::MC17: - return 2730; case SCL_gameVersion::MC18: - return 2865; case SCL_gameVersion::MC19: - return 3105; // 1.19.0 + case SCL_gameVersion::MC20: + return uint64_t(MCDataVersion::suggested_version(g)); default: return 1919810; } diff --git a/SlopeCraftMain/MainWindow.cpp b/SlopeCraftMain/MainWindow.cpp index 46fb6a91..26ed7e32 100644 --- a/SlopeCraftMain/MainWindow.cpp +++ b/SlopeCraftMain/MainWindow.cpp @@ -861,6 +861,7 @@ void MainWindow::kernelSetType() { if (ui->isGame17->isChecked()) ver = SlopeCraft::gameVersion::MC17; if (ui->isGame18->isChecked()) ver = SlopeCraft::gameVersion::MC18; if (ui->isGame19->isChecked()) ver = SlopeCraft::gameVersion::MC19; + if (ui->isGame20->isChecked()) ver = SlopeCraft::gameVersion::MC20; } bool allowedBaseColor[64]; @@ -1539,7 +1540,7 @@ void MainWindow::onExportDataclicked(QString path) { files += ';' + files_to_be_covered[idx]; } - auto ret=QMessageBox::warning( + auto ret = QMessageBox::warning( this, tr("导出时将会覆盖部分地图文件"), tr("%1 " "个文件将被覆盖:\n%" @@ -1548,13 +1549,12 @@ void MainWindow::onExportDataclicked(QString path) { .arg(files), QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No}); - if(ret==QMessageBox::StandardButton::No) { + if (ret == QMessageBox::StandardButton::No) { return; } } } - ui->InputDataIndex->setEnabled(false); ui->ExportData->setEnabled(false); ui->FinshExData->setEnabled(false); @@ -1686,8 +1686,8 @@ void MainWindow::showError(void *p, SlopeCraft::errorFlag error, break; case SlopeCraft::errorFlag::LOSSYCOMPRESS_FAILED: title = tr("有损压缩失败"); - text = tr( - "在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 \ + text = + tr("在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 \ 这可能是因为地图画行数过大。 \ 尝试启用无损压缩,或者提高最大允许高度"); break; diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index 5a3d1060..e69cedf6 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -24,8 +24,8 @@ This file is part of SlopeCraft. #include -MCDataVersion::MCDataVersion_t -MCDataVersion::string_to_data_version(const char *str, bool *ok) noexcept { +MCDataVersion::MCDataVersion_t MCDataVersion::string_to_data_version( + const char *str, bool *ok) noexcept { const auto mcdv = magic_enum::enum_cast(str); if (mcdv.has_value()) { @@ -46,57 +46,61 @@ const char *MCDataVersion::data_version_to_string( return mcdv.data(); } -MCDataVersion::MCDataVersion_t -MCDataVersion::max_supported_version(SCL_gameVersion v) noexcept { +MCDataVersion::MCDataVersion_t MCDataVersion::max_supported_version( + SCL_gameVersion v) noexcept { switch (v) { - case SCL_gameVersion::MC12: - return MCDataVersion_t::Java_1_12_2; - case SCL_gameVersion::MC13: - return MCDataVersion_t::Java_1_13_2; - case SCL_gameVersion::MC14: - return MCDataVersion_t::Java_1_14_4; - case SCL_gameVersion::MC15: - return MCDataVersion_t::Java_1_15_2; - case SCL_gameVersion::MC16: - return MCDataVersion_t::Java_1_16_5; - case SCL_gameVersion::MC17: - return MCDataVersion_t::Java_1_17_1; - case SCL_gameVersion::MC18: - return MCDataVersion_t::Java_1_18_2; - case SCL_gameVersion::MC19: - return MCDataVersion_t::Java_1_19_3; - default: - abort(); - return {}; + case SCL_gameVersion::MC12: + return MCDataVersion_t::Java_1_12_2; + case SCL_gameVersion::MC13: + return MCDataVersion_t::Java_1_13_2; + case SCL_gameVersion::MC14: + return MCDataVersion_t::Java_1_14_4; + case SCL_gameVersion::MC15: + return MCDataVersion_t::Java_1_15_2; + case SCL_gameVersion::MC16: + return MCDataVersion_t::Java_1_16_5; + case SCL_gameVersion::MC17: + return MCDataVersion_t::Java_1_17_1; + case SCL_gameVersion::MC18: + return MCDataVersion_t::Java_1_18_2; + case SCL_gameVersion::MC19: + return MCDataVersion_t::Java_1_19_3; + case SCL_gameVersion::MC20: + return MCDataVersion_t::Java_1_20_1; + default: + abort(); + return {}; } } -MCDataVersion::MCDataVersion_t -MCDataVersion::min_supported_version(SCL_gameVersion v) noexcept { +MCDataVersion::MCDataVersion_t MCDataVersion::min_supported_version( + SCL_gameVersion v) noexcept { switch (v) { - case SCL_gameVersion::MC12: - return MCDataVersion_t::Java_1_12; - case SCL_gameVersion::MC13: - return MCDataVersion_t::Java_1_13; - case SCL_gameVersion::MC14: - return MCDataVersion_t::Java_1_14; - case SCL_gameVersion::MC15: - return MCDataVersion_t::Java_1_15; - case SCL_gameVersion::MC16: - return MCDataVersion_t::Java_1_16; - case SCL_gameVersion::MC17: - return MCDataVersion_t::Java_1_17; - case SCL_gameVersion::MC18: - return MCDataVersion_t::Java_1_18; - case SCL_gameVersion::MC19: - return MCDataVersion_t::Java_1_19; - default: - abort(); - return {}; + case SCL_gameVersion::MC12: + return MCDataVersion_t::Java_1_12; + case SCL_gameVersion::MC13: + return MCDataVersion_t::Java_1_13; + case SCL_gameVersion::MC14: + return MCDataVersion_t::Java_1_14; + case SCL_gameVersion::MC15: + return MCDataVersion_t::Java_1_15; + case SCL_gameVersion::MC16: + return MCDataVersion_t::Java_1_16; + case SCL_gameVersion::MC17: + return MCDataVersion_t::Java_1_17; + case SCL_gameVersion::MC18: + return MCDataVersion_t::Java_1_18; + case SCL_gameVersion::MC19: + return MCDataVersion_t::Java_1_19; + case SCL_gameVersion::MC20: + return MCDataVersion_t::Java_1_20; + default: + abort(); + return {}; } } -MCDataVersion::MCDataVersion_t -MCDataVersion::suggested_version(SCL_gameVersion v) noexcept { +MCDataVersion::MCDataVersion_t MCDataVersion::suggested_version( + SCL_gameVersion v) noexcept { return max_supported_version(v); } diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index 3a45111e..4bedffe4 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,6 +30,31 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + + Java_1_20_1 = 3465, + Java_1_20_1__rc1 = 3464, + Java_1_20 = 3463, + Java_1_20__rc1 = 3462, + Java_1_20__pre7 = 3461, + Java_1_20__pre6 = 3460, + Java_1_20__pre5 = 3458, + Java_1_20__pre4 = 3457, + Java_1_20__pre3 = 3456, + Java_1_20__pre2 = 3455, + Java_1_20__pre1 = 3454, + Snapshot_23w_18a = 3453, + Snapshot_23w_17a = 3452, + Snapshot_23w_16a = 3449, + Snapshot_23w_14a = 3445, + Snapshot_23w_13a = 3442, + Snapshot_23w_12a = 3442, + Java_1_19_4 = 3337, + Java_1_19_4__rc3 = 3336, + Java_1_19_4__rc2 = 3335, + Java_1_19_4__rc1 = 3334, + Java_1_19_4__pre4 = 3333, + Java_1_19_4__pre3 = 3332, + Java_1_19_4__pre2 = 3331, Java_1_19_4__pre1 = 3330, Snapshot_23w07a = 3329, Snapshot_23w06a = 3326, @@ -515,5 +540,5 @@ inline bool is_data_version_suitable(SCL_gameVersion v, return true; } -} // namespace MCDataVersion -#endif // SLOPECRAFT_UTILITIES_MCDATAVERSION_H \ No newline at end of file +} // namespace MCDataVersion +#endif // SLOPECRAFT_UTILITIES_MCDATAVERSION_H \ No newline at end of file diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index def6ef25..0b67e5b8 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -50,6 +50,8 @@ enum class SCL_gameVersion : int { MC18 = 18, /// 1.19 MC19 = 19, + /// 1.20 + MC20 = 20, /// future version FUTURE = 255 }; @@ -151,7 +153,7 @@ enum class SCL_errorFlag : int { /// is_air_structure_void to false and you don't have minecraft:air in the /// palette EXPORT_SCHEM_STRUCTURE_REQUIRES_AIR = 0x0C, - /// the major game version is less that MC12 or greater than MC19 + /// the major game version is less that MC12 or greater than MC20 UNKNOWN_MAJOR_GAME_VERSION = 0x0D, /// Exporting as WESchem doesn't support MC12, since the format of schematic /// is greatly different. diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index daf3d455..8939a216 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -439,6 +439,7 @@ bool Schem::export_litematic(std::string_view filename, case ::SCL_gameVersion::MC17: case ::SCL_gameVersion::MC18: case ::SCL_gameVersion::MC19: + case ::SCL_gameVersion::MC20: lite.writeInt("MinecraftDataVersion", (int)this->MC_version_number()); lite.writeInt("Version", 5); break; @@ -633,6 +634,7 @@ bool Schem::export_structure(std::string_view filename, case ::SCL_gameVersion::MC17: case ::SCL_gameVersion::MC18: case ::SCL_gameVersion::MC19: + case ::SCL_gameVersion::MC20: file.writeInt("MinecraftDataVersion", (int)this->MC_data_ver); break; default: From d561a74ec32da13eb10b6d23de8ed71d950f08c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 01:31:16 +0800 Subject: [PATCH 0456/1123] adapt to MC20 for VC and vccl --- VisualCraft/CallbackFunctions.cpp | 4 +- VisualCraft/VCWind.cpp | 3 + VisualCraft/VCWind.ui | 59 ++++++++++-------- VisualCraft/vc-config-to-bin-dir.json.in | 4 ++ VisualCraft/vc-config.json | 76 +++++++++++++----------- VisualCraftL/setup_zip_names.cmake | 10 ++-- cmake/configure_vanilla_zips.cmake | 35 +++++------ vccl/vccl-config-to-bin-dir.json.in | 4 ++ vccl/vccl-config.json | 76 +++++++++++++----------- vccl/vccl.cpp | 2 +- 10 files changed, 151 insertions(+), 122 deletions(-) diff --git a/VisualCraft/CallbackFunctions.cpp b/VisualCraft/CallbackFunctions.cpp index 29e45dab..6690a059 100644 --- a/VisualCraft/CallbackFunctions.cpp +++ b/VisualCraft/CallbackFunctions.cpp @@ -44,7 +44,9 @@ void VC_callback::callback_receive_report(VCL_report_type_t type, return; } case VCL_report_type_t::warning: { - ss_warning << msg; + if (msg != nullptr) { + ss_warning << msg; + } if (flush) { std::string res; diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index b21e6543..33c5b644 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -136,6 +136,9 @@ SCL_gameVersion VCWind::current_selected_version() const noexcept { if (ui->rdb_version_19->isChecked()) { return SCL_gameVersion::MC19; } + if (ui->rdb_version_20->isChecked()) { + return SCL_gameVersion::MC20; + } abort(); } diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 85b1d0c3..1f74e331 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -78,17 +78,17 @@ 游戏版本 - - + + - 1.15 + 1.18 - - + + - 1.12 + 1.15 @@ -99,20 +99,6 @@ - - - - 1.13 - - - - - - - 1.14 - - - @@ -130,10 +116,31 @@ - - + + - 1.18 + 1.13 + + + + + + + 1.12 + + + + + + + 1.14 + + + + + + + 1.20 @@ -346,8 +353,8 @@ 0 0 - 861 - 273 + 885 + 302 @@ -1161,7 +1168,7 @@ 0 0 1057 - 27 + 22 diff --git a/VisualCraft/vc-config-to-bin-dir.json.in b/VisualCraft/vc-config-to-bin-dir.json.in index 90b7ed3c..d337204e 100644 --- a/VisualCraft/vc-config-to-bin-dir.json.in +++ b/VisualCraft/vc-config-to-bin-dir.json.in @@ -31,6 +31,10 @@ [ 19, "@VCL_resource_19@" + ], + [ + 20, + "@VCL_resource_20@" ] ], "default_block_state_list": [ diff --git a/VisualCraft/vc-config.json b/VisualCraft/vc-config.json index 585685b0..5246e465 100644 --- a/VisualCraft/vc-config.json +++ b/VisualCraft/vc-config.json @@ -1,39 +1,43 @@ { - "default_resource_pack_zip": [ - [ - 12, - "./Blocks_VCL/Vanilla_1_12_2.zip" - ], - [ - 13, - "./Blocks_VCL/Vanilla_1_13_2.zip" - ], - [ - 14, - "./Blocks_VCL/Vanilla_1_14_4.zip" - ], - [ - 15, - "./Blocks_VCL/Vanilla_1_15_2.zip" - ], - [ - 16, - "./Blocks_VCL/Vanilla_1_16_5.zip" - ], - [ - 17, - "./Blocks_VCL/Vanilla_1_17_1.zip" - ], - [ - 18, - "./Blocks_VCL/Vanilla_1_18_2.zip" - ], - [ - 19, - "./Blocks_VCL/Vanilla_1_19_3.zip" - ] - ], - "default_block_state_list": [ - "./Blocks_VCL/VCL_blocks_fixed.json" + "default_resource_pack_zip": [ + [ + 12, + "./Blocks_VCL/Vanilla_1_12_2.zip" + ], + [ + 13, + "./Blocks_VCL/Vanilla_1_13_2.zip" + ], + [ + 14, + "./Blocks_VCL/Vanilla_1_14_4.zip" + ], + [ + 15, + "./Blocks_VCL/Vanilla_1_15_2.zip" + ], + [ + 16, + "./Blocks_VCL/Vanilla_1_16_5.zip" + ], + [ + 17, + "./Blocks_VCL/Vanilla_1_17_1.zip" + ], + [ + 18, + "./Blocks_VCL/Vanilla_1_18_2.zip" + ], + [ + 19, + "./Blocks_VCL/Vanilla_1_19_3.zip" + ], + [ + 20, + "./Blocks_VCL/Vanilla_1_20_1.zip" ] + ], + "default_block_state_list": [ + "./Blocks_VCL/VCL_blocks_fixed.json" + ] } \ No newline at end of file diff --git a/VisualCraftL/setup_zip_names.cmake b/VisualCraftL/setup_zip_names.cmake index 427a1dc4..bd1b912f 100644 --- a/VisualCraftL/setup_zip_names.cmake +++ b/VisualCraftL/setup_zip_names.cmake @@ -1,16 +1,16 @@ set(VCL_app_files - ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) + ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) -foreach(mcver RANGE 12 19) +foreach (mcver RANGE 12 20) set(VCL_current_var_name VCL_resource_${mcver}) - if(NOT DEFINED ${VCL_current_var_name}) + if (NOT DEFINED ${VCL_current_var_name}) message(WARNING "${VCL_current_var_name} is not defined") - endif() + endif () list(APPEND VCL_app_files ${${VCL_current_var_name}}) -endforeach(mcver RANGE 12 19) +endforeach (mcver RANGE 12 20) unset(mcver) \ No newline at end of file diff --git a/cmake/configure_vanilla_zips.cmake b/cmake/configure_vanilla_zips.cmake index 086fbc3c..bf6969b0 100644 --- a/cmake/configure_vanilla_zips.cmake +++ b/cmake/configure_vanilla_zips.cmake @@ -1,16 +1,17 @@ set(VCL_zip_names - "Vanilla_1_12_2.zip" - "Vanilla_1_13_2.zip" - "Vanilla_1_14_4.zip" - "Vanilla_1_15_2.zip" - "Vanilla_1_16_5.zip" - "Vanilla_1_17_1.zip" - "Vanilla_1_18_2.zip" - "Vanilla_1_19_3.zip") + "Vanilla_1_12_2.zip" + "Vanilla_1_13_2.zip" + "Vanilla_1_14_4.zip" + "Vanilla_1_15_2.zip" + "Vanilla_1_16_5.zip" + "Vanilla_1_17_1.zip" + "Vanilla_1_18_2.zip" + "Vanilla_1_19_3.zip" + "Vanilla_1_20_1.zip") set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") -foreach(mcver RANGE 12 19) +foreach (mcver RANGE 12 20) math(EXPR VCL_resource_idx "${mcver} - 12") # message(STATUS "VCL_resource_idx = ${VCL_resource_idx}") @@ -18,20 +19,20 @@ foreach(mcver RANGE 12 19) set(VCL_resource_${mcver} ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name} CACHE FILEPATH "") - if(EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) + if (EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) # message(STATUS "Found resoruce pack for MC${mcver} (${VCL_current_zip_name}).") continue() - endif() + endif () message(STATUS "${VCL_current_zip_name} not found. Downloading...") file(DOWNLOAD - ${VCL_url_prefix}${VCL_current_zip_name} - ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) + ${VCL_url_prefix} ${VCL_current_zip_name} + ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) - if(EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) + if (EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) message(STATUS "Downloaded resoruce pack for MC${mcver}.") - else() + else () message(FATAL_ERROR "Failed to download resource pack for MC${mcver}.") - endif() -endforeach(mcver RANGE 12 19) \ No newline at end of file + endif () +endforeach (mcver RANGE 12 20) \ No newline at end of file diff --git a/vccl/vccl-config-to-bin-dir.json.in b/vccl/vccl-config-to-bin-dir.json.in index 90b7ed3c..d337204e 100644 --- a/vccl/vccl-config-to-bin-dir.json.in +++ b/vccl/vccl-config-to-bin-dir.json.in @@ -31,6 +31,10 @@ [ 19, "@VCL_resource_19@" + ], + [ + 20, + "@VCL_resource_20@" ] ], "default_block_state_list": [ diff --git a/vccl/vccl-config.json b/vccl/vccl-config.json index 585685b0..5246e465 100644 --- a/vccl/vccl-config.json +++ b/vccl/vccl-config.json @@ -1,39 +1,43 @@ { - "default_resource_pack_zip": [ - [ - 12, - "./Blocks_VCL/Vanilla_1_12_2.zip" - ], - [ - 13, - "./Blocks_VCL/Vanilla_1_13_2.zip" - ], - [ - 14, - "./Blocks_VCL/Vanilla_1_14_4.zip" - ], - [ - 15, - "./Blocks_VCL/Vanilla_1_15_2.zip" - ], - [ - 16, - "./Blocks_VCL/Vanilla_1_16_5.zip" - ], - [ - 17, - "./Blocks_VCL/Vanilla_1_17_1.zip" - ], - [ - 18, - "./Blocks_VCL/Vanilla_1_18_2.zip" - ], - [ - 19, - "./Blocks_VCL/Vanilla_1_19_3.zip" - ] - ], - "default_block_state_list": [ - "./Blocks_VCL/VCL_blocks_fixed.json" + "default_resource_pack_zip": [ + [ + 12, + "./Blocks_VCL/Vanilla_1_12_2.zip" + ], + [ + 13, + "./Blocks_VCL/Vanilla_1_13_2.zip" + ], + [ + 14, + "./Blocks_VCL/Vanilla_1_14_4.zip" + ], + [ + 15, + "./Blocks_VCL/Vanilla_1_15_2.zip" + ], + [ + 16, + "./Blocks_VCL/Vanilla_1_16_5.zip" + ], + [ + 17, + "./Blocks_VCL/Vanilla_1_17_1.zip" + ], + [ + 18, + "./Blocks_VCL/Vanilla_1_18_2.zip" + ], + [ + 19, + "./Blocks_VCL/Vanilla_1_19_3.zip" + ], + [ + 20, + "./Blocks_VCL/Vanilla_1_20_1.zip" ] + ], + "default_block_state_list": [ + "./Blocks_VCL/VCL_blocks_fixed.json" + ] } \ No newline at end of file diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index b3eff688..6d3cab98 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -62,7 +62,7 @@ int main(int argc, char **argv) { int __version; app.add_option("--mcver", __version, "MC version") ->default_val(19) - ->check(CLI::Range(12, 19, "Avaliable versions")); + ->check(CLI::Range(12, 20, "Avaliable versions")); app.add_option("--layers,--layer", input.layers, "Max layers") ->default_val(1) From 8418bd770c26ffefe738bdfa9fdc80ebd3c42def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 13:44:16 +0800 Subject: [PATCH 0457/1123] add 1.20 blocks to SC fixed list --- Blocks/FixedBlocks.json | 3394 ++++++++++---------- Blocks/FixedBlocks/bamboo_block.png | Bin 0 -> 299 bytes Blocks/FixedBlocks/bamboo_planks.png | Bin 0 -> 274 bytes Blocks/FixedBlocks/cherry_leaves.png | Bin 0 -> 339 bytes Blocks/FixedBlocks/cherry_log.png | Bin 0 -> 232 bytes Blocks/FixedBlocks/cherry_planks.png | Bin 0 -> 270 bytes Blocks/FixedBlocks/stripped_cherry_log.png | Bin 0 -> 258 bytes 7 files changed, 1724 insertions(+), 1670 deletions(-) create mode 100644 Blocks/FixedBlocks/bamboo_block.png create mode 100644 Blocks/FixedBlocks/bamboo_planks.png create mode 100644 Blocks/FixedBlocks/cherry_leaves.png create mode 100644 Blocks/FixedBlocks/cherry_log.png create mode 100644 Blocks/FixedBlocks/cherry_planks.png create mode 100644 Blocks/FixedBlocks/stripped_cherry_log.png diff --git a/Blocks/FixedBlocks.json b/Blocks/FixedBlocks.json index b415758a..34826f54 100644 --- a/Blocks/FixedBlocks.json +++ b/Blocks/FixedBlocks.json @@ -1,1672 +1,1726 @@ { - "FixedBlocks": [ - { - "baseColor": 0, - "id": "minecraft:glass", - "nameZH": "玻璃", - "nameEN": "Glass", - "icon": "glass.png", - "version": 0 - }, - { - "baseColor": 1, - "id": "minecraft:grass_block[snowy=false]", - "nameZH": "草方块", - "nameEN": "Grass block", - "icon": "grass_block.png", - "version": 0, - "idOld": "minecraft:grass[snowy=false]", - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 1, - "id": "minecraft:slime_block", - "nameZH": "黏液块", - "nameEN": "Slime block", - "icon": "slime_block.png", - "version": 0, - "idOld": "minecraft:slime" - }, - { - "baseColor": 2, - "id": "minecraft:birch_planks", - "nameZH": "白桦木板", - "nameEN": "Birch plank", - "icon": "birch_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=birch]", - "burnable": true - }, - { - "baseColor": 2, - "id": "minecraft:smooth_sandstone", - "nameZH": "平滑砂岩", - "nameEN": "Smooth sandstone", - "icon": "smooth_sandstone.png", - "version": 0, - "idOld": "minecraft:sandstone[type=smooth_sandstone]" - }, - { - "baseColor": 2, - "id": "minecraft:glowstone", - "nameZH": "荧石", - "nameEN": "Glowstone", - "icon": "glowstone.png", - "version": 0, - "isGlowing": true - }, - { - "baseColor": 2, - "id": "minecraft:end_stone", - "nameZH": "末地石", - "nameEN": "End stone", - "icon": "end_stone.png", - "version": 0 - }, - { - "baseColor": 2, - "id": "minecraft:end_stone_bricks", - "nameZH": "末地石砖", - "nameEN": "Endstone bricks", - "icon": "end_stone_bricks.png", - "version": 0, - "idOld": "minecraft:end_bricks" - }, - { - "baseColor": 2, - "id": "minecraft:turtle_egg[eggs=4,hatch=0]", - "nameZH": "海龟蛋", - "nameEN": "Turtle egg", - "icon": "turtle_egg.png", - "version": 13, - "needGlass": true, - "wallUseable": false - }, - { - "baseColor": 2, - "id": "minecraft:ochre_froglight[axis=y]", - "nameZH": "赭黄蛙明灯", - "nameEN": "Ochre Froglight", - "icon": "ochre_froglight_top.png", - "version": 19, - "isGlowing": true - }, - { - "baseColor": 3, - "id": "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "蘑菇柄", - "nameEN": "Mushroom stem", - "icon": "mushroom_stem.png", - "version": 13, - "burnable": true - }, - { - "baseColor": 3, - "id": "minecraft:cobweb", - "nameZH": "蜘蛛网", - "nameEN": "Cobweb", - "icon": "cobweb.png", - "version": 0, - "idOld": "minecraft:web" - }, - { - "baseColor": 4, - "id": "minecraft:redstone_block", - "nameZH": "红石块", - "nameEN": "Redstone block", - "icon": "redstone_block.png", - "version": 0 - }, - { - "baseColor": 4, - "id": "minecraft:tnt[unstable=false]", - "nameZH": "TNT", - "nameEN": "TNT", - "icon": "tnt.png", - "version": 0, - "idOld": "minecraft:tnt[explode=false]", - "endermanPickable": true, - "burnable": true - }, - { - "baseColor": 5, - "id": "minecraft:ice", - "nameZH": "冰", - "nameEN": "Ice", - "icon": "ice.png", - "version": 0 - }, - { - "baseColor": 5, - "id": "minecraft:packed_ice", - "nameZH": "浮冰", - "nameEN": "Packed ice", - "icon": "packed_ice.png", - "version": 0 - }, - { - "baseColor": 5, - "id": "minecraft:blue_ice", - "nameZH": "蓝冰", - "nameEN": "Blue ice", - "icon": "blue_ice.png", - "version": 13 - }, - { - "baseColor": 6, - "id": "minecraft:iron_block", - "nameZH": "铁块", - "nameEN": "Iron block", - "icon": "iron_block.png", - "version": 0 - }, - { - "baseColor": 6, - "id": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", - "nameZH": "酿造台", - "nameEN": "brewing stand", - "icon": "brewing_stand.png", - "version": 0, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:heavy_weighted_pressure_plate[power=0]", - "nameZH": "重质测重压力板", - "nameEN": "Iron pressure plate", - "icon": "heavy_weighted_pressure_plate.png", - "version": 0, - "needGlass": true, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:iron_trapdoor[facing=north,half=top,open=false,powered=false,waterlogged=false]", - "nameZH": "铁活板门", - "nameEN": "Iron trapdoor", - "icon": "iron_trapdoor.png", - "version": 0, - "idOld": "minecraft:iron_trapdoor[facing=north,half=top,open=false]", - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:lantern[hanging=false]", - "nameZH": "灯笼", - "nameEN": "lantern", - "icon": "lantern.png", - "version": 14, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:grindstone[face=floor,facing=north]", - "nameZH": "砂轮", - "nameEN": "Grindstone", - "icon": "grindstone.png", - "version": 14, - "wallUseable": false - }, - { - "baseColor": 7, - "id": "minecraft:oak_leaves[distance=7,persistent=true]", - "nameZH": "橡树树叶", - "nameEN": "Oak leaves", - "icon": "oak_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:spruce_leaves[distance=7,persistent=true]", - "nameZH": "云杉树叶", - "nameEN": "Spurce leaves", - "icon": "spruce_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:birch_leaves[distance=7,persistent=true]", - "nameZH": "白桦树叶", - "nameEN": "Brich leaves", - "icon": "birch_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:jungle_leaves[distance=7,persistent=true]", - "nameZH": "丛林树叶", - "nameEN": "Jungle leaves", - "icon": "jungle_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:acacia_leaves[distance=7,persistent=true]", - "nameZH": "金合欢树叶", - "nameEN": "Acacia leaves", - "icon": "acacia_leaves.png", - "version": 0, - "idOld": "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:dark_oak_leaves[distance=7,persistent=true]", - "nameZH": "深色橡树树叶", - "nameEN": "Dark oat leaves", - "icon": "dark_oak_leaves.png", - "version": 0, - "idOld": "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" - }, - { - "baseColor": 8, - "id": "minecraft:white_concrete", - "nameZH": "白色混凝土", - "nameEN": "White concrete", - "icon": "white_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:white_wool", - "nameZH": "白色羊毛", - "nameEN": "White wool", - "icon": "white_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:white_stained_glass", - "nameZH": "白色染色玻璃", - "nameEN": "White glass", - "icon": "white_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:snow_block", - "nameZH": "雪块", - "nameEN": "Snow", - "icon": "snow_block.png", - "version": 0, - "idOld": "minecraft:snow" - }, - { - "baseColor": 9, - "id": "minecraft:clay", - "nameZH": "黏土块", - "nameEN": "Clay block", - "icon": "clay.png", - "version": 0, - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:coarse_dirt", - "nameZH": "砂土", - "nameEN": "Coarse dirt", - "icon": "coarse_dirt.png", - "version": 13, - "idOld": "minecraft:dirt[variant=coarse_dirt,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:polished_granite", - "nameZH": "磨制花岗岩", - "nameEN": "Polished granite", - "icon": "polished_granite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_granite]" - }, - { - "baseColor": 10, - "id": "minecraft:jungle_planks", - "nameZH": "丛林木板", - "nameEN": "Jungle plank", - "icon": "jungle_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=jungle]", - "burnable": true - }, - { - "baseColor": 10, - "id": "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "棕色蘑菇方块", - "nameEN": "Brown mushroom block", - "icon": "brown_mushroom_block.png", - "version": 0, - "idOld": "minecraft:brown_mushroom_block[variant=all_outside]" - }, - { - "baseColor": 10, - "id": "minecraft:dirt", - "nameZH": "泥土", - "nameEN": "Dirt", - "icon": "dirt.png", - "version": 0, - "idOld": "minecraft:dirt[variant=dirt,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:packed_mud", - "nameZH": "泥坯", - "nameEN": "Packed mud", - "icon": "packed_mud.png", - "version": 19 - }, - { - "baseColor": 11, - "id": "minecraft:cobblestone", - "nameZH": "圆石", - "nameEN": "Cobblestone", - "icon": "cobblestone.png", - "version": 0 - }, - { - "baseColor": 11, - "id": "minecraft:stone", - "nameZH": "石头", - "nameEN": "Stone", - "icon": "stone.png", - "version": 0, - "idOld": "minecraft:stone[variant=stone]" - }, - { - "baseColor": 11, - "id": "minecraft:smooth_stone", - "nameZH": "平滑石头", - "nameEN": "Smooth stone", - "icon": "smooth_stone.png", - "version": 13 - }, - { - "baseColor": 11, - "id": "minecraft:stone_bricks", - "nameZH": "石砖", - "nameEN": "Stone brick", - "icon": "stone_bricks.png", - "version": 0, - "idOld": "minecraft:stonebrick[variant=stonebrick]" - }, - { - "baseColor": 12, - "id": "minecraft:water[level=0]", - "nameZH": "水", - "nameEN": "Water", - "icon": "water.png", - "version": 0, - "wallUseable": false - }, - { - "baseColor": 13, - "id": "minecraft:oak_planks", - "nameZH": "橡木木板", - "nameEN": "Oak plank", - "icon": "oak_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=oak]", - "burnable": true - }, - { - "baseColor": 14, - "id": "minecraft:polished_diorite", - "nameZH": "磨制闪长岩", - "nameEN": "Polished diorite", - "icon": "polished_diorite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_diorite]" - }, - { - "baseColor": 14, - "id": "minecraft:quartz_block", - "nameZH": "石英块", - "nameEN": "Quartz block", - "icon": "quartz_block.png", - "version": 0, - "idOld": "minecraft:quartz_block[variant=default]" - }, - { - "baseColor": 14, - "id": "minecraft:sea_lantern", - "nameZH": "海晶灯", - "nameEN": "Sea lantern", - "icon": "sea_lantern.png", - "version": 0 - }, - { - "baseColor": 14, - "id": "minecraft:target[power=0]", - "nameZH": "标靶", - "nameEN": "Target", - "icon": "target.png", - "version": 16 - }, - { - "baseColor": 15, - "id": "minecraft:orange_concrete", - "nameZH": "橙色混凝土", - "nameEN": "Orange concrete", - "icon": "orange_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:orange_wool", - "nameZH": "橙色羊毛", - "nameEN": "Orange wool", - "icon": "orange_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:orange_stained_glass", - "nameZH": "橙色染色玻璃", - "nameEN": "Orange glass", - "icon": "orange_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:acacia_planks", - "nameZH": "金合欢木板", - "nameEN": "Acacia plank", - "icon": "acacia_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=acacia]", - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:pumpkin", - "nameZH": "南瓜", - "nameEN": "Pumpkin", - "icon": "pumpkin.png", - "version": 0, - "idOld": "minecraft:pumpkin[variant=north]", - "endermanPickable": true - }, - { - "baseColor": 15, - "id": "minecraft:terracotta", - "nameZH": "陶瓦", - "nameEN": "Terracotta", - "icon": "terracotta.png", - "version": 0, - "idOld": "minecraft:hardened_clay" - }, - { - "baseColor": 15, - "id": "minecraft:smooth_red_sandstone", - "nameZH": "平滑红砂岩", - "nameEN": "Smooth red sandstone", - "icon": "smooth_red_sandstone.png", - "version": 0, - "idOld": "minecraft:red_sandstone[type=smooth_red_sandstone]" - }, - { - "baseColor": 15, - "id": "minecraft:honey_block", - "nameZH": "蜂蜜块", - "nameEN": "Honey block", - "icon": "honey_block.png", - "version": 15 - }, - { - "baseColor": 15, - "id": "minecraft:honeycomb_block", - "nameZH": "蜜脾块", - "nameEN": "Honey comb block", - "icon": "honeycomb_block.png", - "version": 15 - }, - { - "baseColor": 15, - "id": "minecraft:raw_copper_block", - "nameZH": "粗铜块", - "nameEN": "Raw copper block", - "icon": "raw_copper_block.png", - "version": 17 - }, - { - "baseColor": 15, - "id": "minecraft:waxed_copper_block", - "nameZH": "涂蜡铜块", - "nameEN": "Waxed copper", - "icon": "waxed_copper_block.png", - "version": 17 - }, - { - "baseColor": 15, - "id": "minecraft:waxed_cut_copper", - "nameZH": "涂蜡切制铜块", - "nameEN": "Waxed cut copper", - "icon": "waxed_cut_copper.png", - "version": 17 - }, - { - "baseColor": 16, - "id": "minecraft:magenta_concrete", - "nameZH": "品红色混凝土", - "nameEN": "Magenta concrete", - "icon": "magenta_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:magenta_wool", - "nameZH": "品红色羊毛", - "nameEN": "Magenta wool", - "icon": "magenta_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:magenta_stained_glass", - "nameZH": "品红色染色玻璃", - "nameEN": "Magenta glass", - "icon": "magenta_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:purpur_block", - "nameZH": "紫珀块", - "nameEN": "Purpur block", - "icon": "purpur_block.png", - "version": 0 - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_concrete", - "nameZH": "淡蓝色混凝土", - "nameEN": "Light blue concrete", - "icon": "light_blue_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=light_blue]" - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_wool", - "nameZH": "淡蓝色羊毛", - "nameEN": "light blue wool", - "icon": "light_blue_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=light_blue]" - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_stained_glass", - "nameZH": "淡蓝色染色玻璃", - "nameEN": "Light blue glass", - "icon": "light_blue_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=light_blue]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_concrete", - "nameZH": "黄色混凝土", - "nameEN": "Yellow concrete", - "icon": "yellow_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_wool", - "nameZH": "黄色羊毛", - "nameEN": "Yellow wool", - "icon": "yellow_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_stained_glass", - "nameZH": "黄色染色玻璃", - "nameEN": "yellow glass", - "icon": "yellow_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:hay_block[axis=y]", - "nameZH": "干草捆", - "nameEN": "Hay block", - "icon": "hay_block.png", - "version": 0 - }, - { - "baseColor": 19, - "id": "minecraft:lime_concrete", - "nameZH": "黄绿色混凝土", - "nameEN": "Lime concrete", - "icon": "lime_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=lime]" - }, - { - "baseColor": 19, - "id": "minecraft:lime_wool", - "nameZH": "黄绿色羊毛", - "nameEN": "Lime wool", - "icon": "lime_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=lime]" - }, - { - "baseColor": 19, - "id": "minecraft:lime_stained_glass", - "nameZH": "黄绿色染色玻璃", - "nameEN": "Lime glass", - "icon": "lime_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=lime]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_concrete", - "nameZH": "粉红色混凝土", - "nameEN": "Pink concrete", - "icon": "pink_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_wool", - "nameZH": "粉红色羊毛", - "nameEN": "Pink wool", - "icon": "pink_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_stained_glass", - "nameZH": "粉红色染色玻璃", - "nameEN": "Pink glass", - "icon": "pink_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pearlescent_froglight[axis=y]", - "nameZH": "珠光蛙明灯", - "nameEN": "Verdant Froglight", - "icon": "pearlescent_froglight_top.png", - "version": 19, - "isGlowing": true - }, - { - "baseColor": 21, - "id": "minecraft:gray_concrete", - "nameZH": "灰色混凝土", - "nameEN": "Gray concrete", - "icon": "gray_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=gray]" - }, - { - "baseColor": 21, - "id": "minecraft:gray_wool", - "nameZH": "灰色羊毛", - "nameEN": "Gray wool", - "icon": "gray_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=gray]", - "burnable": true - }, - { - "baseColor": 21, - "id": "minecraft:gray_stained_glass", - "nameZH": "灰色染色玻璃", - "nameEN": "Gray glass", - "icon": "gray_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=gray]" - }, - { - "baseColor": 21, - "id": "minecraft:tinted_glass", - "nameZH": "遮光玻璃", - "nameEN": "Tinted glass", - "icon": "tinted_glass.png", - "version": 17 - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_concrete", - "nameZH": "淡灰色混凝土", - "nameEN": "Light gray concrete", - "icon": "light_gray_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=silver]" - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_wool", - "nameZH": "淡灰色羊毛", - "nameEN": "Light gray wool", - "icon": "light_gray_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=silver]", - "burnable": true - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_stained_glass", - "nameZH": "淡灰色染色玻璃", - "nameEN": "Light gray glass", - "icon": "light_gray_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=silver]" - }, - { - "baseColor": 23, - "id": "minecraft:cyan_concrete", - "nameZH": "青色混凝土", - "nameEN": "Cyan concrete", - "icon": "cyan_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=cyan]" - }, - { - "baseColor": 23, - "id": "minecraft:cyan_wool", - "nameZH": "青色羊毛", - "nameEN": "Cyan wool", - "icon": "cyan_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=cyan]", - "burnable": true - }, - { - "baseColor": 23, - "id": "minecraft:cyan_stained_glass", - "nameZH": "青色染色玻璃", - "nameEN": "Cyan glass", - "icon": "cyan_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=cyan]" - }, - { - "baseColor": 23, - "id": "minecraft:prismarine", - "nameZH": "海晶石", - "nameEN": "Prismarine", - "icon": "prismarine.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=prismarine]" - }, - { - "baseColor": 23, - "id": "minecraft:sculk_sensor[power=0,sculk_sensor_phase=inactive,waterlogged=false]", - "nameZH": "幽匿感测体", - "nameEN": "Sculk sensor", - "icon": "sculk_sensor_side.png", - "version": 19 - }, - { - "baseColor": 24, - "id": "minecraft:purple_concrete", - "nameZH": "紫色混凝土", - "nameEN": "Purple concrete", - "icon": "purple_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=purple]" - }, - { - "baseColor": 24, - "id": "minecraft:purple_wool", - "nameZH": "紫色羊毛", - "nameEN": "Purple wool", - "icon": "purple_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=purple]", - "burnable": true - }, - { - "baseColor": 24, - "id": "minecraft:purple_stained_glass", - "nameZH": "紫色染色玻璃", - "nameEN": "Purple glass", - "icon": "purple_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=purple]" - }, - { - "baseColor": 24, - "id": "minecraft:amethyst_block", - "nameZH": "紫水晶块", - "nameEN": "Amethyst block", - "icon": "amethyst_block.png", - "version": 17 - }, - { - "baseColor": 25, - "id": "minecraft:blue_concrete", - "nameZH": "蓝色混凝土", - "nameEN": "Blue concrete", - "icon": "blue_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=blue]" - }, - { - "baseColor": 25, - "id": "minecraft:blue_wool", - "nameZH": "蓝色羊毛", - "nameEN": "Blue wool", - "icon": "blue_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=blue]", - "burnable": true - }, - { - "baseColor": 25, - "id": "minecraft:blue_stained_glass", - "nameZH": "蓝色染色玻璃", - "nameEN": "Blue glass", - "icon": "blue_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=blue]" - }, - { - "baseColor": 26, - "id": "minecraft:brown_concrete", - "nameZH": "棕色混凝土", - "nameEN": "Brown concrete", - "icon": "brown_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=brown]" - }, - { - "baseColor": 26, - "id": "minecraft:brown_wool", - "nameZH": "棕色羊毛", - "nameEN": "Brown wool", - "icon": "brown_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=brown]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:brown_stained_glass", - "nameZH": "棕色染色玻璃", - "nameEN": "Brown glass", - "icon": "brown_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=brown]" - }, - { - "baseColor": 26, - "id": "minecraft:dark_oak_planks", - "nameZH": "深色橡木木板", - "nameEN": "Dark oak plank", - "icon": "dark_oak_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=dark_oak]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:soul_sand", - "nameZH": "灵魂沙", - "nameEN": "Soul sand", - "icon": "soul_sand.png", - "version": 0 - }, - { - "baseColor": 26, - "id": "minecraft:soul_soil", - "nameZH": "灵魂土", - "nameEN": "Soul soil", - "icon": "soul_soil.png", - "version": 16 - }, - { - "baseColor": 27, - "id": "minecraft:green_concrete", - "nameZH": "绿色混凝土", - "nameEN": "Green concrete", - "icon": "green_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=green]" - }, - { - "baseColor": 27, - "id": "minecraft:green_wool", - "nameZH": "绿色羊毛", - "nameEN": "Green wool", - "icon": "green_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=green]", - "burnable": true - }, - { - "baseColor": 27, - "id": "minecraft:green_stained_glass", - "nameZH": "绿色染色玻璃", - "nameEN": "Green glass", - "icon": "green_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=green]" - }, - { - "baseColor": 27, - "id": "minecraft:dried_kelp_block", - "nameZH": "海带块", - "nameEN": "Kelp block", - "icon": "dried_kelp_block.png", - "version": 13 - }, - { - "baseColor": 28, - "id": "minecraft:red_concrete", - "nameZH": "红色混凝土", - "nameEN": "Red concrete", - "icon": "red_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=red]" - }, - { - "baseColor": 28, - "id": "minecraft:red_wool", - "nameZH": "红色羊毛", - "nameEN": "Red wool", - "icon": "red_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=red]", - "burnable": true - }, - { - "baseColor": 28, - "id": "minecraft:red_stained_glass", - "nameZH": "红色染色玻璃", - "nameEN": "Red glass", - "icon": "red_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=red]" - }, - { - "baseColor": 28, - "id": "minecraft:bricks", - "nameZH": "红砖块", - "nameEN": "Bricks", - "icon": "bricks.png", - "version": 0, - "idOld": "minecraft:brick_block" - }, - { - "baseColor": 28, - "id": "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "红色蘑菇方块", - "nameEN": "Red mushroom block", - "icon": "red_mushroom_block.png", - "version": 0, - "idOld": "minecraft:red_mushroom_block[variant=all_outside]", - "burnable": true - }, - { - "baseColor": 28, - "id": "minecraft:nether_wart_block", - "nameZH": "下界疣块", - "nameEN": "Nether wart block", - "icon": "nether_wart_block.png", - "version": 0 - }, - { - "baseColor": 28, - "id": "minecraft:shroomlight", - "nameZH": "菌光体", - "nameEN": "Shroomlight", - "icon": "shroomlight.png", - "version": 16, - "isGlowing": true - }, - { - "baseColor": 28, - "id": "minecraft:mangrove_planks", - "nameZH": "红树木板", - "nameEN": "Mangrove planks", - "icon": "mangrove_planks.png", - "version": 19, - "burnable": true - }, - { - "baseColor": 29, - "id": "minecraft:black_concrete", - "nameZH": "黑色混凝土", - "nameEN": "Black concrete", - "icon": "black_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=black]" - }, - { - "baseColor": 29, - "id": "minecraft:black_wool", - "nameZH": "黑色羊毛", - "nameEN": "Black wool", - "icon": "black_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=black]", - "burnable": true - }, - { - "baseColor": 29, - "id": "minecraft:black_stained_glass", - "nameZH": "黑色染色玻璃", - "nameEN": "Blakc glass", - "icon": "black_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=black]" - }, - { - "baseColor": 29, - "id": "minecraft:obsidian", - "nameZH": "黑曜石", - "nameEN": "Obsidian", - "icon": "obsidian.png", - "version": 0 - }, - { - "baseColor": 29, - "id": "minecraft:coal_block", - "nameZH": "煤炭块", - "nameEN": "Coal block", - "icon": "coal_block.png", - "version": 0 - }, - { - "baseColor": 29, - "id": "minecraft:polished_basalt[axis=y]", - "nameZH": "磨制玄武岩", - "nameEN": "Polished basalt", - "icon": "polished_basalt.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:polished_blackstone", - "nameZH": "磨制黑石", - "nameEN": "Polished blackstone", - "icon": "polished_blackstone.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:sculk", - "nameZH": "幽匿块", - "nameEN": "Sculk block", - "icon": "sculk.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_catalyst[bloom=false]", - "nameZH": "幽匿催发体", - "nameEN": "Sculk catalyst", - "icon": "sculk_catalyst_top.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_shrieker[shrieking=false,waterlogged=false]", - "nameZH": "幽匿尖啸体", - "nameEN": "Sculk shrieker", - "icon": "sculk_shrieker_side.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_vein[down=true,east=false,north=false,south=false,up=false,waterlogged=false,west=false]", - "nameZH": "幽匿脉络", - "nameEN": "Sculk vein", - "icon": "sculk_vein.png", - "version": 19, - "needGlass": true - }, - { - "baseColor": 30, - "id": "minecraft:gold_block", - "nameZH": "金块", - "nameEN": "Gold block", - "icon": "gold_block.png", - "version": 0 - }, - { - "baseColor": 30, - "id": "minecraft:light_weighted_pressure_plate[power=0]", - "nameZH": "轻质测重压力板", - "nameEN": "Gold pressure plate", - "icon": "light_weighted_pressure_plate.png", - "version": 0, - "needGlass": true - }, - { - "baseColor": 30, - "id": "minecraft:raw_gold_block", - "nameZH": "粗金块", - "nameEN": "Raw gold block", - "icon": "raw_gold_block.png", - "version": 17 - }, - { - "baseColor": 31, - "id": "minecraft:diamond_block", - "nameZH": "钻石块", - "nameEN": "Diamond block", - "icon": "diamond_block.png", - "version": 0 - }, - { - "baseColor": 31, - "id": "minecraft:prismarine_bricks", - "nameZH": "海晶石砖", - "nameEN": "Prismarine bricks", - "icon": "prismarine_bricks.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=prismarine_bricks]" - }, - { - "baseColor": 31, - "id": "minecraft:dark_prismarine", - "nameZH": "暗海晶石", - "nameEN": "Dark prismarine", - "icon": "dark_prismarine.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=dark_prismarine]" - }, - { - "baseColor": 32, - "id": "minecraft:lapis_block", - "nameZH": "青金石块", - "nameEN": "Lapis block", - "icon": "lapis_block.png", - "version": 0 - }, - { - "baseColor": 33, - "id": "minecraft:emerald_block", - "nameZH": "绿宝石块", - "nameEN": "Emerald block", - "icon": "emerald_block.png", - "version": 0 - }, - { - "baseColor": 34, - "id": "minecraft:podzol[snowy=false]", - "nameZH": "灰化土", - "nameEN": "Podzol", - "icon": "podzol.png", - "version": 0, - "idOld": "minecraft:dirt[variant=podzol,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 34, - "id": "minecraft:spruce_planks", - "nameZH": "云杉木板", - "nameEN": "Spruce plank", - "icon": "spruce_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=spruce]", - "burnable": true - }, - { - "baseColor": 34, - "id": "minecraft:campfire[facing=north,lit=true,signal_fire=false,waterlogged=false]", - "nameZH": "营火", - "nameEN": "Campfire", - "icon": "campfire.png", - "version": 14, - "isGlowing": true, - "wallUseable": false - }, - { - "baseColor": 35, - "id": "minecraft:netherrack", - "nameZH": "下界岩", - "nameEN": "Netherrack", - "icon": "netherrack.png", - "version": 0 - }, - { - "baseColor": 35, - "id": "minecraft:nether_bricks", - "nameZH": "下界砖块", - "nameEN": "Nether brick", - "icon": "nether_bricks.png", - "version": 0, - "idOld": "minecraft:nether_brick" - }, - { - "baseColor": 35, - "id": "minecraft:magma_block", - "nameZH": "岩浆块", - "nameEN": "Magma block", - "icon": "magma_block.png", - "version": 0, - "idOld": "minecraft:magma" - }, - { - "baseColor": 36, - "id": "minecraft:white_terracotta", - "nameZH": "白色陶瓦", - "nameEN": "White terracotta", - "icon": "white_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=white]" - }, - { - "baseColor": 36, - "id": "minecraft:calcite", - "nameZH": "方解石", - "nameEN": "Calcite", - "icon": "calcite.png", - "version": 17 - }, - { - "baseColor": 37, - "id": "minecraft:orange_terracotta", - "nameZH": "橙色陶瓦", - "nameEN": "Orange terracotta", - "icon": "orange_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=orange]" - }, - { - "baseColor": 38, - "id": "minecraft:magenta_terracotta", - "nameZH": "品红色陶瓦", - "nameEN": "Magenta terracotta", - "icon": "magenta_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=magenta]" - }, - { - "baseColor": 39, - "id": "minecraft:light_blue_terracotta", - "nameZH": "淡蓝色陶瓦", - "nameEN": "Light blue terracotta", - "icon": "light_blue_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=light_blue]" - }, - { - "baseColor": 40, - "id": "minecraft:yellow_terracotta", - "nameZH": "黄色陶瓦", - "nameEN": "Yellow terracotta", - "icon": "yellow_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=yellow]" - }, - { - "baseColor": 41, - "id": "minecraft:lime_terracotta", - "nameZH": "黄绿色陶瓦", - "nameEN": "Lime terracotta", - "icon": "lime_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=lime]" - }, - { - "baseColor": 42, - "id": "minecraft:pink_terracotta", - "nameZH": "粉红色陶瓦", - "nameEN": "Pink terracotta", - "icon": "pink_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=pink]" - }, - { - "baseColor": 43, - "id": "minecraft:gray_terracotta", - "nameZH": "灰色陶瓦", - "nameEN": "Gray terracotta", - "icon": "gray_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=gray]" - }, - { - "baseColor": 44, - "id": "minecraft:light_gray_terracotta", - "nameZH": "淡灰色陶瓦", - "nameEN": "Light gray terracotta", - "icon": "light_gray_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=silver]" - }, - { - "baseColor": 44, - "id": "minecraft:waxed_exposed_copper", - "nameZH": "斑驳的涂蜡铜块", - "nameEN": "Waxed exposed copper", - "icon": "waxed_exposed_copper.png", - "version": 17 - }, - { - "baseColor": 44, - "id": "minecraft:waxed_exposed_cut_copper", - "nameZH": "斑驳的涂蜡切制铜块", - "nameEN": "Waxed exposed cut copper", - "icon": "waxed_exposed_cut_copper.png", - "version": 17 - }, - { - "baseColor": 44, - "id": "minecraft:mud_bricks", - "nameZH": "泥砖", - "nameEN": "Mud bricks", - "icon": "mud_bricks.png", - "version": 19 - }, - { - "baseColor": 45, - "id": "minecraft:cyan_terracotta", - "nameZH": "青色陶瓦", - "nameEN": "Cyan terracotta", - "icon": "cyan_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=cyan]" - }, - { - "baseColor": 45, - "id": "minecraft:mud", - "nameZH": "泥巴", - "nameEN": "Mud", - "icon": "mud.png", - "version": 19 - }, - { - "baseColor": 46, - "id": "minecraft:purple_terracotta", - "nameZH": "紫色陶瓦", - "nameEN": "Purple terracotta", - "icon": "purple_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=purple]" - }, - { - "baseColor": 47, - "id": "minecraft:blue_terracotta", - "nameZH": "蓝色陶瓦", - "nameEN": "Blue terracotta", - "icon": "blue_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=blue]" - }, - { - "baseColor": 48, - "id": "minecraft:brown_terracotta", - "nameZH": "棕色陶瓦", - "nameEN": "Brown terracotta", - "icon": "brown_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=brown]" - }, - { - "baseColor": 48, - "id": "minecraft:dripstone_block", - "nameZH": "滴水石块", - "nameEN": "DripStone Block", - "icon": "dripstone_block.png", - "version": 17 - }, - { - "baseColor": 49, - "id": "minecraft:green_terracotta", - "nameZH": "绿色陶瓦", - "nameEN": "Green terracotta", - "icon": "green_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=green]" - }, - { - "baseColor": 50, - "id": "minecraft:red_terracotta", - "nameZH": "红色陶瓦", - "nameEN": "Red terracotta", - "icon": "red_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=red]" - }, - { - "baseColor": 51, - "id": "minecraft:black_terracotta", - "nameZH": "黑色陶瓦", - "nameEN": "Black terracotta", - "icon": "black_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=black]" - }, - { - "baseColor": 52, - "id": "minecraft:crimson_nylium", - "nameZH": "绯红菌岩", - "nameEN": "Crimson nylium", - "icon": "crimson_nylium.png", - "version": 16, - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 53, - "id": "minecraft:crimson_planks", - "nameZH": "绯红木板", - "nameEN": "Crimson plank", - "icon": "crimson_planks.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 53, - "id": "minecraft:stripped_crimson_stem[axis=y]", - "nameZH": "去皮绯红菌柄", - "nameEN": "Stripped crimson log", - "icon": "stripped_crimson_stem.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 54, - "id": "minecraft:crimson_hyphae[axis=y]", - "nameZH": "绯红菌核", - "nameEN": "Crimson hyphae", - "icon": "crimson_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 54, - "id": "minecraft:stripped_crimson_hyphae[axis=y]", - "nameZH": "去皮绯红菌核", - "nameEN": "Stripped crimson hyphae", - "icon": "stripped_crimson_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 55, - "id": "minecraft:warped_nylium", - "nameZH": "诡异菌岩", - "nameEN": "Warped nylium", - "icon": "warped_nylium.png", - "version": 16, - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 55, - "id": "minecraft:waxed_oxidized_copper", - "nameZH": "氧化的涂蜡铜块", - "nameEN": "Waxed oxided copper", - "icon": "waxed_oxidized_copper.png", - "version": 17 - }, - { - "baseColor": 55, - "id": "minecraft:waxed_oxidized_cut_copper", - "nameZH": "氧化的涂蜡切制铜块", - "nameEN": "Waxed oxided cut copper", - "icon": "waxed_oxidized_cut_copper.png", - "version": 17 - }, - { - "baseColor": 56, - "id": "minecraft:warped_planks", - "nameZH": "诡异木板", - "nameEN": "Warped plank", - "icon": "warped_planks.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 56, - "id": "minecraft:stripped_warped_stem[axis=y]", - "nameZH": "去皮诡异菌柄", - "nameEN": "Stripped warped log", - "icon": "stripped_warped_stem.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 56, - "id": "minecraft:waxed_weathered_copper", - "nameZH": "锈蚀的涂蜡铜块", - "nameEN": "Waxed weathered copper", - "icon": "waxed_weathered_copper.png", - "version": 17 - }, - { - "baseColor": 56, - "id": "minecraft:waxed_weathered_cut_copper", - "nameZH": "锈蚀的涂蜡切制铜块", - "nameEN": "Waxed weathered cut copper", - "icon": "waxed_weathered_cut_copper.png", - "version": 17 - }, - { - "baseColor": 57, - "id": "minecraft:warped_hyphae[axis=y]", - "nameZH": "诡异菌核", - "nameEN": "Warped hyphae", - "icon": "warped_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 57, - "id": "minecraft:stripped_warped_hyphae[axis=y]", - "nameZH": "去皮诡异菌核", - "nameEN": "Stripped warped hyphae", - "icon": "stripped_warped_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 58, - "id": "minecraft:warped_wart_block", - "nameZH": "诡异疣块", - "nameEN": "Warped wart block", - "icon": "warped_wart_block.png", - "version": 16 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate", - "nameZH": "深板岩", - "nameEN": "Deepslate", - "icon": "deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:chiseled_deepslate", - "nameZH": "雕纹深板岩", - "nameEN": "Chiseled deepslate", - "icon": "chiseled_deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:polished_deepslate", - "nameZH": "磨制深板岩", - "nameEN": "Polished deepslate", - "icon": "polished_deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_bricks", - "nameZH": "深板岩砖", - "nameEN": "Deepslate bricks", - "icon": "deepslate_bricks.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_tiles", - "nameZH": "深板岩瓦", - "nameEN": "Deepslate tiles", - "icon": "deepslate_tiles.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:cobbled_deepslate", - "nameZH": "深板岩圆石", - "nameEN": "Cobbled deepslate", - "icon": "cobbled_deepslate.png", - "version": 17 - }, - { - "baseColor": 60, - "id": "minecraft:raw_iron_block", - "nameZH": "粗铁块", - "nameEN": "Raw iron block", - "icon": "raw_iron_block.png", - "version": 17 - }, - { - "baseColor": 61, - "id": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", - "nameZH": "发光地衣", - "nameEN": "Glow lichen", - "icon": "glow_lichen.png", - "version": 17, - "needGlass": true, - "isGlowing": true, - "burnable": true, - "wallUseable": false - }, - { - "baseColor": 61, - "id": "minecraft:verdant_froglight[axis=y]", - "nameZH": "青翠蛙明灯", - "nameEN": "Verdant Froglight", - "icon": "verdant_froglight_top.png", - "version": 19, - "isGlowing": true - } - ] + "FixedBlocks": [ + { + "baseColor": 0, + "id": "minecraft:glass", + "nameZH": "玻璃", + "nameEN": "Glass", + "icon": "glass.png", + "version": 0 + }, + { + "baseColor": 1, + "id": "minecraft:grass_block[snowy=false]", + "nameZH": "草方块", + "nameEN": "Grass block", + "icon": "grass_block.png", + "version": 0, + "idOld": "minecraft:grass[snowy=false]", + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 1, + "id": "minecraft:slime_block", + "nameZH": "黏液块", + "nameEN": "Slime block", + "icon": "slime_block.png", + "version": 0, + "idOld": "minecraft:slime" + }, + { + "baseColor": 2, + "id": "minecraft:birch_planks", + "nameZH": "白桦木板", + "nameEN": "Birch plank", + "icon": "birch_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=birch]", + "burnable": true + }, + { + "baseColor": 2, + "id": "minecraft:smooth_sandstone", + "nameZH": "平滑砂岩", + "nameEN": "Smooth sandstone", + "icon": "smooth_sandstone.png", + "version": 0, + "idOld": "minecraft:sandstone[type=smooth_sandstone]" + }, + { + "baseColor": 2, + "id": "minecraft:glowstone", + "nameZH": "荧石", + "nameEN": "Glowstone", + "icon": "glowstone.png", + "version": 0, + "isGlowing": true + }, + { + "baseColor": 2, + "id": "minecraft:end_stone", + "nameZH": "末地石", + "nameEN": "End stone", + "icon": "end_stone.png", + "version": 0 + }, + { + "baseColor": 2, + "id": "minecraft:end_stone_bricks", + "nameZH": "末地石砖", + "nameEN": "Endstone bricks", + "icon": "end_stone_bricks.png", + "version": 0, + "idOld": "minecraft:end_bricks" + }, + { + "baseColor": 2, + "id": "minecraft:turtle_egg[eggs=4,hatch=0]", + "nameZH": "海龟蛋", + "nameEN": "Turtle egg", + "icon": "turtle_egg.png", + "version": 13, + "needGlass": true, + "wallUseable": false + }, + { + "baseColor": 2, + "id": "minecraft:ochre_froglight[axis=y]", + "nameZH": "赭黄蛙明灯", + "nameEN": "Ochre Froglight", + "icon": "ochre_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 3, + "id": "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "蘑菇柄", + "nameEN": "Mushroom stem", + "icon": "mushroom_stem.png", + "version": 13, + "burnable": true + }, + { + "baseColor": 3, + "id": "minecraft:cobweb", + "nameZH": "蜘蛛网", + "nameEN": "Cobweb", + "icon": "cobweb.png", + "version": 0, + "idOld": "minecraft:web" + }, + { + "baseColor": 4, + "id": "minecraft:redstone_block", + "nameZH": "红石块", + "nameEN": "Redstone block", + "icon": "redstone_block.png", + "version": 0 + }, + { + "baseColor": 4, + "id": "minecraft:tnt[unstable=false]", + "nameZH": "TNT", + "nameEN": "TNT", + "icon": "tnt.png", + "version": 0, + "idOld": "minecraft:tnt[explode=false]", + "endermanPickable": true, + "burnable": true + }, + { + "baseColor": 5, + "id": "minecraft:ice", + "nameZH": "冰", + "nameEN": "Ice", + "icon": "ice.png", + "version": 0 + }, + { + "baseColor": 5, + "id": "minecraft:packed_ice", + "nameZH": "浮冰", + "nameEN": "Packed ice", + "icon": "packed_ice.png", + "version": 0 + }, + { + "baseColor": 5, + "id": "minecraft:blue_ice", + "nameZH": "蓝冰", + "nameEN": "Blue ice", + "icon": "blue_ice.png", + "version": 13 + }, + { + "baseColor": 6, + "id": "minecraft:iron_block", + "nameZH": "铁块", + "nameEN": "Iron block", + "icon": "iron_block.png", + "version": 0 + }, + { + "baseColor": 6, + "id": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", + "nameZH": "酿造台", + "nameEN": "brewing stand", + "icon": "brewing_stand.png", + "version": 0, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:heavy_weighted_pressure_plate[power=0]", + "nameZH": "重质测重压力板", + "nameEN": "Iron pressure plate", + "icon": "heavy_weighted_pressure_plate.png", + "version": 0, + "needGlass": true, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:iron_trapdoor[facing=north,half=top,open=false,powered=false,waterlogged=false]", + "nameZH": "铁活板门", + "nameEN": "Iron trapdoor", + "icon": "iron_trapdoor.png", + "version": 0, + "idOld": "minecraft:iron_trapdoor[facing=north,half=top,open=false]", + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:lantern[hanging=false]", + "nameZH": "灯笼", + "nameEN": "lantern", + "icon": "lantern.png", + "version": 14, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:grindstone[face=floor,facing=north]", + "nameZH": "砂轮", + "nameEN": "Grindstone", + "icon": "grindstone.png", + "version": 14, + "wallUseable": false + }, + { + "baseColor": 7, + "id": "minecraft:oak_leaves[distance=7,persistent=true]", + "nameZH": "橡树树叶", + "nameEN": "Oak leaves", + "icon": "oak_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:spruce_leaves[distance=7,persistent=true]", + "nameZH": "云杉树叶", + "nameEN": "Spurce leaves", + "icon": "spruce_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:birch_leaves[distance=7,persistent=true]", + "nameZH": "白桦树叶", + "nameEN": "Brich leaves", + "icon": "birch_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:jungle_leaves[distance=7,persistent=true]", + "nameZH": "丛林树叶", + "nameEN": "Jungle leaves", + "icon": "jungle_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:acacia_leaves[distance=7,persistent=true]", + "nameZH": "金合欢树叶", + "nameEN": "Acacia leaves", + "icon": "acacia_leaves.png", + "version": 0, + "idOld": "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:dark_oak_leaves[distance=7,persistent=true]", + "nameZH": "深色橡树树叶", + "nameEN": "Dark oat leaves", + "icon": "dark_oak_leaves.png", + "version": 0, + "idOld": "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" + }, + { + "baseColor": 8, + "id": "minecraft:white_concrete", + "nameZH": "白色混凝土", + "nameEN": "White concrete", + "icon": "white_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:white_wool", + "nameZH": "白色羊毛", + "nameEN": "White wool", + "icon": "white_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:white_stained_glass", + "nameZH": "白色染色玻璃", + "nameEN": "White glass", + "icon": "white_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:snow_block", + "nameZH": "雪块", + "nameEN": "Snow", + "icon": "snow_block.png", + "version": 0, + "idOld": "minecraft:snow" + }, + { + "baseColor": 9, + "id": "minecraft:clay", + "nameZH": "黏土块", + "nameEN": "Clay block", + "icon": "clay.png", + "version": 0, + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:coarse_dirt", + "nameZH": "砂土", + "nameEN": "Coarse dirt", + "icon": "coarse_dirt.png", + "version": 13, + "idOld": "minecraft:dirt[variant=coarse_dirt,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:polished_granite", + "nameZH": "磨制花岗岩", + "nameEN": "Polished granite", + "icon": "polished_granite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_granite]" + }, + { + "baseColor": 10, + "id": "minecraft:jungle_planks", + "nameZH": "丛林木板", + "nameEN": "Jungle plank", + "icon": "jungle_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=jungle]", + "burnable": true + }, + { + "baseColor": 10, + "id": "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "棕色蘑菇方块", + "nameEN": "Brown mushroom block", + "icon": "brown_mushroom_block.png", + "version": 0, + "idOld": "minecraft:brown_mushroom_block[variant=all_outside]" + }, + { + "baseColor": 10, + "id": "minecraft:dirt", + "nameZH": "泥土", + "nameEN": "Dirt", + "icon": "dirt.png", + "version": 0, + "idOld": "minecraft:dirt[variant=dirt,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:packed_mud", + "nameZH": "泥坯", + "nameEN": "Packed mud", + "icon": "packed_mud.png", + "version": 19 + }, + { + "baseColor": 11, + "id": "minecraft:cobblestone", + "nameZH": "圆石", + "nameEN": "Cobblestone", + "icon": "cobblestone.png", + "version": 0 + }, + { + "baseColor": 11, + "id": "minecraft:stone", + "nameZH": "石头", + "nameEN": "Stone", + "icon": "stone.png", + "version": 0, + "idOld": "minecraft:stone[variant=stone]" + }, + { + "baseColor": 11, + "id": "minecraft:smooth_stone", + "nameZH": "平滑石头", + "nameEN": "Smooth stone", + "icon": "smooth_stone.png", + "version": 13 + }, + { + "baseColor": 11, + "id": "minecraft:stone_bricks", + "nameZH": "石砖", + "nameEN": "Stone brick", + "icon": "stone_bricks.png", + "version": 0, + "idOld": "minecraft:stonebrick[variant=stonebrick]" + }, + { + "baseColor": 12, + "id": "minecraft:water[level=0]", + "nameZH": "水", + "nameEN": "Water", + "icon": "water.png", + "version": 0, + "wallUseable": false + }, + { + "baseColor": 13, + "id": "minecraft:oak_planks", + "nameZH": "橡木木板", + "nameEN": "Oak plank", + "icon": "oak_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=oak]", + "burnable": true + }, + { + "baseColor": 14, + "id": "minecraft:polished_diorite", + "nameZH": "磨制闪长岩", + "nameEN": "Polished diorite", + "icon": "polished_diorite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_diorite]" + }, + { + "baseColor": 14, + "id": "minecraft:quartz_block", + "nameZH": "石英块", + "nameEN": "Quartz block", + "icon": "quartz_block.png", + "version": 0, + "idOld": "minecraft:quartz_block[variant=default]" + }, + { + "baseColor": 14, + "id": "minecraft:sea_lantern", + "nameZH": "海晶灯", + "nameEN": "Sea lantern", + "icon": "sea_lantern.png", + "version": 0 + }, + { + "baseColor": 14, + "id": "minecraft:target[power=0]", + "nameZH": "标靶", + "nameEN": "Target", + "icon": "target.png", + "version": 16 + }, + { + "baseColor": 15, + "id": "minecraft:orange_concrete", + "nameZH": "橙色混凝土", + "nameEN": "Orange concrete", + "icon": "orange_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:orange_wool", + "nameZH": "橙色羊毛", + "nameEN": "Orange wool", + "icon": "orange_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:orange_stained_glass", + "nameZH": "橙色染色玻璃", + "nameEN": "Orange glass", + "icon": "orange_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:acacia_planks", + "nameZH": "金合欢木板", + "nameEN": "Acacia plank", + "icon": "acacia_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=acacia]", + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:pumpkin", + "nameZH": "南瓜", + "nameEN": "Pumpkin", + "icon": "pumpkin.png", + "version": 0, + "idOld": "minecraft:pumpkin[variant=north]", + "endermanPickable": true + }, + { + "baseColor": 15, + "id": "minecraft:terracotta", + "nameZH": "陶瓦", + "nameEN": "Terracotta", + "icon": "terracotta.png", + "version": 0, + "idOld": "minecraft:hardened_clay" + }, + { + "baseColor": 15, + "id": "minecraft:smooth_red_sandstone", + "nameZH": "平滑红砂岩", + "nameEN": "Smooth red sandstone", + "icon": "smooth_red_sandstone.png", + "version": 0, + "idOld": "minecraft:red_sandstone[type=smooth_red_sandstone]" + }, + { + "baseColor": 15, + "id": "minecraft:honey_block", + "nameZH": "蜂蜜块", + "nameEN": "Honey block", + "icon": "honey_block.png", + "version": 15 + }, + { + "baseColor": 15, + "id": "minecraft:honeycomb_block", + "nameZH": "蜜脾块", + "nameEN": "Honey comb block", + "icon": "honeycomb_block.png", + "version": 15 + }, + { + "baseColor": 15, + "id": "minecraft:raw_copper_block", + "nameZH": "粗铜块", + "nameEN": "Raw copper block", + "icon": "raw_copper_block.png", + "version": 17 + }, + { + "baseColor": 15, + "id": "minecraft:waxed_copper_block", + "nameZH": "涂蜡铜块", + "nameEN": "Waxed copper", + "icon": "waxed_copper_block.png", + "version": 17 + }, + { + "baseColor": 15, + "id": "minecraft:waxed_cut_copper", + "nameZH": "涂蜡切制铜块", + "nameEN": "Waxed cut copper", + "icon": "waxed_cut_copper.png", + "version": 17 + }, + { + "baseColor": 16, + "id": "minecraft:magenta_concrete", + "nameZH": "品红色混凝土", + "nameEN": "Magenta concrete", + "icon": "magenta_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:magenta_wool", + "nameZH": "品红色羊毛", + "nameEN": "Magenta wool", + "icon": "magenta_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:magenta_stained_glass", + "nameZH": "品红色染色玻璃", + "nameEN": "Magenta glass", + "icon": "magenta_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:purpur_block", + "nameZH": "紫珀块", + "nameEN": "Purpur block", + "icon": "purpur_block.png", + "version": 0 + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_concrete", + "nameZH": "淡蓝色混凝土", + "nameEN": "Light blue concrete", + "icon": "light_blue_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=light_blue]" + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_wool", + "nameZH": "淡蓝色羊毛", + "nameEN": "light blue wool", + "icon": "light_blue_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=light_blue]" + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_stained_glass", + "nameZH": "淡蓝色染色玻璃", + "nameEN": "Light blue glass", + "icon": "light_blue_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=light_blue]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_concrete", + "nameZH": "黄色混凝土", + "nameEN": "Yellow concrete", + "icon": "yellow_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_wool", + "nameZH": "黄色羊毛", + "nameEN": "Yellow wool", + "icon": "yellow_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_stained_glass", + "nameZH": "黄色染色玻璃", + "nameEN": "yellow glass", + "icon": "yellow_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:hay_block[axis=y]", + "nameZH": "干草捆", + "nameEN": "Hay block", + "icon": "hay_block.png", + "version": 0 + }, + { + "baseColor": 19, + "id": "minecraft:lime_concrete", + "nameZH": "黄绿色混凝土", + "nameEN": "Lime concrete", + "icon": "lime_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=lime]" + }, + { + "baseColor": 19, + "id": "minecraft:lime_wool", + "nameZH": "黄绿色羊毛", + "nameEN": "Lime wool", + "icon": "lime_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=lime]" + }, + { + "baseColor": 19, + "id": "minecraft:lime_stained_glass", + "nameZH": "黄绿色染色玻璃", + "nameEN": "Lime glass", + "icon": "lime_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=lime]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_concrete", + "nameZH": "粉红色混凝土", + "nameEN": "Pink concrete", + "icon": "pink_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_wool", + "nameZH": "粉红色羊毛", + "nameEN": "Pink wool", + "icon": "pink_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_stained_glass", + "nameZH": "粉红色染色玻璃", + "nameEN": "Pink glass", + "icon": "pink_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pearlescent_froglight[axis=y]", + "nameZH": "珠光蛙明灯", + "nameEN": "Verdant Froglight", + "icon": "pearlescent_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 21, + "id": "minecraft:gray_concrete", + "nameZH": "灰色混凝土", + "nameEN": "Gray concrete", + "icon": "gray_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=gray]" + }, + { + "baseColor": 21, + "id": "minecraft:gray_wool", + "nameZH": "灰色羊毛", + "nameEN": "Gray wool", + "icon": "gray_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=gray]", + "burnable": true + }, + { + "baseColor": 21, + "id": "minecraft:gray_stained_glass", + "nameZH": "灰色染色玻璃", + "nameEN": "Gray glass", + "icon": "gray_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=gray]" + }, + { + "baseColor": 21, + "id": "minecraft:tinted_glass", + "nameZH": "遮光玻璃", + "nameEN": "Tinted glass", + "icon": "tinted_glass.png", + "version": 17 + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_concrete", + "nameZH": "淡灰色混凝土", + "nameEN": "Light gray concrete", + "icon": "light_gray_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=silver]" + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_wool", + "nameZH": "淡灰色羊毛", + "nameEN": "Light gray wool", + "icon": "light_gray_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=silver]", + "burnable": true + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_stained_glass", + "nameZH": "淡灰色染色玻璃", + "nameEN": "Light gray glass", + "icon": "light_gray_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=silver]" + }, + { + "baseColor": 23, + "id": "minecraft:cyan_concrete", + "nameZH": "青色混凝土", + "nameEN": "Cyan concrete", + "icon": "cyan_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=cyan]" + }, + { + "baseColor": 23, + "id": "minecraft:cyan_wool", + "nameZH": "青色羊毛", + "nameEN": "Cyan wool", + "icon": "cyan_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=cyan]", + "burnable": true + }, + { + "baseColor": 23, + "id": "minecraft:cyan_stained_glass", + "nameZH": "青色染色玻璃", + "nameEN": "Cyan glass", + "icon": "cyan_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=cyan]" + }, + { + "baseColor": 23, + "id": "minecraft:prismarine", + "nameZH": "海晶石", + "nameEN": "Prismarine", + "icon": "prismarine.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=prismarine]" + }, + { + "baseColor": 23, + "id": "minecraft:sculk_sensor[power=0,sculk_sensor_phase=inactive,waterlogged=false]", + "nameZH": "幽匿感测体", + "nameEN": "Sculk sensor", + "icon": "sculk_sensor_side.png", + "version": 19 + }, + { + "baseColor": 24, + "id": "minecraft:purple_concrete", + "nameZH": "紫色混凝土", + "nameEN": "Purple concrete", + "icon": "purple_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=purple]" + }, + { + "baseColor": 24, + "id": "minecraft:purple_wool", + "nameZH": "紫色羊毛", + "nameEN": "Purple wool", + "icon": "purple_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=purple]", + "burnable": true + }, + { + "baseColor": 24, + "id": "minecraft:purple_stained_glass", + "nameZH": "紫色染色玻璃", + "nameEN": "Purple glass", + "icon": "purple_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=purple]" + }, + { + "baseColor": 24, + "id": "minecraft:amethyst_block", + "nameZH": "紫水晶块", + "nameEN": "Amethyst block", + "icon": "amethyst_block.png", + "version": 17 + }, + { + "baseColor": 25, + "id": "minecraft:blue_concrete", + "nameZH": "蓝色混凝土", + "nameEN": "Blue concrete", + "icon": "blue_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=blue]" + }, + { + "baseColor": 25, + "id": "minecraft:blue_wool", + "nameZH": "蓝色羊毛", + "nameEN": "Blue wool", + "icon": "blue_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=blue]", + "burnable": true + }, + { + "baseColor": 25, + "id": "minecraft:blue_stained_glass", + "nameZH": "蓝色染色玻璃", + "nameEN": "Blue glass", + "icon": "blue_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=blue]" + }, + { + "baseColor": 26, + "id": "minecraft:brown_concrete", + "nameZH": "棕色混凝土", + "nameEN": "Brown concrete", + "icon": "brown_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=brown]" + }, + { + "baseColor": 26, + "id": "minecraft:brown_wool", + "nameZH": "棕色羊毛", + "nameEN": "Brown wool", + "icon": "brown_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=brown]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:brown_stained_glass", + "nameZH": "棕色染色玻璃", + "nameEN": "Brown glass", + "icon": "brown_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=brown]" + }, + { + "baseColor": 26, + "id": "minecraft:dark_oak_planks", + "nameZH": "深色橡木木板", + "nameEN": "Dark oak plank", + "icon": "dark_oak_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=dark_oak]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:soul_sand", + "nameZH": "灵魂沙", + "nameEN": "Soul sand", + "icon": "soul_sand.png", + "version": 0 + }, + { + "baseColor": 26, + "id": "minecraft:soul_soil", + "nameZH": "灵魂土", + "nameEN": "Soul soil", + "icon": "soul_soil.png", + "version": 16 + }, + { + "baseColor": 27, + "id": "minecraft:green_concrete", + "nameZH": "绿色混凝土", + "nameEN": "Green concrete", + "icon": "green_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=green]" + }, + { + "baseColor": 27, + "id": "minecraft:green_wool", + "nameZH": "绿色羊毛", + "nameEN": "Green wool", + "icon": "green_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=green]", + "burnable": true + }, + { + "baseColor": 27, + "id": "minecraft:green_stained_glass", + "nameZH": "绿色染色玻璃", + "nameEN": "Green glass", + "icon": "green_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=green]" + }, + { + "baseColor": 27, + "id": "minecraft:dried_kelp_block", + "nameZH": "海带块", + "nameEN": "Kelp block", + "icon": "dried_kelp_block.png", + "version": 13 + }, + { + "baseColor": 28, + "id": "minecraft:red_concrete", + "nameZH": "红色混凝土", + "nameEN": "Red concrete", + "icon": "red_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=red]" + }, + { + "baseColor": 28, + "id": "minecraft:red_wool", + "nameZH": "红色羊毛", + "nameEN": "Red wool", + "icon": "red_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=red]", + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:red_stained_glass", + "nameZH": "红色染色玻璃", + "nameEN": "Red glass", + "icon": "red_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=red]" + }, + { + "baseColor": 28, + "id": "minecraft:bricks", + "nameZH": "红砖块", + "nameEN": "Bricks", + "icon": "bricks.png", + "version": 0, + "idOld": "minecraft:brick_block" + }, + { + "baseColor": 28, + "id": "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "红色蘑菇方块", + "nameEN": "Red mushroom block", + "icon": "red_mushroom_block.png", + "version": 0, + "idOld": "minecraft:red_mushroom_block[variant=all_outside]", + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:nether_wart_block", + "nameZH": "下界疣块", + "nameEN": "Nether wart block", + "icon": "nether_wart_block.png", + "version": 0 + }, + { + "baseColor": 28, + "id": "minecraft:shroomlight", + "nameZH": "菌光体", + "nameEN": "Shroomlight", + "icon": "shroomlight.png", + "version": 16, + "isGlowing": true + }, + { + "baseColor": 28, + "id": "minecraft:mangrove_planks", + "nameZH": "红树木板", + "nameEN": "Mangrove planks", + "icon": "mangrove_planks.png", + "version": 19, + "burnable": true + }, + { + "baseColor": 29, + "id": "minecraft:black_concrete", + "nameZH": "黑色混凝土", + "nameEN": "Black concrete", + "icon": "black_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=black]" + }, + { + "baseColor": 29, + "id": "minecraft:black_wool", + "nameZH": "黑色羊毛", + "nameEN": "Black wool", + "icon": "black_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=black]", + "burnable": true + }, + { + "baseColor": 29, + "id": "minecraft:black_stained_glass", + "nameZH": "黑色染色玻璃", + "nameEN": "Blakc glass", + "icon": "black_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=black]" + }, + { + "baseColor": 29, + "id": "minecraft:obsidian", + "nameZH": "黑曜石", + "nameEN": "Obsidian", + "icon": "obsidian.png", + "version": 0 + }, + { + "baseColor": 29, + "id": "minecraft:coal_block", + "nameZH": "煤炭块", + "nameEN": "Coal block", + "icon": "coal_block.png", + "version": 0 + }, + { + "baseColor": 29, + "id": "minecraft:polished_basalt[axis=y]", + "nameZH": "磨制玄武岩", + "nameEN": "Polished basalt", + "icon": "polished_basalt.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:polished_blackstone", + "nameZH": "磨制黑石", + "nameEN": "Polished blackstone", + "icon": "polished_blackstone.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:sculk", + "nameZH": "幽匿块", + "nameEN": "Sculk block", + "icon": "sculk.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_catalyst[bloom=false]", + "nameZH": "幽匿催发体", + "nameEN": "Sculk catalyst", + "icon": "sculk_catalyst_top.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_shrieker[shrieking=false,waterlogged=false]", + "nameZH": "幽匿尖啸体", + "nameEN": "Sculk shrieker", + "icon": "sculk_shrieker_side.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_vein[down=true,east=false,north=false,south=false,up=false,waterlogged=false,west=false]", + "nameZH": "幽匿脉络", + "nameEN": "Sculk vein", + "icon": "sculk_vein.png", + "version": 19, + "needGlass": true + }, + { + "baseColor": 30, + "id": "minecraft:gold_block", + "nameZH": "金块", + "nameEN": "Gold block", + "icon": "gold_block.png", + "version": 0 + }, + { + "baseColor": 30, + "id": "minecraft:light_weighted_pressure_plate[power=0]", + "nameZH": "轻质测重压力板", + "nameEN": "Gold pressure plate", + "icon": "light_weighted_pressure_plate.png", + "version": 0, + "needGlass": true + }, + { + "baseColor": 30, + "id": "minecraft:raw_gold_block", + "nameZH": "粗金块", + "nameEN": "Raw gold block", + "icon": "raw_gold_block.png", + "version": 17 + }, + { + "baseColor": 31, + "id": "minecraft:diamond_block", + "nameZH": "钻石块", + "nameEN": "Diamond block", + "icon": "diamond_block.png", + "version": 0 + }, + { + "baseColor": 31, + "id": "minecraft:prismarine_bricks", + "nameZH": "海晶石砖", + "nameEN": "Prismarine bricks", + "icon": "prismarine_bricks.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=prismarine_bricks]" + }, + { + "baseColor": 31, + "id": "minecraft:dark_prismarine", + "nameZH": "暗海晶石", + "nameEN": "Dark prismarine", + "icon": "dark_prismarine.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=dark_prismarine]" + }, + { + "baseColor": 32, + "id": "minecraft:lapis_block", + "nameZH": "青金石块", + "nameEN": "Lapis block", + "icon": "lapis_block.png", + "version": 0 + }, + { + "baseColor": 33, + "id": "minecraft:emerald_block", + "nameZH": "绿宝石块", + "nameEN": "Emerald block", + "icon": "emerald_block.png", + "version": 0 + }, + { + "baseColor": 34, + "id": "minecraft:podzol[snowy=false]", + "nameZH": "灰化土", + "nameEN": "Podzol", + "icon": "podzol.png", + "version": 0, + "idOld": "minecraft:dirt[variant=podzol,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 34, + "id": "minecraft:spruce_planks", + "nameZH": "云杉木板", + "nameEN": "Spruce plank", + "icon": "spruce_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=spruce]", + "burnable": true + }, + { + "baseColor": 34, + "id": "minecraft:campfire[facing=north,lit=true,signal_fire=false,waterlogged=false]", + "nameZH": "营火", + "nameEN": "Campfire", + "icon": "campfire.png", + "version": 14, + "isGlowing": true, + "wallUseable": false + }, + { + "baseColor": 35, + "id": "minecraft:netherrack", + "nameZH": "下界岩", + "nameEN": "Netherrack", + "icon": "netherrack.png", + "version": 0 + }, + { + "baseColor": 35, + "id": "minecraft:nether_bricks", + "nameZH": "下界砖块", + "nameEN": "Nether brick", + "icon": "nether_bricks.png", + "version": 0, + "idOld": "minecraft:nether_brick" + }, + { + "baseColor": 35, + "id": "minecraft:magma_block", + "nameZH": "岩浆块", + "nameEN": "Magma block", + "icon": "magma_block.png", + "version": 0, + "idOld": "minecraft:magma" + }, + { + "baseColor": 36, + "id": "minecraft:white_terracotta", + "nameZH": "白色陶瓦", + "nameEN": "White terracotta", + "icon": "white_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=white]" + }, + { + "baseColor": 36, + "id": "minecraft:calcite", + "nameZH": "方解石", + "nameEN": "Calcite", + "icon": "calcite.png", + "version": 17 + }, + { + "baseColor": 37, + "id": "minecraft:orange_terracotta", + "nameZH": "橙色陶瓦", + "nameEN": "Orange terracotta", + "icon": "orange_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=orange]" + }, + { + "baseColor": 38, + "id": "minecraft:magenta_terracotta", + "nameZH": "品红色陶瓦", + "nameEN": "Magenta terracotta", + "icon": "magenta_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=magenta]" + }, + { + "baseColor": 39, + "id": "minecraft:light_blue_terracotta", + "nameZH": "淡蓝色陶瓦", + "nameEN": "Light blue terracotta", + "icon": "light_blue_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=light_blue]" + }, + { + "baseColor": 40, + "id": "minecraft:yellow_terracotta", + "nameZH": "黄色陶瓦", + "nameEN": "Yellow terracotta", + "icon": "yellow_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=yellow]" + }, + { + "baseColor": 41, + "id": "minecraft:lime_terracotta", + "nameZH": "黄绿色陶瓦", + "nameEN": "Lime terracotta", + "icon": "lime_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=lime]" + }, + { + "baseColor": 42, + "id": "minecraft:pink_terracotta", + "nameZH": "粉红色陶瓦", + "nameEN": "Pink terracotta", + "icon": "pink_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=pink]" + }, + { + "baseColor": 43, + "id": "minecraft:gray_terracotta", + "nameZH": "灰色陶瓦", + "nameEN": "Gray terracotta", + "icon": "gray_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=gray]" + }, + { + "baseColor": 44, + "id": "minecraft:light_gray_terracotta", + "nameZH": "淡灰色陶瓦", + "nameEN": "Light gray terracotta", + "icon": "light_gray_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=silver]" + }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_copper", + "nameZH": "斑驳的涂蜡铜块", + "nameEN": "Waxed exposed copper", + "icon": "waxed_exposed_copper.png", + "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_cut_copper", + "nameZH": "斑驳的涂蜡切制铜块", + "nameEN": "Waxed exposed cut copper", + "icon": "waxed_exposed_cut_copper.png", + "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:mud_bricks", + "nameZH": "泥砖", + "nameEN": "Mud bricks", + "icon": "mud_bricks.png", + "version": 19 + }, + { + "baseColor": 45, + "id": "minecraft:cyan_terracotta", + "nameZH": "青色陶瓦", + "nameEN": "Cyan terracotta", + "icon": "cyan_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=cyan]" + }, + { + "baseColor": 45, + "id": "minecraft:mud", + "nameZH": "泥巴", + "nameEN": "Mud", + "icon": "mud.png", + "version": 19 + }, + { + "baseColor": 46, + "id": "minecraft:purple_terracotta", + "nameZH": "紫色陶瓦", + "nameEN": "Purple terracotta", + "icon": "purple_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=purple]" + }, + { + "baseColor": 47, + "id": "minecraft:blue_terracotta", + "nameZH": "蓝色陶瓦", + "nameEN": "Blue terracotta", + "icon": "blue_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=blue]" + }, + { + "baseColor": 48, + "id": "minecraft:brown_terracotta", + "nameZH": "棕色陶瓦", + "nameEN": "Brown terracotta", + "icon": "brown_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=brown]" + }, + { + "baseColor": 48, + "id": "minecraft:dripstone_block", + "nameZH": "滴水石块", + "nameEN": "DripStone Block", + "icon": "dripstone_block.png", + "version": 17 + }, + { + "baseColor": 49, + "id": "minecraft:green_terracotta", + "nameZH": "绿色陶瓦", + "nameEN": "Green terracotta", + "icon": "green_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=green]" + }, + { + "baseColor": 50, + "id": "minecraft:red_terracotta", + "nameZH": "红色陶瓦", + "nameEN": "Red terracotta", + "icon": "red_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=red]" + }, + { + "baseColor": 51, + "id": "minecraft:black_terracotta", + "nameZH": "黑色陶瓦", + "nameEN": "Black terracotta", + "icon": "black_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=black]" + }, + { + "baseColor": 52, + "id": "minecraft:crimson_nylium", + "nameZH": "绯红菌岩", + "nameEN": "Crimson nylium", + "icon": "crimson_nylium.png", + "version": 16, + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 53, + "id": "minecraft:crimson_planks", + "nameZH": "绯红木板", + "nameEN": "Crimson plank", + "icon": "crimson_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 53, + "id": "minecraft:stripped_crimson_stem[axis=y]", + "nameZH": "去皮绯红菌柄", + "nameEN": "Stripped crimson log", + "icon": "stripped_crimson_stem.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 54, + "id": "minecraft:crimson_hyphae[axis=y]", + "nameZH": "绯红菌核", + "nameEN": "Crimson hyphae", + "icon": "crimson_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 54, + "id": "minecraft:stripped_crimson_hyphae[axis=y]", + "nameZH": "去皮绯红菌核", + "nameEN": "Stripped crimson hyphae", + "icon": "stripped_crimson_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 55, + "id": "minecraft:warped_nylium", + "nameZH": "诡异菌岩", + "nameEN": "Warped nylium", + "icon": "warped_nylium.png", + "version": 16, + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_copper", + "nameZH": "氧化的涂蜡铜块", + "nameEN": "Waxed oxided copper", + "icon": "waxed_oxidized_copper.png", + "version": 17 + }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_cut_copper", + "nameZH": "氧化的涂蜡切制铜块", + "nameEN": "Waxed oxided cut copper", + "icon": "waxed_oxidized_cut_copper.png", + "version": 17 + }, + { + "baseColor": 56, + "id": "minecraft:warped_planks", + "nameZH": "诡异木板", + "nameEN": "Warped plank", + "icon": "warped_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:stripped_warped_stem[axis=y]", + "nameZH": "去皮诡异菌柄", + "nameEN": "Stripped warped log", + "icon": "stripped_warped_stem.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_copper", + "nameZH": "锈蚀的涂蜡铜块", + "nameEN": "Waxed weathered copper", + "icon": "waxed_weathered_copper.png", + "version": 17 + }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_cut_copper", + "nameZH": "锈蚀的涂蜡切制铜块", + "nameEN": "Waxed weathered cut copper", + "icon": "waxed_weathered_cut_copper.png", + "version": 17 + }, + { + "baseColor": 57, + "id": "minecraft:warped_hyphae[axis=y]", + "nameZH": "诡异菌核", + "nameEN": "Warped hyphae", + "icon": "warped_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 57, + "id": "minecraft:stripped_warped_hyphae[axis=y]", + "nameZH": "去皮诡异菌核", + "nameEN": "Stripped warped hyphae", + "icon": "stripped_warped_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 58, + "id": "minecraft:warped_wart_block", + "nameZH": "诡异疣块", + "nameEN": "Warped wart block", + "icon": "warped_wart_block.png", + "version": 16 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate", + "nameZH": "深板岩", + "nameEN": "Deepslate", + "icon": "deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:chiseled_deepslate", + "nameZH": "雕纹深板岩", + "nameEN": "Chiseled deepslate", + "icon": "chiseled_deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:polished_deepslate", + "nameZH": "磨制深板岩", + "nameEN": "Polished deepslate", + "icon": "polished_deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_bricks", + "nameZH": "深板岩砖", + "nameEN": "Deepslate bricks", + "icon": "deepslate_bricks.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_tiles", + "nameZH": "深板岩瓦", + "nameEN": "Deepslate tiles", + "icon": "deepslate_tiles.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:cobbled_deepslate", + "nameZH": "深板岩圆石", + "nameEN": "Cobbled deepslate", + "icon": "cobbled_deepslate.png", + "version": 17 + }, + { + "baseColor": 60, + "id": "minecraft:raw_iron_block", + "nameZH": "粗铁块", + "nameEN": "Raw iron block", + "icon": "raw_iron_block.png", + "version": 17 + }, + { + "baseColor": 61, + "id": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", + "nameZH": "发光地衣", + "nameEN": "Glow lichen", + "icon": "glow_lichen.png", + "version": 17, + "needGlass": true, + "isGlowing": true, + "burnable": true, + "wallUseable": false + }, + { + "baseColor": 61, + "id": "minecraft:verdant_froglight[axis=y]", + "nameZH": "青翠蛙明灯", + "nameEN": "Verdant Froglight", + "icon": "verdant_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 43, + "id": "minecraft:cherry_wood", + "nameZH": "樱花木头", + "nameEN": "Cherry wood", + "icon": "cherry_log.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 36, + "id": "minecraft:cherry_planks", + "nameZH": "樱花木板", + "nameEN": "Cherry planks", + "icon": "cherry_planks.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 42, + "id": "minecraft:stripped_cherry_wood[axis=y]", + "nameZH": "去皮樱花木头", + "nameEN": "Stripped cherry wood", + "icon": "stripped_cherry_log.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_planks", + "nameZH": "竹板", + "nameEN": "Bamboo planks", + "icon": "bamboo_planks.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_block[axis=x]", + "nameZH": "竹块(侧面)", + "nameEN": "Bamboo block(axis=x)", + "icon": "bamboo_block.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 20, + "id": "minecraft:cherry_leaves[persistent=true]", + "nameZH": "樱花树叶", + "nameEN": "Cherry leaves", + "icon": "cherry_leaves.png", + "version": 20, + "burnable": true + } + ] } \ No newline at end of file diff --git a/Blocks/FixedBlocks/bamboo_block.png b/Blocks/FixedBlocks/bamboo_block.png new file mode 100644 index 0000000000000000000000000000000000000000..330987e8718df52335b111de1ca876ed90d8d814 GIT binary patch literal 299 zcmV+`0o4A9P)Vx3z3LK(1`=+6iSVYILwoIGMoA1e^I^c+uhlj*)109 zPCDO5X?g6Y$-I@yO*hB8%OK6lcK$zIhdK5<;sO9DKp`7YfIq}&V4eU3M7~%ZJ`+%| z-S^V%IZlt)G{1;B@h5;5fDw{-m2wlq08ouCi4*G>h6Dnz0sk5^?+n94bsdZxfD&~; zmcTVSfSbk!XBZyP6rJb|h;?fjz)kTr`4)6*A)#(<4&ZSxP!DKQohOv|b;^1N|Lk2Q xRsg8UZ{H>Afbc*Yd_vP2D<*n_GV%sD@eLcSN9U48xSs$3002ovPDHLkV1im|dHVnW literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/bamboo_planks.png b/Blocks/FixedBlocks/bamboo_planks.png new file mode 100644 index 0000000000000000000000000000000000000000..2085be49cf9a3122fb2505114e6e4a29a11a3372 GIT binary patch literal 274 zcmV+t0qy>YP)5cVu973y$}w1qFK!z9a(G-< zB{1B#6UaZW!;Ev^br^?z3B(7)yWf@X*j4Tt1)jgT63U1&-%~W Y54Z)s5ec(EeEP)bp>J z!ee@dCl^TOg!jv>fw|BClc{K%mj)6lQByFg;-spqYoSLNE%f{iVcRa7LA!s`?qpw-P$J+iOisb9Y5)x!^mV`j95YBJeqT(%GKC8EMA} i_5QF(XMdmDQlcNS>4Pz;xY4Zu0000`-87B&_Kg5a+>%ahq$79rdvn@lo0*|@J)^I>{yH!?Zz z)Ae;c>x-ikeQ{Kv;?U1WIG8b{p1Zy52LM9_rV8WpG*t#r(oVn)Bn5!w1l6C*O_phR zPM**Jg-@p8(Cr&Q_pn4GX%kyafMV`igwE%k(!chlMOdN{HeR{|Y Date: Sat, 1 Jul 2023 14:09:07 +0800 Subject: [PATCH 0458/1123] add decorated pot --- Blocks/FixedBlocks.json | 8 ++++++++ Blocks/FixedBlocks/burn_pottery_pattern.png | Bin 0 -> 294 bytes 2 files changed, 8 insertions(+) create mode 100644 Blocks/FixedBlocks/burn_pottery_pattern.png diff --git a/Blocks/FixedBlocks.json b/Blocks/FixedBlocks.json index 34826f54..368ab8d6 100644 --- a/Blocks/FixedBlocks.json +++ b/Blocks/FixedBlocks.json @@ -1721,6 +1721,14 @@ "icon": "cherry_leaves.png", "version": 20, "burnable": true + }, + { + "baseColor": 50, + "id": "minecraft:decorated_pot", + "nameZH": "陶罐", + "nameEN": "Decorated pot", + "icon": "burn_pottery_pattern.png", + "version": 20 } ] } \ No newline at end of file diff --git a/Blocks/FixedBlocks/burn_pottery_pattern.png b/Blocks/FixedBlocks/burn_pottery_pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..824f7fd1a962b32e559b3e93d43d83d13c7abd3c GIT binary patch literal 294 zcmV+>0oneEP)fB{V9aF8597Qx==>UZ{KI!lO7Ym z5Vai-T&k}CQpedSgbA<|0H^sxHLASlpR0cE0R&1RV**eEfG`1=$D1gC+yONKr~yDt z2tgeHn=oRI5Z5dSJV}5I)6658fPFDk4L~f#PzAsOC5^G@K_&nmo6 Date: Sat, 1 Jul 2023 14:16:06 +0800 Subject: [PATCH 0459/1123] add cherry slab --- Blocks/CustomBlocks.json | 675 ++++++++++++++-------------- Blocks/CustomBlocks/cherry_slab.png | Bin 0 -> 231 bytes 2 files changed, 342 insertions(+), 333 deletions(-) create mode 100644 Blocks/CustomBlocks/cherry_slab.png diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 0ed4377f..8890f893 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -1,335 +1,344 @@ { - "CustomBlocks": [ - // 这个文件列出了所有用户自定义的方块的信息", - // 你可以按照这样的格式自定义添加新的方块,包括 mod 方块", - // 但必须遵守 json 格式", - // 如果 json 格式出错,整个文件都会无法解析,SlopeCraft 会报错。 - { - // baseColor 是这种方块对应的基色,是必填项(非常非常重要!!!!!!!)", - "baseColor": 15, - // id 是这种方块的 id,也是必填项,最好附带完整的方块状态,必须加 minecraft:前缀", - "id": "minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]", - // nameZH 是方块中文名称,必填", - "nameZH": "涂蜡切制铜台阶", - // nameEN 是方块英文名称,必填", - "nameEN": "Waxed cut copper slab", - // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", - "icon": "waxed_cut_copper.png", - // version 是方块最早出现的版本。0 代表早于 1.12,12 代表 1.12,13 代表 1.13,如此类推。255 代表尚未出现的版本", - "version": 17 - // idOld 是该方块在 1.12 的方块 id(如果有的话),必须加 minecraft:前缀,选填,默认为空字符串", - // needGlass 代表这个方块的下方需要依附其他方块,默认为否", - // isGlowing 代表这个方块是发光的,默认为否", - // endermanPickable 代表这个方块可以被末影人偷走,默认为否", - // burnable 代表这个方块会被火焰、岩浆或闪电点燃并燃烧,默认为否 - }, - // This json file includes information of all custom blocks. - // You can add your custom block in such format, including mod-blocks. - // But always remember to follow json format - // The whole file will failed to be parsed once an error occurred in json format, then SlopeCraft will complain. - { - // baseColor is the base color of this block on map, a compulsory item(EXTREMELY IMPORTANT!!!!) - "baseColor": 11, - // id is the block id with full blockstatus with minecraft: prefix. Compulsory item. - "id": "minecraft:stone_slab[type=top,waterlogged=false]", - // nameZH is the Chinese name. Compulsory item. - "nameZH": "石头台阶", - // nameEN is the English name. Compulsory item. - "nameEN": "Stone slab", - // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. - "icon": "stone.png", - // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. - "version": 0, - // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string - "idOld": "minecraft:stone_slab[half=top,variant=stone]" - // needGlass means if this block must be setted on a solid block, default value is false - // isGlowing means if the block glows, default value is false. - // endermanPickable means if the block can be picked by enderman, default value is false - // burnable means if the block can be lit by fire, lava or lightning blot, default value is false - }, - { - "baseColor": 2, - "id": "minecraft:sandstone_slab[type=top,waterlogged=false]", - "nameZH": "砂岩台阶", - "nameEN": "Sandstone slab", - "icon": "smooth_sandstone.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=sandstone]" - }, - { - "baseColor": 11, - "id": "minecraft:cobblestone_slab[type=top,waterlogged=false]", - "nameZH": "圆石台阶", - "nameEN": "Cobblestone slab", - "icon": "cobblestone.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" - }, - { - "baseColor": 28, - "id": "minecraft:brick_slab[type=top,waterlogged=false]", - "nameZH": "红砖台阶", - "nameEN": "Brick slab", - "icon": "bricks.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=brick]" - }, - { - "baseColor": 11, - "id": "minecraft:stone_brick_slab[type=top,waterlogged=false]", - "nameZH": "石砖台阶", - "nameEN": "Stonebrick slab", - "icon": "stone_bricks.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=stone_brick]" - }, - { - "baseColor": 35, - "id": "minecraft:nether_brick_slab[type=top,waterlogged=false]", - "nameZH": "下界砖台阶", - "nameEN": "Nether brick slab", - "icon": "nether_bricks.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=nether_brick]" - }, - { - "baseColor": 14, - "id": "minecraft:quartz_slab[type=top,waterlogged=false]", - "nameZH": "石英台阶", - "nameEN": "Quartz slab", - "icon": "quartz_block.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=quartz]" - }, - { - "baseColor": 13, - "id": "minecraft:oak_slab[type=top,waterlogged=false]", - "nameZH": "橡木台阶", - "nameEN": "Oak slab", - "icon": "oak_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=oak]" - }, - { - "baseColor": 34, - "id": "minecraft:spruce_slab[type=top,waterlogged=false]", - "nameZH": "云杉木台阶", - "nameEN": "Spruce slab", - "icon": "spruce_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=spruce]", - "burnable": true - }, - { - "baseColor": 2, - "id": "minecraft:birch_slab[type=top,waterlogged=false]", - "nameZH": "白桦木台阶", - "nameEN": "Birch slab", - "icon": "birch_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=birch]", - "burnable": true - }, - { - "baseColor": 10, - "id": "minecraft:jungle_slab[type=top,waterlogged=false]", - "nameZH": "丛林木台阶", - "nameEN": "Jungle slab", - "icon": "jungle_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=jungle]", - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:acacia_slab[type=top,waterlogged=false]", - "nameZH": "金合欢木台阶", - "nameEN": "Acacia slab", - "icon": "acacia_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=acacia]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:dark_oak_slab[type=top,waterlogged=false]", - "nameZH": "深色橡木台阶", - "nameEN": "Dark oak slab", - "icon": "dark_oak_planks.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", - "nameZH": "红砂岩台阶", - "nameEN": "Red sandstone slab", - "icon": "smooth_red_sandstone.png", - "version": 0, - "idOld": "minecraft:stone_slab2[half=top,variant=red_sandstone]" - }, - { - "baseColor": 16, - "id": "minecraft:purpur_slab[type=top,waterlogged=false]", - "nameZH": "紫珀台阶", - "nameEN": "Purpur slab", - "icon": "purpur_block.png", - "version": 0, - "idOld": "minecraft:purpur_slab[half=top,variant=default]" - }, - { - "baseColor": 23, - "id": "minecraft:prismarine_slab[type=top,waterlogged=false]", - "nameZH": "海晶石台阶", - "nameEN": "Prismarine slab", - "icon": "prismarine.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=prismarine]" - }, - { - "baseColor": 31, - "id": "minecraft:prismarine_brick_slab[type=top,waterlogged=false]", - "nameZH": "海晶石砖台阶", - "nameEN": "Prismarine brick slab", - "icon": "prismarine_bricks.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=prismarine_bricks]" - }, - { - "baseColor": 31, - "id": "minecraft:dark_prismarine_slab[type=top,waterlogged=false]", - "nameZH": "暗海晶石台阶", - "nameEN": "Dark prismarine slab", - "icon": "dark_prismarine.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=dark_prismarine]" - }, - { - "baseColor": 2, - "id": "minecraft:sandstone", - "nameZH": "砂岩", - "nameEN": "Sand stone", - "icon": "sandstone.png", - "version": 0 - }, - { - "baseColor": 2, - "id": "minecraft:bone_block[axis=y]", - "nameZH": "骨块", - "nameEN": "Bone block", - "icon": "bone_block_top.png", - "version": 0 - }, - { - "baseColor": 10, - "id": "minecraft:granite", - "nameZH": "花岗岩", - "nameEN": "Granite", - "icon": "granite.png", - "version": 0, - "idOld": "minecraft:stone[variant=granite]" - }, - { - "baseColor": 11, - "id": "minecraft:andesite", - "nameZH": "安山岩", - "nameEN": "Andesite", - "icon": "andesite.png", - "version": 0, - "idOld": "minecraft:stone[variant=andesite]" - }, - { - "baseColor": 11, - "id": "minecraft:polished_andesite", - "nameZH": "磨制安山岩", - "nameEN": "Polished andesite", - "icon": "polished_andesite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_andesite]" - }, - { - "baseColor": 14, - "id": "minecraft:diorite", - "nameZH": "闪长岩", - "nameEN": "Diorite", - "icon": "diorite.png", - "version": 0, - "idOld": "minecraft:stone[variant=diorite]" - }, - { - "baseColor": 15, - "id": "minecraft:red_sandstone", - "nameZH": "红砂岩", - "nameEN": "Red sandstone", - "icon": "red_sandstone.png", - "version": 0, - "idOld": "minecraft:red_sandstone[type=red_sandstone]" - }, - { - "baseColor": 19, - "id": "minecraft:melon", - "nameZH": "西瓜", - "nameEN": "Melon", - "icon": "melon_top.png", - "version": 0, - "idOld": "minecraft:melon_block" - }, - { - "baseColor": 24, - "id": "minecraft:mycelium[snowy=false]", - "nameZH": "菌丝体", - "nameEN": "Mycelium", - "icon": "mycelium_top.png", - "version": 0 - }, - { - "baseColor": 27, - "id": "minecraft:moss_block", - "nameZH": "苔藓块", - "nameEN": "Moss block", - "icon": "moss_block.png", - "version": 17 - }, - { - "baseColor": 29, - "id": "minecraft:basalt[axis=y]", - "nameZH": "玄武岩", - "nameEN": "Basalt", - "icon": "basalt_top.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:blackstone", - "nameZH": "黑石", - "nameEN": "Black stone", - "icon": "blackstone.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:crying_obsidian", - "nameZH": "哭泣的黑曜石", - "nameEN": "Crying obsidian", - "icon": "crying_obsidian.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:netherite_block", - "nameZH": "下界合金块", - "nameEN": "Netherite block", - "icon": "netherite_block.png", - "version": 16 - }, - { - "baseColor": 43, - "id": "minecraft:tuff", - "nameZH": "凝灰岩", - "nameEN": "Tuff", - "icon": "tuff.png", - "version": 17 - } - ] + "CustomBlocks": [ + // 这个文件列出了所有用户自定义的方块的信息", + // 你可以按照这样的格式自定义添加新的方块,包括 mod 方块", + // 但必须遵守 json 格式", + // 如果 json 格式出错,整个文件都会无法解析,SlopeCraft 会报错。 + { + // baseColor 是这种方块对应的基色,是必填项(非常非常重要!!!!!!!)", + "baseColor": 15, + // id 是这种方块的 id,也是必填项,最好附带完整的方块状态,必须加 minecraft:前缀", + "id": "minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]", + // nameZH 是方块中文名称,必填", + "nameZH": "涂蜡切制铜台阶", + // nameEN 是方块英文名称,必填", + "nameEN": "Waxed cut copper slab", + // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", + "icon": "waxed_cut_copper.png", + // version 是方块最早出现的版本。0 代表早于 1.12,12 代表 1.12,13 代表 1.13,如此类推。255 代表尚未出现的版本", + "version": 17 + // idOld 是该方块在 1.12 的方块 id(如果有的话),必须加 minecraft:前缀,选填,默认为空字符串", + // needGlass 代表这个方块的下方需要依附其他方块,默认为否", + // isGlowing 代表这个方块是发光的,默认为否", + // endermanPickable 代表这个方块可以被末影人偷走,默认为否", + // burnable 代表这个方块会被火焰、岩浆或闪电点燃并燃烧,默认为否 + }, + // This json file includes information of all custom blocks. + // You can add your custom block in such format, including mod-blocks. + // But always remember to follow json format + // The whole file will failed to be parsed once an error occurred in json format, then SlopeCraft will complain. + { + // baseColor is the base color of this block on map, a compulsory item(EXTREMELY IMPORTANT!!!!) + "baseColor": 11, + // id is the block id with full blockstatus with minecraft: prefix. Compulsory item. + "id": "minecraft:stone_slab[type=top,waterlogged=false]", + // nameZH is the Chinese name. Compulsory item. + "nameZH": "石头台阶", + // nameEN is the English name. Compulsory item. + "nameEN": "Stone slab", + // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. + "icon": "stone.png", + // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. + "version": 0, + // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string + "idOld": "minecraft:stone_slab[half=top,variant=stone]" + // needGlass means if this block must be setted on a solid block, default value is false + // isGlowing means if the block glows, default value is false. + // endermanPickable means if the block can be picked by enderman, default value is false + // burnable means if the block can be lit by fire, lava or lightning blot, default value is false + }, + { + "baseColor": 2, + "id": "minecraft:sandstone_slab[type=top,waterlogged=false]", + "nameZH": "砂岩台阶", + "nameEN": "Sandstone slab", + "icon": "smooth_sandstone.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=sandstone]" + }, + { + "baseColor": 11, + "id": "minecraft:cobblestone_slab[type=top,waterlogged=false]", + "nameZH": "圆石台阶", + "nameEN": "Cobblestone slab", + "icon": "cobblestone.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" + }, + { + "baseColor": 28, + "id": "minecraft:brick_slab[type=top,waterlogged=false]", + "nameZH": "红砖台阶", + "nameEN": "Brick slab", + "icon": "bricks.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=brick]" + }, + { + "baseColor": 11, + "id": "minecraft:stone_brick_slab[type=top,waterlogged=false]", + "nameZH": "石砖台阶", + "nameEN": "Stonebrick slab", + "icon": "stone_bricks.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=stone_brick]" + }, + { + "baseColor": 35, + "id": "minecraft:nether_brick_slab[type=top,waterlogged=false]", + "nameZH": "下界砖台阶", + "nameEN": "Nether brick slab", + "icon": "nether_bricks.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=nether_brick]" + }, + { + "baseColor": 14, + "id": "minecraft:quartz_slab[type=top,waterlogged=false]", + "nameZH": "石英台阶", + "nameEN": "Quartz slab", + "icon": "quartz_block.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=quartz]" + }, + { + "baseColor": 13, + "id": "minecraft:oak_slab[type=top,waterlogged=false]", + "nameZH": "橡木台阶", + "nameEN": "Oak slab", + "icon": "oak_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=oak]" + }, + { + "baseColor": 34, + "id": "minecraft:spruce_slab[type=top,waterlogged=false]", + "nameZH": "云杉木台阶", + "nameEN": "Spruce slab", + "icon": "spruce_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=spruce]", + "burnable": true + }, + { + "baseColor": 2, + "id": "minecraft:birch_slab[type=top,waterlogged=false]", + "nameZH": "白桦木台阶", + "nameEN": "Birch slab", + "icon": "birch_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=birch]", + "burnable": true + }, + { + "baseColor": 10, + "id": "minecraft:jungle_slab[type=top,waterlogged=false]", + "nameZH": "丛林木台阶", + "nameEN": "Jungle slab", + "icon": "jungle_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=jungle]", + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:acacia_slab[type=top,waterlogged=false]", + "nameZH": "金合欢木台阶", + "nameEN": "Acacia slab", + "icon": "acacia_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=acacia]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:dark_oak_slab[type=top,waterlogged=false]", + "nameZH": "深色橡木台阶", + "nameEN": "Dark oak slab", + "icon": "dark_oak_planks.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", + "nameZH": "红砂岩台阶", + "nameEN": "Red sandstone slab", + "icon": "smooth_red_sandstone.png", + "version": 0, + "idOld": "minecraft:stone_slab2[half=top,variant=red_sandstone]" + }, + { + "baseColor": 16, + "id": "minecraft:purpur_slab[type=top,waterlogged=false]", + "nameZH": "紫珀台阶", + "nameEN": "Purpur slab", + "icon": "purpur_block.png", + "version": 0, + "idOld": "minecraft:purpur_slab[half=top,variant=default]" + }, + { + "baseColor": 23, + "id": "minecraft:prismarine_slab[type=top,waterlogged=false]", + "nameZH": "海晶石台阶", + "nameEN": "Prismarine slab", + "icon": "prismarine.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=prismarine]" + }, + { + "baseColor": 31, + "id": "minecraft:prismarine_brick_slab[type=top,waterlogged=false]", + "nameZH": "海晶石砖台阶", + "nameEN": "Prismarine brick slab", + "icon": "prismarine_bricks.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=prismarine_bricks]" + }, + { + "baseColor": 31, + "id": "minecraft:dark_prismarine_slab[type=top,waterlogged=false]", + "nameZH": "暗海晶石台阶", + "nameEN": "Dark prismarine slab", + "icon": "dark_prismarine.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=dark_prismarine]" + }, + { + "baseColor": 2, + "id": "minecraft:sandstone", + "nameZH": "砂岩", + "nameEN": "Sand stone", + "icon": "sandstone.png", + "version": 0 + }, + { + "baseColor": 2, + "id": "minecraft:bone_block[axis=y]", + "nameZH": "骨块", + "nameEN": "Bone block", + "icon": "bone_block_top.png", + "version": 0 + }, + { + "baseColor": 10, + "id": "minecraft:granite", + "nameZH": "花岗岩", + "nameEN": "Granite", + "icon": "granite.png", + "version": 0, + "idOld": "minecraft:stone[variant=granite]" + }, + { + "baseColor": 11, + "id": "minecraft:andesite", + "nameZH": "安山岩", + "nameEN": "Andesite", + "icon": "andesite.png", + "version": 0, + "idOld": "minecraft:stone[variant=andesite]" + }, + { + "baseColor": 11, + "id": "minecraft:polished_andesite", + "nameZH": "磨制安山岩", + "nameEN": "Polished andesite", + "icon": "polished_andesite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_andesite]" + }, + { + "baseColor": 14, + "id": "minecraft:diorite", + "nameZH": "闪长岩", + "nameEN": "Diorite", + "icon": "diorite.png", + "version": 0, + "idOld": "minecraft:stone[variant=diorite]" + }, + { + "baseColor": 15, + "id": "minecraft:red_sandstone", + "nameZH": "红砂岩", + "nameEN": "Red sandstone", + "icon": "red_sandstone.png", + "version": 0, + "idOld": "minecraft:red_sandstone[type=red_sandstone]" + }, + { + "baseColor": 19, + "id": "minecraft:melon", + "nameZH": "西瓜", + "nameEN": "Melon", + "icon": "melon_top.png", + "version": 0, + "idOld": "minecraft:melon_block" + }, + { + "baseColor": 24, + "id": "minecraft:mycelium[snowy=false]", + "nameZH": "菌丝体", + "nameEN": "Mycelium", + "icon": "mycelium_top.png", + "version": 0 + }, + { + "baseColor": 27, + "id": "minecraft:moss_block", + "nameZH": "苔藓块", + "nameEN": "Moss block", + "icon": "moss_block.png", + "version": 17 + }, + { + "baseColor": 29, + "id": "minecraft:basalt[axis=y]", + "nameZH": "玄武岩", + "nameEN": "Basalt", + "icon": "basalt_top.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:blackstone", + "nameZH": "黑石", + "nameEN": "Black stone", + "icon": "blackstone.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:crying_obsidian", + "nameZH": "哭泣的黑曜石", + "nameEN": "Crying obsidian", + "icon": "crying_obsidian.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:netherite_block", + "nameZH": "下界合金块", + "nameEN": "Netherite block", + "icon": "netherite_block.png", + "version": 16 + }, + { + "baseColor": 43, + "id": "minecraft:tuff", + "nameZH": "凝灰岩", + "nameEN": "Tuff", + "icon": "tuff.png", + "version": 17 + }, + { + "baseColor": 36, + "id": "minecraft:cherry_slab[type=top,waterlogged=false]", + "nameZH": "樱花木台阶", + "nameEN": "Cherry slab", + "icon": "cherry_slab.png", + "version": 20, + "burnable": true + } + ] } \ No newline at end of file diff --git a/Blocks/CustomBlocks/cherry_slab.png b/Blocks/CustomBlocks/cherry_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5d080253f65ebaf51e91083501cbca5f2149b9 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;jQF zi(`nz>9-RU`5Fv(T&qiX(j62FBt$d{R3wD@8V+noo+A3=^nD?bK83h#WpCquyM{jH z{ls14bfC9+SLLn^)%Rl+zPGHud)rOb Date: Sat, 1 Jul 2023 15:27:55 +0800 Subject: [PATCH 0460/1123] adapt to MC20 --- README-en.md | 38 +- README.md | 12 +- SlopeCraftL/TokiSlopeCraft.cpp | 2 +- VisualCraft/BlockBrowser.cpp | 4 +- VisualCraftL/VCL_blocks_fixed.json | 7155 +++++++++-------- VisualCraftL/VisualCraftL.cpp | 2 +- VisualCraftL/generate_tests.cmake | 22 +- VisualCraftL/tests/test_VCL_blockstate.cpp | 6 +- VisualCraftL/tests/test_VCL_model.cpp | 3 +- VisualCraftL/tests/test_VCL_project_image.cpp | 3 +- utilities/SC_GlobalEnums.h | 2 +- vccl/add_test_vccl.cmake | 4 +- 12 files changed, 3632 insertions(+), 3621 deletions(-) diff --git a/README-en.md b/README-en.md index 8f13c44f..842f0868 100644 --- a/README-en.md +++ b/README-en.md @@ -7,7 +7,7 @@

- + @@ -24,27 +24,34 @@ SlopeCraft is created using Qt + Eigen + zlib for creating 3D pixel map arts within Minecraft. -The difference between this program and SpriteCraft is that this program focuses on pixel art on maps. Its purpose is to record the pixel art with the map, then display it in an item frame (the map here refers to the in-game item, and not the saving files). +The difference between this program and SpriteCraft is that this program focuses on pixel art on maps. Its purpose is to +record the pixel art with the map, then display it in an item frame (the map here refers to the in-game item, and not +the saving files). -The color modification module is targeted towards the map. The pixel art is meant to resemble the art in the "point of view" of the map - not of the player. +The color modification module is targeted towards the map. The pixel art is meant to resemble the art in the "point of +view" of the map - not of the player. -Since the color within the map is related to the relative height of the block, the pixel art created by SlopeCraft is usually in 3D, which I call 3D Pixel Art. +Since the color within the map is related to the relative height of the block, the pixel art created by SlopeCraft is +usually in 3D, which I call 3D Pixel Art. In summary, SlopeCraft is created for map pixel art. -This is why maps made by SlopeCraft have higher quality than exporting a picture from SpriteCraft then recording it with a map - because SlopeCraft is specifically designed for map pixel art. +This is why maps made by SlopeCraft have higher quality than exporting a picture from SpriteCraft then recording it with +a map - because SlopeCraft is specifically designed for map pixel art. ## ⚙️ Installation -1. Download the latest version of SlopeCraft from the [Release](https://github.com/SlopeCraft/SlopeCraft/releases/latest) page. +1. Download the latest version of SlopeCraft from + the [Release](https://github.com/SlopeCraft/SlopeCraft/releases/latest) page. 2. Run SlopeCraft - - Windows Users: Download `SlopeCraft-x.x.x-win.zip`, unzip and run `SlopeCraft.exe` - - macOS Users: Download `SlopeCraft-x.x.x-mac.zip`, unzip and drag `SlopeCraft.app` into the Applications folder and run `SlopeCraft` - - Linux Users: Download `SlopeCraft-x.x.x-linux.tar.xz`, unzip and run `SlopeCraft` + - Windows Users: Download `SlopeCraft-x.x.x-win.zip`, unzip and run `SlopeCraft.exe` + - macOS Users: Download `SlopeCraft-x.x.x-mac.zip`, unzip and drag `SlopeCraft.app` into the Applications folder and + run `SlopeCraft` + - Linux Users: Download `SlopeCraft-x.x.x-linux.tar.xz`, unzip and run `SlopeCraft` - ::: tips - The `x.x.x` mentioned above is the version number of SlopeCraft, for example, `5.0.0`. + ::: tips + The `x.x.x` mentioned above is the version number of SlopeCraft, for example, `5.0.0`. 3. Make sure you have read the [FAQ](https://slopecraft.readthedocs.io/en/faq/) and the tutorial before doing anything. @@ -65,13 +72,16 @@ This is why maps made by SlopeCraft have higher quality than exporting a picture ### Compilation Guide -- If you want to compile SlopeCraft yourself, you can refer to the [Compilation Guide](https://slopecraft.readthedocs.io/en/compilation-guide/) for operation. +- If you want to compile SlopeCraft yourself, you can refer to + the [Compilation Guide](https://slopecraft.readthedocs.io/en/compilation-guide/) for operation. ## 🛠️ Other Related Repositories * [NBTWriter](https://github.com/ToKiNoBug/NBTWriter-of-Toki) - Lib for writing NBT files. * [SlopeCraftTutorial](https://github.com/ToKiNoBug/SlopeCraftTutorial) - Tutorials -* [SlopeCraftCompressLib](https://github.com/ToKiNoBug/SlopeCraftCompressLib) - Lib for building height map and lossless compression lib. -* [SlopeCraftLossyCompression](https://github.com/ToKiNoBug/SlopeCraftLossyCompression) - Lossy compression lib, based on SlopeCraftCompressLib. +* [SlopeCraftCompressLib](https://github.com/ToKiNoBug/SlopeCraftCompressLib) - Lib for building height map and lossless + compression lib. +* [SlopeCraftLossyCompression](https://github.com/ToKiNoBug/SlopeCraftLossyCompression) - Lossy compression lib, based + on SlopeCraftCompressLib. * [SlopeCraftGlassBuilder](https://github.com/ToKiNoBug/SlopeCraftGlassBuilder) - Glass bridge building lib. * [HeuristicFlow](https://github.com/TokiNoBug/HeuristicFlow) - GA implementation. diff --git a/README.md b/README.md index 9280233f..78290601 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

- + @@ -39,12 +39,12 @@ SlopeCraft 是一款基于 Qt + Eigen + zlib 开发的,用于在 Minecraft 中 1. 从 [Release](https://github.com/SlopeCraft/SlopeCraft/releases/latest) 页面下载最新版本的 SlopeCraft。 2. 运行 SlopeCraft - - Windows 用户:下载 `SlopeCraft-x.x.x-win.zip`,解压后运行 `SlopeCraft.exe` - - macOS 用户:下载 `SlopeCraft-x.x.x-mac.zip`,解压后将 `SlopeCraft.app` 拖入应用程序文件夹并运行 `SlopeCraft` - - Linux 用户:下载 `SlopeCraft-x.x.x-linux.tar.xz`,解压后运行 `SlopeCraft` + - Windows 用户:下载 `SlopeCraft-x.x.x-win.zip`,解压后运行 `SlopeCraft.exe` + - macOS 用户:下载 `SlopeCraft-x.x.x-mac.zip`,解压后将 `SlopeCraft.app` 拖入应用程序文件夹并运行 `SlopeCraft` + - Linux 用户:下载 `SlopeCraft-x.x.x-linux.tar.xz`,解压后运行 `SlopeCraft` - ::: tips - 此处的 `x.x.x` 为 SlopeCraft 的版本号,例如 `5.0.0`。 + ::: tips + 此处的 `x.x.x` 为 SlopeCraft 的版本号,例如 `5.0.0`。 3. 在进行任何操作前,请确保你已经阅读了 [常见问题](https://slopecraft.readthedocs.io/faq/) 和使用教程。 diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 57ce37a4..2abcff22 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -36,7 +36,7 @@ const colorset_basic_t TokiSlopeCraft::Basic(SlopeCraft::RGBBasicSource); colorset_allowed_t TokiSlopeCraft::Allowed; gameVersion TokiSlopeCraft::mcVer{ - SCL_gameVersion::MC17}; // 12,13,14,15,16,17,18,19 + SCL_gameVersion::MC17}; // 12,13,14,15,16,17,18,19,20 mapTypes TokiSlopeCraft::mapType; std::vector TokiSlopeCraft::blockPalette(0); diff --git a/VisualCraft/BlockBrowser.cpp b/VisualCraft/BlockBrowser.cpp index 57a843ae..9ed0b7dd 100644 --- a/VisualCraft/BlockBrowser.cpp +++ b/VisualCraft/BlockBrowser.cpp @@ -102,7 +102,7 @@ void BlockBrowser::fetch_content() noexcept { QVariant::fromValue((void *)blk)); } { - this->ui->tw_version->setRowCount(19 - 12 + 1); + this->ui->tw_version->setRowCount(20 - 12 + 1); this->ui->tw_version->setColumnCount(2); // if (false) for (int r = 0; r < this->ui->tw_version->rowCount(); r++) { @@ -265,7 +265,7 @@ void BlockBrowser::on_combobox_select_blk_all_currentIndexChanged( this->ui->tb_blockid_all->setText(VCL_get_block_id(blk)); - for (int v = 12; v <= 19; v++) { + for (int v = 12; v <= 20; v++) { const int r = v - 12; QTableWidgetItem *qtwi = this->ui->tw_version->item(r, 1); assert(qtwi != nullptr); diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 7a54a2a9..6d636030 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -1,3578 +1,3585 @@ { - "minecraft:air": { - "class": "others", - "nameEN": "Air", - "nameZH": "空气", - "version": "all", - "is_air": true - }, - "minecraft:brick_block": { - "class": "clay", - "nameEN": "Bricks (1.12)", - "nameZH": "砖块 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:bricks": { - "class": "clay", - "nameEN": "Bricks", - "nameZH": "砖块", - "version": 13 - }, - "minecraft:clay": { - "class": "clay", - "endermanPickable": true, - "nameEN": "Clay block", - "nameZH": "黏土块", - "version": "all", - "reproducible": false - }, - "minecraft:black_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=black]" - ] - ], - "nameEN": "Black concrete", - "nameZH": "黑色混凝土", - "version": "all" - }, - "minecraft:blue_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=blue]" - ] - ], - "nameEN": "Blue concrete", - "nameZH": "蓝色混凝土", - "version": "all" - }, - "minecraft:brown_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=brown]" - ] - ], - "nameEN": "Brown concrete", - "nameZH": "棕色混凝土", - "version": "all" - }, - "minecraft:cyan_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=cyan]" - ] - ], - "nameEN": "Cyan concrete", - "nameZH": "青色混凝土", - "version": "all" - }, - "minecraft:gray_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=gray]" - ] - ], - "nameEN": "Gray concrete", - "nameZH": "灰色混凝土", - "version": "all" - }, - "minecraft:green_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=green]" - ] - ], - "nameEN": "Green concrete", - "nameZH": "绿色混凝土", - "version": "all" - }, - "minecraft:light_blue_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=light_blue]" - ] - ], - "nameEN": "Light blue concrete", - "nameZH": "浅蓝混凝土", - "version": "all" - }, - "minecraft:light_gray_concrete": { - "background": true, - "class": "concrete", - "nameEN": "Light gray concrete", - "nameZH": "浅灰混凝土", - "version": 13 - }, - "minecraft:lime_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=lime]" - ] - ], - "nameEN": "Lime concrete", - "nameZH": "浅绿混凝土", - "version": "all" - }, - "minecraft:magenta_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=magenta]" - ] - ], - "nameEN": "Magenta concrete", - "nameZH": "品红色混凝土", - "version": "all" - }, - "minecraft:orange_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=orange]" - ] - ], - "nameEN": "Orange concrete", - "nameZH": "橙色混凝土", - "version": "all" - }, - "minecraft:pink_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=pink]" - ] - ], - "nameEN": "Pink concrete", - "nameZH": "粉色混凝土", - "version": "all" - }, - "minecraft:purple_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=purple]" - ] - ], - "nameEN": "Purple concrete", - "nameZH": "紫色混凝土", - "version": "all" - }, - "minecraft:red_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=red]" - ] - ], - "nameEN": "Red concrete", - "nameZH": "红色混凝土", - "version": "all" - }, - "minecraft:silver_concrete": { - "background": true, - "class": "concrete", - "nameEN": "Silver concrete (1.12)", - "nameZH": "银色混凝土 (1.12)", - "version": [ - 12 - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=silver]" - ] - ] - }, - "minecraft:white_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=white]" - ] - ], - "nameEN": "White concrete", - "nameZH": "白色混凝土", - "version": "all" - }, - "minecraft:yellow_concrete": { - "background": true, - "class": "concrete", - "id_replace_list": [ - [ - 12, - "minecraft:concrete[color=yellow]" - ] - ], - "nameEN": "Yellow concrete", - "nameZH": "黄色混凝土", - "version": "all" - }, - "minecraft:hay_block[axis=y]": { - "class": "crafted", - "nameEN": "Hay block", - "nameZH": "干草块", - "version": "all" - }, - "minecraft:coarse_dirt": { - "class": "desert", - "endermanPickable": true, - "nameEN": "Coarse dirt", - "nameZH": "砂土", - "version": 13 - }, - "minecraft:red_sandstone[type=smooth_red_sandstone]": { - "class": "desert", - "nameEN": "Smooth red sandstone", - "nameZH": "平滑红砂岩 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:sandstone[type=smooth_sandstone]": { - "class": "desert", - "nameEN": "Smooth sandstone", - "nameZH": "平滑砂岩 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:smooth_red_sandstone": { - "class": "desert", - "nameEN": "Smooth red sandstone", - "nameZH": "平滑红砂岩", - "version": 13 - }, - "minecraft:smooth_sandstone": { - "class": "desert", - "nameEN": "Smooth sandstone", - "nameZH": "平滑砂岩", - "version": 13 - }, - "minecraft:black_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=black]" - ] - ], - "nameEN": "Blakc glass", - "nameZH": "黑色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:blue_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=blue]" - ] - ], - "nameEN": "Blue glass", - "nameZH": "蓝色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:brown_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=brown]" - ] - ], - "nameEN": "Brown glass", - "nameZH": "棕色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:cyan_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=cyan]" - ] - ], - "nameEN": "Cyan glass", - "nameZH": "青色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:gray_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=gray]" - ] - ], - "nameEN": "Gray glass", - "nameZH": "灰色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:green_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=green]" - ] - ], - "nameEN": "Green glass", - "nameZH": "绿色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:light_blue_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=light]" - ] - ], - "nameEN": "Light blue glass", - "nameZH": "浅蓝染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:light_gray_stained_glass": { - "class": "glass", - "nameEN": "Light gray glass", - "nameZH": "浅灰染色玻璃", - "transparent": true, - "version": 13 - }, - "minecraft:lime_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=lime]" - ] - ], - "nameEN": "Lime glass", - "nameZH": "浅绿染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:magenta_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=magenta]" - ] - ], - "nameEN": "Magenta glass", - "nameZH": "品红染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:orange_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=orange]" - ] - ], - "nameEN": "Orange glass", - "nameZH": "橙色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:pink_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=pink]" - ] - ], - "nameEN": "Pink glass", - "nameZH": "粉色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:purple_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=purple]" - ] - ], - "nameEN": "Purple glass", - "nameZH": "紫色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:red_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=red]" - ] - ], - "nameEN": "Red glass", - "nameZH": "红色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:silver_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=silver]" - ] - ], - "nameEN": "Light gray glass (1.12)", - "nameZH": "浅灰染色玻璃 (1.12)", - "transparent": true, - "version": [ - 12 - ] - }, - "minecraft:tinted_glass": { - "class": "glass", - "nameEN": "Tinted glass", - "nameZH": "遮光玻璃", - "transparent": true, - "version": 17 - }, - "minecraft:white_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=white]" - ] - ], - "nameEN": "White glass", - "nameZH": "白色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:yellow_stained_glass": { - "class": "glass", - "id_replace_list": [ - [ - 12, - "minecraft:stained_glass[color=yellow]" - ] - ], - "nameEN": "yellow glass", - "nameZH": "黄色染色玻璃", - "transparent": true, - "version": "all" - }, - "minecraft:acacia_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Acacia leaves", - "nameZH": "金合欢树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:birch_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Brich leaves", - "nameZH": "白桦树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:dark_oak_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Dark oat leaves", - "nameZH": "黑橡树树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:jungle_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Jungle leaves", - "nameZH": "丛林木树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:oak_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Oak leaves", - "nameZH": "橡树树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:spruce_leaves[distance=7,persistent=true]": { - "burnable": true, - "class": "leaves", - "id_replace_list": [ - [ - 12, - "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" - ] - ], - "nameEN": "Spurce leaves", - "nameZH": "云杉树叶", - "version": "all", - "is_foliage": true - }, - "minecraft:blue_ice": { - "class": "natural", - "nameEN": "Blue ice", - "nameZH": "蓝冰", - "version": 13 - }, - "minecraft:dirt": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Dirt", - "nameZH": "泥土", - "version": 13 - }, - "minecraft:dirt[variant=coarse_dirt,snowy=false]": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Coarse dirt (1.12)", - "nameZH": "砂土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:dirt[variant=dirt,snowy=false]": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Dirt (1.12)", - "nameZH": "泥土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:dirt[variant=podzol,snowy=false]": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Podzol (1.12)", - "nameZH": "灰化土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:grass[snowy=false]": { - "class": "natural", - "endermanPickable": true, - "faces": [ - "up" - ], - "nameEN": "Grass block (1.12)", - "nameZH": "草方块 (1.12)", - "version": [ - 12 - ], - "is_grass": true - }, - "minecraft:grass_block[snowy=false]": { - "class": "natural", - "endermanPickable": true, - "faces": [ - "up" - ], - "nameEN": "Grass block", - "nameZH": "草方块", - "version": 13, - "is_grass": true - }, - "minecraft:honeycomb_block": { - "class": "natural", - "nameEN": "Honey comb block", - "nameZH": "蜜脾块", - "version": 15 - }, - "minecraft:ice": { - "class": "natural", - "nameEN": "Ice", - "nameZH": "冰", - "transparent": true, - "version": "all" - }, - "minecraft:mud": { - "class": "natural", - "nameEN": "Mud", - "nameZH": "泥巴", - "version": 19 - }, - "minecraft:mud_bricks": { - "class": "natural", - "nameEN": "Mud bricks", - "nameZH": "泥砖", - "version": 19 - }, - "minecraft:mycelium[snowy=false]": { - "class": "natural", - "faces": [ - "up" - ], - "nameEN": "Mycelium", - "nameZH": "菌丝", - "version": "all" - }, - "minecraft:ochre_froglight[axis=y]": { - "class": "natural", - "isGlowing": true, - "nameEN": "Ochre Froglight", - "nameZH": "黄色蛙鸣灯", - "version": 19, - "rare": true - }, - "minecraft:packed_ice": { - "class": "natural", - "nameEN": "Packed ice", - "nameZH": "浮冰", - "version": "all" - }, - "minecraft:packed_mud": { - "class": "natural", - "nameEN": "Packed mud", - "nameZH": "泥坯", - "version": 19 - }, - "minecraft:pearlescent_froglight[axis=y]": { - "class": "natural", - "isGlowing": true, - "nameEN": "Verdant Froglight", - "nameZH": "紫色蛙鸣灯", - "version": 19, - "rare": true - }, - "minecraft:podzol[snowy=false]": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Podzol", - "nameZH": "灰化土", - "version": 13 - }, - "minecraft:pumpkin": { - "class": "natural", - "endermanPickable": true, - "nameEN": "Pumpkin", - "nameZH": "南瓜", - "version": 13 - }, - "minecraft:pumpkin[facing=east]": { - "class": "natural", - "endermanPickable": true, - "faces": [ - "east" - ], - "id_replace_list": [ - [ - 12, - "minecraft:pumpkin[variant=east]" - ] - ], - "nameEN": "Pumpkin(east) (1.12)", - "nameZH": "南瓜(东) (1.12)", - "version": [ - 12 - ] - }, - "minecraft:pumpkin[facing=north]": { - "class": "natural", - "endermanPickable": true, - "id_replace_list": [ - [ - 12, - "minecraft:pumpkin[variant=north]" - ] - ], - "nameEN": "Pumpkin(north) (1.12)", - "nameZH": "南瓜(北) (1.12)", - "version": [ - 12 - ] - }, - "minecraft:pumpkin[facing=south]": { - "class": "natural", - "endermanPickable": true, - "faces": [ - "south", - "north" - ], - "id_replace_list": [ - [ - 12, - "minecraft:pumpkin[variant=south]" - ] - ], - "nameEN": "Pumpkin(south) (1.12)", - "nameZH": "南瓜(南) (1.12)", - "version": [ - 12 - ] - }, - "minecraft:pumpkin[facing=west]": { - "class": "natural", - "endermanPickable": true, - "faces": [ - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:pumpkin[variant=west]" - ] - ], - "nameEN": "Pumpkin(west) (1.12)", - "nameZH": "南瓜(西) (1.12)", - "version": [ - 12 - ] - }, - "minecraft:shroomlight": { - "class": "natural", - "isGlowing": true, - "nameEN": "Shroomlight", - "nameZH": "菌光体", - "version": 16 - }, - "minecraft:snow": { - "class": "natural", - "nameEN": "Snow (1.12)", - "nameZH": "雪块 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:snow_block": { - "class": "natural", - "nameEN": "Snow", - "nameZH": "雪块", - "version": 13 - }, - "minecraft:verdant_froglight[axis=y]": { - "class": "natural", - "isGlowing": true, - "nameEN": "Verdant Froglight", - "nameZH": "绿色蛙鸣灯", - "version": 19, - "rare": true - }, - "minecraft:crimson_nylium": { - "class": "nether", - "endermanPickable": true, - "faces": [ - "up" - ], - "nameEN": "Crimson nylium", - "nameZH": "绯红菌岩", - "version": 16 - }, - "minecraft:glowstone": { - "class": "nether", - "isGlowing": true, - "nameEN": "Glowstone", - "nameZH": "萤石", - "version": "all" - }, - "minecraft:magma": { - "class": "nether", - "nameEN": "Magma block (1.12)", - "nameZH": "岩浆块 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:magma_block": { - "class": "nether", - "nameEN": "Magma block", - "nameZH": "岩浆块", - "version": 13 - }, - "minecraft:nether_brick": { - "class": "nether", - "nameEN": "Nether brick (1.12)", - "nameZH": "地狱砖块 (1.12)", - "version": [ - 12 - ], - "reproducible": false - }, - "minecraft:nether_bricks": { - "class": "nether", - "nameEN": "Nether brick", - "nameZH": "地狱砖块", - "version": 13, - "reproducible": false - }, - "minecraft:nether_wart_block": { - "class": "nether", - "nameEN": "Nether wart block", - "nameZH": "地狱疣块", - "version": "all" - }, - "minecraft:netherrack": { - "class": "nether", - "nameEN": "Netherrack", - "nameZH": "地狱岩", - "version": "all", - "reproducible": false - }, - "minecraft:soul_sand": { - "class": "nether", - "nameEN": "Soul sand", - "nameZH": "灵魂沙", - "version": "all", - "reproducible": false - }, - "minecraft:soul_soil": { - "class": "nether", - "nameEN": "Soul soil", - "nameZH": "灵魂土", - "version": 16, - "reproducible": false - }, - "minecraft:warped_nylium": { - "class": "nether", - "endermanPickable": true, - "faces": [ - "up" - ], - "nameEN": "Warped nylium", - "nameZH": "扭曲菌岩", - "version": 16 - }, - "minecraft:warped_wart_block": { - "class": "nether", - "nameEN": "Warped wart block", - "nameZH": "扭曲疣块", - "version": 16 - }, - "minecraft:dark_prismarine": { - "class": "ocean", - "nameEN": "Dark prismarine", - "nameZH": "暗海晶石", - "version": 13 - }, - "minecraft:dried_kelp_block": { - "class": "ocean", - "nameEN": "Kelp block", - "nameZH": "海带块", - "version": 13 - }, - "minecraft:prismarine": { - "class": "ocean", - "nameEN": "Prismarine", - "nameZH": "海晶石", - "version": 13 - }, - "minecraft:prismarine[variant=dark_prismarine]": { - "class": "ocean", - "nameEN": "Dark prismarine (1.12)", - "nameZH": "暗海晶石 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:prismarine[variant=prismarine]": { - "class": "ocean", - "nameEN": "Prismarine (1.12)", - "nameZH": "海晶石 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:prismarine[variant=prismarine_bricks]": { - "class": "ocean", - "nameEN": "Prismarine bricks (1.12)", - "nameZH": "海晶石砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:prismarine_bricks": { - "class": "ocean", - "nameEN": "Prismarine bricks", - "nameZH": "海晶石砖", - "version": 13 - }, - "minecraft:sea_lantern": { - "class": "ocean", - "nameEN": "Sea lantern", - "nameZH": "海晶灯", - "version": "all" - }, - "minecraft:amethyst_block": { - "class": "ore", - "nameEN": "Amethyst block", - "nameZH": "紫水晶块", - "version": 17, - "rare": true - }, - "minecraft:coal_block": { - "burnable": true, - "class": "ore", - "nameEN": "Coal block", - "nameZH": "煤块", - "version": "all" - }, - "minecraft:diamond_block": { - "class": "ore", - "nameEN": "Diamond block", - "nameZH": "钻石块", - "version": "all", - "reproducible": false, - "rare": true - }, - "minecraft:emerald_block": { - "class": "ore", - "nameEN": "Emerald block", - "nameZH": "绿宝石块", - "version": "all", - "rare": true - }, - "minecraft:gold_block": { - "class": "ore", - "nameEN": "Gold block", - "nameZH": "金块", - "version": "all", - "rare": true - }, - "minecraft:iron_block": { - "class": "ore", - "nameEN": "Iron block", - "nameZH": "铁块", - "version": "all", - "rare": true - }, - "minecraft:lapis_block": { - "class": "ore", - "nameEN": "Lapis block", - "nameZH": "青金石块", - "version": "all", - "reproducible": false, - "rare": true - }, - "minecraft:raw_copper_block": { - "class": "ore", - "nameEN": "Raw copper block", - "nameZH": "生铜块", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:raw_gold_block": { - "class": "ore", - "nameEN": "Raw gold block", - "nameZH": "粗金块", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:raw_iron_block": { - "class": "ore", - "nameEN": "Raw iron block", - "nameZH": "生铁块", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:waxed_copper_block": { - "class": "ore", - "nameEN": "Waxed copper", - "nameZH": "涂蜡铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_cut_copper": { - "class": "ore", - "nameEN": "Waxed cut copper", - "nameZH": "涂蜡切制铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_exposed_copper": { - "class": "ore", - "nameEN": "Waxed exposed copper", - "nameZH": "涂蜡斑驳铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_exposed_cut_copper": { - "class": "ore", - "nameEN": "Waxed exposed cut copper", - "nameZH": "涂蜡切制斑驳铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_oxidized_copper": { - "class": "ore", - "nameEN": "Waxed oxided copper", - "nameZH": "涂蜡氧化铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_oxidized_cut_copper": { - "class": "ore", - "nameEN": "Waxed oxided cut copper", - "nameZH": "涂蜡切制氧化铜块", - "version": 17, - "rare": true - }, - "minecraft:waxed_weathered_copper": { - "class": "ore", - "nameEN": "Waxed weathered copper", - "nameZH": "涂蜡生锈铜块", - "version": 17, - "rare": true - }, - "minecraft:gilded_blackstone": { - "class": "ore", - "nameEN": "Glided blackstone", - "nameZH": "镶金黑石", - "version": 16, - "reproducible": false, - "rare": true - }, - "minecraft:coal_ore": { - "class": "ore", - "nameEN": "Coal ore", - "nameZH": "煤矿", - "version": "all", - "reproducible": false - }, - "minecraft:deepslate_coal_ore": { - "class": "ore", - "nameEN": "Deepslate coal ore", - "nameZH": "深板岩煤矿", - "version": 17, - "reproducible": false - }, - "minecraft:copper_ore": { - "class": "ore", - "nameEN": "Copper ore", - "nameZH": "铜矿", - "version": 17, - "reproducible": false - }, - "minecraft:deepslate_copper_ore": { - "class": "ore", - "nameEN": "Deepslate copper ore", - "nameZH": "深板岩铜矿", - "version": 17, - "reproducible": false - }, - "minecraft:diamond_ore": { - "class": "ore", - "nameEN": "Diamond ore", - "nameZH": "钻石矿", - "version": "all", - "reproducible": false, - "rare": true - }, - "minecraft:deepslate_diamond_ore": { - "class": "ore", - "nameEN": "Deepslate diamond ore", - "nameZH": "深板岩钻石矿", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:emerald_ore": { - "class": "ore", - "nameEN": "Emerald ore", - "nameZH": "绿宝石矿", - "version": "all", - "reproducible": false, - "rare": true - }, - "minecraft:deepslate_emerald_ore": { - "class": "ore", - "nameEN": "Deepslate emerald ore", - "nameZH": "深板岩绿宝石矿", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:gold_ore": { - "class": "ore", - "nameEN": "Gold ore", - "nameZH": "金矿", - "version": "all", - "reproducible": false - }, - "minecraft:deepslate_gold_ore": { - "class": "ore", - "nameEN": "Deepslate gold ore", - "nameZH": "深板岩金矿", - "version": 17, - "reproducible": false - }, - "minecraft:iron_ore": { - "class": "ore", - "nameEN": "Iron ore", - "nameZH": "铁矿", - "version": "all", - "reproducible": false - }, - "minecraft:deepslate_iron_ore": { - "class": "ore", - "nameEN": "Deepslate iron ore", - "nameZH": "深板岩铁矿", - "version": 17, - "reproducible": false - }, - "minecraft:lapis_ore": { - "class": "ore", - "nameEN": "Lapis ore", - "nameZH": "青金石矿", - "version": "all", - "reproducible": false - }, - "minecraft:deepslate_lapis_ore": { - "class": "ore", - "nameEN": "Deepslate lapis ore", - "nameZH": "深板岩青金石矿", - "version": 17, - "reproducible": false - }, - "minecraft:redstone_ore": { - "class": "ore", - "nameEN": "Redstone ore (1.12&1.16+)", - "nameZH": "红石矿 (1.12&1.16+)", - "version": [ - 12, - 16, - 17, - 18, - 19 - ], - "reproducible": false - }, - "minecraft:redstone_ore[lit=false]": { - "class": "ore", - "nameEN": "Redstone ore (1.13~1.15)", - "nameZH": "红石矿 (1.13~1.15)", - "version": [ - 13, - 14, - 15 - ], - "reproducible": false - }, - "minecraft:deepslate_redstone_ore": { - "class": "ore", - "nameEN": "Deepslate redstone ore", - "nameZH": "深板岩红石矿", - "version": 17, - "reproducible": false - }, - "minecraft:nether_gold_ore": { - "class": "ore", - "nameEN": "Nether gold ore", - "nameZH": "下界金矿", - "version": 16, - "reproducible": false - }, - "minecraft:nether_quartz_ore": { - "class": "ore", - "nameEN": "Nether quartz ore", - "nameZH": "下界石英矿", - "version": 13, - "reproducible": false - }, - "minecraft:quartz_ore": { - "class": "ore", - "nameEN": "Nether quartz ore (1.12)", - "nameZH": "下界石英矿 (1.12)", - "version": [ - 12 - ], - "reproducible": false - }, - "minecraft:ancient_debris": { - "class": "ore", - "nameEN": "Ancient debris", - "nameZH": "远古残骸", - "version": 16, - "reproducible": false, - "rare": true - }, - "minecraft:sculk": { - "class": "others", - "nameEN": "Sculk block", - "nameZH": "潜声方块", - "version": 19, - "rare": true - }, - "minecraft:sculk_catalyst[bloom=false]": { - "class": "others", - "nameEN": "Sculk catalyst", - "nameZH": "潜声催化剂", - "version": 19, - "rare": true - }, - "minecraft:acacia_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=acacia]" - ] - ], - "nameEN": "Acacia plank", - "nameZH": "金合欢木板", - "version": "all" - }, - "minecraft:birch_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=birch]" - ] - ], - "nameEN": "Birch plank", - "nameZH": "白桦木板", - "version": "all" - }, - "minecraft:crimson_planks": { - "burnable": true, - "class": "planks", - "nameEN": "Crimson plank", - "nameZH": "绯红木板", - "version": 16 - }, - "minecraft:dark_oak_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=dark_oak]" - ] - ], - "nameEN": "Dark oak plank", - "nameZH": "黑橡木木板", - "version": "all" - }, - "minecraft:jungle_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=jungle]" - ] - ], - "nameEN": "Jungle plank", - "nameZH": "丛林木板", - "version": "all" - }, - "minecraft:mangrove_planks": { - "burnable": true, - "class": "planks", - "nameEN": "Mangrove planks", - "nameZH": "红树木板", - "version": 19 - }, - "minecraft:oak_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=oak]" - ] - ], - "nameEN": "Oak plank", - "nameZH": "橡木木板", - "version": "all" - }, - "minecraft:spruce_planks": { - "burnable": true, - "class": "planks", - "id_replace_list": [ - [ - 12, - "minecraft:planks[variant=spruce]" - ] - ], - "nameEN": "Spruce plank", - "nameZH": "云杉木板", - "version": "all" - }, - "minecraft:warped_planks": { - "burnable": true, - "class": "planks", - "nameEN": "Warped plank", - "nameZH": "扭曲木板", - "version": 16 - }, - "minecraft:honey_block": { - "class": "redstone", - "nameEN": "Honey block", - "nameZH": "蜜块", - "version": 15 - }, - "minecraft:redstone_block": { - "class": "redstone", - "nameEN": "Redstone block", - "nameZH": "红石块", - "version": "all" - }, - "minecraft:slime": { - "class": "redstone", - "nameEN": "Slime block (1.12)", - "nameZH": "粘液块 (1.12)", - "transparent": true, - "version": [ - 12 - ] - }, - "minecraft:slime_block": { - "class": "redstone", - "nameEN": "Slime block", - "nameZH": "粘液块", - "transparent": true, - "version": 13 - }, - "minecraft:target[power=0]": { - "class": "redstone", - "nameEN": "Target", - "nameZH": "靶子", - "version": 16 - }, - "minecraft:tnt[explode=false]": { - "burnable": true, - "class": "redstone", - "endermanPickable": true, - "nameEN": "TNT (1.12)", - "nameZH": "TNT (1.12)", - "version": [ - 12 - ] - }, - "minecraft:tnt[unstable=false]": { - "burnable": true, - "class": "redstone", - "endermanPickable": true, - "nameEN": "TNT", - "nameZH": "TNT", - "version": 13 - }, - "minecraft:acacia_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=acacia]" - ] - ], - "nameEN": "Acacia slab (1.12)", - "nameZH": "金合欢木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:acacia_slab[type=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Acacia slab", - "nameZH": "金合欢木上半砖", - "version": 13 - }, - "minecraft:birch_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=birch]" - ] - ], - "nameEN": "Birch slab (1.12)", - "nameZH": "白桦木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:birch_slab[type=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Birch slab", - "nameZH": "白桦木上半砖", - "version": 13 - }, - "minecraft:brick_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=brick]" - ] - ], - "nameEN": "Brick slab (1.12)", - "nameZH": "砖块上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:brick_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Brick slab", - "nameZH": "砖块上半砖", - "version": 13 - }, - "minecraft:cobblestone_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=cobblestone]" - ] - ], - "nameEN": "Cobblestone slab (1.12)", - "nameZH": "圆石上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:cobblestone_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Cobblestone slab", - "nameZH": "圆石上半砖", - "version": 13 - }, - "minecraft:dark_oak_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=dark_oak]" - ] - ], - "nameEN": "Dark oak slab (1.12)", - "nameZH": "黑橡木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:dark_oak_slab[type=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Dark oak slab", - "nameZH": "黑橡木上半砖", - "version": 13 - }, - "minecraft:dark_prismarine_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Dark prismarine slab", - "nameZH": "暗海晶石上半砖", - "version": 13 - }, - "minecraft:jungle_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=jungle]" - ] - ], - "nameEN": "Jungle slab (1.12)", - "nameZH": "丛林木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:jungle_slab[type=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Jungle slab", - "nameZH": "丛林木上半砖", - "version": 13 - }, - "minecraft:nether_brick_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=nether_brick]" - ] - ], - "nameEN": "Nether brick slab (1.12)", - "nameZH": "地狱砖块上半砖 (1.12)", - "version": [ - 12 - ], - "reproducible": false - }, - "minecraft:nether_brick_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Nether brick slab", - "nameZH": "地狱砖块上半砖", - "version": 13, - "reproducible": false - }, - "minecraft:oak_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=oak]" - ] - ], - "nameEN": "Oak slab (1.12)", - "nameZH": "橡木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:oak_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Oak slab", - "nameZH": "橡木上半砖", - "version": 13 - }, - "minecraft:prismarine_brick_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Prismarine brick slab", - "nameZH": "海晶石砖上半砖", - "version": 13 - }, - "minecraft:prismarine_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Prismarine slab", - "nameZH": "海晶石上半砖", - "version": 13 - }, - "minecraft:purpur_slab[half=top,variant=default]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Purpur slab (1.12)", - "nameZH": "紫珀上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:purpur_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Purpur slab", - "nameZH": "紫珀上半砖", - "version": 13 - }, - "minecraft:quartz_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=quartz]" - ] - ], - "nameEN": "Quartz slab (1.12)", - "nameZH": "石英上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:quartz_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Quartz slab", - "nameZH": "石英上半砖", - "version": 13 - }, - "minecraft:red_sandstone_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab2[half=top,variant=red_sandstone]" - ] - ], - "nameEN": "Red sandstone slab (1.12)", - "nameZH": "红砂岩上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:red_sandstone_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Red sandstone slab", - "nameZH": "红砂岩上半砖", - "version": 13 - }, - "minecraft:sandstone_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=sandstone]" - ] - ], - "nameEN": "Sandstone slab (1.12)", - "nameZH": "砂岩上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:sandstone_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Sandstone slab", - "nameZH": "砂岩上半砖", - "version": 13 - }, - "minecraft:spruce_slab[half=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:wooden_slab[half=top,variant=spruce]" - ] - ], - "nameEN": "Spruce slab (1.12)", - "nameZH": "云杉木上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:spruce_slab[type=top]": { - "burnable": true, - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Spruce slab", - "nameZH": "云杉木上半砖", - "version": 13 - }, - "minecraft:stone_brick_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=stone_brick]" - ] - ], - "nameEN": "Stonebrick slab (1.12)", - "nameZH": "石砖上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:stone_brick_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Stonebrick slab", - "nameZH": "石砖上半砖", - "version": 13 - }, - "minecraft:stone_slab[half=top]": { - "class": "slab", - "faces": [ - "up" - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone_slab[half=top,variant=stone]" - ] - ], - "nameEN": "Stone slab (1.12)", - "nameZH": "石头上半砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:stone_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Stone slab", - "nameZH": "石头上半砖", - "version": 13 - }, - "minecraft:waxed_cut_copper_slab[type=top]": { - "class": "slab", - "faces": [ - "up" - ], - "nameEN": "Waxed cut copper slab", - "nameZH": "涂蜡切制铜上半砖", - "version": 17, - "rare": true - }, - "minecraft:tuff": { - "class": "stone", - "nameEN": "Tuff", - "nameZH": "凝灰岩", - "version": 17, - "reproducible": false - }, - "minecraft:calcite": { - "class": "stone", - "nameEN": "Calcite", - "nameZH": "方解石", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:chiseled_deepslate": { - "class": "stone", - "nameEN": "Chiseled deepslate", - "nameZH": "錾制深板岩", - "version": 17, - "reproducible": false - }, - "minecraft:cobbled_deepslate": { - "class": "stone", - "nameEN": "Cobbled deepslate", - "nameZH": "深板岩圆石", - "version": 17, - "reproducible": false - }, - "minecraft:cobblestone": { - "class": "stone", - "nameEN": "Cobblestone", - "nameZH": "圆石", - "version": "all" - }, - "minecraft:mossy_cobblestone": { - "class": "stone", - "nameEN": "Mossy cobblestone", - "nameZH": "苔石", - "version": "all" - }, - "minecraft:deepslate[axis=y]": { - "class": "stone", - "nameEN": "Deepslate", - "nameZH": "深板岩", - "version": 17, - "reproducible": false - }, - "minecraft:deepslate_bricks": { - "class": "stone", - "nameEN": "Deepslate bricks", - "nameZH": "深板岩砖", - "version": 17, - "reproducible": false - }, - "minecraft:deepslate_tiles": { - "class": "stone", - "nameEN": "Deepslate tiles", - "nameZH": "深板岩瓦", - "version": 17, - "reproducible": false - }, - "minecraft:dripstone_block": { - "class": "stone", - "nameEN": "DripStone Block", - "nameZH": "滴水石块", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:obsidian": { - "class": "stone", - "nameEN": "Obsidian", - "nameZH": "黑曜石", - "version": "all" - }, - "minecraft:crying_obsidian": { - "class": "stone", - "nameEN": "Crying obsidian", - "nameZH": "哭泣的黑曜石", - "version": 16, - "rare": true - }, - "minecraft:polished_basalt[axis=y]": { - "class": "stone", - "nameEN": "Polished basalt", - "nameZH": "磨制玄武岩", - "version": 16, - "reproducible": false - }, - "minecraft:polished_blackstone": { - "class": "stone", - "nameEN": "Polished blackstone", - "nameZH": "磨制黑石", - "version": 16, - "reproducible": false - }, - "minecraft:polished_deepslate": { - "class": "stone", - "nameEN": "Polished deepslate", - "nameZH": "磨制深板岩", - "version": 17, - "reproducible": false - }, - "minecraft:polished_diorite": { - "class": "stone", - "nameEN": "Polished diorite", - "nameZH": "磨制闪长岩", - "version": 13, - "reproducible": false - }, - "minecraft:polished_granite": { - "class": "stone", - "nameEN": "Polished granite", - "nameZH": "磨制花岗岩", - "version": 13, - "reproducible": false - }, - "minecraft:quartz_block": { - "class": "ore", - "nameEN": "Quartz block", - "nameZH": "石英块", - "version": 13 - }, - "minecraft:quartz_block[variant=default]": { - "class": "ore", - "nameEN": "Quartz block (1.12)", - "nameZH": "石英块 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:smooth_stone": { - "class": "stone", - "nameEN": "Smooth stone", - "nameZH": "平滑石", - "version": 13 - }, - "minecraft:stone": { - "class": "stone", - "nameEN": "Stone", - "nameZH": "石头", - "version": 13 - }, - "minecraft:andesite": { - "class": "stone", - "nameEN": "Andesite", - "nameZH": "安山岩", - "version": "all", - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=andesite]" - ] - ], - "reproducible": false - }, - "minecraft:diorite": { - "class": "stone", - "nameEN": "Diorite", - "nameZH": "闪长岩", - "version": "all", - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=diorite]" - ] - ], - "reproducible": false - }, - "minecraft:granite": { - "class": "stone", - "nameEN": "Granite", - "nameZH": "花岗岩", - "version": "all", - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=granite]" - ] - ], - "reproducible": false - }, - "minecraft:smooth_andesite": { - "class": "stone", - "nameEN": "Polished andesite (1.12)", - "nameZH": "磨制安山岩 (1.12)", - "version": [ - 12 - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=smooth_andesite]" - ] - ], - "reproducible": false - }, - "minecraft:smooth_diorite": { - "class": "stone", - "nameEN": "Polished diorite (1.12)", - "nameZH": "磨制闪长岩 (1.12)", - "version": [ - 12 - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=smooth_diorite]" - ] - ], - "reproducible": false - }, - "minecraft:smooth_granite": { - "class": "stone", - "nameEN": "Polished granite (1.12)", - "nameZH": "磨制花岗岩 (1.12)", - "version": [ - 12 - ], - "id_replace_list": [ - [ - 12, - "minecraft:stone[variant=smooth_granite]" - ] - ], - "reproducible": false - }, - "minecraft:stone[variant=stone]": { - "class": "stone", - "nameEN": "Stone (1.12)", - "nameZH": "石头 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:stone_bricks": { - "class": "stone", - "nameEN": "Stone brick", - "nameZH": "石砖", - "version": 13 - }, - "minecraft:stonebrick[variant=stonebrick]": { - "class": "stone", - "nameEN": "Stone brick (1.12)", - "nameZH": "石砖 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:black_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=black]" - ] - ], - "nameEN": "Black hardened clay (1.12)", - "nameZH": "黑色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:black_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Black terracotta", - "nameZH": "黑色陶瓦", - "version": 13 - }, - "minecraft:blue_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=blue]" - ] - ], - "nameEN": "Blue hardened clay (1.12)", - "nameZH": "蓝色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:blue_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Blue terracotta", - "nameZH": "蓝色陶瓦", - "version": 13 - }, - "minecraft:brown_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=brown]" - ] - ], - "nameEN": "Brown hardened clay (1.12)", - "nameZH": "棕色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:brown_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Brown terracotta", - "nameZH": "棕色陶瓦", - "version": 13 - }, - "minecraft:cyan_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=cyan]" - ] - ], - "nameEN": "Cyan hardened clay (1.12)", - "nameZH": "青色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:cyan_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Cyan terracotta", - "nameZH": "青色陶瓦", - "version": 13 - }, - "minecraft:gray_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=gray]" - ] - ], - "nameEN": "Gray hardened clay (1.12)", - "nameZH": "灰色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:gray_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Gray terracotta", - "nameZH": "灰色陶瓦", - "version": 13 - }, - "minecraft:green_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=green]" - ] - ], - "nameEN": "Green hardened clay (1.12)", - "nameZH": "绿色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:green_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Green terracotta", - "nameZH": "绿色陶瓦", - "version": 13 - }, - "minecraft:hardened_clay": { - "background": true, - "class": "terracotta", - "nameEN": "Hardened clay (1.12)", - "nameZH": "硬化粘土 (1.12)", - "version": [ - 12 - ], - "reproducible": false - }, - "minecraft:light_blue_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=light_blue]" - ] - ], - "nameEN": "Light blue hardened clay (1.12)", - "nameZH": "浅蓝硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:light_blue_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Light blue terracotta", - "nameZH": "浅蓝陶瓦", - "version": 13 - }, - "minecraft:light_gray_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Light gray terracotta", - "nameZH": "浅灰陶瓦", - "version": 13 - }, - "minecraft:lime_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=lime]" - ] - ], - "nameEN": "Lime hardened clay (1.12)", - "nameZH": "浅绿硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:lime_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Lime terracotta", - "nameZH": "浅绿陶瓦", - "version": 13 - }, - "minecraft:magenta_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=magenta]" - ] - ], - "nameEN": "Magenta hardened clay (1.12)", - "nameZH": "品红硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:magenta_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Magenta terracotta", - "nameZH": "品红陶瓦", - "version": 13 - }, - "minecraft:orange_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=orange]" - ] - ], - "nameEN": "Orange hardened clay (1.12)", - "nameZH": "橙色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:orange_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Orange terracotta", - "nameZH": "橙色陶瓦", - "version": 13 - }, - "minecraft:pink_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=pink]" - ] - ], - "nameEN": "Pink hardened clay (1.12)", - "nameZH": "粉色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:pink_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Pink terracotta", - "nameZH": "粉色陶瓦", - "version": 13 - }, - "minecraft:purple_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=purple]" - ] - ], - "nameEN": "Purple hardened clay (1.12)", - "nameZH": "紫色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:purple_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Purple terracotta", - "nameZH": "紫色陶瓦", - "version": 13 - }, - "minecraft:red_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=red]" - ] - ], - "nameEN": "Red hardened clay (1.12)", - "nameZH": "红色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:red_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Red terracotta", - "nameZH": "红色陶瓦", - "version": 13 - }, - "minecraft:silver_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=silver]" - ] - ], - "nameEN": "Light gray hardened clay (1.12)", - "nameZH": "浅灰硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "Terracotta", - "nameZH": "陶瓦", - "version": 13, - "reproducible": false - }, - "minecraft:white_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=white]" - ] - ], - "nameEN": "White hardened clay (1.12)", - "nameZH": "白色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:white_terracotta": { - "background": true, - "class": "terracotta", - "nameEN": "White terracotta", - "nameZH": "白色陶瓦", - "version": 13 - }, - "minecraft:yellow_stained_hardened_clay": { - "background": true, - "class": "terracotta", - "id_replace_list": [ - [ - 12, - "minecraft:stained_hardened_clay[color=yellow]" - ] - ], - "nameEN": "Yellow hardened clay (1.12)", - "nameZH": "黄色硬化粘土 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:yellow_terracotta": { - "background": true, - "burnable": true, - "class": "terracotta", - "nameEN": "Yellow terracotta", - "nameZH": "黄色陶瓦", - "version": 13 - }, - "minecraft:end_bricks": { - "class": "the_end", - "nameEN": "Endstone bricks (1.12)", - "nameZH": "末地石砖 (1.12)", - "version": [ - 12 - ], - "reproducible": false - }, - "minecraft:end_stone": { - "class": "the_end", - "nameEN": "End stone", - "nameZH": "末地石", - "version": "all", - "reproducible": false - }, - "minecraft:end_stone_bricks": { - "class": "the_end", - "nameEN": "Endstone bricks", - "nameZH": "末地石砖", - "version": 13, - "reproducible": false - }, - "minecraft:purpur_block": { - "class": "the_end", - "nameEN": "Purpur block", - "nameZH": "紫珀块", - "version": "all" - }, - "minecraft:acacia_log[axis=y]": { - "class": "wood", - "nameEN": "Acacia log (Y axis)", - "nameZH": "金合欢原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=acacia,axis=y]" - ] - ] - }, - "minecraft:acacia_log[axis=x]": { - "class": "wood", - "nameEN": "Acacia log (X axis)", - "nameZH": "金合欢原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=acacia,axis=x]" - ] - ] - }, - "minecraft:acacia_log[axis=z]": { - "class": "wood", - "nameEN": "Acacia log (Z axis)", - "nameZH": "金合欢原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=acacia,axis=z]" - ] - ] - }, - "minecraft:dark_oak_log[axis=y]": { - "class": "wood", - "nameEN": "Dark oak log (Y axis)", - "nameZH": "黑橡树原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=dark_oak,axis=y]" - ] - ] - }, - "minecraft:dark_oak_log[axis=x]": { - "class": "wood", - "nameEN": "Dark oak log (X axis)", - "nameZH": "黑橡树原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=dark_oak,axis=x]" - ] - ] - }, - "minecraft:dark_oak_log[axis=z]": { - "class": "wood", - "nameEN": "Dark oak log (Z axis)", - "nameZH": "黑橡树原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log2[variant=dark_oak,axis=z]" - ] - ] - }, - "minecraft:jungle_log[axis=y]": { - "class": "wood", - "nameEN": "Jungle log (Y axis)", - "nameZH": "丛林木原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=jungle,axis=y]" - ] - ] - }, - "minecraft:jungle_log[axis=x]": { - "class": "wood", - "nameEN": "Jungle log (X axis)", - "nameZH": "丛林木原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=jungle,axis=x]" - ] - ] - }, - "minecraft:jungle_log[axis=z]": { - "class": "wood", - "nameEN": "Jungle log (Z axis)", - "nameZH": "丛林木原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=jungle,axis=z]" - ] - ] - }, - "minecraft:birch_log[axis=y]": { - "class": "wood", - "nameEN": "Birch log (Y axis)", - "nameZH": "白桦原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=birch,axis=y]" - ] - ] - }, - "minecraft:birch_log[axis=x]": { - "class": "wood", - "nameEN": "Birch log (X axis)", - "nameZH": "白桦原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=birch,axis=x]" - ] - ] - }, - "minecraft:birch_log[axis=z]": { - "class": "wood", - "nameEN": "Birch log (Z axis)", - "nameZH": "白桦原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=birch,axis=z]" - ] - ] - }, - "minecraft:spruce_log[axis=y]": { - "class": "wood", - "nameEN": "Spruce log (Y axis)", - "nameZH": "云杉原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=spruce,axis=y]" - ] - ] - }, - "minecraft:spruce_log[axis=x]": { - "class": "wood", - "nameEN": "Spruce log (X axis)", - "nameZH": "云杉原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=spruce,axis=x]" - ] - ] - }, - "minecraft:spruce_log[axis=z]": { - "class": "wood", - "nameEN": "Spruce log (Z axis)", - "nameZH": "云杉原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=spruce,axis=z]" - ] - ] - }, - "minecraft:oak_log[axis=y]": { - "class": "wood", - "nameEN": "Oak log (Y axis)", - "nameZH": "橡木原木 (Y 轴)", - "version": "all", - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=oak,axis=y]" - ] - ] - }, - "minecraft:oak_log[axis=x]": { - "class": "wood", - "nameEN": "Oak log (X axis)", - "nameZH": "橡木原木 (X 轴)", - "version": "all", - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=oak,axis=x]" - ] - ] - }, - "minecraft:oak_log[axis=z]": { - "class": "wood", - "nameEN": "Oak log (Z axis)", - "nameZH": "橡木原木 (Z 轴)", - "version": "all", - "faces": [ - "north", - "south" - ], - "burnable": true, - "id_replace_list": [ - [ - 12, - "minecraft:log[variant=oak,axis=z]" - ] - ] - }, - "minecraft:mangrove_log[axis=y]": { - "class": "wood", - "nameEN": "Mangrove log (Y axis)", - "nameZH": "红树原木 (Y 轴)", - "version": 19, - "burnable": true - }, - "minecraft:mangrove_log[axis=x]": { - "class": "wood", - "nameEN": "Mangrove log (X axis)", - "nameZH": "红树原木 (X 轴)", - "version": 19, - "faces": [ - "east", - "west", - "up", - "down" - ], - "burnable": true - }, - "minecraft:mangrove_log[axis=z]": { - "class": "wood", - "nameEN": "Mangrove log (Z axis)", - "nameZH": "红树原木 (Z 轴)", - "version": 19, - "faces": [ - "north", - "south" - ], - "burnable": true - }, - "minecraft:crimson_hyphae[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Crimson hyphae", - "nameZH": "绯红树皮", - "version": 16 - }, - "minecraft:stripped_crimson_hyphae[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Stripped crimson hyphae", - "nameZH": "去皮绯红树皮", - "version": 16 - }, - "minecraft:stripped_crimson_stem[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Stripped crimson log", - "nameZH": "去皮绯红原木", - "version": 16 - }, - "minecraft:stripped_warped_hyphae[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Stripped warped hyphae", - "nameZH": "去皮扭曲树皮", - "version": 16 - }, - "minecraft:stripped_warped_stem[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Stripped warped log", - "nameZH": "去皮扭曲原木", - "version": 16 - }, - "minecraft:warped_hyphae[axis=y]": { - "burnable": true, - "class": "wood", - "nameEN": "Warped hyphae", - "nameZH": "扭曲树皮", - "version": 16 - }, - "minecraft:black_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=black]" - ] - ], - "nameEN": "Black wool", - "nameZH": "黑色羊毛", - "version": "all" - }, - "minecraft:blue_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=blue]" - ] - ], - "nameEN": "Blue wool", - "nameZH": "蓝色羊毛", - "version": "all" - }, - "minecraft:brown_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=brown]" - ] - ], - "nameEN": "Brown wool", - "nameZH": "棕色羊毛", - "version": "all" - }, - "minecraft:cyan_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=cyan]" - ] - ], - "nameEN": "Cyan wool", - "nameZH": "青色羊毛", - "version": "all" - }, - "minecraft:gray_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=gray]" - ] - ], - "nameEN": "Gray wool", - "nameZH": "灰色羊毛", - "version": "all" - }, - "minecraft:green_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=green]" - ] - ], - "nameEN": "Green wool", - "nameZH": "绿色羊毛", - "version": "all" - }, - "minecraft:light_blue_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=light_blue]" - ] - ], - "nameEN": "light blue wool", - "nameZH": "浅蓝羊毛", - "version": "all" - }, - "minecraft:light_gray_wool": { - "background": true, - "burnable": true, - "class": "wool", - "nameEN": "Light gray wool", - "nameZH": "浅灰羊毛", - "version": 13 - }, - "minecraft:lime_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=lime]" - ] - ], - "nameEN": "Lime wool", - "nameZH": "浅绿羊毛", - "version": "all" - }, - "minecraft:magenta_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=magenta]" - ] - ], - "nameEN": "Magenta wool", - "nameZH": "品红色羊毛", - "version": "all" - }, - "minecraft:orange_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=orange]" - ] - ], - "nameEN": "Orange wool", - "nameZH": "橙色羊毛", - "version": "all" - }, - "minecraft:pink_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=pink]" - ] - ], - "nameEN": "Pink wool", - "nameZH": "粉色羊毛", - "version": "all" - }, - "minecraft:purple_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=purple]" - ] - ], - "nameEN": "Purple wool", - "nameZH": "紫色羊毛", - "version": "all" - }, - "minecraft:red_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=red]" - ] - ], - "nameEN": "Red wool", - "nameZH": "红色羊毛", - "version": "all" - }, - "minecraft:silver_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=silver]" - ] - ], - "nameEN": "Light gray wool (1.12)", - "nameZH": "浅灰羊毛 (1.12)", - "version": [ - 12 - ] - }, - "minecraft:white_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=white]" - ] - ], - "nameEN": "White wool", - "nameZH": "白色羊毛", - "version": "all" - }, - "minecraft:yellow_wool": { - "background": true, - "burnable": true, - "class": "wool", - "id_replace_list": [ - [ - 12, - "minecraft:wool[color=yellow]" - ] - ], - "nameEN": "Yellow wool", - "nameZH": "黄色羊毛", - "version": "all" - }, - "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]": { - "nameEN": "Brown mushroom block", - "nameZH": "棕色蘑菇块", - "class": "mushroom", - "version": 13 - }, - "minecraft:brown_mushroom_block[variant=all_outside]": { - "nameEN": "Brown mushroom block (1.12)", - "nameZH": "棕色蘑菇块 (1.12)", - "class": "mushroom", - "version": [ - 12 - ] - }, - "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]": { - "burnable": true, - "nameEN": "Mushroom stem", - "nameZH": "蘑菇柄", - "class": "mushroom", - "version": 13 - }, - "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]": { - "burnable": true, - "nameEN": "Red mushroom block", - "nameZH": "红色蘑菇块", - "class": "mushroom", - "version": 13 - }, - "minecraft:red_mushroom_block[variant=all_outside]": { - "burnable": true, - "nameEN": "Red mushroom block (1.12)", - "nameZH": "红色蘑菇块 (1.12)", - "class": "mushroom", - "version": [ - 12 - ] - }, - "minecraft:white_glazed_terracotta[facing=north]": { - "nameEN": "White glazed terracotta", - "nameZH": "白色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:orange_glazed_terracotta[facing=north]": { - "nameEN": "Orange glazed terracotta", - "nameZH": "橙色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:magenta_glazed_terracotta[facing=north]": { - "nameEN": "Magenta glazed terracotta", - "nameZH": "品红色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:light_blue_glazed_terracotta[facing=north]": { - "nameEN": "Light blue glazed terracotta", - "nameZH": "浅蓝色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:yellow_glazed_terracotta[facing=north]": { - "nameEN": "Yellow glazed terracotta", - "nameZH": "黄色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:lime_glazed_terracotta[facing=north]": { - "nameEN": "Lime glazed terracotta", - "nameZH": "浅绿色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:pink_glazed_terracotta[facing=north]": { - "nameEN": "Pink glazed terracotta", - "nameZH": "粉色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:gray_glazed_terracotta[facing=north]": { - "nameEN": "Gray glazed terracotta", - "nameZH": "灰色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:light_gray_glazed_terracotta[facing=north]": { - "nameEN": "Light gray glazed terracotta", - "nameZH": "浅灰色带釉陶瓦", - "class": "glazed_terracotta", - "version": 13, - "background": true - }, - "minecraft:silver_glazed_terracotta[facing=north]": { - "nameEN": "Silver glazed hardened clay (1.12)", - "nameZH": "银色带釉硬化粘土 (1.12)", - "class": "glazed_terracotta", - "version": [ - 12 - ], - "background": true - }, - "minecraft:cyan_glazed_terracotta[facing=north]": { - "nameEN": "Cyan glazed terracotta", - "nameZH": "青色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:blue_glazed_terracotta[facing=north]": { - "nameEN": "Blue glazed terracotta", - "nameZH": "蓝色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:brown_glazed_terracotta[facing=north]": { - "nameEN": "Brown glazed terracotta", - "nameZH": "棕色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:red_glazed_terracotta[facing=north]": { - "nameEN": "Red glazed terracotta", - "nameZH": "红色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:black_glazed_terracotta[facing=north]": { - "nameEN": "Black glazed terracotta", - "nameZH": "黑色带釉陶瓦", - "class": "glazed_terracotta", - "version": "all", - "background": true - }, - "minecraft:white_concrete_powder": { - "nameEN": "White concrete powder", - "nameZH": "白色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=white]" - ] - ] - }, - "minecraft:orange_concrete_powder": { - "nameEN": "Orange concrete powder", - "nameZH": "橙色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=orange]" - ] - ] - }, - "minecraft:magenta_concrete_powder": { - "nameEN": "Magenta concrete powder", - "nameZH": "品红色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=magenta]" - ] - ] - }, - "minecraft:light_blue_concrete_powder": { - "nameEN": "Light blue concrete powder", - "nameZH": "浅蓝色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=light_blue]" - ] - ] - }, - "minecraft:yellow_concrete_powder": { - "nameEN": "Yellow concrete powder", - "nameZH": "黄色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=yellow]" - ] - ] - }, - "minecraft:lime_concrete_powder": { - "nameEN": "Lime concrete powder", - "nameZH": "浅绿色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=lime]" - ] - ] - }, - "minecraft:pink_concrete_powder": { - "nameEN": "Pink concrete powder", - "nameZH": "粉色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=pink]" - ] - ] - }, - "minecraft:gray_concrete_powder": { - "nameEN": "Gray concrete powder", - "nameZH": "灰色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=gray]" - ] - ] - }, - "minecraft:light_gray_concrete_powder": { - "nameEN": "Light gray concrete powder", - "nameZH": "浅灰色混凝土粉末", - "class": "concrete_powder", - "version": 13, - "faces": [ - "up", - "north", - "south", - "east", - "west" - ] - }, - "minecraft:silver_concrete_powder": { - "nameEN": "Silver concrete powder (1.12)", - "nameZH": "银色混凝土粉末 (1.12)", - "class": "concrete_powder", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "version": [ - 12 - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=silver]" - ] - ] - }, - "minecraft:cyan_concrete_powder": { - "nameEN": "Cyan concrete powder", - "nameZH": "青色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=cyan]" - ] - ] - }, - "minecraft:blue_concrete_powder": { - "nameEN": "Blue concrete powder", - "nameZH": "蓝色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=blue]" - ] - ] - }, - "minecraft:brown_concrete_powder": { - "nameEN": "Brown concrete powder", - "nameZH": "棕色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=brown]" - ] - ] - }, - "minecraft:red_concrete_powder": { - "nameEN": "Red concrete powder", - "nameZH": "红色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=red]" - ] - ] - }, - "minecraft:black_concrete_powder": { - "nameEN": "Black concrete powder", - "nameZH": "黑色混凝土粉末", - "class": "concrete_powder", - "version": "all", - "faces": [ - "up", - "north", - "south", - "east", - "west" - ], - "id_replace_list": [ - [ - 12, - "minecraft:concrete_powder[color=black]" - ] - ] - }, - "minecraft:bedrock": { - "nameEN": "Bedrock", - "nameZH": "基岩", - "class": "creative_only", - "version": "all", - "reproducible": false, - "rare": true - }, - "minecraft:budding_amethyst": { - "nameEN": "Budding amethyst", - "nameZH": "紫水晶母岩", - "class": "creative_only", - "version": 17, - "reproducible": false, - "rare": true - }, - "minecraft:reinforced_deepslate": { - "nameEN": "Reinforced deepslate", - "nameZH": "强化深板岩", - "class": "creative_only", - "version": 19, - "reproducible": false, - "rare": true - } - /*, + "minecraft:air": { + "class": "others", + "nameEN": "Air", + "nameZH": "空气", + "version": "all", + "is_air": true + }, + "minecraft:brick_block": { + "class": "clay", + "nameEN": "Bricks (1.12)", + "nameZH": "砖块 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:bricks": { + "class": "clay", + "nameEN": "Bricks", + "nameZH": "砖块", + "version": 13 + }, + "minecraft:clay": { + "class": "clay", + "endermanPickable": true, + "nameEN": "Clay block", + "nameZH": "黏土块", + "version": "all", + "reproducible": false + }, + "minecraft:black_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=black]" + ] + ], + "nameEN": "Black concrete", + "nameZH": "黑色混凝土", + "version": "all" + }, + "minecraft:blue_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=blue]" + ] + ], + "nameEN": "Blue concrete", + "nameZH": "蓝色混凝土", + "version": "all" + }, + "minecraft:brown_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=brown]" + ] + ], + "nameEN": "Brown concrete", + "nameZH": "棕色混凝土", + "version": "all" + }, + "minecraft:cyan_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=cyan]" + ] + ], + "nameEN": "Cyan concrete", + "nameZH": "青色混凝土", + "version": "all" + }, + "minecraft:gray_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=gray]" + ] + ], + "nameEN": "Gray concrete", + "nameZH": "灰色混凝土", + "version": "all" + }, + "minecraft:green_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=green]" + ] + ], + "nameEN": "Green concrete", + "nameZH": "绿色混凝土", + "version": "all" + }, + "minecraft:light_blue_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=light_blue]" + ] + ], + "nameEN": "Light blue concrete", + "nameZH": "浅蓝混凝土", + "version": "all" + }, + "minecraft:light_gray_concrete": { + "background": true, + "class": "concrete", + "nameEN": "Light gray concrete", + "nameZH": "浅灰混凝土", + "version": 13 + }, + "minecraft:lime_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=lime]" + ] + ], + "nameEN": "Lime concrete", + "nameZH": "浅绿混凝土", + "version": "all" + }, + "minecraft:magenta_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=magenta]" + ] + ], + "nameEN": "Magenta concrete", + "nameZH": "品红色混凝土", + "version": "all" + }, + "minecraft:orange_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=orange]" + ] + ], + "nameEN": "Orange concrete", + "nameZH": "橙色混凝土", + "version": "all" + }, + "minecraft:pink_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=pink]" + ] + ], + "nameEN": "Pink concrete", + "nameZH": "粉色混凝土", + "version": "all" + }, + "minecraft:purple_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=purple]" + ] + ], + "nameEN": "Purple concrete", + "nameZH": "紫色混凝土", + "version": "all" + }, + "minecraft:red_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=red]" + ] + ], + "nameEN": "Red concrete", + "nameZH": "红色混凝土", + "version": "all" + }, + "minecraft:silver_concrete": { + "background": true, + "class": "concrete", + "nameEN": "Silver concrete (1.12)", + "nameZH": "银色混凝土 (1.12)", + "version": [ + 12 + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=silver]" + ] + ] + }, + "minecraft:white_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=white]" + ] + ], + "nameEN": "White concrete", + "nameZH": "白色混凝土", + "version": "all" + }, + "minecraft:yellow_concrete": { + "background": true, + "class": "concrete", + "id_replace_list": [ + [ + 12, + "minecraft:concrete[color=yellow]" + ] + ], + "nameEN": "Yellow concrete", + "nameZH": "黄色混凝土", + "version": "all" + }, + "minecraft:hay_block[axis=y]": { + "class": "crafted", + "nameEN": "Hay block", + "nameZH": "干草块", + "version": "all" + }, + "minecraft:coarse_dirt": { + "class": "desert", + "endermanPickable": true, + "nameEN": "Coarse dirt", + "nameZH": "砂土", + "version": 13 + }, + "minecraft:red_sandstone[type=smooth_red_sandstone]": { + "class": "desert", + "nameEN": "Smooth red sandstone", + "nameZH": "平滑红砂岩 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:sandstone[type=smooth_sandstone]": { + "class": "desert", + "nameEN": "Smooth sandstone", + "nameZH": "平滑砂岩 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:smooth_red_sandstone": { + "class": "desert", + "nameEN": "Smooth red sandstone", + "nameZH": "平滑红砂岩", + "version": 13 + }, + "minecraft:smooth_sandstone": { + "class": "desert", + "nameEN": "Smooth sandstone", + "nameZH": "平滑砂岩", + "version": 13 + }, + "minecraft:black_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=black]" + ] + ], + "nameEN": "Blakc glass", + "nameZH": "黑色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:blue_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=blue]" + ] + ], + "nameEN": "Blue glass", + "nameZH": "蓝色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:brown_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=brown]" + ] + ], + "nameEN": "Brown glass", + "nameZH": "棕色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:cyan_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=cyan]" + ] + ], + "nameEN": "Cyan glass", + "nameZH": "青色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:gray_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=gray]" + ] + ], + "nameEN": "Gray glass", + "nameZH": "灰色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:green_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=green]" + ] + ], + "nameEN": "Green glass", + "nameZH": "绿色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:light_blue_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=light]" + ] + ], + "nameEN": "Light blue glass", + "nameZH": "浅蓝染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:light_gray_stained_glass": { + "class": "glass", + "nameEN": "Light gray glass", + "nameZH": "浅灰染色玻璃", + "transparent": true, + "version": 13 + }, + "minecraft:lime_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=lime]" + ] + ], + "nameEN": "Lime glass", + "nameZH": "浅绿染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:magenta_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=magenta]" + ] + ], + "nameEN": "Magenta glass", + "nameZH": "品红染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:orange_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=orange]" + ] + ], + "nameEN": "Orange glass", + "nameZH": "橙色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:pink_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=pink]" + ] + ], + "nameEN": "Pink glass", + "nameZH": "粉色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:purple_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=purple]" + ] + ], + "nameEN": "Purple glass", + "nameZH": "紫色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:red_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=red]" + ] + ], + "nameEN": "Red glass", + "nameZH": "红色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:silver_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=silver]" + ] + ], + "nameEN": "Light gray glass (1.12)", + "nameZH": "浅灰染色玻璃 (1.12)", + "transparent": true, + "version": [ + 12 + ] + }, + "minecraft:tinted_glass": { + "class": "glass", + "nameEN": "Tinted glass", + "nameZH": "遮光玻璃", + "transparent": true, + "version": 17 + }, + "minecraft:white_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=white]" + ] + ], + "nameEN": "White glass", + "nameZH": "白色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:yellow_stained_glass": { + "class": "glass", + "id_replace_list": [ + [ + 12, + "minecraft:stained_glass[color=yellow]" + ] + ], + "nameEN": "yellow glass", + "nameZH": "黄色染色玻璃", + "transparent": true, + "version": "all" + }, + "minecraft:acacia_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Acacia leaves", + "nameZH": "金合欢树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:birch_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Brich leaves", + "nameZH": "白桦树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:dark_oak_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Dark oat leaves", + "nameZH": "黑橡树树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:jungle_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Jungle leaves", + "nameZH": "丛林木树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:oak_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Oak leaves", + "nameZH": "橡树树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:spruce_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "id_replace_list": [ + [ + 12, + "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" + ] + ], + "nameEN": "Spurce leaves", + "nameZH": "云杉树叶", + "version": "all", + "is_foliage": true + }, + "minecraft:blue_ice": { + "class": "natural", + "nameEN": "Blue ice", + "nameZH": "蓝冰", + "version": 13 + }, + "minecraft:dirt": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Dirt", + "nameZH": "泥土", + "version": 13 + }, + "minecraft:dirt[variant=coarse_dirt,snowy=false]": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Coarse dirt (1.12)", + "nameZH": "砂土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:dirt[variant=dirt,snowy=false]": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Dirt (1.12)", + "nameZH": "泥土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:dirt[variant=podzol,snowy=false]": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Podzol (1.12)", + "nameZH": "灰化土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:grass[snowy=false]": { + "class": "natural", + "endermanPickable": true, + "faces": [ + "up" + ], + "nameEN": "Grass block (1.12)", + "nameZH": "草方块 (1.12)", + "version": [ + 12 + ], + "is_grass": true + }, + "minecraft:grass_block[snowy=false]": { + "class": "natural", + "endermanPickable": true, + "faces": [ + "up" + ], + "nameEN": "Grass block", + "nameZH": "草方块", + "version": 13, + "is_grass": true + }, + "minecraft:honeycomb_block": { + "class": "natural", + "nameEN": "Honey comb block", + "nameZH": "蜜脾块", + "version": 15 + }, + "minecraft:ice": { + "class": "natural", + "nameEN": "Ice", + "nameZH": "冰", + "transparent": true, + "version": "all" + }, + "minecraft:mud": { + "class": "natural", + "nameEN": "Mud", + "nameZH": "泥巴", + "version": 19 + }, + "minecraft:mud_bricks": { + "class": "natural", + "nameEN": "Mud bricks", + "nameZH": "泥砖", + "version": 19 + }, + "minecraft:mycelium[snowy=false]": { + "class": "natural", + "faces": [ + "up" + ], + "nameEN": "Mycelium", + "nameZH": "菌丝", + "version": "all" + }, + "minecraft:ochre_froglight[axis=y]": { + "class": "natural", + "isGlowing": true, + "nameEN": "Ochre Froglight", + "nameZH": "黄色蛙鸣灯", + "version": 19, + "rare": true + }, + "minecraft:packed_ice": { + "class": "natural", + "nameEN": "Packed ice", + "nameZH": "浮冰", + "version": "all" + }, + "minecraft:packed_mud": { + "class": "natural", + "nameEN": "Packed mud", + "nameZH": "泥坯", + "version": 19 + }, + "minecraft:pearlescent_froglight[axis=y]": { + "class": "natural", + "isGlowing": true, + "nameEN": "Verdant Froglight", + "nameZH": "紫色蛙鸣灯", + "version": 19, + "rare": true + }, + "minecraft:podzol[snowy=false]": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Podzol", + "nameZH": "灰化土", + "version": 13 + }, + "minecraft:pumpkin": { + "class": "natural", + "endermanPickable": true, + "nameEN": "Pumpkin", + "nameZH": "南瓜", + "version": 13 + }, + "minecraft:pumpkin[facing=east]": { + "class": "natural", + "endermanPickable": true, + "faces": [ + "east" + ], + "id_replace_list": [ + [ + 12, + "minecraft:pumpkin[variant=east]" + ] + ], + "nameEN": "Pumpkin(east) (1.12)", + "nameZH": "南瓜(东) (1.12)", + "version": [ + 12 + ] + }, + "minecraft:pumpkin[facing=north]": { + "class": "natural", + "endermanPickable": true, + "id_replace_list": [ + [ + 12, + "minecraft:pumpkin[variant=north]" + ] + ], + "nameEN": "Pumpkin(north) (1.12)", + "nameZH": "南瓜(北) (1.12)", + "version": [ + 12 + ] + }, + "minecraft:pumpkin[facing=south]": { + "class": "natural", + "endermanPickable": true, + "faces": [ + "south", + "north" + ], + "id_replace_list": [ + [ + 12, + "minecraft:pumpkin[variant=south]" + ] + ], + "nameEN": "Pumpkin(south) (1.12)", + "nameZH": "南瓜(南) (1.12)", + "version": [ + 12 + ] + }, + "minecraft:pumpkin[facing=west]": { + "class": "natural", + "endermanPickable": true, + "faces": [ + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:pumpkin[variant=west]" + ] + ], + "nameEN": "Pumpkin(west) (1.12)", + "nameZH": "南瓜(西) (1.12)", + "version": [ + 12 + ] + }, + "minecraft:shroomlight": { + "class": "natural", + "isGlowing": true, + "nameEN": "Shroomlight", + "nameZH": "菌光体", + "version": 16 + }, + "minecraft:snow": { + "class": "natural", + "nameEN": "Snow (1.12)", + "nameZH": "雪块 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:snow_block": { + "class": "natural", + "nameEN": "Snow", + "nameZH": "雪块", + "version": 13 + }, + "minecraft:verdant_froglight[axis=y]": { + "class": "natural", + "isGlowing": true, + "nameEN": "Verdant Froglight", + "nameZH": "绿色蛙鸣灯", + "version": 19, + "rare": true + }, + "minecraft:crimson_nylium": { + "class": "nether", + "endermanPickable": true, + "faces": [ + "up" + ], + "nameEN": "Crimson nylium", + "nameZH": "绯红菌岩", + "version": 16 + }, + "minecraft:glowstone": { + "class": "nether", + "isGlowing": true, + "nameEN": "Glowstone", + "nameZH": "萤石", + "version": "all" + }, + "minecraft:magma": { + "class": "nether", + "nameEN": "Magma block (1.12)", + "nameZH": "岩浆块 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:magma_block": { + "class": "nether", + "nameEN": "Magma block", + "nameZH": "岩浆块", + "version": 13 + }, + "minecraft:nether_brick": { + "class": "nether", + "nameEN": "Nether brick (1.12)", + "nameZH": "地狱砖块 (1.12)", + "version": [ + 12 + ], + "reproducible": false + }, + "minecraft:nether_bricks": { + "class": "nether", + "nameEN": "Nether brick", + "nameZH": "地狱砖块", + "version": 13, + "reproducible": false + }, + "minecraft:nether_wart_block": { + "class": "nether", + "nameEN": "Nether wart block", + "nameZH": "地狱疣块", + "version": "all" + }, + "minecraft:netherrack": { + "class": "nether", + "nameEN": "Netherrack", + "nameZH": "地狱岩", + "version": "all", + "reproducible": false + }, + "minecraft:soul_sand": { + "class": "nether", + "nameEN": "Soul sand", + "nameZH": "灵魂沙", + "version": "all", + "reproducible": false + }, + "minecraft:soul_soil": { + "class": "nether", + "nameEN": "Soul soil", + "nameZH": "灵魂土", + "version": 16, + "reproducible": false + }, + "minecraft:warped_nylium": { + "class": "nether", + "endermanPickable": true, + "faces": [ + "up" + ], + "nameEN": "Warped nylium", + "nameZH": "扭曲菌岩", + "version": 16 + }, + "minecraft:warped_wart_block": { + "class": "nether", + "nameEN": "Warped wart block", + "nameZH": "扭曲疣块", + "version": 16 + }, + "minecraft:dark_prismarine": { + "class": "ocean", + "nameEN": "Dark prismarine", + "nameZH": "暗海晶石", + "version": 13 + }, + "minecraft:dried_kelp_block": { + "class": "ocean", + "nameEN": "Kelp block", + "nameZH": "海带块", + "version": 13 + }, + "minecraft:prismarine": { + "class": "ocean", + "nameEN": "Prismarine", + "nameZH": "海晶石", + "version": 13 + }, + "minecraft:prismarine[variant=dark_prismarine]": { + "class": "ocean", + "nameEN": "Dark prismarine (1.12)", + "nameZH": "暗海晶石 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:prismarine[variant=prismarine]": { + "class": "ocean", + "nameEN": "Prismarine (1.12)", + "nameZH": "海晶石 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:prismarine[variant=prismarine_bricks]": { + "class": "ocean", + "nameEN": "Prismarine bricks (1.12)", + "nameZH": "海晶石砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:prismarine_bricks": { + "class": "ocean", + "nameEN": "Prismarine bricks", + "nameZH": "海晶石砖", + "version": 13 + }, + "minecraft:sea_lantern": { + "class": "ocean", + "nameEN": "Sea lantern", + "nameZH": "海晶灯", + "version": "all" + }, + "minecraft:amethyst_block": { + "class": "ore", + "nameEN": "Amethyst block", + "nameZH": "紫水晶块", + "version": 17, + "rare": true + }, + "minecraft:coal_block": { + "burnable": true, + "class": "ore", + "nameEN": "Coal block", + "nameZH": "煤块", + "version": "all" + }, + "minecraft:diamond_block": { + "class": "ore", + "nameEN": "Diamond block", + "nameZH": "钻石块", + "version": "all", + "reproducible": false, + "rare": true + }, + "minecraft:emerald_block": { + "class": "ore", + "nameEN": "Emerald block", + "nameZH": "绿宝石块", + "version": "all", + "rare": true + }, + "minecraft:gold_block": { + "class": "ore", + "nameEN": "Gold block", + "nameZH": "金块", + "version": "all", + "rare": true + }, + "minecraft:iron_block": { + "class": "ore", + "nameEN": "Iron block", + "nameZH": "铁块", + "version": "all", + "rare": true + }, + "minecraft:lapis_block": { + "class": "ore", + "nameEN": "Lapis block", + "nameZH": "青金石块", + "version": "all", + "reproducible": false, + "rare": true + }, + "minecraft:raw_copper_block": { + "class": "ore", + "nameEN": "Raw copper block", + "nameZH": "生铜块", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:raw_gold_block": { + "class": "ore", + "nameEN": "Raw gold block", + "nameZH": "粗金块", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:raw_iron_block": { + "class": "ore", + "nameEN": "Raw iron block", + "nameZH": "生铁块", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:waxed_copper_block": { + "class": "ore", + "nameEN": "Waxed copper", + "nameZH": "涂蜡铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_cut_copper": { + "class": "ore", + "nameEN": "Waxed cut copper", + "nameZH": "涂蜡切制铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_exposed_copper": { + "class": "ore", + "nameEN": "Waxed exposed copper", + "nameZH": "涂蜡斑驳铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_exposed_cut_copper": { + "class": "ore", + "nameEN": "Waxed exposed cut copper", + "nameZH": "涂蜡切制斑驳铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_oxidized_copper": { + "class": "ore", + "nameEN": "Waxed oxided copper", + "nameZH": "涂蜡氧化铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_oxidized_cut_copper": { + "class": "ore", + "nameEN": "Waxed oxided cut copper", + "nameZH": "涂蜡切制氧化铜块", + "version": 17, + "rare": true + }, + "minecraft:waxed_weathered_copper": { + "class": "ore", + "nameEN": "Waxed weathered copper", + "nameZH": "涂蜡生锈铜块", + "version": 17, + "rare": true + }, + "minecraft:gilded_blackstone": { + "class": "ore", + "nameEN": "Glided blackstone", + "nameZH": "镶金黑石", + "version": 16, + "reproducible": false, + "rare": true + }, + "minecraft:coal_ore": { + "class": "ore", + "nameEN": "Coal ore", + "nameZH": "煤矿", + "version": "all", + "reproducible": false + }, + "minecraft:deepslate_coal_ore": { + "class": "ore", + "nameEN": "Deepslate coal ore", + "nameZH": "深板岩煤矿", + "version": 17, + "reproducible": false + }, + "minecraft:copper_ore": { + "class": "ore", + "nameEN": "Copper ore", + "nameZH": "铜矿", + "version": 17, + "reproducible": false + }, + "minecraft:deepslate_copper_ore": { + "class": "ore", + "nameEN": "Deepslate copper ore", + "nameZH": "深板岩铜矿", + "version": 17, + "reproducible": false + }, + "minecraft:diamond_ore": { + "class": "ore", + "nameEN": "Diamond ore", + "nameZH": "钻石矿", + "version": "all", + "reproducible": false, + "rare": true + }, + "minecraft:deepslate_diamond_ore": { + "class": "ore", + "nameEN": "Deepslate diamond ore", + "nameZH": "深板岩钻石矿", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:emerald_ore": { + "class": "ore", + "nameEN": "Emerald ore", + "nameZH": "绿宝石矿", + "version": "all", + "reproducible": false, + "rare": true + }, + "minecraft:deepslate_emerald_ore": { + "class": "ore", + "nameEN": "Deepslate emerald ore", + "nameZH": "深板岩绿宝石矿", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:gold_ore": { + "class": "ore", + "nameEN": "Gold ore", + "nameZH": "金矿", + "version": "all", + "reproducible": false + }, + "minecraft:deepslate_gold_ore": { + "class": "ore", + "nameEN": "Deepslate gold ore", + "nameZH": "深板岩金矿", + "version": 17, + "reproducible": false + }, + "minecraft:iron_ore": { + "class": "ore", + "nameEN": "Iron ore", + "nameZH": "铁矿", + "version": "all", + "reproducible": false + }, + "minecraft:deepslate_iron_ore": { + "class": "ore", + "nameEN": "Deepslate iron ore", + "nameZH": "深板岩铁矿", + "version": 17, + "reproducible": false + }, + "minecraft:lapis_ore": { + "class": "ore", + "nameEN": "Lapis ore", + "nameZH": "青金石矿", + "version": "all", + "reproducible": false + }, + "minecraft:deepslate_lapis_ore": { + "class": "ore", + "nameEN": "Deepslate lapis ore", + "nameZH": "深板岩青金石矿", + "version": 17, + "reproducible": false + }, + "minecraft:redstone_ore": { + "class": "ore", + "nameEN": "Redstone ore (1.12&1.16+)", + "nameZH": "红石矿 (1.12&1.16+)", + "version": [ + 12, + 16, + 17, + 18, + 19, + 20 + ], + "reproducible": false + }, + "minecraft:redstone_ore[lit=false]": { + "class": "ore", + "nameEN": "Redstone ore (1.13~1.15)", + "nameZH": "红石矿 (1.13~1.15)", + "version": [ + 13, + 14, + 15 + ], + "reproducible": false + }, + "minecraft:deepslate_redstone_ore": { + "class": "ore", + "nameEN": "Deepslate redstone ore", + "nameZH": "深板岩红石矿", + "version": 17, + "reproducible": false + }, + "minecraft:nether_gold_ore": { + "class": "ore", + "nameEN": "Nether gold ore", + "nameZH": "下界金矿", + "version": 16, + "reproducible": false + }, + "minecraft:nether_quartz_ore": { + "class": "ore", + "nameEN": "Nether quartz ore", + "nameZH": "下界石英矿", + "version": 13, + "reproducible": false + }, + "minecraft:quartz_ore": { + "class": "ore", + "nameEN": "Nether quartz ore (1.12)", + "nameZH": "下界石英矿 (1.12)", + "version": [ + 12 + ], + "reproducible": false + }, + "minecraft:ancient_debris": { + "class": "ore", + "nameEN": "Ancient debris", + "nameZH": "远古残骸", + "version": 16, + "reproducible": false, + "rare": true + }, + "minecraft:sculk": { + "class": "others", + "nameEN": "Sculk block", + "nameZH": "潜声方块", + "version": 19, + "rare": true + }, + "minecraft:sculk_catalyst[bloom=false]": { + "class": "others", + "nameEN": "Sculk catalyst", + "nameZH": "潜声催化剂", + "version": 19, + "rare": true + }, + "minecraft:acacia_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=acacia]" + ] + ], + "nameEN": "Acacia plank", + "nameZH": "金合欢木板", + "version": "all" + }, + "minecraft:birch_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=birch]" + ] + ], + "nameEN": "Birch plank", + "nameZH": "白桦木板", + "version": "all" + }, + "minecraft:crimson_planks": { + "burnable": true, + "class": "planks", + "nameEN": "Crimson plank", + "nameZH": "绯红木板", + "version": 16 + }, + "minecraft:dark_oak_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=dark_oak]" + ] + ], + "nameEN": "Dark oak plank", + "nameZH": "黑橡木木板", + "version": "all" + }, + "minecraft:jungle_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=jungle]" + ] + ], + "nameEN": "Jungle plank", + "nameZH": "丛林木板", + "version": "all" + }, + "minecraft:mangrove_planks": { + "burnable": true, + "class": "planks", + "nameEN": "Mangrove planks", + "nameZH": "红树木板", + "version": 19 + }, + "minecraft:oak_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=oak]" + ] + ], + "nameEN": "Oak plank", + "nameZH": "橡木木板", + "version": "all" + }, + "minecraft:spruce_planks": { + "burnable": true, + "class": "planks", + "id_replace_list": [ + [ + 12, + "minecraft:planks[variant=spruce]" + ] + ], + "nameEN": "Spruce plank", + "nameZH": "云杉木板", + "version": "all" + }, + "minecraft:warped_planks": { + "burnable": true, + "class": "planks", + "nameEN": "Warped plank", + "nameZH": "扭曲木板", + "version": 16 + }, + "minecraft:honey_block": { + "class": "redstone", + "nameEN": "Honey block", + "nameZH": "蜜块", + "version": 15 + }, + "minecraft:redstone_block": { + "class": "redstone", + "nameEN": "Redstone block", + "nameZH": "红石块", + "version": "all" + }, + "minecraft:slime": { + "class": "redstone", + "nameEN": "Slime block (1.12)", + "nameZH": "粘液块 (1.12)", + "transparent": true, + "version": [ + 12 + ] + }, + "minecraft:slime_block": { + "class": "redstone", + "nameEN": "Slime block", + "nameZH": "粘液块", + "transparent": true, + "version": 13 + }, + "minecraft:target[power=0]": { + "class": "redstone", + "nameEN": "Target", + "nameZH": "靶子", + "version": 16 + }, + "minecraft:tnt[explode=false]": { + "burnable": true, + "class": "redstone", + "endermanPickable": true, + "nameEN": "TNT (1.12)", + "nameZH": "TNT (1.12)", + "version": [ + 12 + ] + }, + "minecraft:tnt[unstable=false]": { + "burnable": true, + "class": "redstone", + "endermanPickable": true, + "nameEN": "TNT", + "nameZH": "TNT", + "version": 13 + }, + "minecraft:acacia_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=acacia]" + ] + ], + "nameEN": "Acacia slab (1.12)", + "nameZH": "金合欢木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:acacia_slab[type=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Acacia slab", + "nameZH": "金合欢木上半砖", + "version": 13 + }, + "minecraft:birch_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=birch]" + ] + ], + "nameEN": "Birch slab (1.12)", + "nameZH": "白桦木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:birch_slab[type=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Birch slab", + "nameZH": "白桦木上半砖", + "version": 13 + }, + "minecraft:brick_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=brick]" + ] + ], + "nameEN": "Brick slab (1.12)", + "nameZH": "砖块上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:brick_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Brick slab", + "nameZH": "砖块上半砖", + "version": 13 + }, + "minecraft:cobblestone_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=cobblestone]" + ] + ], + "nameEN": "Cobblestone slab (1.12)", + "nameZH": "圆石上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:cobblestone_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Cobblestone slab", + "nameZH": "圆石上半砖", + "version": 13 + }, + "minecraft:dark_oak_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=dark_oak]" + ] + ], + "nameEN": "Dark oak slab (1.12)", + "nameZH": "黑橡木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:dark_oak_slab[type=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Dark oak slab", + "nameZH": "黑橡木上半砖", + "version": 13 + }, + "minecraft:dark_prismarine_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Dark prismarine slab", + "nameZH": "暗海晶石上半砖", + "version": 13 + }, + "minecraft:jungle_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=jungle]" + ] + ], + "nameEN": "Jungle slab (1.12)", + "nameZH": "丛林木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:jungle_slab[type=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Jungle slab", + "nameZH": "丛林木上半砖", + "version": 13 + }, + "minecraft:nether_brick_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=nether_brick]" + ] + ], + "nameEN": "Nether brick slab (1.12)", + "nameZH": "地狱砖块上半砖 (1.12)", + "version": [ + 12 + ], + "reproducible": false + }, + "minecraft:nether_brick_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Nether brick slab", + "nameZH": "地狱砖块上半砖", + "version": 13, + "reproducible": false + }, + "minecraft:oak_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=oak]" + ] + ], + "nameEN": "Oak slab (1.12)", + "nameZH": "橡木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:oak_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Oak slab", + "nameZH": "橡木上半砖", + "version": 13 + }, + "minecraft:prismarine_brick_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Prismarine brick slab", + "nameZH": "海晶石砖上半砖", + "version": 13 + }, + "minecraft:prismarine_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Prismarine slab", + "nameZH": "海晶石上半砖", + "version": 13 + }, + "minecraft:purpur_slab[half=top,variant=default]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Purpur slab (1.12)", + "nameZH": "紫珀上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:purpur_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Purpur slab", + "nameZH": "紫珀上半砖", + "version": 13 + }, + "minecraft:quartz_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=quartz]" + ] + ], + "nameEN": "Quartz slab (1.12)", + "nameZH": "石英上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:quartz_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Quartz slab", + "nameZH": "石英上半砖", + "version": 13 + }, + "minecraft:red_sandstone_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab2[half=top,variant=red_sandstone]" + ] + ], + "nameEN": "Red sandstone slab (1.12)", + "nameZH": "红砂岩上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:red_sandstone_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Red sandstone slab", + "nameZH": "红砂岩上半砖", + "version": 13 + }, + "minecraft:sandstone_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=sandstone]" + ] + ], + "nameEN": "Sandstone slab (1.12)", + "nameZH": "砂岩上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:sandstone_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Sandstone slab", + "nameZH": "砂岩上半砖", + "version": 13 + }, + "minecraft:spruce_slab[half=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:wooden_slab[half=top,variant=spruce]" + ] + ], + "nameEN": "Spruce slab (1.12)", + "nameZH": "云杉木上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:spruce_slab[type=top]": { + "burnable": true, + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Spruce slab", + "nameZH": "云杉木上半砖", + "version": 13 + }, + "minecraft:stone_brick_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=stone_brick]" + ] + ], + "nameEN": "Stonebrick slab (1.12)", + "nameZH": "石砖上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:stone_brick_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Stonebrick slab", + "nameZH": "石砖上半砖", + "version": 13 + }, + "minecraft:stone_slab[half=top]": { + "class": "slab", + "faces": [ + "up" + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone_slab[half=top,variant=stone]" + ] + ], + "nameEN": "Stone slab (1.12)", + "nameZH": "石头上半砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:stone_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Stone slab", + "nameZH": "石头上半砖", + "version": 13 + }, + "minecraft:waxed_cut_copper_slab[type=top]": { + "class": "slab", + "faces": [ + "up" + ], + "nameEN": "Waxed cut copper slab", + "nameZH": "涂蜡切制铜上半砖", + "version": 17, + "rare": true + }, + "minecraft:tuff": { + "class": "stone", + "nameEN": "Tuff", + "nameZH": "凝灰岩", + "version": 17, + "reproducible": false + }, + "minecraft:calcite": { + "class": "stone", + "nameEN": "Calcite", + "nameZH": "方解石", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:chiseled_deepslate": { + "class": "stone", + "nameEN": "Chiseled deepslate", + "nameZH": "錾制深板岩", + "version": 17, + "reproducible": false + }, + "minecraft:cobbled_deepslate": { + "class": "stone", + "nameEN": "Cobbled deepslate", + "nameZH": "深板岩圆石", + "version": 17, + "reproducible": false + }, + "minecraft:cobblestone": { + "class": "stone", + "nameEN": "Cobblestone", + "nameZH": "圆石", + "version": "all" + }, + "minecraft:mossy_cobblestone": { + "class": "stone", + "nameEN": "Mossy cobblestone", + "nameZH": "苔石", + "version": "all" + }, + "minecraft:deepslate[axis=y]": { + "class": "stone", + "nameEN": "Deepslate", + "nameZH": "深板岩", + "version": 17, + "reproducible": false + }, + "minecraft:deepslate_bricks": { + "class": "stone", + "nameEN": "Deepslate bricks", + "nameZH": "深板岩砖", + "version": 17, + "reproducible": false + }, + "minecraft:deepslate_tiles": { + "class": "stone", + "nameEN": "Deepslate tiles", + "nameZH": "深板岩瓦", + "version": 17, + "reproducible": false + }, + "minecraft:dripstone_block": { + "class": "stone", + "nameEN": "DripStone Block", + "nameZH": "滴水石块", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:obsidian": { + "class": "stone", + "nameEN": "Obsidian", + "nameZH": "黑曜石", + "version": "all" + }, + "minecraft:crying_obsidian": { + "class": "stone", + "nameEN": "Crying obsidian", + "nameZH": "哭泣的黑曜石", + "version": 16, + "rare": true + }, + "minecraft:polished_basalt[axis=y]": { + "class": "stone", + "nameEN": "Polished basalt", + "nameZH": "磨制玄武岩", + "version": 16, + "reproducible": false + }, + "minecraft:polished_blackstone": { + "class": "stone", + "nameEN": "Polished blackstone", + "nameZH": "磨制黑石", + "version": 16, + "reproducible": false + }, + "minecraft:polished_deepslate": { + "class": "stone", + "nameEN": "Polished deepslate", + "nameZH": "磨制深板岩", + "version": 17, + "reproducible": false + }, + "minecraft:polished_diorite": { + "class": "stone", + "nameEN": "Polished diorite", + "nameZH": "磨制闪长岩", + "version": 13, + "reproducible": false + }, + "minecraft:polished_granite": { + "class": "stone", + "nameEN": "Polished granite", + "nameZH": "磨制花岗岩", + "version": 13, + "reproducible": false + }, + "minecraft:quartz_block": { + "class": "ore", + "nameEN": "Quartz block", + "nameZH": "石英块", + "version": 13 + }, + "minecraft:quartz_block[variant=default]": { + "class": "ore", + "nameEN": "Quartz block (1.12)", + "nameZH": "石英块 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:smooth_stone": { + "class": "stone", + "nameEN": "Smooth stone", + "nameZH": "平滑石", + "version": 13 + }, + "minecraft:stone": { + "class": "stone", + "nameEN": "Stone", + "nameZH": "石头", + "version": 13 + }, + "minecraft:andesite": { + "class": "stone", + "nameEN": "Andesite", + "nameZH": "安山岩", + "version": "all", + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=andesite]" + ] + ], + "reproducible": false + }, + "minecraft:diorite": { + "class": "stone", + "nameEN": "Diorite", + "nameZH": "闪长岩", + "version": "all", + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=diorite]" + ] + ], + "reproducible": false + }, + "minecraft:granite": { + "class": "stone", + "nameEN": "Granite", + "nameZH": "花岗岩", + "version": "all", + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=granite]" + ] + ], + "reproducible": false + }, + "minecraft:smooth_andesite": { + "class": "stone", + "nameEN": "Polished andesite (1.12)", + "nameZH": "磨制安山岩 (1.12)", + "version": [ + 12 + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=smooth_andesite]" + ] + ], + "reproducible": false + }, + "minecraft:smooth_diorite": { + "class": "stone", + "nameEN": "Polished diorite (1.12)", + "nameZH": "磨制闪长岩 (1.12)", + "version": [ + 12 + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=smooth_diorite]" + ] + ], + "reproducible": false + }, + "minecraft:smooth_granite": { + "class": "stone", + "nameEN": "Polished granite (1.12)", + "nameZH": "磨制花岗岩 (1.12)", + "version": [ + 12 + ], + "id_replace_list": [ + [ + 12, + "minecraft:stone[variant=smooth_granite]" + ] + ], + "reproducible": false + }, + "minecraft:stone[variant=stone]": { + "class": "stone", + "nameEN": "Stone (1.12)", + "nameZH": "石头 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:stone_bricks": { + "class": "stone", + "nameEN": "Stone brick", + "nameZH": "石砖", + "version": 13 + }, + "minecraft:stonebrick[variant=stonebrick]": { + "class": "stone", + "nameEN": "Stone brick (1.12)", + "nameZH": "石砖 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:black_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=black]" + ] + ], + "nameEN": "Black hardened clay (1.12)", + "nameZH": "黑色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:black_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Black terracotta", + "nameZH": "黑色陶瓦", + "version": 13 + }, + "minecraft:blue_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=blue]" + ] + ], + "nameEN": "Blue hardened clay (1.12)", + "nameZH": "蓝色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:blue_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Blue terracotta", + "nameZH": "蓝色陶瓦", + "version": 13 + }, + "minecraft:brown_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=brown]" + ] + ], + "nameEN": "Brown hardened clay (1.12)", + "nameZH": "棕色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:brown_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Brown terracotta", + "nameZH": "棕色陶瓦", + "version": 13 + }, + "minecraft:cyan_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=cyan]" + ] + ], + "nameEN": "Cyan hardened clay (1.12)", + "nameZH": "青色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:cyan_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Cyan terracotta", + "nameZH": "青色陶瓦", + "version": 13 + }, + "minecraft:gray_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=gray]" + ] + ], + "nameEN": "Gray hardened clay (1.12)", + "nameZH": "灰色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:gray_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Gray terracotta", + "nameZH": "灰色陶瓦", + "version": 13 + }, + "minecraft:green_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=green]" + ] + ], + "nameEN": "Green hardened clay (1.12)", + "nameZH": "绿色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:green_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Green terracotta", + "nameZH": "绿色陶瓦", + "version": 13 + }, + "minecraft:hardened_clay": { + "background": true, + "class": "terracotta", + "nameEN": "Hardened clay (1.12)", + "nameZH": "硬化粘土 (1.12)", + "version": [ + 12 + ], + "reproducible": false + }, + "minecraft:light_blue_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=light_blue]" + ] + ], + "nameEN": "Light blue hardened clay (1.12)", + "nameZH": "浅蓝硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:light_blue_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Light blue terracotta", + "nameZH": "浅蓝陶瓦", + "version": 13 + }, + "minecraft:light_gray_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Light gray terracotta", + "nameZH": "浅灰陶瓦", + "version": 13 + }, + "minecraft:lime_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=lime]" + ] + ], + "nameEN": "Lime hardened clay (1.12)", + "nameZH": "浅绿硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:lime_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Lime terracotta", + "nameZH": "浅绿陶瓦", + "version": 13 + }, + "minecraft:magenta_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=magenta]" + ] + ], + "nameEN": "Magenta hardened clay (1.12)", + "nameZH": "品红硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:magenta_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Magenta terracotta", + "nameZH": "品红陶瓦", + "version": 13 + }, + "minecraft:orange_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=orange]" + ] + ], + "nameEN": "Orange hardened clay (1.12)", + "nameZH": "橙色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:orange_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Orange terracotta", + "nameZH": "橙色陶瓦", + "version": 13 + }, + "minecraft:pink_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=pink]" + ] + ], + "nameEN": "Pink hardened clay (1.12)", + "nameZH": "粉色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:pink_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Pink terracotta", + "nameZH": "粉色陶瓦", + "version": 13 + }, + "minecraft:purple_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=purple]" + ] + ], + "nameEN": "Purple hardened clay (1.12)", + "nameZH": "紫色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:purple_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Purple terracotta", + "nameZH": "紫色陶瓦", + "version": 13 + }, + "minecraft:red_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=red]" + ] + ], + "nameEN": "Red hardened clay (1.12)", + "nameZH": "红色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:red_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Red terracotta", + "nameZH": "红色陶瓦", + "version": 13 + }, + "minecraft:silver_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=silver]" + ] + ], + "nameEN": "Light gray hardened clay (1.12)", + "nameZH": "浅灰硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "Terracotta", + "nameZH": "陶瓦", + "version": 13, + "reproducible": false + }, + "minecraft:white_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=white]" + ] + ], + "nameEN": "White hardened clay (1.12)", + "nameZH": "白色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:white_terracotta": { + "background": true, + "class": "terracotta", + "nameEN": "White terracotta", + "nameZH": "白色陶瓦", + "version": 13 + }, + "minecraft:yellow_stained_hardened_clay": { + "background": true, + "class": "terracotta", + "id_replace_list": [ + [ + 12, + "minecraft:stained_hardened_clay[color=yellow]" + ] + ], + "nameEN": "Yellow hardened clay (1.12)", + "nameZH": "黄色硬化粘土 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:yellow_terracotta": { + "background": true, + "burnable": true, + "class": "terracotta", + "nameEN": "Yellow terracotta", + "nameZH": "黄色陶瓦", + "version": 13 + }, + "minecraft:end_bricks": { + "class": "the_end", + "nameEN": "Endstone bricks (1.12)", + "nameZH": "末地石砖 (1.12)", + "version": [ + 12 + ], + "reproducible": false + }, + "minecraft:end_stone": { + "class": "the_end", + "nameEN": "End stone", + "nameZH": "末地石", + "version": "all", + "reproducible": false + }, + "minecraft:end_stone_bricks": { + "class": "the_end", + "nameEN": "Endstone bricks", + "nameZH": "末地石砖", + "version": 13, + "reproducible": false + }, + "minecraft:purpur_block": { + "class": "the_end", + "nameEN": "Purpur block", + "nameZH": "紫珀块", + "version": "all" + }, + "minecraft:acacia_log[axis=y]": { + "class": "wood", + "nameEN": "Acacia log (Y axis)", + "nameZH": "金合欢原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=acacia,axis=y]" + ] + ] + }, + "minecraft:acacia_log[axis=x]": { + "class": "wood", + "nameEN": "Acacia log (X axis)", + "nameZH": "金合欢原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=acacia,axis=x]" + ] + ] + }, + "minecraft:acacia_log[axis=z]": { + "class": "wood", + "nameEN": "Acacia log (Z axis)", + "nameZH": "金合欢原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=acacia,axis=z]" + ] + ] + }, + "minecraft:dark_oak_log[axis=y]": { + "class": "wood", + "nameEN": "Dark oak log (Y axis)", + "nameZH": "黑橡树原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=dark_oak,axis=y]" + ] + ] + }, + "minecraft:dark_oak_log[axis=x]": { + "class": "wood", + "nameEN": "Dark oak log (X axis)", + "nameZH": "黑橡树原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=dark_oak,axis=x]" + ] + ] + }, + "minecraft:dark_oak_log[axis=z]": { + "class": "wood", + "nameEN": "Dark oak log (Z axis)", + "nameZH": "黑橡树原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log2[variant=dark_oak,axis=z]" + ] + ] + }, + "minecraft:jungle_log[axis=y]": { + "class": "wood", + "nameEN": "Jungle log (Y axis)", + "nameZH": "丛林木原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=jungle,axis=y]" + ] + ] + }, + "minecraft:jungle_log[axis=x]": { + "class": "wood", + "nameEN": "Jungle log (X axis)", + "nameZH": "丛林木原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=jungle,axis=x]" + ] + ] + }, + "minecraft:jungle_log[axis=z]": { + "class": "wood", + "nameEN": "Jungle log (Z axis)", + "nameZH": "丛林木原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=jungle,axis=z]" + ] + ] + }, + "minecraft:birch_log[axis=y]": { + "class": "wood", + "nameEN": "Birch log (Y axis)", + "nameZH": "白桦原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=birch,axis=y]" + ] + ] + }, + "minecraft:birch_log[axis=x]": { + "class": "wood", + "nameEN": "Birch log (X axis)", + "nameZH": "白桦原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=birch,axis=x]" + ] + ] + }, + "minecraft:birch_log[axis=z]": { + "class": "wood", + "nameEN": "Birch log (Z axis)", + "nameZH": "白桦原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=birch,axis=z]" + ] + ] + }, + "minecraft:spruce_log[axis=y]": { + "class": "wood", + "nameEN": "Spruce log (Y axis)", + "nameZH": "云杉原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=spruce,axis=y]" + ] + ] + }, + "minecraft:spruce_log[axis=x]": { + "class": "wood", + "nameEN": "Spruce log (X axis)", + "nameZH": "云杉原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=spruce,axis=x]" + ] + ] + }, + "minecraft:spruce_log[axis=z]": { + "class": "wood", + "nameEN": "Spruce log (Z axis)", + "nameZH": "云杉原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=spruce,axis=z]" + ] + ] + }, + "minecraft:oak_log[axis=y]": { + "class": "wood", + "nameEN": "Oak log (Y axis)", + "nameZH": "橡木原木 (Y 轴)", + "version": "all", + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=oak,axis=y]" + ] + ] + }, + "minecraft:oak_log[axis=x]": { + "class": "wood", + "nameEN": "Oak log (X axis)", + "nameZH": "橡木原木 (X 轴)", + "version": "all", + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=oak,axis=x]" + ] + ] + }, + "minecraft:oak_log[axis=z]": { + "class": "wood", + "nameEN": "Oak log (Z axis)", + "nameZH": "橡木原木 (Z 轴)", + "version": "all", + "faces": [ + "north", + "south" + ], + "burnable": true, + "id_replace_list": [ + [ + 12, + "minecraft:log[variant=oak,axis=z]" + ] + ] + }, + "minecraft:mangrove_log[axis=y]": { + "class": "wood", + "nameEN": "Mangrove log (Y axis)", + "nameZH": "红树原木 (Y 轴)", + "version": 19, + "burnable": true + }, + "minecraft:mangrove_log[axis=x]": { + "class": "wood", + "nameEN": "Mangrove log (X axis)", + "nameZH": "红树原木 (X 轴)", + "version": 19, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:mangrove_log[axis=z]": { + "class": "wood", + "nameEN": "Mangrove log (Z axis)", + "nameZH": "红树原木 (Z 轴)", + "version": 19, + "faces": [ + "north", + "south" + ], + "burnable": true + }, + "minecraft:crimson_hyphae[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Crimson hyphae", + "nameZH": "绯红树皮", + "version": 16 + }, + "minecraft:stripped_crimson_hyphae[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Stripped crimson hyphae", + "nameZH": "去皮绯红树皮", + "version": 16 + }, + "minecraft:stripped_crimson_stem[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Stripped crimson log", + "nameZH": "去皮绯红原木", + "version": 16 + }, + "minecraft:stripped_warped_hyphae[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Stripped warped hyphae", + "nameZH": "去皮扭曲树皮", + "version": 16 + }, + "minecraft:stripped_warped_stem[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Stripped warped log", + "nameZH": "去皮扭曲原木", + "version": 16 + }, + "minecraft:warped_hyphae[axis=y]": { + "burnable": true, + "class": "wood", + "nameEN": "Warped hyphae", + "nameZH": "扭曲树皮", + "version": 16 + }, + "minecraft:black_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=black]" + ] + ], + "nameEN": "Black wool", + "nameZH": "黑色羊毛", + "version": "all" + }, + "minecraft:blue_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=blue]" + ] + ], + "nameEN": "Blue wool", + "nameZH": "蓝色羊毛", + "version": "all" + }, + "minecraft:brown_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=brown]" + ] + ], + "nameEN": "Brown wool", + "nameZH": "棕色羊毛", + "version": "all" + }, + "minecraft:cyan_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=cyan]" + ] + ], + "nameEN": "Cyan wool", + "nameZH": "青色羊毛", + "version": "all" + }, + "minecraft:gray_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=gray]" + ] + ], + "nameEN": "Gray wool", + "nameZH": "灰色羊毛", + "version": "all" + }, + "minecraft:green_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=green]" + ] + ], + "nameEN": "Green wool", + "nameZH": "绿色羊毛", + "version": "all" + }, + "minecraft:light_blue_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=light_blue]" + ] + ], + "nameEN": "light blue wool", + "nameZH": "浅蓝羊毛", + "version": "all" + }, + "minecraft:light_gray_wool": { + "background": true, + "burnable": true, + "class": "wool", + "nameEN": "Light gray wool", + "nameZH": "浅灰羊毛", + "version": 13 + }, + "minecraft:lime_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=lime]" + ] + ], + "nameEN": "Lime wool", + "nameZH": "浅绿羊毛", + "version": "all" + }, + "minecraft:magenta_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=magenta]" + ] + ], + "nameEN": "Magenta wool", + "nameZH": "品红色羊毛", + "version": "all" + }, + "minecraft:orange_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=orange]" + ] + ], + "nameEN": "Orange wool", + "nameZH": "橙色羊毛", + "version": "all" + }, + "minecraft:pink_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=pink]" + ] + ], + "nameEN": "Pink wool", + "nameZH": "粉色羊毛", + "version": "all" + }, + "minecraft:purple_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=purple]" + ] + ], + "nameEN": "Purple wool", + "nameZH": "紫色羊毛", + "version": "all" + }, + "minecraft:red_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=red]" + ] + ], + "nameEN": "Red wool", + "nameZH": "红色羊毛", + "version": "all" + }, + "minecraft:silver_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=silver]" + ] + ], + "nameEN": "Light gray wool (1.12)", + "nameZH": "浅灰羊毛 (1.12)", + "version": [ + 12 + ] + }, + "minecraft:white_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=white]" + ] + ], + "nameEN": "White wool", + "nameZH": "白色羊毛", + "version": "all" + }, + "minecraft:yellow_wool": { + "background": true, + "burnable": true, + "class": "wool", + "id_replace_list": [ + [ + 12, + "minecraft:wool[color=yellow]" + ] + ], + "nameEN": "Yellow wool", + "nameZH": "黄色羊毛", + "version": "all" + }, + "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]": { + "nameEN": "Brown mushroom block", + "nameZH": "棕色蘑菇块", + "class": "mushroom", + "version": 13 + }, + "minecraft:brown_mushroom_block[variant=all_outside]": { + "nameEN": "Brown mushroom block (1.12)", + "nameZH": "棕色蘑菇块 (1.12)", + "class": "mushroom", + "version": [ + 12 + ] + }, + "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]": { + "burnable": true, + "nameEN": "Mushroom stem", + "nameZH": "蘑菇柄", + "class": "mushroom", + "version": 13 + }, + "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]": { + "burnable": true, + "nameEN": "Red mushroom block", + "nameZH": "红色蘑菇块", + "class": "mushroom", + "version": 13 + }, + "minecraft:red_mushroom_block[variant=all_outside]": { + "burnable": true, + "nameEN": "Red mushroom block (1.12)", + "nameZH": "红色蘑菇块 (1.12)", + "class": "mushroom", + "version": [ + 12 + ] + }, + "minecraft:white_glazed_terracotta[facing=north]": { + "nameEN": "White glazed terracotta", + "nameZH": "白色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:orange_glazed_terracotta[facing=north]": { + "nameEN": "Orange glazed terracotta", + "nameZH": "橙色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:magenta_glazed_terracotta[facing=north]": { + "nameEN": "Magenta glazed terracotta", + "nameZH": "品红色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:light_blue_glazed_terracotta[facing=north]": { + "nameEN": "Light blue glazed terracotta", + "nameZH": "浅蓝色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:yellow_glazed_terracotta[facing=north]": { + "nameEN": "Yellow glazed terracotta", + "nameZH": "黄色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:lime_glazed_terracotta[facing=north]": { + "nameEN": "Lime glazed terracotta", + "nameZH": "浅绿色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:pink_glazed_terracotta[facing=north]": { + "nameEN": "Pink glazed terracotta", + "nameZH": "粉色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:gray_glazed_terracotta[facing=north]": { + "nameEN": "Gray glazed terracotta", + "nameZH": "灰色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:light_gray_glazed_terracotta[facing=north]": { + "nameEN": "Light gray glazed terracotta", + "nameZH": "浅灰色带釉陶瓦", + "class": "glazed_terracotta", + "version": 13, + "background": true + }, + "minecraft:silver_glazed_terracotta[facing=north]": { + "nameEN": "Silver glazed hardened clay (1.12)", + "nameZH": "银色带釉硬化粘土 (1.12)", + "class": "glazed_terracotta", + "version": [ + 12 + ], + "background": true + }, + "minecraft:cyan_glazed_terracotta[facing=north]": { + "nameEN": "Cyan glazed terracotta", + "nameZH": "青色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:blue_glazed_terracotta[facing=north]": { + "nameEN": "Blue glazed terracotta", + "nameZH": "蓝色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:brown_glazed_terracotta[facing=north]": { + "nameEN": "Brown glazed terracotta", + "nameZH": "棕色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:red_glazed_terracotta[facing=north]": { + "nameEN": "Red glazed terracotta", + "nameZH": "红色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:black_glazed_terracotta[facing=north]": { + "nameEN": "Black glazed terracotta", + "nameZH": "黑色带釉陶瓦", + "class": "glazed_terracotta", + "version": "all", + "background": true + }, + "minecraft:white_concrete_powder": { + "nameEN": "White concrete powder", + "nameZH": "白色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=white]" + ] + ] + }, + "minecraft:orange_concrete_powder": { + "nameEN": "Orange concrete powder", + "nameZH": "橙色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=orange]" + ] + ] + }, + "minecraft:magenta_concrete_powder": { + "nameEN": "Magenta concrete powder", + "nameZH": "品红色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=magenta]" + ] + ] + }, + "minecraft:light_blue_concrete_powder": { + "nameEN": "Light blue concrete powder", + "nameZH": "浅蓝色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=light_blue]" + ] + ] + }, + "minecraft:yellow_concrete_powder": { + "nameEN": "Yellow concrete powder", + "nameZH": "黄色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=yellow]" + ] + ] + }, + "minecraft:lime_concrete_powder": { + "nameEN": "Lime concrete powder", + "nameZH": "浅绿色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=lime]" + ] + ] + }, + "minecraft:pink_concrete_powder": { + "nameEN": "Pink concrete powder", + "nameZH": "粉色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=pink]" + ] + ] + }, + "minecraft:gray_concrete_powder": { + "nameEN": "Gray concrete powder", + "nameZH": "灰色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=gray]" + ] + ] + }, + "minecraft:light_gray_concrete_powder": { + "nameEN": "Light gray concrete powder", + "nameZH": "浅灰色混凝土粉末", + "class": "concrete_powder", + "version": 13, + "faces": [ + "up", + "north", + "south", + "east", + "west" + ] + }, + "minecraft:silver_concrete_powder": { + "nameEN": "Silver concrete powder (1.12)", + "nameZH": "银色混凝土粉末 (1.12)", + "class": "concrete_powder", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "version": [ + 12 + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=silver]" + ] + ] + }, + "minecraft:cyan_concrete_powder": { + "nameEN": "Cyan concrete powder", + "nameZH": "青色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=cyan]" + ] + ] + }, + "minecraft:blue_concrete_powder": { + "nameEN": "Blue concrete powder", + "nameZH": "蓝色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=blue]" + ] + ] + }, + "minecraft:brown_concrete_powder": { + "nameEN": "Brown concrete powder", + "nameZH": "棕色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=brown]" + ] + ] + }, + "minecraft:red_concrete_powder": { + "nameEN": "Red concrete powder", + "nameZH": "红色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=red]" + ] + ] + }, + "minecraft:black_concrete_powder": { + "nameEN": "Black concrete powder", + "nameZH": "黑色混凝土粉末", + "class": "concrete_powder", + "version": "all", + "faces": [ + "up", + "north", + "south", + "east", + "west" + ], + "id_replace_list": [ + [ + 12, + "minecraft:concrete_powder[color=black]" + ] + ] + }, + "minecraft:bedrock": { + "nameEN": "Bedrock", + "nameZH": "基岩", + "class": "creative_only", + "version": "all", + "reproducible": false, + "rare": true + }, + "minecraft:budding_amethyst": { + "nameEN": "Budding amethyst", + "nameZH": "紫水晶母岩", + "class": "creative_only", + "version": 17, + "reproducible": false, + "rare": true + }, + "minecraft:reinforced_deepslate": { + "nameEN": "Reinforced deepslate", + "nameZH": "强化深板岩", + "class": "creative_only", + "version": 19, + "reproducible": false, + "rare": true + }, + "minecraft:bamboo_planks": { + "nameEN": "Bamboo planks", + "nameZH": "竹板", + "class": "planks", + "version": 20 + } + /*, "minecraft:beacon": { "nameEN": "Beacon", "nameZH": "信标", diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index c15923ca..7455339e 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1260,7 +1260,7 @@ const char *VCL_biome_name_ZH(VCL_biome_t b) noexcept { case VCL_biome_t::end_barrens: return "末地荒地"; case VCL_biome_t::cherry_grove: - return "樱花树林 (1.20)"; + return "樱花树林"; } return "Unamed"; } diff --git a/VisualCraftL/generate_tests.cmake b/VisualCraftL/generate_tests.cmake index 5d849800..db90d73d 100644 --- a/VisualCraftL/generate_tests.cmake +++ b/VisualCraftL/generate_tests.cmake @@ -5,25 +5,25 @@ set(temp_testname_prefix test_block_list) set(list_faces "up" "down" "north" "south" "east" "west") -foreach(_layers RANGE 1 3 1) - foreach(_ver RANGE 12 19) - if(_ver EQUAL 12) +foreach (_layers RANGE 1 3 1) + foreach (_ver RANGE 12 20) + if (_ver EQUAL 12) set(zip_file ${VCL_resource_12}) - else() + else () set(zip_file ${VCL_resource_latest}) - endif() + endif () - foreach(_face ${list_faces}) + foreach (_face ${list_faces}) # message(STATUS ${temp_testname_prefix}_${_ver}_${_face}) set(test_name ${temp_testname_prefix}_${_ver}_${_face}_layer${_layers}) # message(STATUS ${test_name}) add_test(NAME ${test_name} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND test_VCL_blockstate ${CMAKE_CURRENT_SOURCE_DIR}/VCL_blocks_fixed.json ${zip_file} --version ${_ver} --face ${_face} --layers ${_layers}) - endforeach(_face ${list_faces}) - endforeach(_ver RANGE 12 19) -endforeach(_layers RANGE 1 3 1) + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND test_VCL_blockstate ${CMAKE_CURRENT_SOURCE_DIR}/VCL_blocks_fixed.json ${zip_file} --version ${_ver} --face ${_face} --layers ${_layers}) + endforeach (_face ${list_faces}) + endforeach (_ver RANGE 12 20) +endforeach (_layers RANGE 1 3 1) # add_test(NAME test_block_list_01 # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/VisualCraftL/tests/test_VCL_blockstate.cpp b/VisualCraftL/tests/test_VCL_blockstate.cpp index ad3e6a80..54eac48e 100644 --- a/VisualCraftL/tests/test_VCL_blockstate.cpp +++ b/VisualCraftL/tests/test_VCL_blockstate.cpp @@ -31,7 +31,6 @@ This file is part of SlopeCraft. using std::cout, std::endl; int main(int argc, char **argv) { - CLI::App app; std::vector input_files; @@ -45,7 +44,7 @@ int main(int argc, char **argv) { int __version; app.add_option("--version", __version, "MC version.") ->default_val(19) - ->check(CLI::Range(12, 19, "Avaliable versions.")); + ->check(CLI::Range(12, int(max_version), "Avaliable versions.")); int __layers; app.add_option("--layers", __layers, "Max layers") ->default_val(3) @@ -83,7 +82,6 @@ int main(int argc, char **argv) { } { - std::vector zip_filenames, json_filenames; for (const std::string &i : input_files) { @@ -140,7 +138,6 @@ int main(int argc, char **argv) { return 1; } } else { - if (!VCL_set_resource_copy(rp, bsl, option)) { cout << "Failed to set resource pack" << endl; VCL_destroy_block_state_list(bsl); @@ -169,7 +166,6 @@ int main(int argc, char **argv) { return 1; } if (!VCL_set_allowed_blocks(blocks.data(), blocks.size())) { - cout << "VCL_set_allowed_blocks failed." << endl; VCL_destroy_kernel(kernel); diff --git a/VisualCraftL/tests/test_VCL_model.cpp b/VisualCraftL/tests/test_VCL_model.cpp index 79e6fc8a..fd983389 100644 --- a/VisualCraftL/tests/test_VCL_model.cpp +++ b/VisualCraftL/tests/test_VCL_model.cpp @@ -30,7 +30,6 @@ This file is part of SlopeCraft. using std::cout, std::endl; int main(int argc, char **argv) { - CLI::App app; std::vector input_files; @@ -53,7 +52,7 @@ int main(int argc, char **argv) { int __version; app.add_option("--version", __version, "MC version.") ->default_val(19) - ->check(CLI::Range(12, 19, "Avaliable versions.")); + ->check(CLI::Range(12, 20, "Avaliable versions.")); */ /* diff --git a/VisualCraftL/tests/test_VCL_project_image.cpp b/VisualCraftL/tests/test_VCL_project_image.cpp index 35d7978f..c7a149db 100644 --- a/VisualCraftL/tests/test_VCL_project_image.cpp +++ b/VisualCraftL/tests/test_VCL_project_image.cpp @@ -35,7 +35,6 @@ bool rewrite_png(const char *const filename, Eigen::RowMajor> &img) noexcept; int main(int argc, char **argv) { - CLI::App app; std::vector input_files; @@ -57,7 +56,7 @@ int main(int argc, char **argv) { int __version; app.add_option("--version", __version, "MC version.") ->default_val(19) - ->check(CLI::Range(12, 19, "Avaliable versions.")); + ->check(CLI::Range(12, int(max_version), "Avaliable versions.")); /* int __layers; app.add_option("--layers", __layers, "Max layers") diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 0b67e5b8..e125c377 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -56,7 +56,7 @@ enum class SCL_gameVersion : int { FUTURE = 255 }; -const SCL_gameVersion max_version = SCL_gameVersion::MC19; +constexpr SCL_gameVersion max_version = SCL_gameVersion::MC20; /// color difference formula used to match colors enum class SCL_convertAlgo : char { diff --git a/vccl/add_test_vccl.cmake b/vccl/add_test_vccl.cmake index a78bba88..4dc98211 100644 --- a/vccl/add_test_vccl.cmake +++ b/vccl/add_test_vccl.cmake @@ -44,7 +44,7 @@ endif () # set(dither "true" "false") foreach (_layers RANGE 1 3 1) - foreach (_ver RANGE 12 19) + foreach (_ver RANGE 12 20) set(VCL_current_var_name VCL_resource_${mcver}) set(zip_file ${VCL_current_var_name}) @@ -73,7 +73,7 @@ foreach (_layers RANGE 1 3 1) endforeach (_dither ${dither}) endforeach (_algo ${algos}) endforeach (_face ${list_faces}) - endforeach (_ver RANGE 12 19) + endforeach (_ver RANGE 12 20) endforeach (_layers RANGE 1 3 1) From ad2d978abac30cbe849a82efb6ee69b7dd5228e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 15:46:51 +0800 Subject: [PATCH 0461/1123] add 1.20 blocks to VCL --- VisualCraftL/VCL_blocks_fixed.json | 157 ++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 1 deletion(-) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 6d636030..2c8e0890 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -594,6 +594,22 @@ "version": "all", "is_foliage": true }, + "minecraft:mangrove_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "nameEN": "Mangrove leaves", + "nameZH": "红树树叶", + "version": 19, + "is_foliage": true + }, + "minecraft:cherry_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "nameEN": "Cherry leaves", + "nameZH": "樱花树叶", + "version": 20, + "is_foliage": true + }, "minecraft:blue_ice": { "class": "natural", "nameEN": "Blue ice", @@ -3577,7 +3593,146 @@ "nameEN": "Bamboo planks", "nameZH": "竹板", "class": "planks", - "version": 20 + "version": 20, + "burnable": true + }, + "minecraft:cherry_planks": { + "nameEN": "Cherry planks", + "nameZH": "樱花木板", + "class": "planks", + "version": 20, + "burnable": true + }, + "minecraft:bamboo_mosaic": { + "nameEN": "Bamboo mosaic", + "nameZH": "竹马赛克", + "class": "planks", + "version": 20, + "burnable": true + }, + "minecraft:bamboo_block[axis=y]": { + "class": "wood", + "nameEN": "Bamboo block (Y axis)", + "nameZH": "竹块 (Y 轴)", + "version": 20, + "burnable": true + }, + "minecraft:bamboo_block[axis=x]": { + "class": "wood", + "nameEN": "Bamboo block (X axis)", + "nameZH": "竹块 (X 轴)", + "version": 20, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:bamboo_block[axis=z]": { + "class": "wood", + "nameEN": "Bamboo block (Z axis)", + "nameZH": "竹块 (Z 轴)", + "version": 20, + "faces": [ + "north", + "south" + ], + "burnable": true + }, + "minecraft:stripped_bamboo_block[axis=y]": { + "class": "wood", + "nameEN": "Bamboo block (Y axis)", + "nameZH": "去皮竹块 (Y 轴)", + "version": 20, + "burnable": true + }, + "minecraft:stripped_bamboo_block[axis=x]": { + "class": "wood", + "nameEN": "Bamboo block (X axis)", + "nameZH": "去皮竹块 (X 轴)", + "version": 20, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:stripped_bamboo_block[axis=z]": { + "class": "wood", + "nameEN": "Bamboo block (Z axis)", + "nameZH": "去皮竹块 (Z 轴)", + "version": 20, + "faces": [ + "north", + "south" + ], + "burnable": true + }, + "minecraft:cherry_log[axis=y]": { + "class": "wood", + "nameEN": "Cherry log (Y axis)", + "nameZH": "樱花原木 (Y 轴)", + "version": 20, + "burnable": true + }, + "minecraft:cherry_log[axis=x]": { + "class": "wood", + "nameEN": "Cherry log (X axis)", + "nameZH": "樱花原木 (X 轴)", + "version": 20, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:cherry_log[axis=z]": { + "class": "wood", + "nameEN": "Cherry log (Z axis)", + "nameZH": "樱花原木 (Z 轴)", + "version": 20, + "faces": [ + "north", + "south" + ], + "burnable": true + }, + "minecraft:stripped_cherry_log[axis=y]": { + "class": "wood", + "nameEN": "Cherry log (Y axis)", + "nameZH": "去皮樱花原木 (Y 轴)", + "version": 20, + "burnable": true + }, + "minecraft:stripped_cherry_log[axis=x]": { + "class": "wood", + "nameEN": "Cherry log (X axis)", + "nameZH": "去皮樱花原木 (X 轴)", + "version": 20, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:stripped_cherry_log[axis=z]": { + "class": "wood", + "nameEN": "Cherry log (Z axis)", + "nameZH": "去皮樱花原木 (Z 轴)", + "version": 20, + "faces": [ + "north", + "south" + ], + "burnable": true } /*, "minecraft:beacon": { From 98319207192c6367567addf2203d38807f5cd0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 15:51:19 +0800 Subject: [PATCH 0462/1123] fix VCL vanilla zips downloading --- cmake/configure_vanilla_zips.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/configure_vanilla_zips.cmake b/cmake/configure_vanilla_zips.cmake index bf6969b0..c877287d 100644 --- a/cmake/configure_vanilla_zips.cmake +++ b/cmake/configure_vanilla_zips.cmake @@ -8,7 +8,7 @@ set(VCL_zip_names "Vanilla_1_18_2.zip" "Vanilla_1_19_3.zip" "Vanilla_1_20_1.zip") - +#https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/Vanilla_1_20_1.zip set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") foreach (mcver RANGE 12 20) @@ -26,13 +26,14 @@ foreach (mcver RANGE 12 20) message(STATUS "${VCL_current_zip_name} not found. Downloading...") + string(CONCAT VCL_current_download_url ${VCL_url_prefix} ${VCL_current_zip_name}) file(DOWNLOAD - ${VCL_url_prefix} ${VCL_current_zip_name} + ${VCL_current_download_url} ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) if (EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) message(STATUS "Downloaded resoruce pack for MC${mcver}.") else () - message(FATAL_ERROR "Failed to download resource pack for MC${mcver}.") + message(FATAL_ERROR "Failed to download resource pack for MC${mcver} from ${VCL_current_download_url}.") endif () endforeach (mcver RANGE 12 20) \ No newline at end of file From a8b242cc5a0bac581bcb3cfb56affdc2fc457898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 15:53:55 +0800 Subject: [PATCH 0463/1123] rename github actions --- .github/workflows/build-dev-clang.yml | 41 +++++----- .github/workflows/build-dev-gcc.yml | 103 +++++++++++++------------- 2 files changed, 71 insertions(+), 73 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 7a354938..18fbe0b5 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -1,11 +1,10 @@ -name: Build dev version artifacts -on: +name: Beta version built with clang(for windows and macos) +on: pull_request: push: branches: - main - dev - - update-sc-ui jobs: @@ -13,9 +12,9 @@ jobs: runs-on: windows-latest strategy: matrix: - build_type: [Debug, Release] - gpu_api: [None] - vectorize: [true, false] + build_type: [ Debug, Release ] + gpu_api: [ None ] + vectorize: [ true, false ] exclude: - gpu_api: OpenCL vectorize: false @@ -25,12 +24,12 @@ jobs: VECTORIZE: ${{ matrix.vectorize }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | + run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" - name: check clang - run: | + run: | where clang where clang-cl clang --version @@ -54,7 +53,7 @@ jobs: mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty mkdir bin/dependencies - + - name: Build and install zlib run: | $basedir=(pwd).path.replace("\\","/") @@ -69,7 +68,7 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib - + - name: Build and install libzip run: | $basedir=(pwd).path.replace("\\","/") @@ -100,7 +99,7 @@ jobs: - name: Install Eigen3 run: vcpkg install --triplet=x64-windows eigen3 - + - name: Download Qt6.5.0-msvc-shared and extract run: | cmd @@ -108,8 +107,8 @@ jobs: 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z exit tree /f bin/Qt6.5.0-msvc-shared - # Qt installation dir: bin/Qt6.5.0-msvc-shared - + # Qt installation dir: bin/Qt6.5.0-msvc-shared + - name: CMake configure shell: cmd run: | @@ -145,18 +144,18 @@ jobs: - name: Upload 7z pack uses: actions/upload-artifact@v3 - with: + with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z path: pack/SlopeCraft*.7z - if-no-files-found: error + if-no-files-found: error + - macos-build: runs-on: macos-latest strategy: matrix: - build_type: [Debug, Release] - gpu_api: [None] + build_type: [ Debug, Release ] + gpu_api: [ None ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -164,13 +163,13 @@ jobs: - name: brew update run: brew update - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | + run: | echo $BUILD_TYPE echo $GPU_API - name: Install build system run: brew install ninja cmake - name: Install dependencies - run: | + run: | brew install libpng qt@6 eigen brew reinstall libomp - name: Add /usr/local/lib to PATH @@ -194,7 +193,7 @@ jobs: chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl # chmod +x vccl.app/Contents/MacOS/vccl - name: Compress as zip - run: | + run: | cd ./build/install zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index e0567320..fd37043c 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -1,19 +1,18 @@ -name: Build dev version artifacts -on: +name: Beta version built with gcc(for windows, linux and macos) +on: pull_request: push: branches: - main - dev - - update-sc-ui jobs: macos-build: runs-on: macos-latest strategy: matrix: - build_type: [Debug, Release] - gpu_api: [None] + build_type: [ Debug, Release ] + gpu_api: [ None ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -21,13 +20,13 @@ jobs: - name: brew update run: brew update - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | + run: | echo $BUILD_TYPE echo $GPU_API - name: Install Ninja build system run: brew install ninja - name: Install dependencies - run: | + run: | brew install libpng brew install qt@6 - name: Add /usr/local/lib to PATH @@ -51,7 +50,7 @@ jobs: chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl # chmod +x vccl.app/Contents/MacOS/vccl - name: Compress as zip - run: | + run: | cd ./build/install zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* @@ -67,19 +66,19 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - build_type: [Debug, Release] - gpu_api: [None, OpenCL] + build_type: [ Debug, Release ] + gpu_api: [ None, OpenCL ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | + run: | echo $BUILD_TYPE echo $GPU_API - name: apt update run: sudo apt update - + - name: Make directories run: mkdir build install pack @@ -94,14 +93,14 @@ jobs: - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - + - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL sdk if: matrix.gpu_api == 'OpenCL' run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo - + - name: See clinfo if: matrix.gpu_api == 'OpenCL' run: clinfo @@ -114,23 +113,23 @@ jobs: - name: CMake configure run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - + - name: CMake build run: cmake --build ./build --parallel - + - name: CMake install run: cmake --install ./build - + - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - + - name: Make deb and tar.xz packs with cpack - run: | + run: | cd build cpack -G DEB -B ../pack cpack -G TXZ -B ../pack cd .. - + - name: Upload deb pack uses: actions/upload-artifact@v3 with: @@ -153,35 +152,35 @@ jobs: - name: Test deb pack run: sudo dpkg -i ./pack/*.deb - # linux-test-deb: - # runs-on: ubunut-latest - # needs: linux-build - # strategy: - # matrix: - # build_type: [Debug, Release] - # gpu_api: [None, OpenCL] - # steps: - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - # - name: Download deb - # uses: actions/download-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - # - # - name: ls - # run: ls . - # - # - name: Try installing deb - # run: sudo dpkg -i ./*.deb + # linux-test-deb: + # runs-on: ubunut-latest + # needs: linux-build + # strategy: + # matrix: + # build_type: [Debug, Release] + # gpu_api: [None, OpenCL] + # steps: + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Download deb + # uses: actions/download-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + # + # - name: ls + # run: ls . + # + # - name: Try installing deb + # run: sudo dpkg -i ./*.deb windows-build: runs-on: windows-latest strategy: matrix: - build_type: [Debug, Release] - gpu_api: [None] - vectorize: [true, false] + build_type: [ Debug, Release ] + gpu_api: [ None ] + vectorize: [ true, false ] exclude: - gpu_api: OpenCL vectorize: false @@ -191,7 +190,7 @@ jobs: VECTORIZE: ${{ matrix.vectorize }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | + run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" @@ -233,7 +232,7 @@ jobs: mkdir 3rdParty - name: Download mingw64 and extract - run: | + run: | cmd curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" 7z x -obin bin/gcc12.7z @@ -255,7 +254,7 @@ jobs: cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" cmake --build bin/build-zlib --parallel cmake --install bin/build-zlib - + - name: Build and install libzip run: | $basedir=(pwd).path.replace("\\","/") @@ -283,7 +282,7 @@ jobs: cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" cmake --build bin/build-libpng --parallel cmake --install bin/build-libpng - + - name: Download Qt6.4.0-gcc12-shared and extract run: | cmd @@ -302,7 +301,7 @@ jobs: mkdir build mkdir install cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - + - name: CMake build run: | $basedir=(pwd).path.replace("\\","/") @@ -341,10 +340,10 @@ jobs: - name: Upload 7z pack uses: actions/upload-artifact@v3 - with: + with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-gcc-7z path: pack/SlopeCraft*.7z - if-no-files-found: error + if-no-files-found: error #- name: Tree /f @@ -356,7 +355,7 @@ jobs: # path: bin/all_files_on_D.txt # if-no-files-found: error - + #- name: Upload gcc # uses: actions/upload-artifact@v3 From 8f4eaab702f23f66ce508932a777c1444bbf3016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 16:00:35 +0800 Subject: [PATCH 0464/1123] rename github actions --- .github/workflows/build-dev-clang.yml | 4 ++-- .github/workflows/build-dev-gcc.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 18fbe0b5..dc61d2ec 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -195,7 +195,7 @@ jobs: - name: Compress as zip run: | cd ./build/install - zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* + zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -203,4 +203,4 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang - path: build/install/SlopeCraft-5.0.0-macos.zip \ No newline at end of file + path: build/install/SlopeCraft-5.2.0-macos.zip \ No newline at end of file diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index fd37043c..d5a143f8 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -52,7 +52,7 @@ jobs: - name: Compress as zip run: | cd ./build/install - zip -9 -r -y SlopeCraft-5.0.0-macos.zip ./* + zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -60,7 +60,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - path: build/install/SlopeCraft-5.0.0-macos.zip + path: build/install/SlopeCraft-5.2.0-macos.zip linux-build: runs-on: ubuntu-latest From 6cb9befb5224d74ce1bef41591276a425dff1b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 16:00:44 +0800 Subject: [PATCH 0465/1123] update version number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da708d73..72a19251 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.1.0) +set(SlopeCraft_version 5.2.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 9fc355fc8e639650eb44277a105e102caab780ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 16:02:55 +0800 Subject: [PATCH 0466/1123] fix version number --- .github/workflows/build-dev-clang.yml | 4 ++-- .github/workflows/build-dev-gcc.yml | 4 ++-- CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index dc61d2ec..6d0cba62 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -195,7 +195,7 @@ jobs: - name: Compress as zip run: | cd ./build/install - zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* + zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -203,4 +203,4 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang - path: build/install/SlopeCraft-5.2.0-macos.zip \ No newline at end of file + path: build/install/SlopeCraft-5.1.0-macos.zip \ No newline at end of file diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index d5a143f8..3a7f0cb0 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -52,7 +52,7 @@ jobs: - name: Compress as zip run: | cd ./build/install - zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* + zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -60,7 +60,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - path: build/install/SlopeCraft-5.2.0-macos.zip + path: build/install/SlopeCraft-5.1.0-macos.zip linux-build: runs-on: ubuntu-latest diff --git a/CMakeLists.txt b/CMakeLists.txt index 72a19251..da708d73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.0) +set(SlopeCraft_version 5.1.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 6ed4fb20b21c041fd98432dbbf2f5a97640d4c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 16:03:36 +0800 Subject: [PATCH 0467/1123] hide macos build with clang --- .github/workflows/build-dev-clang.yml | 110 +++++++++++++------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 6d0cba62..9e9ccaad 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -1,4 +1,4 @@ -name: Beta version built with clang(for windows and macos) +name: Beta version built with clang(for windows and macos) (macos build is hidden) on: pull_request: push: @@ -150,57 +150,57 @@ jobs: if-no-files-found: error - macos-build: - runs-on: macos-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: brew update - run: brew update - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install build system - run: brew install ninja cmake - - name: Install dependencies - run: | - brew install libpng qt@6 eigen - brew reinstall libomp - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build and Install - run: | - cd build - cmake --build . --parallel - cmake --install . - cd install - chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - chmod +x MapViewer.app/Contents/MacOS/MapViewer - chmod +x imageCutter.app/Contents/MacOS/imageCutter - chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl - # chmod +x vccl.app/Contents/MacOS/vccl - - name: Compress as zip - run: | - cd ./build/install - zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang - path: build/install/SlopeCraft-5.1.0-macos.zip \ No newline at end of file +# macos-build: +# runs-on: macos-latest +# strategy: +# matrix: +# build_type: [ Debug, Release ] +# gpu_api: [ None ] +# env: +# BUILD_TYPE: ${{ matrix.build_type }} +# GPU_API: ${{ matrix.gpu_api }} +# steps: +# - name: brew update +# run: brew update +# - name: echo matrix variables (build_type = ${{ matrix.build_type }}) +# run: | +# echo $BUILD_TYPE +# echo $GPU_API +# - name: Install build system +# run: brew install ninja cmake +# - name: Install dependencies +# run: | +# brew install libpng qt@6 eigen +# brew reinstall libomp +# - name: Add /usr/local/lib to PATH +# run: echo "/usr/local/lib" >> $GITHUB_PATH +# - name: Check PATH +# run: echo $PATH +# - name: Checkout repository +# uses: actions/checkout@v2 +# - name: Configure CMake +# run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar +# - name: Build and Install +# run: | +# cd build +# cmake --build . --parallel +# cmake --install . +# cd install +# chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft +# chmod +x MapViewer.app/Contents/MacOS/MapViewer +# chmod +x imageCutter.app/Contents/MacOS/imageCutter +# chmod +x VisualCraft.app/Contents/MacOS/VisualCraft +# chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl +# # chmod +x vccl.app/Contents/MacOS/vccl +# - name: Compress as zip +# run: | +# cd ./build/install +# zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* +# +# - name: Get short SHA +# run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV +# - name: Upload Artifacts +# uses: actions/upload-artifact@v2 +# with: +# name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang +# path: build/install/SlopeCraft-5.1.0-macos.zip \ No newline at end of file From 2501e3af2ba71ce5859afd219cd7436dbb17fdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 1 Jul 2023 19:08:00 +0800 Subject: [PATCH 0468/1123] Install dll correctly for .lib export libs --- cmake/install.cmake | 65 +++++++++++++++--------------- cmake/install_if_is_shared.cmake | 62 +++++++++++++++------------- cmake/scan_deps_for_lib.cmake | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 59 deletions(-) create mode 100644 cmake/scan_deps_for_lib.cmake diff --git a/cmake/install.cmake b/cmake/install.cmake index c6d9c6bf..b89b1d60 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -1,70 +1,71 @@ set(SlopeCraft_readme_and_license_files - LICENSE - README.md - README-en.md - license-translations/LICENSE-zh.md -) + LICENSE + README.md + README-en.md + license-translations/LICENSE-zh.md + ) include(${CMAKE_SOURCE_DIR}/cmake/add_compiler_path_to_prefix.cmake) -if(${WIN32}) +if (${WIN32}) + include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") function(SlopeCraft_install_dll dllname dest is_required) find_library(dll_file - NAMES ${dllname} - PATHS ${CMAKE_PREFIX_PATH} - NO_CMAKE_INSTALL_PREFIX - NO_CACHE) - - if(NOT dll_file) - find_file(dll_file - NAMES "lib${dllname}.dll" + NAMES ${dllname} PATHS ${CMAKE_PREFIX_PATH} NO_CMAKE_INSTALL_PREFIX NO_CACHE) - endif() - if(NOT dll_file) - if(${is_required}) + if (NOT dll_file) + find_file(dll_file + NAMES "lib${dllname}.dll" + PATHS ${CMAKE_PREFIX_PATH} + NO_CMAKE_INSTALL_PREFIX + NO_CACHE) + endif () + + if (NOT dll_file) + if (${is_required}) message(FATAL_ERROR "Failed to find ${dllname} dll.") - else() + else () message(WARNING "Failed to find ${dllname} dll.") - endif() + endif () return() - endif() + endif () message(STATUS "Install ${dll_file} to ${dest}") install(FILES ${dll_file} - DESTINATION ${dest}) + DESTINATION ${dest}) endfunction(SlopeCraft_install_dll) - if(${MSVC}) + if (${MSVC}) SlopeCraft_install_dll(omp . true) - else() + else () SlopeCraft_install_dll(gomp-1 . true) SlopeCraft_install_dll(stdc++-6 . true) SlopeCraft_install_dll(gcc_s_seh-1 . true) SlopeCraft_install_dll(winpthread-1 . true) - endif() + endif () return() -endif() +endif () -if(${LINUX}) +if (${LINUX}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) return() -endif() +endif () -if(${APPLE}) +if (${APPLE}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) return() -endif() +endif () message(WARNING "No rule to install readme and license files. Unknown system name.") \ No newline at end of file diff --git a/cmake/install_if_is_shared.cmake b/cmake/install_if_is_shared.cmake index a9ee153a..97393065 100644 --- a/cmake/install_if_is_shared.cmake +++ b/cmake/install_if_is_shared.cmake @@ -1,8 +1,23 @@ +if (${WIN32}) + include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) +endif () + function(SlopeCraft_install_lib lib_location dest) cmake_path(GET lib_location EXTENSION extension) + if (extension STREQUAL ".dll") + message(STATUS "Install ${lib_location} to ${dest}") + install(FILES ${lib_location} + DESTINATION ${dest}) + return() + endif () + # message(STATUS "extension of ${lib_location} is ${extension}") - if((extension MATCHES ".dll.a") OR(extension MATCHES ".dll.lib")) + is_export_library(${lib_location} is_export) + message(STATUS "is_export = ${is_export}") + + if (${is_export}) + message(STATUS "${lib_location} is a export library") cmake_path(GET lib_location STEM lib_stem) # message(STATUS "lib_stem = ${lib_stem}") @@ -21,40 +36,33 @@ function(SlopeCraft_install_lib lib_location dest) # PATH_SUFFIXES bin # NO_CACHE) find_library(dll_location - NAMES lib_stem - PATHS ${search_dir} - PATH_SUFFIXES bin - NO_CACHE) + NAMES lib_stem + PATHS ${search_dir} + PATH_SUFFIXES bin + NO_CACHE) - if(NOT dll_location) + if (NOT dll_location) # message(STATUS "find_library failed to find ${dll_name}, retry with file GLOB") file(GLOB dll_location "${search_dir}/bin/${lib_stem}*.dll") list(LENGTH dll_location len) - if(len LESS_EQUAL 0) + if (len LESS_EQUAL 0) message(FATAL_ERROR "Trying to install dll of ${lib_location}, but failed to find ${dll_name}. The released package may failed to find this dll.") return() - endif() - endif() + endif () + endif () SlopeCraft_install_lib(${dll_location} ${dest}) return() - endif() - - if(extension MATCHES ".dll") - message(STATUS "Install ${lib_location} to ${dest}") - install(FILES ${lib_location} - DESTINATION ${dest}) - return() - endif() + endif () - if((extension MATCHES ".a") OR(extension MATCHES ".lib")) + if ((extension MATCHES ".a") OR (extension MATCHES ".lib")) message(STATUS "\"${lib_location}\" is a static library, skip installation of it.") return() - endif() + endif () message(FATAL_ERROR "Unknown library extension: ${extension}") endfunction(SlopeCraft_install_lib) @@ -74,22 +82,22 @@ function(SlopeCraft_install_if_is_shared target dest) # message(STATUS "Location of ${target} is : ${target_location}") set(skip_this false) - if(${target_type} STREQUAL EXECUTABLE) + if (${target_type} STREQUAL EXECUTABLE) set(skip_this true) - endif() + endif () - if(${target_type} STREQUAL STATIC_LIBRARY) + if (${target_type} STREQUAL STATIC_LIBRARY) set(skip_this true) - endif() + endif () - if(${target_type} STREQUAL OBJECT_LIBRARY) + if (${target_type} STREQUAL OBJECT_LIBRARY) set(skip_this true) - endif() + endif () - if(${skip_this}) + if (${skip_this}) message(STATUS "Skip installing ${target} because it is not a shared lib. TYPE = ${target_type}") return() - endif() + endif () SlopeCraft_install_lib(${target_location} ${dest}) endfunction(SlopeCraft_install_if_is_shared) \ No newline at end of file diff --git a/cmake/scan_deps_for_lib.cmake b/cmake/scan_deps_for_lib.cmake new file mode 100644 index 00000000..b99408ed --- /dev/null +++ b/cmake/scan_deps_for_lib.cmake @@ -0,0 +1,69 @@ +if (NOT ${WIN32}) + message(FATAL_ERROR "This cmake script is included with incorrect system, expected windows.") +endif () + + +find_file(SC_MSVC_lib_exe lib.exe) + + +function(scan_deps_of_msvc_lib_file lib_file_name dest_depend_files) + + if (NOT SC_MSVC_lib_exe) + message(FATAL_ERROR "You are using msvc-like compiler on windows, but cmake failed to find lib.exe of visual studio.") + endif () + + + execute_process(COMMAND ${SC_MSVC_lib_exe} /list ${lib_file_name} + OUTPUT_VARIABLE MSVC_lib_output COMMAND_ERROR_IS_FATAL ANY) + + #message(STATUS "output of ${lib_file_name} is : ${MSVC_lib_output}") + string(REPLACE "\n" ";" MSVC_lib_output ${MSVC_lib_output}) + set(temp) + foreach (item ${MSVC_lib_output}) + if ((${item} MATCHES "Microsoft") OR (${item} MATCHES "Copyright")) + message(STATUS "Filter out ${item}") + continue() + endif () + list(APPEND temp ${item}) + endforeach () + + set(${dest_depend_files} ${temp} PARENT_SCOPE) +endfunction() + +function(is_export_library lib_file_name dest_is_export_lib) + + + if ((${lib_file_name} MATCHES ".dll.a")) + message(STATUS "${lib_file_name} is a export lib.") + set({dest_is_export_lib} ON PARENT_SCOPE) + return() + endif () + + cmake_path(GET lib_file_name EXTENSION extension) + + if ((${extension} STREQUAL ".a") OR (${extension} STREQUAL ".obj") OR (${extension} STREQUAL ".o") OR (${extension} STREQUAL ".dll")) + message(STATUS "${lib_file_name} is a static or dynamic lib or a object.") + set({dest_is_export_lib} OFF PARENT_SCOPE) + return() + endif () + + if (NOT ${extension} STREQUAL ".lib") + message(FATAL_ERROR "Failed to deduce library type of ${lib_file_name}") + endif () + + scan_deps_of_msvc_lib_file(${lib_file_name} dep_list) + message(STATUS "dep_list = ${dep_list}") + + foreach (dep_file ${dep_list}) + message("dep_file = ${dep_file}") + if (${dep_file} MATCHES ".dll") + message(STATUS "${lib_file_name} is a export lib.") + set(${dest_is_export_lib} ON PARENT_SCOPE) + return() + endif () + endforeach () + message(STATUS "${lib_file_name} is a static lib.") + set(${dest_is_export_lib} OFF PARENT_SCOPE) + + +endfunction() \ No newline at end of file From b662a27739d1856ebd5d41ef4ccfd71aeeafb4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 2 Jul 2023 00:36:48 +0800 Subject: [PATCH 0469/1123] add preset parsing and saving to VCL --- VisualCraftL/VCL_internal.h | 5 +- VisualCraftL/VisualCraftL.cpp | 154 ++++++++++++++++++++++++ VisualCraftL/VisualCraftL.h | 107 +++++++++------- VisualCraftL/others/VisualCraftL.def.in | 16 ++- 4 files changed, 236 insertions(+), 46 deletions(-) diff --git a/VisualCraftL/VCL_internal.h b/VisualCraftL/VCL_internal.h index 392e26a2..b4e70e86 100644 --- a/VisualCraftL/VCL_internal.h +++ b/VisualCraftL/VCL_internal.h @@ -29,4 +29,7 @@ This file is part of SlopeCraft. void VCL_report(VCL_report_type_t, const char *, bool flush = false) noexcept; -#endif // SLOPECRAFT_VISUALCRAFTL_VCL_INTERNAL_H \ No newline at end of file +void write_to_string_deliver(std::string_view sv, + VCL_string_deliver *strp) noexcept; + +#endif // SLOPECRAFT_VISUALCRAFTL_VCL_INTERNAL_H \ No newline at end of file diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 7455339e..09da1306 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1416,4 +1416,158 @@ VCL_EXPORT_FUN uint32_t VCL_locate_colormap(const VCL_resource_pack *rp, } return rp->standard_color(info, !is_grass); +} + +class VCL_preset { + public: + std::unordered_set ids; + std::unordered_set classes; +}; + +void write_to_string_deliver(std::string_view sv, + VCL_string_deliver *strp) noexcept { + if (strp == nullptr) { + return; + } + if (strp->data == nullptr || strp->capacity <= 0) { + return; + } + + const size_t written_bytes = std::min(sv.size(), strp->capacity - 1); + memcpy(strp->data, sv.data(), written_bytes); + strp->size = written_bytes; + strp->data[strp->capacity - 1] = '\0'; +} + +#include +#include +using njson = nlohmann::json; + +VCL_EXPORT VCL_preset *VCL_create_preset() { return new VCL_preset{}; } +VCL_EXPORT VCL_preset *VCL_load_preset(const char *filename, + VCL_string_deliver *error) { + write_to_string_deliver("", error); + njson block_ids; + njson block_classes; + try { + std::ifstream ifs{filename}; + auto nj = njson::parse(ifs, nullptr, true, true); + block_ids = std::move(nj.at("block_ids")); + block_classes = std::move(nj.at("block_classes")); + } catch (std::exception &e) { + auto err = fmt::format("Exception occurred when parsing {}, detail: {}", + filename, e.what()); + write_to_string_deliver(err, error); + return nullptr; + } + + VCL_preset *p = new VCL_preset{}; + p->ids.reserve(block_ids.size()); + + for (auto &pair : block_ids.items()) { + p->ids.emplace(std::move(pair.key())); + } + for (auto &pair : block_classes.items()) { + auto cls = magic_enum::enum_cast(pair.key()); + if (!cls.has_value()) { + auto err = fmt::format( + "Invalid block class \"{}\" can not be converted to " + "VCL_block_class_t", + pair.key()); + write_to_string_deliver(err, error); + delete p; + return nullptr; + } + p->classes.emplace(cls.value()); + } + return p; +} + +VCL_EXPORT bool VCL_save_preset(const VCL_preset *p, const char *filename, + VCL_string_deliver *error) { + write_to_string_deliver("", error); + njson nj; + { + njson classes, ids; + for (const auto &id : p->ids) { + ids.emplace(id, njson::object_t{}); + } + for (const auto cls : p->classes) { + classes.emplace(magic_enum::enum_name(cls), njson::object_t{}); + } + nj.emplace("block_ids", std::move(ids)); + nj.emplace("block_classes", std::move(classes)); + } + + std::ofstream ofs{filename}; + if (!ofs) { + write_to_string_deliver(fmt::format("Failed to open/create {}", filename), + error); + return false; + } + ofs << nj.dump(2); + ofs.close(); + return true; +} + +VCL_EXPORT void VCL_destroy_preset(VCL_preset *p) { delete p; } + +VCL_EXPORT bool VCL_preset_contains_id(const VCL_preset *p, const char *id) { + return p->ids.contains(id); +} + +VCL_EXPORT void VCL_preset_emplace_id(VCL_preset *p, const char *id) { + p->ids.emplace(id); +} + +VCL_EXPORT bool VCL_preset_contains_class(const VCL_preset *p, + VCL_block_class_t cls) { + return p->classes.contains(cls); +} + +VCL_EXPORT void VCL_preset_emplace_class(VCL_preset *p, VCL_block_class_t cls) { + p->classes.emplace(cls); +} + +VCL_EXPORT void VCL_preset_clear(VCL_preset *p) { + p->ids.clear(); + p->classes.clear(); +} + +VCL_EXPORT size_t VCL_preset_num_ids(const VCL_preset *p) { + return p->ids.size(); +} + +VCL_EXPORT size_t VCL_preset_get_ids(const VCL_preset *p, const char **id_dest, + size_t capacity) { + size_t written_num{0}; + + for (const auto &pair : p->ids) { + if (capacity <= written_num) { + break; + } + + id_dest[written_num] = pair.c_str(); + written_num++; + } + return written_num; +} + +VCL_EXPORT size_t VCL_preset_num_classes(const VCL_preset *p) { + return p->classes.size(); +} + +VCL_EXPORT size_t VCL_preset_get_classes(const VCL_preset *p, + VCL_block_class_t *class_dest, + size_t capacity) { + size_t written_num{0}; + for (const auto cls : p->classes) { + if (capacity <= written_num) { + break; + } + + class_dest[written_num] = cls; + written_num++; + } + return written_num; } \ No newline at end of file diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index cade947b..e4d11ced 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -177,6 +177,12 @@ enum class VCL_upper_direction_t : uint8_t { }; */ +struct VCL_string_deliver { + char *data{nullptr}; + size_t size{0}; + size_t capacity{0}; +}; + class VCL_Kernel; class VCL_resource_pack; class VCL_block_state_list; @@ -187,7 +193,7 @@ class VCL_GPU_Platform; class VCL_GPU_Device; class VCL_Kernel { -public: + public: VCL_Kernel() = default; virtual ~VCL_Kernel() = default; @@ -217,9 +223,9 @@ class VCL_Kernel { virtual int64_t cols() const noexcept = 0; // virtual int64_t layers() const noexcept = 0; - virtual const uint32_t * - raw_image(int64_t *const rows, int64_t *const cols, - bool *const is_row_major) const noexcept = 0; + virtual const uint32_t *raw_image( + int64_t *const rows, int64_t *const cols, + bool *const is_row_major) const noexcept = 0; //////////////////////////////////////////////////////////////////////// virtual bool convert(::SCL_convertAlgo algo, @@ -233,8 +239,8 @@ class VCL_Kernel { // [row_start,row_end) * [o,col_count) will be written int64_t row_start; int64_t row_end; - int32_t split_line_row_margin; // 0 or negative number means no split lines - int32_t split_line_col_margin; // 0 or negative number means no split lines + int32_t split_line_row_margin; // 0 or negative number means no split lines + int32_t split_line_col_margin; // 0 or negative number means no split lines int png_compress_level{9}; int png_compress_memory_level{8}; }; @@ -281,18 +287,16 @@ extern "C" { VCL_EXPORT_FUN void VCL_destroy_kernel(VCL_Kernel *const ptr); // create and destroy resource pack -[[nodiscard]] VCL_EXPORT_FUN VCL_resource_pack * -VCL_create_resource_pack(const int zip_file_count, - const char *const *const zip_file_names); +[[nodiscard]] VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( + const int zip_file_count, const char *const *const zip_file_names); VCL_EXPORT_FUN void VCL_destroy_resource_pack(VCL_resource_pack *const ptr); // create and destroy block state list -[[nodiscard]] VCL_EXPORT_FUN VCL_block_state_list * -VCL_create_block_state_list(const int file_count, - const char *const *const json_file_names); +[[nodiscard]] VCL_EXPORT_FUN VCL_block_state_list *VCL_create_block_state_list( + const int file_count, const char *const *const json_file_names); -VCL_EXPORT_FUN void -VCL_destroy_block_state_list(VCL_block_state_list *const ptr); +VCL_EXPORT_FUN void VCL_destroy_block_state_list( + VCL_block_state_list *const ptr); struct VCL_set_resource_option { const uint64_t lib_version{SC_VERSION_U64}; @@ -303,21 +307,18 @@ struct VCL_set_resource_option { bool is_render_quality_fast; }; -VCL_EXPORT_FUN double -VCL_estimate_color_num(size_t num_layers, size_t num_foreground, - size_t num_background, - size_t num_nontransparent_non_background); +VCL_EXPORT_FUN double VCL_estimate_color_num( + size_t num_layers, size_t num_foreground, size_t num_background, + size_t num_nontransparent_non_background); // set resource for kernel -VCL_EXPORT_FUN bool -VCL_set_resource_copy(const VCL_resource_pack *const rp, - const VCL_block_state_list *const bsl, - const VCL_set_resource_option &option); +VCL_EXPORT_FUN bool VCL_set_resource_copy( + const VCL_resource_pack *const rp, const VCL_block_state_list *const bsl, + const VCL_set_resource_option &option); -VCL_EXPORT_FUN bool -VCL_set_resource_move(VCL_resource_pack **rp_ptr, - VCL_block_state_list **bsl_ptr, - const VCL_set_resource_option &option); +VCL_EXPORT_FUN bool VCL_set_resource_move( + VCL_resource_pack **rp_ptr, VCL_block_state_list **bsl_ptr, + const VCL_set_resource_option &option); VCL_EXPORT_FUN void VCL_discard_resource(); @@ -332,15 +333,13 @@ VCL_EXPORT_FUN size_t VCL_num_basic_colors(); /** \returns the number of blocks of this color. */ -VCL_EXPORT_FUN int -VCL_get_basic_color_composition(size_t color_idx, - const VCL_block **const blocks_dest = nullptr, - uint32_t *const color_dest = nullptr); +VCL_EXPORT_FUN int VCL_get_basic_color_composition( + size_t color_idx, const VCL_block **const blocks_dest = nullptr, + uint32_t *const color_dest = nullptr); // set allowed blocks for kernel -VCL_EXPORT_FUN bool -VCL_set_allowed_blocks(const VCL_block *const *const blocks_allowed, - size_t num_block_allowed); +VCL_EXPORT_FUN bool VCL_set_allowed_blocks( + const VCL_block *const *const blocks_allowed, size_t num_block_allowed); VCL_EXPORT_FUN void VCL_discard_allowed_blocks(); VCL_EXPORT_FUN bool VCL_is_allowed_colorset_ok(); @@ -425,12 +424,11 @@ VCL_EXPORT_FUN bool VCL_compare_block(const VCL_block *b1, const VCL_block *b2); VCL_EXPORT_FUN VCL_block_class_t VCL_string_to_block_class(const char *str, bool *ok = nullptr); -[[nodiscard]] VCL_EXPORT_FUN VCL_model * -VCL_get_block_model(const VCL_block *block, - const VCL_resource_pack *resource_pack); +[[nodiscard]] VCL_EXPORT_FUN VCL_model *VCL_get_block_model( + const VCL_block *block, const VCL_resource_pack *resource_pack); -[[nodiscard]] VCL_EXPORT_FUN VCL_model * -VCL_get_block_model_by_name(const VCL_resource_pack *, const char *name); +[[nodiscard]] VCL_EXPORT_FUN VCL_model *VCL_get_block_model_by_name( + const VCL_resource_pack *, const char *name); VCL_EXPORT_FUN void VCL_destroy_block_model(VCL_model *); @@ -463,8 +461,8 @@ i = if other values, the function will return INT_MIN. */ VCL_EXPORT_FUN int VCL_version_component(int i); -VCL_EXPORT_FUN bool -VCL_is_version_ok(uint64_t version_at_caller_s_build_time = SC_VERSION_U64); +VCL_EXPORT_FUN bool VCL_is_version_ok( + uint64_t version_at_caller_s_build_time = SC_VERSION_U64); VCL_EXPORT_FUN bool VCL_have_gpu_api(); VCL_EXPORT_FUN const char *VCL_get_GPU_api_name(); @@ -476,9 +474,8 @@ VCL_EXPORT_FUN void VCL_release_platform(VCL_GPU_Platform *); VCL_EXPORT_FUN const char *VCL_get_platform_name(const VCL_GPU_Platform *); VCL_EXPORT_FUN size_t VCL_get_device_num(const VCL_GPU_Platform *); -[[nodiscard]] VCL_EXPORT_FUN VCL_GPU_Device * -VCL_get_device(const VCL_GPU_Platform *, size_t device_idx, - int *errorcode = nullptr); +[[nodiscard]] VCL_EXPORT_FUN VCL_GPU_Device *VCL_get_device( + const VCL_GPU_Platform *, size_t device_idx, int *errorcode = nullptr); VCL_EXPORT_FUN void VCL_release_device(VCL_GPU_Device *); VCL_EXPORT_FUN const char *VCL_get_device_name(const VCL_GPU_Device *); @@ -493,6 +490,28 @@ VCL_EXPORT_FUN const char *VCL_biome_name(VCL_biome_t, uint8_t is_ZH); VCL_EXPORT_FUN uint32_t VCL_locate_colormap(const VCL_resource_pack *, bool is_grass, VCL_biome_info info, int *row, int *col); + +class VCL_preset; + +VCL_EXPORT VCL_preset *VCL_create_preset(); +VCL_EXPORT VCL_preset *VCL_load_preset(const char *filename, + VCL_string_deliver *error); +VCL_EXPORT bool VCL_save_preset(const VCL_preset *, const char *filename, + VCL_string_deliver *error); +VCL_EXPORT void VCL_destroy_preset(VCL_preset *); +VCL_EXPORT bool VCL_preset_contains_id(const VCL_preset *, const char *id); +VCL_EXPORT void VCL_preset_emplace_id(VCL_preset *, const char *id); +VCL_EXPORT bool VCL_preset_contains_class(const VCL_preset *, + VCL_block_class_t); +VCL_EXPORT void VCL_preset_emplace_class(VCL_preset *, VCL_block_class_t); +VCL_EXPORT size_t VCL_preset_num_ids(const VCL_preset *p); +VCL_EXPORT size_t VCL_preset_get_ids(const VCL_preset *p, const char **id_dest, + size_t capacity); +VCL_EXPORT size_t VCL_preset_num_classes(const VCL_preset *p); +VCL_EXPORT size_t VCL_preset_get_classes(const VCL_preset *p, + VCL_block_class_t *class_dest, + size_t capacity); +VCL_EXPORT void VCL_preset_clear(VCL_preset *); } -#endif // SLOPECRAFT_VISUALCRAFT_VISUALCRAFT_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_VISUALCRAFT_H \ No newline at end of file diff --git a/VisualCraftL/others/VisualCraftL.def.in b/VisualCraftL/others/VisualCraftL.def.in index f688ed3c..3c31f2ba 100644 --- a/VisualCraftL/others/VisualCraftL.def.in +++ b/VisualCraftL/others/VisualCraftL.def.in @@ -66,4 +66,18 @@ VCL_release_device VCL_get_device_name VCL_get_biome_info VCL_biome_name -VCL_locate_colormap \ No newline at end of file +VCL_locate_colormap +VCL_create_preset +VCL_load_preset +VCL_save_preset +VCL_destroy_preset +VCL_preset_contains_id +VCL_preset_emplace_id +VCL_preset_contains_class +VCL_preset_emplace_class +VCL_preset_num_ids +VCL_preset_get_ids +VCL_preset_num_classes +VCL_preset_get_classes +VCL_preset_clear + From 5438354e66f3645e04a1f1756c18144df0740f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 2 Jul 2023 00:37:04 +0800 Subject: [PATCH 0470/1123] add preset parsing and saving to VC --- VisualCraft/VCWind.h | 7 ++ VisualCraft/VCWind.ui | 79 +++++++++++++++-------- VisualCraft/VCWind_select.cpp | 117 +++++++++++++++++++++++++++++++++- 3 files changed, 174 insertions(+), 29 deletions(-) diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index 49d745c9..9f51c6c5 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -192,6 +192,9 @@ class VCWind : public QMainWindow { void flush_export_tabel() noexcept; + [[nodiscard]] std::unordered_map + id_blockclass_map() noexcept; + static constexpr int export_col_filename = 0; static constexpr int export_col_imagesize = 1; static constexpr int export_col_lite = 2; @@ -267,8 +270,12 @@ class VCWind : public QMainWindow { // auto connected void on_pb_custom_select_clicked() noexcept; + void on_pb_load_preset_clicked() noexcept; + void on_pb_save_preset_clicked() noexcept; + // manually connected void setup_block_widgets() noexcept; + // void when_allowed_colorset_changed() noexcept; // for page 2 ------------------------------------------ diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 1f74e331..1c998ac5 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -10,7 +10,7 @@ 0 0 1057 - 476 + 479 @@ -337,33 +337,6 @@ 方块列表 - - - - 全部方块 - - - - - - true - - - - - 0 - 0 - 885 - 302 - - - - - - - - - @@ -435,6 +408,56 @@ + + + + 预设 + + + + + + 加载预设 + + + + + + + 保存当前预设 + + + + + + + + + + 全部方块 + + + + + + true + + + + + 0 + 0 + 885 + 305 + + + + + + + + + diff --git a/VisualCraft/VCWind_select.cpp b/VisualCraft/VCWind_select.cpp index 5fdbaf21..687f286f 100644 --- a/VisualCraft/VCWind_select.cpp +++ b/VisualCraft/VCWind_select.cpp @@ -23,10 +23,11 @@ This file is part of SlopeCraft. #include "VCWind.h" #include "VC_block_class.h" #include "ui_VCWind.h" +#include +#include void VCWind::apply_selection( std::function selector) noexcept { - for (auto &blk_class : this->map_VC_block_class) { for (auto &blk_pair : blk_class.second->blocks_vector()) { selector(blk_pair.first, blk_pair.second); @@ -107,4 +108,118 @@ void VCWind::on_pb_invselect_blockwise_clicked() noexcept { this->apply_selection([](const VCL_block *, QCheckBox *cb) { cb->setChecked(!cb->isChecked()); }); +} + +[[nodiscard]] std::unordered_map +VCWind::id_blockclass_map() noexcept { + std::unordered_map ret; + for (auto &blk_class_pair : this->map_VC_block_class) { + for (auto &blk : blk_class_pair.second->blocks_vector()) { + ret.emplace(VCL_get_block_id(blk.first), blk.second); + } + } + + return ret; +} + +void VCWind::on_pb_load_preset_clicked() noexcept { + static QString prev_dir{""}; + QString preset_file = QFileDialog::getOpenFileName(this, tr("选择预设文件"), + prev_dir, "*.vc_preset"); + if (preset_file.isEmpty()) { + return; + } + prev_dir = QFileInfo{preset_file}.dir().absolutePath(); + + std::string err; + err.resize(8192); + VCL_string_deliver vsd{err.data(), err.size(), err.size()}; + auto preset = VCL_load_preset(preset_file.toLocal8Bit().data(), &vsd); + err.resize(vsd.size); + + if (preset == nullptr) { + QMessageBox::warning( + this, tr("加载预设失败"), + tr("无法解析预设文件,详细信息:\n%1").arg(err.data()), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok}); + return; + } + + for (auto &cls : this->map_VC_block_class) { + const bool enable = VCL_preset_contains_class(preset, cls.first); + cls.second->chbox_enabled()->setChecked(enable); + } + // select ids + { + std::vector ids; + ids.resize(VCL_preset_num_ids(preset)); + { + const size_t num = VCL_preset_get_ids(preset, ids.data(), ids.size()); + ids.resize(num); + } + + auto id_blk_mapping = this->id_blockclass_map(); + for (auto &pair : id_blk_mapping) { + pair.second->setChecked(false); + } + for (auto id : ids) { + auto it = id_blk_mapping.find(id); + if (it == id_blk_mapping.end()) { + auto ret = QMessageBox::warning( + this, tr("无法加载预设"), + tr("预设中包含%1,但可用方块中没有 id 相同的方块。点击 Ignore " + "以跳过这个方块,点击 Close 终止此次操作。"), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, + QMessageBox::StandardButton::Close); + if (ret == QMessageBox::StandardButton::Close) { + VCL_destroy_preset(preset); + return; + } + continue; + } + it->second->setChecked(true); + } + } + + VCL_destroy_preset(preset); +} + +void VCWind::on_pb_save_preset_clicked() noexcept { + static QString prev_dir{""}; + QString preset_file = QFileDialog::getSaveFileName(this, tr("选择预设文件"), + prev_dir, "*.vc_preset"); + if (preset_file.isEmpty()) { + return; + } + prev_dir = QFileInfo{preset_file}.dir().absolutePath(); + + VCL_preset *preset = VCL_create_preset(); + + for (const auto &it : this->map_VC_block_class) { + if (it.second->chbox_enabled()->isChecked()) { + VCL_preset_emplace_class(preset, it.first); + } + for (const auto &jt : it.second->blocks_vector()) { + if (jt.second->isChecked()) { + VCL_preset_emplace_id(preset, VCL_get_block_id(jt.first)); + } + } + } + + std::string err; + err.resize(8192); + VCL_string_deliver vsd{err.data(), err.size(), err.size()}; + const bool ok = + VCL_save_preset(preset, preset_file.toLocal8Bit().data(), &vsd); + err.resize(vsd.size); + + if (!ok) { + QMessageBox::warning( + this, tr("保存预设文件失败"), + tr("无法保存预设文件,详细信息:\n%1").arg(err.c_str())); + VCL_destroy_preset(preset); + return; + } + + VCL_destroy_preset(preset); } \ No newline at end of file From 7f4856b6a321b1b4dfa18d8f16f617b8277bbc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 5 Jul 2023 13:11:32 +0800 Subject: [PATCH 0471/1123] export testing schem in VC --- VisualCraft/VCWind.cpp | 1 + VisualCraft/VCWind.h | 1 + VisualCraft/VCWind_export.cpp | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 33c5b644..7c2dc127 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -552,6 +552,7 @@ void VCWind::update_hash_allowed(const allowed_colorset_option &opt) noexcept { void VCWind::setup_allowed_colorset() noexcept { this->setup_basical_colorset(); + this->ui->ac_export_test_schem->setEnabled(true); allowed_colorset_option cur_option; if (VCL_is_allowed_colorset_ok() && diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index 9f51c6c5..ee2d30c2 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -221,6 +221,7 @@ class VCWind : public QMainWindow { // for all pages ------------------------------------------ void on_ac_flush_warnings_triggered() noexcept; + void on_ac_export_test_schem_triggered() noexcept; // auto connected void on_tabWidget_main_currentChanged(int page) noexcept; diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 1b92b66b..4819c184 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -486,4 +486,20 @@ void VCWind::on_pb_execute_clicked() noexcept { for (auto &pair : this->image_cache) { this->setup_image(pair.second.first); } +} + +void VCWind::on_ac_export_test_schem_triggered() noexcept { + static QString prev_dir{""}; + QString file = QFileDialog::getSaveFileName( + this, tr("保存测试投影"), prev_dir, "*.litematic;;*.nbt;;*.schem"); + if (file.isEmpty()) { + return; + } + prev_dir = QFileInfo{file}.dir().absolutePath(); + + bool ok = VCL_export_test_litematic(file.toLocal8Bit().data()); + if (!ok) { + QMessageBox::warning(this, tr("无法输出测试投影"), + tr("详细错误信息在之前的窗口中")); + } } \ No newline at end of file From c7e4d8857b50eff1f19ae4a5bf7548f498680bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 5 Jul 2023 13:41:09 +0800 Subject: [PATCH 0472/1123] improve gpu-related error message --- VisualCraft/VCWind.ui | 6 +++--- VisualCraft/VCWind_gpu.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 1c998ac5..7152960b 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -140,7 +140,7 @@ - 1.20 + 1.20 @@ -447,8 +447,8 @@ 0 0 - 885 - 305 + 98 + 28 diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index 2dd5898b..6ab9801c 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -184,11 +184,14 @@ void VCWind::on_combobox_select_device_currentIndexChanged(int idx) noexcept { if (!err.isEmpty()) { auto ret = QMessageBox::critical( - this, VCWind::tr("设置计算设备失败"), err, + this, VCWind::tr("设置计算设备失败"), + tr("%1\n\n这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU " + "计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft") + .arg(err), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); if (ret == QMessageBox::StandardButton::Close) { - abort(); + exit(1); } } } From 8aae9a66649c40e95988c9723e41092c6f766fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 5 Jul 2023 13:41:25 +0800 Subject: [PATCH 0473/1123] update translations --- SlopeCraft/others/SlopeCraft_en_US.ts | 1204 +---------------------- VisualCraft/others/VisualCraft_en_US.ts | 349 ++++--- imageCutter/imageCutter_en_US.ts | 4 - 3 files changed, 246 insertions(+), 1311 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 14b35a27..4e78bef1 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -9,1034 +9,90 @@ Set AiConverter parameters - 允许提前收敛 - Enable fail times - - - - 最大提前收敛代数: - Max fail times : - - - - 交叉概率: - Crossover prob : - - - - 种群数量: - Population size : - - - - 最大进化代数: - Max generation : - - - - 变异概率: - Mutation prob : - - - - BatchUi - - SlopeCraft批量操作 - SlopeCraft batch operation - - - 开始执行 - Start - - - 导出格式 - Export format - - - Litematica投影文件 - Litematica - - - 原版结构方块文件 - Vanilla structure - - - 地图文件 - Map data files - - - 地图文件输出位置 - Map data files directory - - - 浏览 - Browse - - - 选择输出文件夹 - Select a directory - - - 目标文件夹不可用 - Invalid directory - - - 主窗体中选择了纯文件地图画,冲突 - Confilction : you assigned file-only maps in main window - - - 就绪 - Ready - - - 批量处理中: - Batch operation working ...... - - - 正在转化为地图画 - Converting image to map - - - 正在构建三维结构 - Building 3D structure - - - 正在导出三维结构 - Exporting 3D structure - - - 正在导出地图文件 - Exporting map data files - - - 批量处理完成 - All tasks finished - - - - CompressEffectViewer - - - 预览压缩效果 - Compress effect - - - - 保存图像 - - - - - 保存压缩后图片 - - - - - 保存图像失败 - Failed to save image - - - - 无法保存图像 %1 - - - - - ExportTableModel - - - 原图文件名 - Image file - - - - 图像大小 - Image size - - - - 地图大小 - Map size - - - - 地图序号范围 - Map index range - - - - 第一个地图文件名 - First map - - - - 最后一个地图文件名 - Last map - - - - MainWindow - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">地图画</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">Map Arts</span></p></body></html> - - - 开始 - Start - - - 导入图片 - Import image - - - 地图画类型 - Type of map - - - 方块列表 - Block List - - - 调整颜色 - Convert to Map - - - 导出为 - Export - - - 投影文件 - Litematic - - - 地图文件 - Map data files - - - 结构文件 - Structure - - - 完成 - Finish - - - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">联系作者</span></p></body></html> - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">Contact Us</span></p></body></html> - - - 反馈Bug - Report bugs - - - 创建平板地图画 - Create Flat Map - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">传统的地图画样式</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Traditional 2D map pixel art</span></p></body></html> - - - 创建立体地图画 - Create 3D Map - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">原版生存的最高画质</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Best quality in vanilla survival</span></p></body></html> - - - 创建纯文件地图画 - Create File-only Map - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Highest quality, but requires to edit saves.</span></p></body></html> - - - 设置 - Settings - - - 下一步 - Next - - - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - <html><head/><body><p>Step 1,click the load Image button, choose the image you want to make into map.</p><p>The size of image should be multiple of 128 pixels.</p><p></p><p></p><p>Provided that you want to build it, don't choose a large image. 128×128 is enough.</p></body></html> - - - <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> - <html><head/><body><p align="justify">Step 2</p><p align="justify">Set the type and gameversion of your map.</p><p align="justify">3D means 3D map paintings built in survival.</p><p align="justify">Flat is like a floor which is easiest to build.</p><p align="justify">File-only Maps has most colors but can't be built.</p></body></html> - - - 游戏版本 - Game Version - - - 立体地图画 - 3D Map - - - 平板地图画 - Flat Map - - - 纯文件地图画 - File-only Map - - - 预设方块列表 - Presets - - - <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> - <html><head/><body><p align="justify">Step 3</p><p align="justify">Select a block for each colors. </p><p align="justify">Here we have 4 presets above, You can also set your custom block list in the scroll area.</p></body></html> - - - 优先混凝土 - Use Concrete - - - 优先羊毛 - Use Wool - - - 优先染色玻璃 - Use Glass - - - 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 -六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 -调整颜色可能会比较慢,下面的进度条指示了进度。 - Step 4, Convert image to map. Your map should only consist of map colors. -6 Algorithms correspond to different method to adjust pixel colors, you can try each. If "Dithering" is turned on,SlopeCraft will try to fit image better through mixing similar colors. -It might be laggy, the progressbar shows the progress. - - - 导出为 -地图文件 - Export -map files - - - 显示原图 - Show image - - - 显示地图画 - Show Map - - - 转换为地图画 - Convert to map - - - 算法 - Algothrims - - - 抖动仿色 - Dithering - - - 无损压缩 - Lossless Compress - - - 最大允许高度: - Max height: - - - 智能有损压缩 - Intelligent Lossy Compress - - - 投影名称 - Litematic name - - - 总方块数 - Total count - - - 压缩高度 - Compressing - - - 防火 - Fire Proof - - - 层 - layers - - - 搭桥间隔: - Construct interval: - - - 投影尺寸 - Size - - - 允许搭桥 - Construct Glass Bridge - - - 防末影人 - Enderman Proof - - - 投影区域名称 - Region name - - - 其他选项 - Others - - - 搭桥 - Glass Bridge - - - <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> - <html><head/><body><p align="justify"> - The last step is to make your map into a litematic file, to make it easier to be built.</p><p align="justify">3 blanks on the left side are some properties of your litematic file. </p><p align="justify">If you turn on "Compress height(lossless)", SlopeCraft will try to compress the height of 3d map according to rule of maps, in order to prevent it from surpassing 256(not always effective on all kinds of images).</p><p align="justify">Two bars below exhibit some information of your map. </p><p align="justify">This process might be quite slow, see the progress bar.</p></body></html> - - - 结束 - Finish - - - 导出 - Export - - - 预览 - Preview - - - 平面示意图 - Flat diagram - - - 透明度相关设置 - About transparency - - - 适合创造 - Suitable for creative mod - - - 适合生存早期 - Suitable for survival mod(undeveloped) - - - 适合光影 - Suitable for shaders - - - 自定义 - Custom - - - RGB欧式距离 - RGB Euclidean Distance - - - 更好的RGB色差公式 - A better RGB color difference formula - - - 不是简单的欧式距离 - Not simple Euclidean distance - - - Lab1994公式 - The Lab1994 color difference formula - - - Lab2000公式 - The Lab2000 color difference formula - - - XYZ欧式距离 - XYZ Euclidean Distance - - - 遗传算法 - Genetic algorithm - - - GACvter - GACvter - - - 用分辨率换颜色 - Trade colors with resolution - - - 方便建造,耗费玻璃 - Easy to build but cost many glass blocks - - - 降低总高度,破坏连续性 - Lower the total height and break the continousness - - - 用玻璃包围防火方块 - Cover burnable blocks with glass - - - 用玻璃包围可偷方块 - Cover stealable blocks with glasses - - - 降低总高度,微调颜色 - Lower the total height and modify colors slightly - - - 节省大量存储空间 - Save disk space greatly - - - 用结构空位代替 - Replace with structure void - - - 空气处理方式 - Air processing method - - - 原理图名称 - Name of schematic - - - 依赖mod名称 - Dependent mods - - - 导出平面示意图 - Export flat diagram - - - 导出三维结构 - Export 3D - - - GACvter参数 - GACvter parameters - - - 构建三维结构 - Build 3D - - - WE原理图 - WE Schem - - - 保存当前图片 - Save current Image - - - 导出为 -原版结构文件 - Export - Vanilla structure - - - 导出为 -WorldEdit原理图 - Export -WE Schem - - - 导出为 -Litematica投影 - Export -Litematic - - - <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> - <html><head/><body><p align="justify">The last step is to generate map data files.</p><p align="justify">The name of map data files is like<span style=" font-weight:700;"> map_3.dat</span>, it's used to storage content of maps. In it's file name, 3 refers to the sequence number of map data files. Sequence number starts with 0.</p><p align="justify">Located in<span style=" font-weight:700;"> data</span> folder in your saves, map data files can only be manipulated with enough authority. If you are neither single-player nor op in a server, you should export it as litematic instead of map data files.</p><p align="justify">Each map can only show a 128×128 frame, a large image results to multiple map data files. Thus, a continuous series of sequence numbers will be occupied.</p><p align="justify">For ex, run <span style=" font-weight:700;">/give @s filled_map{map:3}</span> will give you the map of <span style=" font-weight:700;">map_3.dat </span><p align="justify">1.12Command: /give @p filled_map 1 3</p><span style=" font-style:italic;">.</span></p><p align="justify">This is suitable for large images, but not for servers.</p></body></html> - - - 导出的文件名 - Map data files - - - 地图文件起始序号 - Beginning -sequence number - - - 地图画行数 - Map rows - - - 地图画列数 - Map cols - - - 地图文件数量 - Map counts - - - 查看导出的文件 - See exported file - - - 联系作者 - Contact with me - - - 退出 - Exit - - - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021 TokiNoBug</span></p></body></html> - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">Your map is finished!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">About SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">You are currently using the 3rd generation of SlopeCraft, based on Qt, Eigen and zlib. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono) made great effort to the designing and optimization, and also developed a brand-new interface based on SlopeCraft's kernel. Besides, Cubik65536 and 67au made contribution to the adaption on MacOS and Linux platforms respectively.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Contact with me:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft on github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">My homepage on GitHub</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">This program is released under license GPL-3.0 or later.</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - - - 关于 - About - - - 地图画 - Map - - - 高级 - Advanced - - - 批量操作 - Batch operation - - - 方块列表预设 - Blocklist preset - - - 转到页面 - Goto this page - - - 导出为投影文件 - Export as litematic - - - 导出为mcfunction - Export as mcfunction - - - 导出为地图文件 - Export as map files - - - 关于SlopeCraft - About SlopeCraft - - - 测试方块列表 - Test block list - - - 设置导出参数 - Set exporting parameters - - - 保存预设 - Save preset - - - 加载预设 - Load preset - - - 输出当前颜色表 - Export current colorset - - - 使用教程 - Tutorial - - - 检查更新 - Check updates - - - 设置地图画类型 - Set map type - - - 设置方块列表 - Set BlockList - - - 选择图片 - Select Image - - - 打开图片失败 - Failed to read image - - - SlopeCraft 无法加载必需方块列表 - SlopeCraft failed to load fixed block list - - - SlopeCraft 必须退出 - SlopeCraft must exit - - - SlopeCraft 无法加载可选方块列表 - SlopeCraft failed to load custom block list - - - 此错误可以忽略 - This error can be ignored - - - 加载默认预设失败 - Failed to load default presets - - - 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 -具体报错信息: -%1 - One or more internal presets failed to be parsed. SlopeCraft may have been damaged, please reinstall it. -Detail information: -%1 - - - 要不试试换一张图片吧! - Why not try another one? - - - 图片尺寸: - Image size: - - - 像素 - Pixels - - - 图片中存在透明/半透明像素,已处理,您可以点击“设置”重新选择处理透明/半透明像素的方式。 -重新设置处理方式后,需要重新导入一次。 - There's transparent pixels in your image, SlopeCraft has processed it. You can click "Settings" to reset the strategy of processing transparent pixels. -After you reset the strategy, load the image again. - - - 导出为投影/结构方块文件 - Export as litematic or structure - - - 投影文件导出失败 - Failed to export as litematic. - - - 这可能是汉字编码错误造成的。请检查路径中是否有汉字 - There might be sth wrong with characters' encoding, check if the filepath includes non-English characters. - - - 错误信息: - Error details : - - - 你输入的起始序号不可用 - Invalid sequence number. - - - 请选择导出的文件夹 - Please select a folder for exporting. - - - 你选择的文件夹不存在! - Folder dosen't exist! - - - 请稍等 - Please wait - - - -具体信息: - Detail: - - - 未知游戏版本 - Unknown game version - - - 导出原理图失败 - Failed to export. - - - 方块种类超出上限。 - The types of blocks overflow. - - - 错误的文件扩展名 - Invalid file extension name - - - 三维结构中存在错误的方块 - Wrong block in 3D structure. - - - 无法创建/打开文件 - Failed to create/open file - - - 导出原版结构方块文件失败 - Failed to export vanilla structure file. - - - 导出时指定不使用结构空位表示空气,但方块列表中不包含空气。 - When exporting as structure, you assigned not to replace air with structure void, but there is no air in the block palette. - - - 转化原图为地图画时出错 - Error occurred when converting image to map - - - 原图为空!你可能没有导入原图! - Your source image is empty! You might have forgot to import source image! - - - 构建高度矩阵时出现错误 - Error occurred when making height martix - - - 原版地图画不允许出现第三个阴影(不存在的几何关系不可能生存实装!) -请检查你的地图画类型,纯文件地图画不可以导出为投影! - The third shadow shouldn't apper in vanilla map! -Check your map type, remember that file-only map can't be exported as litematic! - - - 跳步操作 - You skipped a step - - - 有损压缩失败 - Inteligent lossy compression failed - - - 最大允许高度太小了 - The maxmium allowed height is too low - - - 允许使用的颜色过少 - Too few colors allowed! - - - 你应该勾选启用尽可能多的基色,颜色太少是不行的! - You should enable as much base colors as possible. - - - 这可能是因为路径中含有中文字符! - This might because of non-English characters in filename of path. - - - 删除临时文件失败 - Failed to remove temporary file - - - 在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 这可能是因为地图画行数过大。 尝试启用无损压缩,或者提高最大允许高度 - Lossy compression failed to compress the maximun height down to max allowed hehight when computing height map. This may be caused by a too large image. Try enabling lossless compression, or enlarge max allowed height. - - - 导出为 mcfunction - Export as mcfunction - - - 图片 (*.png *.bmp *.jpg *.tif *.GIF ) - Image (*.png *.bmp *.jpg *.tif *.GIF ) - - - 投影文件 (*.litematic) - Litematic file (*.litematic) - - - 结构方块文件 (*.nbt) - Structure file(*.nbt) - - - WorldEdit 原理图 (*.schem) - WorldEdit schematic (*.schem) - - - (xz 坐标=-65±128×整数) - (xz coordinate = -65±128×<any integer>) - - - 你输入的起始序号不可用,请输入大于等于 0 的整数! - The initial sequence number is invalid, expected non-negative number! - - - 请输入大于等于 0 的整数! - Please input a non negative number! - - - 你可以选择存档中的 data 文件夹 - You can select the "data" dir in the saves of MC. - - - 导出时将会覆盖部分地图文件 - Some files will be replaced - - - %1 个文件将被覆盖: -%2 - -点击"Yes"将继续并覆盖这些文件,点击"No"将撤销本次操作。 - %1 file(s) will be replaced: -%2 - -Click "Yes" to continue and replace these files, or click "No" to cancel this operation. - - - 导出 WorldEdit 原理图失败 - Failed to export WorldEdit schem - - - 不支持导出 1.12 WorldEdit 原理图(.schematic 格式),仅支持.schem 格式 - Exporting as WE schematic is not supported in MC 12(*.schematic), only *.schem is supported - - - SlopeCraft 不允许你跳步操作,请按照左侧竖边栏的顺序操作! - Skipping any step is not allowed by SlopeCraft - - - 有损压缩的最大允许不要低于 14,否则很容易压缩失败 - The maximum height of lossy compression should not be less than 14 - - - 导出时 Gzip 压缩文件失败 - Failed to compress a exported file - - - 正在构建高度矩阵 - Making height matrix - - - 正在构建三维结构 - Building 3D structure - - - 正在收集整张图片的颜色 - Collecting colors of the whole image - - - 正在压缩立体地图画 - Compressing 3D map pixel arts - - - 正在为立体地图画搭桥 - Constructing glass bridge - - - 正在匹配颜色 - Matching colors - - - 正在使用抖动仿色 - Dithering - - - 正在将平板地图画变为墙面地图画 - Converting flat map art to wall map art - - - 正在写入三维结构 - Writing 3D structure - - - 正在写入方块列表 - Writing block palette - - - 正在写入地图数据文件 - Writing map data - - - 正在写入基础信息 - Writing meta data - - - 可用 - + + 最大提前收敛代数: + Max fail times : - 种颜色 - colors available. + + 交叉概率: + Crossover prob : - 保存截屏 - Save screenshot + + 种群数量: + Population size : - 图片 (*.jpg *.jpeg *.tif *.bmp *.png) - Image (*.jpg *.jpeg *.tif *.bmp *.png) + + 最大进化代数: + Max generation : - 保存当前显示图片 - Save current image + + 变异概率: + Mutation prob : + + + CompressEffectViewer - 图片 (*.png) - Image (*.png) + + 预览压缩效果 + Compress effect - 保存预设文件失败 - Failed to save preset file + + 保存图像 + - 无法创建文件"%1" - Failed to create file "%1" + + 保存压缩后图片 + - 选择预设文件 - Select a preset file + + 保存图像失败 + Failed to save image - 加载预设失败 - Failed to load preset + + 无法保存图像 %1 + + + + ExportTableModel - 测试方块列表的结构文件 - Svae structure file for blocklist testing + + 原图文件名 + Image file - 测试方块列表失败 - Failed to test the block list. + + 图像大小 + Image size - 具体信息: - Detailed information: + + 地图大小 + Map size - 保存颜色表 - Save palette + + 地图序号范围 + Map index range - 保存颜色表失败 - Failed to save colormap image + + 第一个地图文件名 + First map - 分配内存失败 - Failed to allocate memory for image + + 最后一个地图文件名 + Last map @@ -1067,46 +123,6 @@ Click "Yes" to continue and replace these files, or click "No&quo PreviewWind - - 预览投影文件 - Preview Schematic - - - 材料表 - Material List - - - 方块 - Blocks - - - 投影尺寸 - Size - - - 数量 - Count - - - 总方块数 - Total count - - - 总体积 - Volume - - - 切换单位 - Switch Unit - - - 预览地图画 - Preview map - - - 如果使用了有损压缩,上一步生成的地图画可能会被轻微的修改 - The converted image might be slightly modified if lossy compression is enabled. - @@ -1156,18 +172,6 @@ Click "Yes" to continue and replace these files, or click "No&quo QObject - - 个 - block(s) - - - 盒 - SB - - - 组 - stacks - 加载图片 %1 失败。 @@ -1298,10 +302,6 @@ Click "Yes" to continue and replace these files, or click "No&quo 抖动 Dithering - - GACvter - GACvter - 转化当前图像 @@ -2080,33 +1080,6 @@ Click Ignore to skip, Retry to retry and Cancel to cancel %2 - - TaskBox - - 浏览 - Browse - - - 投影/结构文件名 - Schematic name - - - 占用的地图序号: - Map sequence number : - - - 选择图片 - Select Image - - - 图片(*.png *.bmp *.jpg *.tif *.GIF ) - Images(*.png *.bmp *.jpg *.tif *.GIF ) - - - 图片格式损坏 - Damaged image - - TransparentStrategyWind @@ -2197,73 +1170,4 @@ You should load the image again after you confirmed these settings.Set background color - - tpStrategyWind - - 透明像素处理策略 - Transparent pixels processing strategy - - - 确定 - OK - - - 取消 - Cancel - - - 恢复默认设定 - Restore to default - - - 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 -”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 -”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 -完成设置后,需重新导入图片。 - Transparency is hardly supported in map paintings. 3d maps and flat maps cannot implement transparent pixels. Although transparent pixels do exist in file-only maps, they just let the background of map/item go through. Thus it's necessary to deal with full/semi trasnparent pixels. -"Replace with background" replace pixels with background color, while "Replace with air" with air. -"Compose with backgroundcolor" compose pixel's color with background color accroding to alpha value, and "Reserve color" simply ignore the alpha value, using its RGB directly. -You should load the image again after you confirmed these settings. - - - 纯透明像素 - Full transparent - - - 替换为空气 - Replace with air - - - 替换为背景色 - Replace with background - - - 背景色 - Background color - - - 高级灰(#DCDCDC) - Silver gray(#DCDCDC) - - - 自定义 - Custom - - - 纯白(#FFFFFF) - Pure white(#FFFFFF) - - - 半透明像素 - Semi-transparent - - - 保留颜色 - Reserve color - - - 与背景色叠加 - Compose with backgroundcolor - - diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 3a2dd9ab..2019ad18 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -256,420 +256,435 @@ If you select a block in "Avaliable blocks" page, the other page will MC version - + 最大厚度: Max layers: - + 资源包 Resource packs - - + + 添加 Add - - + + 删除 Remove - + 方块id文件(json) Block state list files (json) - + 像素画方向 Pixel art direction - + 侧面(侧视) Side - + 上面(俯视) Up - + 下面(仰视) Down - + 树叶透明 Transparent leaves - + 方块列表 Blocks - - + + 全部方块 All blocks - + 快捷键 Hot keys - + 全部启用 Select all - + 全部禁用 Deselect all - + 高级匹配 Advanced - + 禁用罕见方块 Disable rare blocks - + 禁用不可再生 Disable non-reproducible - + 全部反选 Select reversely blockwise - + 按类反选 Select reversely classwise - + + 预设 + Presets + + + + 加载预设 + Load preset + + + + 保存当前预设 + Save current preset + + + 选择图片 Select images - + 显示原始尺寸 Original size - + 调色算法 Convertion algorithm - + 抖动 Dithering - + 显示原图 Display original - + 显示转化后图像 Display converted - - + + 导出 Export - + 图像 Image - + 大小(行,列) Size (rows, cols) - + 生成litematica Litematica file - + 生成结构方块文件 Structure file - + 生成WE原理图 WE schem file - + 生成转化后图像 Converted image - + 生成平面示意图 Flat diagram - + 进度 Progress - + 导出类型 Export type - + litematic投影 Litematica - + 原版结构方块文件 Vanilla structure - + WorldEdit原理图 WorldEdit schematic - + 转化后图像 Converted image - + 平面示意图 Flat diagram - + 开始执行 Start - + 设置导出位置 Set export directory - + 平面示意图(*.png) Flat diagram(*.png) - + png压缩级别: png compress level: - - + + 方块 blocks - - + + 间距: margin: - + 垂直分隔线 Vertical split line - + 水平分隔线 Horizontal split line - + png压缩内存级别: png compress memory level: - + 联系开发者 Contact developer - + 关于VisualCraft About VisualCraft - + 反馈bug Report bugs - - + + Github仓库 Github repository - + bilibili ? bilibili - + 生成测试投影 Generate testing litematic - + 查看所有颜色 Browse all colors - + 查看可用颜色 Browse avaliable colors - + 检查更新 Check updates - + 刷新警告信息 Flush warnings - + 使用教程 Tutorial - + 原版结构方块文件(*.nbt) Vanilla structure(*.nbt) - + 用结构空位表示空气 Use structure void as air - + Litematica投影(*.litematic) Litematica file (*.litematic) - + 导出选项 Export options - + 区域名称 Region name - + 投影名称(非文件名) Schematic name(not file name) - + WorldEdit原理图(*.schem) (仅1.13+) WorldEdit schematic(*schem) (1.13+ only) - + 名称(非文件名) Name (not file name) - + 需要的mod名(一行一个,默认为空) Required mods (one mod in one line) - + 显卡设置 GPU settings - + 计算设置 Computation settings - + CPU线程数: CPU threads: - + 选择计算设备 Select compute device - + 测试 Test - + 查看 Browse - + 资源 Resources - + 关于 About - + 方块 Blocks - + 加载资源 Load resources - + 设置可用的方块 Set avaliable blocks - + 生物群系 Biomes @@ -701,18 +716,18 @@ If you select a block in "Avaliable blocks" page, the other page will Vanilla - + 选择资源包 Select resource pack - + 资源包解析失败 Failed to parse resource pack - - + + 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. @@ -722,62 +737,62 @@ If you select a block in "Avaliable blocks" page, the other page will Vanilla - + 选择方块 id json 文件 Select block id json file - + 方块状态列表 json 解析失败 Failed to parse block state json list - + 资源包/方块状态列表 json 解析失败 The resource pack or block list json failed to be parsed - + 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. - + 设置可用方块失败 Failed to set avaliable blocks - + 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. - + 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) - + 选择图片(可多选) Select images - + 读取图片失败 Failed to load image. - + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. - + 设置图片失败 Failed to set image - + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. @@ -828,39 +843,48 @@ If you select a block in "Avaliable blocks" page, the other page will The great amount of colors makes GPU accleration necessary. Now OpenCL is supported, and %1 is what currently being used. - + 可用的计算设备(CPU + %1可用的显卡) Avaliable compute devices (CPU + %1-avaliable-GPUs) - - 无法获取platform信息. 请检查驱动. OpenCL错误码: %1. - Failed to get platform information. Please check GPU driver(s). OpenCL error code : %1. + + 无法获取 platform 信息。请检查驱动。OpenCL 错误码:%1. + Failed to retrieve platform infomation, please check your deiver. OpenCL error code: %1 - - 无法获取device信息. 请检查驱动. OpenCL错误码: %1 - Failed to get device infomation. Please check the driver(s). OpenCL error code : %1 + + 无法获取 device 信息。请检查驱动。OpenCL 错误码:%1 + Failed to retrieve device infomation, please check your deiver. OpenCL error code: %1 - - 设置计算设备失败 - Failed to set compute device + + %1 + +这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft + %1 + +This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - - 创建GPU平台失败,平台序号为%1,设备序号为%2 - Failed to create GPU platform, the index of platform is %1 and index of device is %2 + + 创建 GPU 平台失败,平台序号为%1,设备序号为%2 + Failed to create GPU platform, Platform index = %1, device index = %2 - - 创建GPU设备失败,平台序号为%1,设备序号为%2 - Failed to create GPU device, the index of platform is %1 and index of device is %2 + + 创建 GPU 设备失败,平台序号为%1,设备序号为%2 + Failed to create GPU device, Platform index = %1, device index = %2 - - 设置GPU设备失败。,平台序号为%1,设备序号为%2 - Failed to set GPU device, the index of platform is %1 and index of device is %2 + + 设置 GPU 设备失败。,平台序号为%1,设备序号为%2 + Failed to set GPU device. Platform index = %1, device index = %2 + + + + 设置计算设备失败 + Failed to set compute device @@ -932,22 +956,25 @@ The %2 filename(s) you give is: VisualCraft failed to build 3D structure for image "%1". - 设置任何一种导出类型的输出位置时,都需要在左侧的combo box中选择一个导出类型。请先选择一种导出类型,再设置导出位置。 - When you set the output directory for any type of export, you should select the type of export with the combobox in the left. Please select a type first. + + 保存测试投影 + Save test schematic + + + + 无法输出测试投影 + Failed to export test schematic + + + + 详细错误信息在之前的窗口中 + The detail information is displayed in previous windows 平面示意图输入错误 Invalid input for flatdiagram - - 应输入%1个以";"分隔的文件名,但实际上输入了%2个。 -您输入的%2个文件名是: -%3 - You should input %1 filenames separeted by ";", but %2 is(are) given infact. -The %2 filename(s) you give is: -%3 - 导出平面示意图失败 @@ -963,52 +990,60 @@ The %2 filename(s) you give is: 致命逻辑错误 Impossible error - - 导出页码表格中的图片"%1"不能在this->image_cache中找到对应的缓存。请将这个错误反馈给软件开发者。 - Cache of image named "%1" in the export table cannot be found in this->image_cache. Please send this as a feedback to the developer. - 保存转化后图像失败 Failed to save the converted image - - QImage未能生成"%1"。 - QImage failed to generate "%1". - 构建三维结构失败 Failed to build 3D structure - VisualCraftL不能为图像"%1"构建三维结构。 - VisualCraft failed to build 3D structure for image "%1". + + 导出原版结构方块文件失败 + Failed to export as vanilla structure - 导出litematica失败 - Failed to export as litematic + + + 选择预设文件 + Select preset file - VisualCraftL不能为图像"%1"生成投影文件"%2"。 - VisualCraft failed to generate litematic file "%2" for image "%1". + + 加载预设失败 + Failed to load preset - - 导出原版结构方块文件失败 - Failed to export as vanilla structure + + 无法解析预设文件,详细信息: +%1 + Failed to parse preset file, detail: +%1 - VisualCraftL不能为图像"%1"生成结构方块文件"%2"。 - VisualCraft failed to generate structure file "%2" for image "%1". + + 无法加载预设 + Failed to load preset - 导出World Edit原理图失败 - Failed to export as WE schematic + + 预设中包含%1,但可用方块中没有 id 相同的方块。点击 Ignore 以跳过这个方块,点击 Close 终止此次操作。 + Preset contains %1, but it is not in available blocks. Click Ignore to skip this block, or clock Close to stop this operation. - VisualCraftL不能为图像"%1"生成World Edit原理图"%2"。 - VisualCraft failed to generate WE schematic file "%2" for image "%1". + + 保存预设文件失败 + Failed to save preset file + + + + 无法保存预设文件,详细信息: +%1 + Failed to save preset file, detail: +%1 diff --git a/imageCutter/imageCutter_en_US.ts b/imageCutter/imageCutter_en_US.ts index 812b1b85..741fdf64 100644 --- a/imageCutter/imageCutter_en_US.ts +++ b/imageCutter/imageCutter_en_US.ts @@ -96,10 +96,6 @@ 选择图片 Select image - - 图片 (*.png *.bmp *.jpg *.tif) - Images (*.png *.bmp *.jpg *.tif) - 打开图片失败 From 2c25b54b3919cbc63c2c4cd5fe72847c42313968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 5 Jul 2023 13:57:02 +0800 Subject: [PATCH 0474/1123] restrict searching path for dlls --- cmake/install.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/install.cmake b/cmake/install.cmake index b89b1d60..c1795b55 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -19,6 +19,7 @@ if (${WIN32}) find_library(dll_file NAMES ${dllname} PATHS ${CMAKE_PREFIX_PATH} + PATH_SUFFIXES bin NO_CMAKE_INSTALL_PREFIX NO_CACHE) @@ -26,6 +27,7 @@ if (${WIN32}) find_file(dll_file NAMES "lib${dllname}.dll" PATHS ${CMAKE_PREFIX_PATH} + PATH_SUFFIXES bin NO_CMAKE_INSTALL_PREFIX NO_CACHE) endif () From e9d5d6c3e483d597c31e13dc7352aed481ace71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 5 Jul 2023 14:00:05 +0800 Subject: [PATCH 0475/1123] add brew upgrade to macos-build --- .github/workflows/build-dev-clang.yml | 2 +- .github/workflows/build-dev-gcc.yml | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 9e9ccaad..73f68a4d 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -1,4 +1,4 @@ -name: Beta version built with clang(for windows and macos) (macos build is hidden) +name: clang build(for windows and macos) (macos build is hidden) on: pull_request: push: diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 3a7f0cb0..60108536 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -1,4 +1,4 @@ -name: Beta version built with gcc(for windows, linux and macos) +name: gcc build(for windows, linux and macos) on: pull_request: push: @@ -17,8 +17,10 @@ jobs: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} steps: - - name: brew update - run: brew update + - name: brew upgrade & update + run: | + brew upgrade + brew update - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE From d94ad5f6d1b7c50281ff49c1753162ce2d97e4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Jul 2023 18:08:34 +0800 Subject: [PATCH 0476/1123] install windows deps by DLLDeployer --- CMakeLists.txt | 7 ++- MapViewer/install.cmake | 61 ++++++++++-------- SlopeCraft/install.cmake | 56 ++++++++++------- SlopeCraftL/install.cmake | 22 +++---- VisualCraft/install.cmake | 50 +++++++++------ VisualCraftL/install.cmake | 20 +++--- cmake/configure_DLLDeployer.cmake | 34 ++++++++++ cmake/install.cmake | 100 +++++++++++++++--------------- imageCutter/install.cmake | 53 +++++++++------- vccl/install.cmake | 46 ++++++++------ 10 files changed, 266 insertions(+), 183 deletions(-) create mode 100644 cmake/configure_DLLDeployer.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index da708d73..abfbd079 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,8 @@ include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) if (${WIN32}) - include(cmake/install_if_is_shared.cmake) + #include(cmake/install_if_is_shared.cmake) + include(cmake/configure_DLLDeployer.cmake) endif () # Add compile options -------------------------------------------------------- @@ -130,10 +131,10 @@ include_directories(${CMAKE_BINARY_DIR}/utilities) # Add global custom targets on windows --------------------------------------- if (${WIN32}) add_custom_target(SC_create_all_symlinks - COMMENT "A interface target to create all symlinks on windows") + COMMENT "A interface target to create all symlinks on windows") add_custom_target(SC_deploy_all - COMMENT "A interface target to run windeployqt for all targets") + COMMENT "A interface target to run windeployqt for all targets") endif () # # Language related variables diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index fcf5887d..761d1684 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -1,47 +1,56 @@ set(AppName MapViewer) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) +#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake +# @ONLY) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS MapViewer RUNTIME DESTINATION . - BUNDLE DESTINATION . - ) - - # Run windeployqt at build time - add_custom_target(Windeployqt-MapViewer - COMMAND ${SlopeCraft_Qt_windeployqt_executable} MapViewer.exe ${SlopeCraft_windeployqt_flags_build} - COMMAND_EXPAND_LISTS - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS MapViewer) - add_dependencies(SC_deploy_all Windeployqt-MapViewer) - - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - - SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) + ) + + QD_add_deployqt(MapViewer + BUILD_MODE + FLAGS ${SlopeCraft_windeployqt_flags_build}) + QD_add_deployqt(MapViewer + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_windeployqt_flags_install}) + DLLD_add_deploy(MapViewer + BUILD_MODE + INSTALL_MODE INSTALL_DESTINATION .) + + # # Run windeployqt at build time + # add_custom_target(Windeployqt-MapViewer + # COMMAND ${SlopeCraft_Qt_windeployqt_executable} MapViewer.exe ${SlopeCraft_windeployqt_flags_build} + # COMMAND_EXPAND_LISTS + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # DEPENDS MapViewer) + # add_dependencies(SC_deploy_all Windeployqt-MapViewer) + # + # # Run windeployqt at install time + # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + # + # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") # set_target_properties(MapViewer PROPERTIES INSTALL_RPATH "../lib") install(TARGETS MapViewer RUNTIME DESTINATION bin BUNDLE DESTINATION lib - ) + ) # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS MapViewer RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icon for macOS # MapViewer.app @@ -49,6 +58,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${MapViewer_Icon} DESTINATION MapViewer.app/Contents/Resources) return() -endif() +endif () message(WARNING "No rule to install MapViewer, because the system is not Windows, linux or MacOS.") \ No newline at end of file diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index fb4f94e4..b36dcb2d 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -13,17 +13,17 @@ file(GLOB SlopeCraft_install_presets "${CMAKE_CURRENT_SOURCE_DIR}/others/presets/*.sc_preset_json") set(AppName SlopeCraft) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) +#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake +# @ONLY) -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS # Install app install(TARGETS SlopeCraft RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icons file(GLOB SlopeCraft_Icon @@ -55,24 +55,34 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") # Install app install(TARGETS SlopeCraft RUNTIME DESTINATION . - ) - - # Run windeployqt at build time - add_custom_target(Windeployqt-SlopeCraft - COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe ${SlopeCraft_windeployqt_flags_build} - COMMAND_EXPAND_LISTS - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS SlopeCraft) - add_dependencies(SC_deploy_all Windeployqt-SlopeCraft) - - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + ) + + # # Run windeployqt at build time + # add_custom_target(Windeployqt-SlopeCraft + # COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe ${SlopeCraft_windeployqt_flags_build} + # COMMAND_EXPAND_LISTS + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # DEPENDS SlopeCraft) + # add_dependencies(SC_deploy_all Windeployqt-SlopeCraft) + # + # # Run windeployqt at install time + # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + + QD_add_deployqt(SlopeCraft + BUILD_MODE + FLAGS ${SlopeCraft_windeployqt_flags_build}) + QD_add_deployqt(SlopeCraft + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_windeployqt_flags_install}) + DLLD_add_deploy(SlopeCraft + BUILD_MODE + INSTALL_MODE INSTALL_DESTINATION .) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} @@ -99,15 +109,15 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") # set_target_properties(SlopeCraft PROPERTIES INSTALL_RPATH "../lib") # Install for Linux # Install app install(TARGETS SlopeCraft RUNTIME DESTINATION bin - ) + ) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} @@ -142,6 +152,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() -endif() +endif () message(WARNING "No rule to install SlopeCraft and images, because the system is not Windows, linux or MacOS.") diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index e0217687..ad3c0133 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -12,9 +12,9 @@ set(SlopeCraft_SCL_Cpp_include_files ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h SlopeCraftL.h SlopeCraftL_global.h -) + ) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") # install for applications install(TARGETS SlopeCraftL RUNTIME DESTINATION . @@ -26,7 +26,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib # LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib - ) + ) # install(TARGETS SlopeCraftL_C # RUNTIME DESTINATION ./../install_SlopeCraftL/C/bin @@ -39,13 +39,13 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ./../install_SlopeCraftL/C/include) - SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) - SlopeCraft_install_if_is_shared(PNG::PNG .) + # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) + # SlopeCraft_install_if_is_shared(PNG::PNG .) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") message(STATUS "Install SlopeCraft for linux") # install for applications @@ -56,9 +56,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") install(FILES ${SlopeCraft_SCL_Cpp_include_files} DESTINATION include) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # install for applications install(TARGETS SlopeCraftL RUNTIME DESTINATION . @@ -70,7 +70,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - ) + ) # install(TARGETS SlopeCraftL_C # RUNTIME DESTINATION ../install_SlopeCraftL/C/bin @@ -84,6 +84,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ../install_SlopeCraftL/C/include) return() -endif() +endif () # add_subdirectory(SCL_C) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index e3686769..2fd7d08c 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -1,34 +1,44 @@ set(AppName VisualCraft) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) +#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake +# @ONLY) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft RUNTIME DESTINATION . - ) + ) install(FILES vc-config.json DESTINATION .) - # Run windeployqt at build time - add_custom_target(Windeployqt-VisualCraft - COMMAND ${SlopeCraft_Qt_windeployqt_executable} VisualCraft.exe ${SlopeCraft_windeployqt_flags_build} - COMMAND_EXPAND_LISTS - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS VisualCraft) - add_dependencies(SC_deploy_all Windeployqt-VisualCraft) + QD_add_deployqt(VisualCraft + BUILD_MODE + FLAGS ${SlopeCraft_windeployqt_flags_build}) + QD_add_deployqt(VisualCraft + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_windeployqt_flags_install}) + DLLD_add_deploy(VisualCraft + BUILD_MODE + INSTALL_MODE INSTALL_DESTINATION .) - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + # # Run windeployqt at build time + # add_custom_target(Windeployqt-VisualCraft + # COMMAND ${SlopeCraft_Qt_windeployqt_executable} VisualCraft.exe ${SlopeCraft_windeployqt_flags_build} + # COMMAND_EXPAND_LISTS + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # DEPENDS VisualCraft) + # add_dependencies(SC_deploy_all Windeployqt-VisualCraft) + # + # # Run windeployqt at install time + # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS VisualCraft RUNTIME DESTINATION bin - ) + ) install(FILES vc-config.json DESTINATION bin) @@ -37,9 +47,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS VisualCraft RUNTIME DESTINATION . @@ -63,4 +73,4 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() -endif() \ No newline at end of file +endif () \ No newline at end of file diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index 1f319fc9..d6fb74b5 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -4,13 +4,13 @@ set(VCL_include_headers VisualCraftL.h VisualCraftL_global.h) -if(${WIN32}) +if (${WIN32}) # install for app install(TARGETS VisualCraftL RUNTIME DESTINATION . # LIBRARY DESTINATION . - ) + ) install(FILES ${VCL_app_files} DESTINATION Blocks_VCL) @@ -24,13 +24,13 @@ if(${WIN32}) # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) install(FILES ${VCL_include_headers} DESTINATION ../install_SlopeCraftL/Cpp/include) - SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) - SlopeCraft_install_if_is_shared(libzip::zip .) - SlopeCraft_install_if_is_shared(PNG::PNG .) + # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) + # SlopeCraft_install_if_is_shared(libzip::zip .) + # SlopeCraft_install_if_is_shared(PNG::PNG .) return() -endif() +endif () -if(${LINUX}) +if (${LINUX}) install(TARGETS VisualCraftL RUNTIME DESTINATION bin LIBRARY DESTINATION lib) @@ -48,9 +48,9 @@ if(${LINUX}) # RUNTIME DESTINATION bin # LIBRARY DESTINATION lib) return() -endif() +endif () -if(${APPLE}) +if (${APPLE}) install(TARGETS VisualCraftL RUNTIME DESTINATION . LIBRARY DESTINATION .) @@ -63,6 +63,6 @@ if(${APPLE}) RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) return() -endif() +endif () message(WARNING "No rule to install VisualCraftL") \ No newline at end of file diff --git a/cmake/configure_DLLDeployer.cmake b/cmake/configure_DLLDeployer.cmake new file mode 100644 index 00000000..1f5586dc --- /dev/null +++ b/cmake/configure_DLLDeployer.cmake @@ -0,0 +1,34 @@ + + +function(SC_download url filename) + if (EXISTS ${filename}) + file(SIZE ${filename} size) + if (${size} GREATER 0) + return() + endif () + + file(REMOVE ${filename}) + endif () + + message(STATUS "Downloading ${url} ...") + file(DOWNLOAD ${url} ${filename} + SHOW_PROGRESS + REQUIRED) + + file(SIZE ${filename} size) + if (${size} LESS_EQUAL 0) + message(FATAL_ERROR "Failed to download ${filename} from ${url}, downloaded file is empty") + endif () +endfunction(SC_download) + +set(DLLD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DLLDeployer) +set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) +set(QD_file ${DLLD_download_dir}/QtDeployer.cmake) + +SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.1/DLLDeployer.cmake + ${DLLD_file}) +include(${DLLD_file}) + +SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.1/QtDeployer.cmake + ${QD_file}) +include(${QD_file}) \ No newline at end of file diff --git a/cmake/install.cmake b/cmake/install.cmake index c1795b55..fc48e0be 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -1,72 +1,72 @@ set(SlopeCraft_readme_and_license_files - LICENSE - README.md - README-en.md - license-translations/LICENSE-zh.md - ) + LICENSE + README.md + README-en.md + license-translations/LICENSE-zh.md + ) include(${CMAKE_SOURCE_DIR}/cmake/add_compiler_path_to_prefix.cmake) if (${WIN32}) - include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) + #include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - - function(SlopeCraft_install_dll dllname dest is_required) - find_library(dll_file - NAMES ${dllname} - PATHS ${CMAKE_PREFIX_PATH} - PATH_SUFFIXES bin - NO_CMAKE_INSTALL_PREFIX - NO_CACHE) - - if (NOT dll_file) - find_file(dll_file - NAMES "lib${dllname}.dll" - PATHS ${CMAKE_PREFIX_PATH} - PATH_SUFFIXES bin - NO_CMAKE_INSTALL_PREFIX - NO_CACHE) - endif () - - if (NOT dll_file) - if (${is_required}) - message(FATAL_ERROR "Failed to find ${dllname} dll.") - else () - message(WARNING "Failed to find ${dllname} dll.") - endif () - return() - endif () - - message(STATUS "Install ${dll_file} to ${dest}") - install(FILES ${dll_file} - DESTINATION ${dest}) - endfunction(SlopeCraft_install_dll) - - if (${MSVC}) - SlopeCraft_install_dll(omp . true) - else () - SlopeCraft_install_dll(gomp-1 . true) - SlopeCraft_install_dll(stdc++-6 . true) - SlopeCraft_install_dll(gcc_s_seh-1 . true) - SlopeCraft_install_dll(winpthread-1 . true) - endif () + # set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") + # + # function(SlopeCraft_install_dll dllname dest is_required) + # find_library(dll_file + # NAMES ${dllname} + # PATHS ${CMAKE_PREFIX_PATH} + # PATH_SUFFIXES bin + # NO_CMAKE_INSTALL_PREFIX + # NO_CACHE) + # + # if (NOT dll_file) + # find_file(dll_file + # NAMES "lib${dllname}.dll" + # PATHS ${CMAKE_PREFIX_PATH} + # PATH_SUFFIXES bin + # NO_CMAKE_INSTALL_PREFIX + # NO_CACHE) + # endif () + # + # if (NOT dll_file) + # if (${is_required}) + # message(FATAL_ERROR "Failed to find ${dllname} dll.") + # else () + # message(WARNING "Failed to find ${dllname} dll.") + # endif () + # return() + # endif () + # + # message(STATUS "Install ${dll_file} to ${dest}") + # install(FILES ${dll_file} + # DESTINATION ${dest}) + # endfunction(SlopeCraft_install_dll) + # + # if (${MSVC}) + # SlopeCraft_install_dll(omp . true) + # else () + # SlopeCraft_install_dll(gomp-1 . true) + # SlopeCraft_install_dll(stdc++-6 . true) + # SlopeCraft_install_dll(gcc_s_seh-1 . true) + # SlopeCraft_install_dll(winpthread-1 . true) + # endif () return() endif () if (${LINUX}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) return() endif () if (${APPLE}) install(FILES ${SlopeCraft_readme_and_license_files} - DESTINATION .) + DESTINATION .) return() endif () diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 92b4aed1..88c323dd 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -1,45 +1,54 @@ set(AppName imageCutter) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) +#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake +# @ONLY) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS imageCutter RUNTIME DESTINATION . - BUNDLE DESTINATION . - ) - + ) + + QD_add_deployqt(imageCutter + BUILD_MODE + FLAGS ${SlopeCraft_windeployqt_flags_build}) + QD_add_deployqt(imageCutter + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_windeployqt_flags_install}) + DLLD_add_deploy(imageCutter + BUILD_MODE + INSTALL_MODE INSTALL_DESTINATION .) # Run windeployqt at build time - add_custom_target(Windeployqt-imageCutter - COMMAND ${SlopeCraft_Qt_windeployqt_executable} imageCutter.exe ${SlopeCraft_windeployqt_flags_build} - COMMAND_EXPAND_LISTS - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS imageCutter) - add_dependencies(SC_deploy_all Windeployqt-imageCutter) + # add_custom_target(Windeployqt-imageCutter + # COMMAND ${SlopeCraft_Qt_windeployqt_executable} imageCutter.exe ${SlopeCraft_windeployqt_flags_build} + # COMMAND_EXPAND_LISTS + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # DEPENDS imageCutter) + # add_dependencies(SC_deploy_all Windeployqt-imageCutter) + # + # # Run windeployqt at install time + # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") # et_target_properties(imageCutter PROPERTIES INSTALL_RPATH "../lib") install(TARGETS imageCutter RUNTIME DESTINATION bin BUNDLE DESTINATION lib - ) + ) # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS imageCutter RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icon for macOS file(GLOB imageCutter_Icon @@ -48,6 +57,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION imageCutter.app/Contents/Resources) return() -endif() +endif () message(WARNING "No rule to install imageCutter, because the system is not Windows, linux or MacOS.") \ No newline at end of file diff --git a/vccl/install.cmake b/vccl/install.cmake index 18cd54c3..ff32d577 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -1,29 +1,39 @@ set(AppName vccl) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) +#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake +# @ONLY) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS vccl RUNTIME DESTINATION .) install(FILES vccl-config.json DESTINATION .) - # Run windeployqt at build time - add_custom_target(Windeployqt-vccl - COMMAND ${SlopeCraft_Qt_windeployqt_executable} vccl.exe ${SlopeCraft_windeployqt_flags_build} - COMMAND_EXPAND_LISTS - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS vccl) - add_dependencies(SC_deploy_all Windeployqt-vccl) + QD_add_deployqt(vccl + BUILD_MODE + FLAGS ${SlopeCraft_windeployqt_flags_build}) + QD_add_deployqt(vccl + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_windeployqt_flags_install}) + DLLD_add_deploy(vccl + BUILD_MODE + INSTALL_MODE INSTALL_DESTINATION .) - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + # # Run windeployqt at build time + # add_custom_target(Windeployqt-vccl + # COMMAND ${SlopeCraft_Qt_windeployqt_executable} vccl.exe ${SlopeCraft_windeployqt_flags_build} + # COMMAND_EXPAND_LISTS + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # DEPENDS vccl) + # add_dependencies(SC_deploy_all Windeployqt-vccl) + # + # # Run windeployqt at install time + # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS vccl RUNTIME DESTINATION bin LIBRARY DESTINATION lib) @@ -34,9 +44,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") set(vccl_prefix vccl-contents) configure_file(deploy_qt_for_vccl_macos.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) @@ -57,4 +67,4 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Do not run deploy_qt.cmake, but a specialied one install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) return() -endif() \ No newline at end of file +endif () \ No newline at end of file From 47f213892c5321ac0f13b0c10fd5cf3807641304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 13 Jul 2023 18:08:50 +0800 Subject: [PATCH 0477/1123] remove old win installation tools --- cmake/deploy_qt.cmake.in | 29 --------- cmake/install_if_is_shared.cmake | 103 ------------------------------- cmake/scan_deps_for_lib.cmake | 69 --------------------- 3 files changed, 201 deletions(-) delete mode 100644 cmake/deploy_qt.cmake.in delete mode 100644 cmake/install_if_is_shared.cmake delete mode 100644 cmake/scan_deps_for_lib.cmake diff --git a/cmake/deploy_qt.cmake.in b/cmake/deploy_qt.cmake.in deleted file mode 100644 index 11455ec6..00000000 --- a/cmake/deploy_qt.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# This file is expected to be run during installation and cpack packaging - -if(${WIN32}) - message(STATUS "Running windeployqt for @AppName@ ...") - execute_process( - COMMAND "@SlopeCraft_Qt_windeployqt_executable@" "@AppName@.exe" @SlopeCraft_windeployqt_flags_install@ - WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY) - - message(STATUS "Current directory: ${CMAKE_CURRENT_SOURCE_DIR}") - - return() -endif() - -if(${LINUX}) - return() -endif() - -if(${APPLE}) - message(STATUS "Running macdeployqt for @AppName@ ...") - execute_process( - COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" - WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY) - - return() -endif() \ No newline at end of file diff --git a/cmake/install_if_is_shared.cmake b/cmake/install_if_is_shared.cmake deleted file mode 100644 index 97393065..00000000 --- a/cmake/install_if_is_shared.cmake +++ /dev/null @@ -1,103 +0,0 @@ -if (${WIN32}) - include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) -endif () - -function(SlopeCraft_install_lib lib_location dest) - cmake_path(GET lib_location EXTENSION extension) - - if (extension STREQUAL ".dll") - message(STATUS "Install ${lib_location} to ${dest}") - install(FILES ${lib_location} - DESTINATION ${dest}) - return() - endif () - - # message(STATUS "extension of ${lib_location} is ${extension}") - is_export_library(${lib_location} is_export) - message(STATUS "is_export = ${is_export}") - - if (${is_export}) - message(STATUS "${lib_location} is a export library") - cmake_path(GET lib_location STEM lib_stem) - - # message(STATUS "lib_stem = ${lib_stem}") - set(dll_name "${lib_stem}.dll") - - # message(STATUS "dll_name = ${dll_name}") - cmake_path(GET lib_location PARENT_PATH search_dir) - cmake_path(GET search_dir PARENT_PATH search_dir) - - # message("search_dir = ${search_dir}") - - # find_file(dll_location - # NAMES ${dll_name} - # HINTS ${search_dir}/bin/${dll_name} - # PATHS ${search_dir} - # PATH_SUFFIXES bin - # NO_CACHE) - find_library(dll_location - NAMES lib_stem - PATHS ${search_dir} - PATH_SUFFIXES bin - NO_CACHE) - - if (NOT dll_location) - # message(STATUS "find_library failed to find ${dll_name}, retry with file GLOB") - file(GLOB dll_location "${search_dir}/bin/${lib_stem}*.dll") - - list(LENGTH dll_location len) - - if (len LESS_EQUAL 0) - message(FATAL_ERROR "Trying to install dll of ${lib_location}, but failed to find ${dll_name}. - The released package may failed to find this dll.") - return() - endif () - endif () - - SlopeCraft_install_lib(${dll_location} ${dest}) - - return() - endif () - - if ((extension MATCHES ".a") OR (extension MATCHES ".lib")) - message(STATUS "\"${lib_location}\" is a static library, skip installation of it.") - return() - endif () - - message(FATAL_ERROR "Unknown library extension: ${extension}") -endfunction(SlopeCraft_install_lib) - -function(SlopeCraft_install_if_is_shared target dest) - get_target_property(target_type ${target} TYPE) - - # message(STATUS "Type of ${target} is : ${target_type}") - get_target_property(target_name ${target} NAME) - - # message(STATUS "Name of ${target} is : ${target_name}") - get_target_property(target_suffix ${target} SUFFIX) - - # message(STATUS "Suffix of ${target} is : ${target_suffix}") - get_target_property(target_location ${target} LOCATION) - - # message(STATUS "Location of ${target} is : ${target_location}") - set(skip_this false) - - if (${target_type} STREQUAL EXECUTABLE) - set(skip_this true) - endif () - - if (${target_type} STREQUAL STATIC_LIBRARY) - set(skip_this true) - endif () - - if (${target_type} STREQUAL OBJECT_LIBRARY) - set(skip_this true) - endif () - - if (${skip_this}) - message(STATUS "Skip installing ${target} because it is not a shared lib. TYPE = ${target_type}") - return() - endif () - - SlopeCraft_install_lib(${target_location} ${dest}) -endfunction(SlopeCraft_install_if_is_shared) \ No newline at end of file diff --git a/cmake/scan_deps_for_lib.cmake b/cmake/scan_deps_for_lib.cmake deleted file mode 100644 index b99408ed..00000000 --- a/cmake/scan_deps_for_lib.cmake +++ /dev/null @@ -1,69 +0,0 @@ -if (NOT ${WIN32}) - message(FATAL_ERROR "This cmake script is included with incorrect system, expected windows.") -endif () - - -find_file(SC_MSVC_lib_exe lib.exe) - - -function(scan_deps_of_msvc_lib_file lib_file_name dest_depend_files) - - if (NOT SC_MSVC_lib_exe) - message(FATAL_ERROR "You are using msvc-like compiler on windows, but cmake failed to find lib.exe of visual studio.") - endif () - - - execute_process(COMMAND ${SC_MSVC_lib_exe} /list ${lib_file_name} - OUTPUT_VARIABLE MSVC_lib_output COMMAND_ERROR_IS_FATAL ANY) - - #message(STATUS "output of ${lib_file_name} is : ${MSVC_lib_output}") - string(REPLACE "\n" ";" MSVC_lib_output ${MSVC_lib_output}) - set(temp) - foreach (item ${MSVC_lib_output}) - if ((${item} MATCHES "Microsoft") OR (${item} MATCHES "Copyright")) - message(STATUS "Filter out ${item}") - continue() - endif () - list(APPEND temp ${item}) - endforeach () - - set(${dest_depend_files} ${temp} PARENT_SCOPE) -endfunction() - -function(is_export_library lib_file_name dest_is_export_lib) - - - if ((${lib_file_name} MATCHES ".dll.a")) - message(STATUS "${lib_file_name} is a export lib.") - set({dest_is_export_lib} ON PARENT_SCOPE) - return() - endif () - - cmake_path(GET lib_file_name EXTENSION extension) - - if ((${extension} STREQUAL ".a") OR (${extension} STREQUAL ".obj") OR (${extension} STREQUAL ".o") OR (${extension} STREQUAL ".dll")) - message(STATUS "${lib_file_name} is a static or dynamic lib or a object.") - set({dest_is_export_lib} OFF PARENT_SCOPE) - return() - endif () - - if (NOT ${extension} STREQUAL ".lib") - message(FATAL_ERROR "Failed to deduce library type of ${lib_file_name}") - endif () - - scan_deps_of_msvc_lib_file(${lib_file_name} dep_list) - message(STATUS "dep_list = ${dep_list}") - - foreach (dep_file ${dep_list}) - message("dep_file = ${dep_file}") - if (${dep_file} MATCHES ".dll") - message(STATUS "${lib_file_name} is a export lib.") - set(${dest_is_export_lib} ON PARENT_SCOPE) - return() - endif () - endforeach () - message(STATUS "${lib_file_name} is a static lib.") - set(${dest_is_export_lib} OFF PARENT_SCOPE) - - -endfunction() \ No newline at end of file From 750e343d37ff5bc6f655b2c5c36c71eece67db1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 14 Jul 2023 00:59:40 +0800 Subject: [PATCH 0478/1123] add SCL and VCL to the ignore list of DLLDeployer --- SlopeCraft/install.cmake | 3 ++- SlopeCraftL/install.cmake | 3 +++ VisualCraft/install.cmake | 10 +++++++--- VisualCraftL/install.cmake | 4 ++++ cmake/configure_DLLDeployer.cmake | 12 ++++++------ cmake/find_qt6.cmake | 26 +++++++++----------------- vccl/install.cmake | 3 ++- 7 files changed, 33 insertions(+), 28 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index b36dcb2d..ef8e980e 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -82,7 +82,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") FLAGS ${SlopeCraft_windeployqt_flags_install}) DLLD_add_deploy(SlopeCraft BUILD_MODE - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + IGNORE SlopeCraftL.dll) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index ad3c0133..e85b7177 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -37,6 +37,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(FILES ${SlopeCraft_SCL_Cpp_include_files} DESTINATION ./../install_SlopeCraftL/Cpp/include) + DLLD_add_deploy(SlopeCraftL + INSTALL_MODE INSTALL_DESTINATION .) + # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ./../install_SlopeCraftL/C/include) # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 2fd7d08c..cf481bfb 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -20,7 +20,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") FLAGS ${SlopeCraft_windeployqt_flags_install}) DLLD_add_deploy(VisualCraft BUILD_MODE - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + IGNORE VisualCraftL.dll libVisualCraftL.dll) # # Run windeployqt at build time # add_custom_target(Windeployqt-VisualCraft @@ -67,10 +68,13 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} - DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL) + DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL + ) + QD_add_deployqt(VisualCraft + INSTALL_MODE INSTALL_DESTINATION .) # Run macdeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + #install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() endif () \ No newline at end of file diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index d6fb74b5..9b685572 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -18,6 +18,9 @@ if (${WIN32}) install(TARGETS VisualCraftL RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) + + DLLD_add_deploy(VisualCraftL + INSTALL_MODE INSTALL_DESTINATION .) # install(TARGETS VisualCraftL_static # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin @@ -27,6 +30,7 @@ if (${WIN32}) # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) # SlopeCraft_install_if_is_shared(libzip::zip .) # SlopeCraft_install_if_is_shared(PNG::PNG .) + return() endif () diff --git a/cmake/configure_DLLDeployer.cmake b/cmake/configure_DLLDeployer.cmake index 1f5586dc..91d382ec 100644 --- a/cmake/configure_DLLDeployer.cmake +++ b/cmake/configure_DLLDeployer.cmake @@ -12,8 +12,8 @@ function(SC_download url filename) message(STATUS "Downloading ${url} ...") file(DOWNLOAD ${url} ${filename} - SHOW_PROGRESS - REQUIRED) + SHOW_PROGRESS + REQUIRED) file(SIZE ${filename} size) if (${size} LESS_EQUAL 0) @@ -25,10 +25,10 @@ set(DLLD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DLLDeployer) set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) set(QD_file ${DLLD_download_dir}/QtDeployer.cmake) -SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.1/DLLDeployer.cmake - ${DLLD_file}) +SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/DLLDeployer.cmake + ${DLLD_file}) include(${DLLD_file}) -SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.1/QtDeployer.cmake - ${QD_file}) +SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake + ${QD_file}) include(${QD_file}) \ No newline at end of file diff --git a/cmake/find_qt6.cmake b/cmake/find_qt6.cmake index 1e834b73..8f36ed1c 100644 --- a/cmake/find_qt6.cmake +++ b/cmake/find_qt6.cmake @@ -17,33 +17,25 @@ message(STATUS "Searching for Qt6. CMAKE_PREFIX_PATH = " ${CMAKE_PREFIX_PATH}) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) # find lupdate executable -if(${SlopeCraft_update_ts_files} AND(NOT DEFINED SlopeCraft_Qt_lupdate_executable)) +if (${SlopeCraft_update_ts_files} AND (NOT DEFINED SlopeCraft_Qt_lupdate_executable)) find_program(SlopeCraft_Qt_lupdate_executable name lupdate PATHS ${CMAKE_PREFIX_PATH} REQUIRED) message(STATUS "Found lupdate at : " ${SlopeCraft_Qt_lupdate_executable}) - if(${SlopeCraft_update_ts_no_obsolete}) + if (${SlopeCraft_update_ts_no_obsolete}) set(SlopeCraft_ts_flags) - else() + else () set(SlopeCraft_ts_flags "-no-obsolete") - endif() -endif() + endif () +endif () -if(${WIN32}) - find_program(SlopeCraft_Qt_windeployqt_executable windeployqt PATHS ${CMAKE_PREFIX_PATH}) -endif() - -if(${LINUX}) - if(NOT EXISTS ${Qt6_DIR}) +if (${LINUX}) + if (NOT EXISTS ${Qt6_DIR}) message(WARNING "Qt6_DIR is not set. No way to find platform plugins") - endif() + endif () # message(STATUS "Qt6_DIR = ${Qt6_DIR}") file(GLOB_RECURSE SlopeCraft_Qt_plugin_platform_files "${Qt6_DIR}/../../../plugins/platforms/*") file(GLOB_RECURSE SlopeCraft_Qt_plugin_imageformat_files "${Qt6_DIR}/../../../plugins/imageformats/*") # message(STATUS "Qt platform plugin files: ${SlopeCraft_Qt_plugin_platform_files}") -endif() - -if(${APPLE}) - find_program(SlopeCraft_Qt_macdeployqt_executable macdeployqt PATHS ${CMAKE_PREFIX_PATH}) -endif() +endif () diff --git a/vccl/install.cmake b/vccl/install.cmake index ff32d577..ebde744f 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -18,7 +18,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") FLAGS ${SlopeCraft_windeployqt_flags_install}) DLLD_add_deploy(vccl BUILD_MODE - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + IGNORE VisualCraftL.dll libVisualCraftL.dll) # # Run windeployqt at build time # add_custom_target(Windeployqt-vccl From 77d9c470f1f851bffb958a44797f0146147b5d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 14 Jul 2023 01:00:40 +0800 Subject: [PATCH 0479/1123] reduce useless warnings --- cmake/configure_cereal.cmake | 6 +++--- cmake/configure_fmtlib.cmake | 42 ++++++++++++++++++------------------ cmake/find_Eigen3.cmake | 6 +++--- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cmake/configure_cereal.cmake b/cmake/configure_cereal.cmake index c16c8d12..a904fc39 100644 --- a/cmake/configure_cereal.cmake +++ b/cmake/configure_cereal.cmake @@ -3,11 +3,11 @@ set(BUILD_SANDBOX OFF) set(BUILD_DOC OFF) set(CEREAL_INSTALL OFF) -find_package(cereal) +find_package(cereal QUIET) -if(${cereal_FOUND}) +if (${cereal_FOUND}) return() -endif() +endif () include(FetchContent) diff --git a/cmake/configure_fmtlib.cmake b/cmake/configure_fmtlib.cmake index 6916dad1..f989424c 100644 --- a/cmake/configure_fmtlib.cmake +++ b/cmake/configure_fmtlib.cmake @@ -4,36 +4,36 @@ set(SC_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) -find_package(fmt) +find_package(fmt QUIET) -if(NOT ${fmt_FOUND}) - include(FetchContent) - FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG "9.1.0" - OVERRIDE_FIND_PACKAGE +if (NOT ${fmt_FOUND}) + include(FetchContent) + FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG "9.1.0" + OVERRIDE_FIND_PACKAGE - # QUIET false - # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty - # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args - ) + # QUIET false + # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty + # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args + ) - message(STATUS "Downaloding and building fmtlib......") + message(STATUS "Downaloding and building fmtlib......") - FetchContent_MakeAvailable(fmt) - find_package(fmt REQUIRED) -endif() + FetchContent_MakeAvailable(fmt) + find_package(fmt REQUIRED) +endif () set(CMAKE_CXX_FLAGS ${SC_CMAKE_CXX_FLAGS}) unset(SC_CMAKE_CXX_FLAGS) -if(${MSVC}) - # enable c++ exceptions - add_compile_options("/EHsc") +if (${MSVC}) + # enable c++ exceptions + add_compile_options("/EHsc") - # target_compile_options(fmt::fmt INTERFACE "/EHsc") -endif() + # target_compile_options(fmt::fmt INTERFACE "/EHsc") +endif () # message(STATUS "fmt_POPULATED = " ) diff --git a/cmake/find_Eigen3.cmake b/cmake/find_Eigen3.cmake index 703c1c14..585a35e5 100644 --- a/cmake/find_Eigen3.cmake +++ b/cmake/find_Eigen3.cmake @@ -1,10 +1,10 @@ set(SlopeCraft_Eigen3_found OFF) -find_package(Eigen3 3.4.0) +find_package(Eigen3 3.4.0 QUIET) -if(${Eigen3_FOUND}) +if (${Eigen3_FOUND}) message(STATUS "EIGEN3_INCLUDE_DIR = ${EIGEN3_INCLUDE_DIR}") return() -endif() +endif () include(FetchContent) From 5dfcac6c129ed5ad0a68cede538b34f6871c6f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 14 Jul 2023 11:15:16 +0800 Subject: [PATCH 0480/1123] fix macos build --- CMakeLists.txt | 5 +---- cmake/configure_DLLDeployer.cmake | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abfbd079..bbe51232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,10 +63,7 @@ include(cmake/find_Eigen3.cmake) include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) -if (${WIN32}) - #include(cmake/install_if_is_shared.cmake) - include(cmake/configure_DLLDeployer.cmake) -endif () +include(cmake/configure_DLLDeployer.cmake) # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty diff --git a/cmake/configure_DLLDeployer.cmake b/cmake/configure_DLLDeployer.cmake index 91d382ec..194852b6 100644 --- a/cmake/configure_DLLDeployer.cmake +++ b/cmake/configure_DLLDeployer.cmake @@ -24,11 +24,14 @@ endfunction(SC_download) set(DLLD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DLLDeployer) set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) set(QD_file ${DLLD_download_dir}/QtDeployer.cmake) - -SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/DLLDeployer.cmake - ${DLLD_file}) -include(${DLLD_file}) - -SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake - ${QD_file}) -include(${QD_file}) \ No newline at end of file +if (${WIN32}) + SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/DLLDeployer.cmake + ${DLLD_file}) + include(${DLLD_file}) +endif () + +if (WIN32 OR APPLE) + SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake + ${QD_file}) + include(${QD_file}) +endif () From d2015ef6c14f6a5cf2545ac2132abee29fd857c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 14 Jul 2023 11:38:27 +0800 Subject: [PATCH 0481/1123] fix macos build --- vccl/install.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vccl/install.cmake b/vccl/install.cmake index ebde744f..b78dde5b 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -49,7 +49,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") set(vccl_prefix vccl-contents) - + find_program(SlopeCraft_Qt_macdeployqt_executable macdeployqt REQUIRED) configure_file(deploy_qt_for_vccl_macos.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) From 20023c3035f59db226362a49cc0b98ad435cb709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 4 Aug 2023 11:34:54 +0800 Subject: [PATCH 0482/1123] add more slabs --- Blocks/CustomBlocks.json | 85 ++++++++++++++++++++++-- Blocks/CustomBlocks/bamboo_mosaic.png | Bin 0 -> 253 bytes Blocks/CustomBlocks/bamboo_planks.png | Bin 0 -> 245 bytes Blocks/CustomBlocks/granite.png | Bin 335 -> 259 bytes Blocks/CustomBlocks/mangrove_planks.png | Bin 0 -> 229 bytes 5 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 Blocks/CustomBlocks/bamboo_mosaic.png create mode 100644 Blocks/CustomBlocks/bamboo_planks.png create mode 100644 Blocks/CustomBlocks/mangrove_planks.png diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 8890f893..8ff8339c 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -65,6 +65,15 @@ "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" }, + { + "baseColor": 11, + "id": "minecraft:smooth_stone_slab[type=top,waterlogged=false]", + "nameZH": "平滑石台阶", + "nameEN": "Smooth stone slab", + "icon": "smooth_stone.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=smooth_stone]" + }, { "baseColor": 28, "id": "minecraft:brick_slab[type=top,waterlogged=false]", @@ -160,6 +169,60 @@ "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", "burnable": true }, + { + "baseColor": 53, + "id": "minecraft:crimson_slab[type=top,waterlogged=false]", + "nameZH": "绯红木台阶", + "nameEN": "Crimson slab", + "icon": "crimson_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:warped_slab[type=top,waterlogged=false]", + "nameZH": "诡异木台阶", + "nameEN": "Warped slab", + "icon": "warped_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:mangrove_slab[type=top,waterlogged=false]", + "nameZH": "红树木台阶", + "nameEN": "Mangrove slab", + "icon": "mangrove_planks.png", + "version": 19, + "burnable": true + }, + { + "baseColor": 36, + "id": "minecraft:cherry_slab[type=top,waterlogged=false]", + "nameZH": "樱花木台阶", + "nameEN": "Cherry slab", + "icon": "cherry_slab.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_slab[type=top,waterlogged=false]", + "nameZH": "竹台阶", + "nameEN": "Bamboo slab", + "icon": "bamboo_planks.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_mosaic_slab[type=top,waterlogged=false]", + "nameZH": "竹马赛克台阶", + "nameEN": "Bamboo mosaic slab", + "icon": "bamboo_mosaic.png", + "version": 20, + "burnable": true + }, { "baseColor": 15, "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", @@ -230,6 +293,15 @@ "version": 0, "idOld": "minecraft:stone[variant=granite]" }, + { + "baseColor": 10, + "id": "minecraft:granite_slab[type=top,waterlogged=false]", + "nameZH": "花岗岩台阶", + "nameEN": "Granite slab", + "icon": "granite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=granite]" + }, { "baseColor": 11, "id": "minecraft:andesite", @@ -332,13 +404,12 @@ "version": 17 }, { - "baseColor": 36, - "id": "minecraft:cherry_slab[type=top,waterlogged=false]", - "nameZH": "樱花木台阶", - "nameEN": "Cherry slab", - "icon": "cherry_slab.png", - "version": 20, - "burnable": true + "baseColor": 2, + "id": "minecraft:end_stone_brick_slab[type=top,waterlogged=false]", + "nameZH": "末地石砖台阶", + "nameEN": "Endstone brick slab", + "icon": "end_stone_bricks.png", + "version": 0 } ] } \ No newline at end of file diff --git a/Blocks/CustomBlocks/bamboo_mosaic.png b/Blocks/CustomBlocks/bamboo_mosaic.png new file mode 100644 index 0000000000000000000000000000000000000000..2a40a896f4f046904b02d3f9ca407b973ae9df3e GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;kAc zi(`nz>9-RU`IrKET&nd&Cb68D*T7uRRazlqt`NDkN#WXBr!~$CEj>Y=Fb|x3)Z@XSO^Vah1U&D8ER>l3fmhZ&i zcb-Yqj@!V&uvu~fbLU*X(<>e+9uRP7v02S6^yJ9R#x+fM9y?6i%pkM8CTW-D^94F8 yVg47QIiAeUmOG`OUvoy`e%$X}3hXru^^7H|H{}E^)?5NQox#)9&t;ucLK6VrdR_AX literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/bamboo_planks.png b/Blocks/CustomBlocks/bamboo_planks.png new file mode 100644 index 0000000000000000000000000000000000000000..998a55382ab4139215b685c8d31a676047d3db9a GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;j}Y zi(`nz>9-RU`3?mLxIB-sP~n^~Zvp!Qfvpia`3_A^CZeUG95SnBF&DHbex9s2+c&V3 z<>RHhH`D%~Yfzci@V{w(M8WQN7IU`0(U-P+&%R51-B;6jk;hH0iS#dgl$~`-=y9aV z`BSXP+yBQrNWIpYm3ghVYRhrcqbnn)ZocDg(p~(W>0yygA*{;o`AVZ1TW$qb&ZelF{r5}E+KB4HW; literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/granite.png b/Blocks/CustomBlocks/granite.png index b52ad2868a4d4f79d354b8e8fea52093a1b628ad..4c4711595ac7f32e717881002c55a59b5830a2ec 100644 GIT binary patch delta 231 zcmV4`PFGeVE(-mE|dL4B~?@x*8D808<2#gegWh1SSTu2w5{o z4sO7f*%QHr#5ifCCd4UKp_eGZ7Y; hFpL~4=w1Wq0|2lmsN|W?i**11002ovPDHLkV1ng+SK|Nx delta 308 zcmV-40n7e_0?z`FB!2{FK}|sb0I`n?{9y$E009O`L_t(I%XO124gxU{g?k_*coYtS zAvh9(;{Yo+I4l?h0*%7#0kE8dgDiQIe9hZo5l!1S(>HH^TDsf0zaKXJWw(mGT`yvH zOlvut#NM5nianZrUvS*crvd2xz8(ieI*;A;E(r7(BZOKa8?7F9_sKfo|i`gb9LY%B%R{Lfxxj$?x|D-{=nO+)}bPkqo`0Y zFHDZ;ZF8SU!DV>_Cjn!KxW^#jB9-RMxmq1~T#5xYUi8`^;Bw*9ce#V-?s@6hHnjJhsdH;?`Vu8L3P_Tk>zpynF9Slq35mG9pG|3!5L ZOd2P0qO&wzz5<=d;OXk;vd$@?2>?5KRu}*P literal 0 HcmV?d00001 From 7486cacdf06ed6da5dc689ac558a5669c4003494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Fri, 4 Aug 2023 11:48:24 +0800 Subject: [PATCH 0483/1123] rename slab filenames --- Blocks/CustomBlocks.json | 68 +++++++++--------- ...acia_planks.png => acacia_planks_slab.png} | Bin ...mboo_mosaic.png => bamboo_mosaic_slab.png} | Bin ...mboo_planks.png => bamboo_planks_slab.png} | Bin ...birch_planks.png => birch_planks_slab.png} | Bin .../{bricks.png => bricks_slab.png} | Bin .../{cherry_slab.png => cherry_slab_slab.png} | Bin .../{cobblestone.png => cobblestone_slab.png} | Bin ...son_planks.png => crimson_planks_slab.png} | Bin ...ak_planks.png => dark_oak_planks_slab.png} | Bin ...rismarine.png => dark_prismarine_slab.png} | Bin ...e_bricks.png => deepslate_bricks_slab.png} | Bin ...e_bricks.png => end_stone_bricks_slab.png} | Bin .../{end_stone.png => end_stone_slab.png} | Bin .../{granite.png => granite_slab.png} | Bin ...ngle_planks.png => jungle_planks_slab.png} | Bin ...ve_planks.png => mangrove_planks_slab.png} | Bin ...ther_bricks.png => nether_bricks_slab.png} | Bin .../{oak_planks.png => oak_planks_slab.png} | Bin ..._bricks.png => prismarine_bricks_slab.png} | Bin .../{prismarine.png => prismarine_slab.png} | Bin ...purpur_block.png => purpur_block_slab.png} | Bin ...quartz_block.png => quartz_block_slab.png} | Bin ...tone.png => smooth_red_sandstone_slab.png} | Bin ...andstone.png => smooth_sandstone_slab.png} | Bin ...smooth_stone.png => smooth_stone_slab.png} | Bin ...ruce_planks.png => spruce_planks_slab.png} | Bin ...stone_bricks.png => stone_bricks_slab.png} | Bin .../{stone.png => stone_slab.png} | Bin ...rped_planks.png => warped_planks_slab.png} | Bin ..._block.png => waxed_copper_block_slab.png} | Bin ...t_copper.png => waxed_cut_copper_slab.png} | Bin ...pper.png => waxed_exposed_copper_slab.png} | Bin ....png => waxed_exposed_cut_copper_slab.png} | Bin ...per.png => waxed_oxidized_copper_slab.png} | Bin ...png => waxed_oxidized_cut_copper_slab.png} | Bin ...er.png => waxed_weathered_copper_slab.png} | Bin 37 files changed, 34 insertions(+), 34 deletions(-) rename Blocks/CustomBlocks/{acacia_planks.png => acacia_planks_slab.png} (100%) rename Blocks/CustomBlocks/{bamboo_mosaic.png => bamboo_mosaic_slab.png} (100%) rename Blocks/CustomBlocks/{bamboo_planks.png => bamboo_planks_slab.png} (100%) rename Blocks/CustomBlocks/{birch_planks.png => birch_planks_slab.png} (100%) rename Blocks/CustomBlocks/{bricks.png => bricks_slab.png} (100%) rename Blocks/CustomBlocks/{cherry_slab.png => cherry_slab_slab.png} (100%) rename Blocks/CustomBlocks/{cobblestone.png => cobblestone_slab.png} (100%) rename Blocks/CustomBlocks/{crimson_planks.png => crimson_planks_slab.png} (100%) rename Blocks/CustomBlocks/{dark_oak_planks.png => dark_oak_planks_slab.png} (100%) rename Blocks/CustomBlocks/{dark_prismarine.png => dark_prismarine_slab.png} (100%) rename Blocks/CustomBlocks/{deepslate_bricks.png => deepslate_bricks_slab.png} (100%) rename Blocks/CustomBlocks/{end_stone_bricks.png => end_stone_bricks_slab.png} (100%) rename Blocks/CustomBlocks/{end_stone.png => end_stone_slab.png} (100%) rename Blocks/CustomBlocks/{granite.png => granite_slab.png} (100%) rename Blocks/CustomBlocks/{jungle_planks.png => jungle_planks_slab.png} (100%) rename Blocks/CustomBlocks/{mangrove_planks.png => mangrove_planks_slab.png} (100%) rename Blocks/CustomBlocks/{nether_bricks.png => nether_bricks_slab.png} (100%) rename Blocks/CustomBlocks/{oak_planks.png => oak_planks_slab.png} (100%) rename Blocks/CustomBlocks/{prismarine_bricks.png => prismarine_bricks_slab.png} (100%) rename Blocks/CustomBlocks/{prismarine.png => prismarine_slab.png} (100%) rename Blocks/CustomBlocks/{purpur_block.png => purpur_block_slab.png} (100%) rename Blocks/CustomBlocks/{quartz_block.png => quartz_block_slab.png} (100%) rename Blocks/CustomBlocks/{smooth_red_sandstone.png => smooth_red_sandstone_slab.png} (100%) rename Blocks/CustomBlocks/{smooth_sandstone.png => smooth_sandstone_slab.png} (100%) rename Blocks/CustomBlocks/{smooth_stone.png => smooth_stone_slab.png} (100%) rename Blocks/CustomBlocks/{spruce_planks.png => spruce_planks_slab.png} (100%) rename Blocks/CustomBlocks/{stone_bricks.png => stone_bricks_slab.png} (100%) rename Blocks/CustomBlocks/{stone.png => stone_slab.png} (100%) rename Blocks/CustomBlocks/{warped_planks.png => warped_planks_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_copper_block.png => waxed_copper_block_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_cut_copper.png => waxed_cut_copper_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_exposed_copper.png => waxed_exposed_copper_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_exposed_cut_copper.png => waxed_exposed_cut_copper_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_oxidized_copper.png => waxed_oxidized_copper_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_oxidized_cut_copper.png => waxed_oxidized_cut_copper_slab.png} (100%) rename Blocks/CustomBlocks/{waxed_weathered_copper.png => waxed_weathered_copper_slab.png} (100%) diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 8ff8339c..5dda93ed 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -14,7 +14,7 @@ // nameEN 是方块英文名称,必填", "nameEN": "Waxed cut copper slab", // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", - "icon": "waxed_cut_copper.png", + "icon": "waxed_cut_copper_slab.png", // version 是方块最早出现的版本。0 代表早于 1.12,12 代表 1.12,13 代表 1.13,如此类推。255 代表尚未出现的版本", "version": 17 // idOld 是该方块在 1.12 的方块 id(如果有的话),必须加 minecraft:前缀,选填,默认为空字符串", @@ -37,7 +37,7 @@ // nameEN is the English name. Compulsory item. "nameEN": "Stone slab", // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. - "icon": "stone.png", + "icon": "stone_slab.png", // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. "version": 0, // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string @@ -52,7 +52,7 @@ "id": "minecraft:sandstone_slab[type=top,waterlogged=false]", "nameZH": "砂岩台阶", "nameEN": "Sandstone slab", - "icon": "smooth_sandstone.png", + "icon": "smooth_sandstone_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=sandstone]" }, @@ -61,7 +61,7 @@ "id": "minecraft:cobblestone_slab[type=top,waterlogged=false]", "nameZH": "圆石台阶", "nameEN": "Cobblestone slab", - "icon": "cobblestone.png", + "icon": "cobblestone_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" }, @@ -70,7 +70,7 @@ "id": "minecraft:smooth_stone_slab[type=top,waterlogged=false]", "nameZH": "平滑石台阶", "nameEN": "Smooth stone slab", - "icon": "smooth_stone.png", + "icon": "smooth_stone_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=smooth_stone]" }, @@ -79,7 +79,7 @@ "id": "minecraft:brick_slab[type=top,waterlogged=false]", "nameZH": "红砖台阶", "nameEN": "Brick slab", - "icon": "bricks.png", + "icon": "bricks_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=brick]" }, @@ -88,7 +88,7 @@ "id": "minecraft:stone_brick_slab[type=top,waterlogged=false]", "nameZH": "石砖台阶", "nameEN": "Stonebrick slab", - "icon": "stone_bricks.png", + "icon": "stone_bricks_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=stone_brick]" }, @@ -97,7 +97,7 @@ "id": "minecraft:nether_brick_slab[type=top,waterlogged=false]", "nameZH": "下界砖台阶", "nameEN": "Nether brick slab", - "icon": "nether_bricks.png", + "icon": "nether_bricks_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=nether_brick]" }, @@ -106,7 +106,7 @@ "id": "minecraft:quartz_slab[type=top,waterlogged=false]", "nameZH": "石英台阶", "nameEN": "Quartz slab", - "icon": "quartz_block.png", + "icon": "quartz_block_slab.png", "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=quartz]" }, @@ -115,7 +115,7 @@ "id": "minecraft:oak_slab[type=top,waterlogged=false]", "nameZH": "橡木台阶", "nameEN": "Oak slab", - "icon": "oak_planks.png", + "icon": "oak_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=oak]" }, @@ -124,7 +124,7 @@ "id": "minecraft:spruce_slab[type=top,waterlogged=false]", "nameZH": "云杉木台阶", "nameEN": "Spruce slab", - "icon": "spruce_planks.png", + "icon": "spruce_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=spruce]", "burnable": true @@ -134,7 +134,7 @@ "id": "minecraft:birch_slab[type=top,waterlogged=false]", "nameZH": "白桦木台阶", "nameEN": "Birch slab", - "icon": "birch_planks.png", + "icon": "birch_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=birch]", "burnable": true @@ -144,7 +144,7 @@ "id": "minecraft:jungle_slab[type=top,waterlogged=false]", "nameZH": "丛林木台阶", "nameEN": "Jungle slab", - "icon": "jungle_planks.png", + "icon": "jungle_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=jungle]", "burnable": true @@ -154,7 +154,7 @@ "id": "minecraft:acacia_slab[type=top,waterlogged=false]", "nameZH": "金合欢木台阶", "nameEN": "Acacia slab", - "icon": "acacia_planks.png", + "icon": "acacia_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=acacia]", "burnable": true @@ -164,7 +164,7 @@ "id": "minecraft:dark_oak_slab[type=top,waterlogged=false]", "nameZH": "深色橡木台阶", "nameEN": "Dark oak slab", - "icon": "dark_oak_planks.png", + "icon": "dark_oak_planks_slab.png", "version": 0, "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", "burnable": true @@ -174,7 +174,7 @@ "id": "minecraft:crimson_slab[type=top,waterlogged=false]", "nameZH": "绯红木台阶", "nameEN": "Crimson slab", - "icon": "crimson_planks.png", + "icon": "crimson_planks_slab.png", "version": 16, "burnable": true }, @@ -183,7 +183,7 @@ "id": "minecraft:warped_slab[type=top,waterlogged=false]", "nameZH": "诡异木台阶", "nameEN": "Warped slab", - "icon": "warped_planks.png", + "icon": "warped_planks_slab.png", "version": 16, "burnable": true }, @@ -192,7 +192,7 @@ "id": "minecraft:mangrove_slab[type=top,waterlogged=false]", "nameZH": "红树木台阶", "nameEN": "Mangrove slab", - "icon": "mangrove_planks.png", + "icon": "mangrove_planks_slab.png", "version": 19, "burnable": true }, @@ -201,7 +201,7 @@ "id": "minecraft:cherry_slab[type=top,waterlogged=false]", "nameZH": "樱花木台阶", "nameEN": "Cherry slab", - "icon": "cherry_slab.png", + "icon": "cherry_slab_slab.png", "version": 20, "burnable": true }, @@ -210,7 +210,7 @@ "id": "minecraft:bamboo_slab[type=top,waterlogged=false]", "nameZH": "竹台阶", "nameEN": "Bamboo slab", - "icon": "bamboo_planks.png", + "icon": "bamboo_planks_slab.png", "version": 20, "burnable": true }, @@ -219,7 +219,7 @@ "id": "minecraft:bamboo_mosaic_slab[type=top,waterlogged=false]", "nameZH": "竹马赛克台阶", "nameEN": "Bamboo mosaic slab", - "icon": "bamboo_mosaic.png", + "icon": "bamboo_mosaic_slab.png", "version": 20, "burnable": true }, @@ -228,7 +228,7 @@ "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", "nameZH": "红砂岩台阶", "nameEN": "Red sandstone slab", - "icon": "smooth_red_sandstone.png", + "icon": "smooth_red_sandstone_slab.png", "version": 0, "idOld": "minecraft:stone_slab2[half=top,variant=red_sandstone]" }, @@ -237,7 +237,7 @@ "id": "minecraft:purpur_slab[type=top,waterlogged=false]", "nameZH": "紫珀台阶", "nameEN": "Purpur slab", - "icon": "purpur_block.png", + "icon": "purpur_block_slab.png", "version": 0, "idOld": "minecraft:purpur_slab[half=top,variant=default]" }, @@ -246,7 +246,7 @@ "id": "minecraft:prismarine_slab[type=top,waterlogged=false]", "nameZH": "海晶石台阶", "nameEN": "Prismarine slab", - "icon": "prismarine.png", + "icon": "prismarine_slab.png", "version": 13, "idOld": "minecraft:stone_slab[half=top,variant=prismarine]" }, @@ -255,7 +255,7 @@ "id": "minecraft:prismarine_brick_slab[type=top,waterlogged=false]", "nameZH": "海晶石砖台阶", "nameEN": "Prismarine brick slab", - "icon": "prismarine_bricks.png", + "icon": "prismarine_bricks_slab.png", "version": 13, "idOld": "minecraft:stone_slab[half=top,variant=prismarine_bricks]" }, @@ -264,10 +264,18 @@ "id": "minecraft:dark_prismarine_slab[type=top,waterlogged=false]", "nameZH": "暗海晶石台阶", "nameEN": "Dark prismarine slab", - "icon": "dark_prismarine.png", + "icon": "dark_prismarine_slab.png", "version": 13, "idOld": "minecraft:stone_slab[half=top,variant=dark_prismarine]" }, + { + "baseColor": 2, + "id": "minecraft:end_stone_brick_slab[type=top,waterlogged=false]", + "nameZH": "末地石砖台阶", + "nameEN": "Endstone brick slab", + "icon": "end_stone_bricks_slab.png", + "version": 0 + }, { "baseColor": 2, "id": "minecraft:sandstone", @@ -402,14 +410,6 @@ "nameEN": "Tuff", "icon": "tuff.png", "version": 17 - }, - { - "baseColor": 2, - "id": "minecraft:end_stone_brick_slab[type=top,waterlogged=false]", - "nameZH": "末地石砖台阶", - "nameEN": "Endstone brick slab", - "icon": "end_stone_bricks.png", - "version": 0 } ] } \ No newline at end of file diff --git a/Blocks/CustomBlocks/acacia_planks.png b/Blocks/CustomBlocks/acacia_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/acacia_planks.png rename to Blocks/CustomBlocks/acacia_planks_slab.png diff --git a/Blocks/CustomBlocks/bamboo_mosaic.png b/Blocks/CustomBlocks/bamboo_mosaic_slab.png similarity index 100% rename from Blocks/CustomBlocks/bamboo_mosaic.png rename to Blocks/CustomBlocks/bamboo_mosaic_slab.png diff --git a/Blocks/CustomBlocks/bamboo_planks.png b/Blocks/CustomBlocks/bamboo_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/bamboo_planks.png rename to Blocks/CustomBlocks/bamboo_planks_slab.png diff --git a/Blocks/CustomBlocks/birch_planks.png b/Blocks/CustomBlocks/birch_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/birch_planks.png rename to Blocks/CustomBlocks/birch_planks_slab.png diff --git a/Blocks/CustomBlocks/bricks.png b/Blocks/CustomBlocks/bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/bricks.png rename to Blocks/CustomBlocks/bricks_slab.png diff --git a/Blocks/CustomBlocks/cherry_slab.png b/Blocks/CustomBlocks/cherry_slab_slab.png similarity index 100% rename from Blocks/CustomBlocks/cherry_slab.png rename to Blocks/CustomBlocks/cherry_slab_slab.png diff --git a/Blocks/CustomBlocks/cobblestone.png b/Blocks/CustomBlocks/cobblestone_slab.png similarity index 100% rename from Blocks/CustomBlocks/cobblestone.png rename to Blocks/CustomBlocks/cobblestone_slab.png diff --git a/Blocks/CustomBlocks/crimson_planks.png b/Blocks/CustomBlocks/crimson_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/crimson_planks.png rename to Blocks/CustomBlocks/crimson_planks_slab.png diff --git a/Blocks/CustomBlocks/dark_oak_planks.png b/Blocks/CustomBlocks/dark_oak_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/dark_oak_planks.png rename to Blocks/CustomBlocks/dark_oak_planks_slab.png diff --git a/Blocks/CustomBlocks/dark_prismarine.png b/Blocks/CustomBlocks/dark_prismarine_slab.png similarity index 100% rename from Blocks/CustomBlocks/dark_prismarine.png rename to Blocks/CustomBlocks/dark_prismarine_slab.png diff --git a/Blocks/CustomBlocks/deepslate_bricks.png b/Blocks/CustomBlocks/deepslate_bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/deepslate_bricks.png rename to Blocks/CustomBlocks/deepslate_bricks_slab.png diff --git a/Blocks/CustomBlocks/end_stone_bricks.png b/Blocks/CustomBlocks/end_stone_bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/end_stone_bricks.png rename to Blocks/CustomBlocks/end_stone_bricks_slab.png diff --git a/Blocks/CustomBlocks/end_stone.png b/Blocks/CustomBlocks/end_stone_slab.png similarity index 100% rename from Blocks/CustomBlocks/end_stone.png rename to Blocks/CustomBlocks/end_stone_slab.png diff --git a/Blocks/CustomBlocks/granite.png b/Blocks/CustomBlocks/granite_slab.png similarity index 100% rename from Blocks/CustomBlocks/granite.png rename to Blocks/CustomBlocks/granite_slab.png diff --git a/Blocks/CustomBlocks/jungle_planks.png b/Blocks/CustomBlocks/jungle_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/jungle_planks.png rename to Blocks/CustomBlocks/jungle_planks_slab.png diff --git a/Blocks/CustomBlocks/mangrove_planks.png b/Blocks/CustomBlocks/mangrove_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/mangrove_planks.png rename to Blocks/CustomBlocks/mangrove_planks_slab.png diff --git a/Blocks/CustomBlocks/nether_bricks.png b/Blocks/CustomBlocks/nether_bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/nether_bricks.png rename to Blocks/CustomBlocks/nether_bricks_slab.png diff --git a/Blocks/CustomBlocks/oak_planks.png b/Blocks/CustomBlocks/oak_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/oak_planks.png rename to Blocks/CustomBlocks/oak_planks_slab.png diff --git a/Blocks/CustomBlocks/prismarine_bricks.png b/Blocks/CustomBlocks/prismarine_bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/prismarine_bricks.png rename to Blocks/CustomBlocks/prismarine_bricks_slab.png diff --git a/Blocks/CustomBlocks/prismarine.png b/Blocks/CustomBlocks/prismarine_slab.png similarity index 100% rename from Blocks/CustomBlocks/prismarine.png rename to Blocks/CustomBlocks/prismarine_slab.png diff --git a/Blocks/CustomBlocks/purpur_block.png b/Blocks/CustomBlocks/purpur_block_slab.png similarity index 100% rename from Blocks/CustomBlocks/purpur_block.png rename to Blocks/CustomBlocks/purpur_block_slab.png diff --git a/Blocks/CustomBlocks/quartz_block.png b/Blocks/CustomBlocks/quartz_block_slab.png similarity index 100% rename from Blocks/CustomBlocks/quartz_block.png rename to Blocks/CustomBlocks/quartz_block_slab.png diff --git a/Blocks/CustomBlocks/smooth_red_sandstone.png b/Blocks/CustomBlocks/smooth_red_sandstone_slab.png similarity index 100% rename from Blocks/CustomBlocks/smooth_red_sandstone.png rename to Blocks/CustomBlocks/smooth_red_sandstone_slab.png diff --git a/Blocks/CustomBlocks/smooth_sandstone.png b/Blocks/CustomBlocks/smooth_sandstone_slab.png similarity index 100% rename from Blocks/CustomBlocks/smooth_sandstone.png rename to Blocks/CustomBlocks/smooth_sandstone_slab.png diff --git a/Blocks/CustomBlocks/smooth_stone.png b/Blocks/CustomBlocks/smooth_stone_slab.png similarity index 100% rename from Blocks/CustomBlocks/smooth_stone.png rename to Blocks/CustomBlocks/smooth_stone_slab.png diff --git a/Blocks/CustomBlocks/spruce_planks.png b/Blocks/CustomBlocks/spruce_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/spruce_planks.png rename to Blocks/CustomBlocks/spruce_planks_slab.png diff --git a/Blocks/CustomBlocks/stone_bricks.png b/Blocks/CustomBlocks/stone_bricks_slab.png similarity index 100% rename from Blocks/CustomBlocks/stone_bricks.png rename to Blocks/CustomBlocks/stone_bricks_slab.png diff --git a/Blocks/CustomBlocks/stone.png b/Blocks/CustomBlocks/stone_slab.png similarity index 100% rename from Blocks/CustomBlocks/stone.png rename to Blocks/CustomBlocks/stone_slab.png diff --git a/Blocks/CustomBlocks/warped_planks.png b/Blocks/CustomBlocks/warped_planks_slab.png similarity index 100% rename from Blocks/CustomBlocks/warped_planks.png rename to Blocks/CustomBlocks/warped_planks_slab.png diff --git a/Blocks/CustomBlocks/waxed_copper_block.png b/Blocks/CustomBlocks/waxed_copper_block_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_copper_block.png rename to Blocks/CustomBlocks/waxed_copper_block_slab.png diff --git a/Blocks/CustomBlocks/waxed_cut_copper.png b/Blocks/CustomBlocks/waxed_cut_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_cut_copper.png rename to Blocks/CustomBlocks/waxed_cut_copper_slab.png diff --git a/Blocks/CustomBlocks/waxed_exposed_copper.png b/Blocks/CustomBlocks/waxed_exposed_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_exposed_copper.png rename to Blocks/CustomBlocks/waxed_exposed_copper_slab.png diff --git a/Blocks/CustomBlocks/waxed_exposed_cut_copper.png b/Blocks/CustomBlocks/waxed_exposed_cut_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_exposed_cut_copper.png rename to Blocks/CustomBlocks/waxed_exposed_cut_copper_slab.png diff --git a/Blocks/CustomBlocks/waxed_oxidized_copper.png b/Blocks/CustomBlocks/waxed_oxidized_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_oxidized_copper.png rename to Blocks/CustomBlocks/waxed_oxidized_copper_slab.png diff --git a/Blocks/CustomBlocks/waxed_oxidized_cut_copper.png b/Blocks/CustomBlocks/waxed_oxidized_cut_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_oxidized_cut_copper.png rename to Blocks/CustomBlocks/waxed_oxidized_cut_copper_slab.png diff --git a/Blocks/CustomBlocks/waxed_weathered_copper.png b/Blocks/CustomBlocks/waxed_weathered_copper_slab.png similarity index 100% rename from Blocks/CustomBlocks/waxed_weathered_copper.png rename to Blocks/CustomBlocks/waxed_weathered_copper_slab.png From 733cae15769962d39be0f0cf9687c88ab41fda5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 10:54:14 +0800 Subject: [PATCH 0484/1123] fix crashing when processing full-transparent pixels --- VisualCraftL/TokiVC_build.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/VisualCraftL/TokiVC_build.cpp b/VisualCraftL/TokiVC_build.cpp index c849dae3..cd1856bd 100644 --- a/VisualCraftL/TokiVC_build.cpp +++ b/VisualCraftL/TokiVC_build.cpp @@ -81,8 +81,11 @@ bool TokiVC::build() noexcept { #pragma omp parallel for schedule(static) for (int64_t r = 0; r < this->img_cvter.rows(); r++) { for (int64_t c = 0; c < this->img_cvter.cols(); c++) { - const auto &variant = - TokiVC::LUT_basic_color_idx_to_blocks[color_id_mat(r, c)]; + auto color_id = color_id_mat(r, c); + if (color_id >= 0xFFFF) + continue; // full transparent pixels, use air instead + + const auto &variant = TokiVC::LUT_basic_color_idx_to_blocks[color_id]; const VCL_block *const *blockpp = nullptr; size_t depth_current = 0; From 32a604d015bccd38b784054e13530b376ef00d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 11:36:48 +0800 Subject: [PATCH 0485/1123] update mc data version --- utilities/MCDataVersion/MCDataVersion.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index 4bedffe4..00992e19 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,7 +30,9 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { - + Snapshot_23w33a = 3570, + Snapshot_23w32a = 3569, + Snapshot_23w31a = 3567, Java_1_20_1 = 3465, Java_1_20_1__rc1 = 3464, Java_1_20 = 3463, From c86a1d4b224ba44e9cf752db117b1589683946ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 13:02:42 +0800 Subject: [PATCH 0486/1123] reduce warnings in opencl code --- utilities/GPUWrapper/OpenCL/ColorDiff.cl | 147 +++++++++++------------ 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/utilities/GPUWrapper/OpenCL/ColorDiff.cl b/utilities/GPUWrapper/OpenCL/ColorDiff.cl index 4de0fef6..be851441 100644 --- a/utilities/GPUWrapper/OpenCL/ColorDiff.cl +++ b/utilities/GPUWrapper/OpenCL/ColorDiff.cl @@ -21,8 +21,8 @@ This file is part of SlopeCraft. */ #define SC_OCL_SPOT_NAN true -//#define SC_OCL_SPOT_NAN false - +__constant const float pi_fp32 = M_PI; +// #define SC_OCL_SPOT_NAN false /// Function definations // compute sum(v*v) @@ -57,7 +57,6 @@ float color_diff_RGB_XYZ(float3 RGB1, float3 RGB2) { } float color_diff_RGB_Better(float3 rgb1, float3 rgb2) { - const float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; const float3 w_vec3 = {w_r, w_g, w_b}; const float thre = 1e-4f; @@ -69,20 +68,20 @@ float color_diff_RGB_Better(float3 rgb1, float3 rgb2) { const float SigmaRGB = (sum3(rgb1) + sum3(rgb2)) / 3.0f; const float3 S_rgb_vec3 = fmin((rgb1 + rgb2) / (SigmaRGB + thre), one_vec3); - - - if(SC_OCL_SPOT_NAN&&have_nan(S_rgb_vec3)) { + + if (SC_OCL_SPOT_NAN && have_nan(S_rgb_vec3)) { printf("S_rgb_vec3 contains nan.\n"); return NAN; } const float sumRGBSquare = dot(rgb1, rgb2); - const float theta = - 2.0f / M_PI * acos((sumRGBSquare * rsqrt(SqrModSquare + thre)) / 1.01f); + const float theta = 2.0f / pi_fp32 * + acos((sumRGBSquare * rsqrt(SqrModSquare + thre)) / 1.01f); - if(SC_OCL_SPOT_NAN&&isnan(theta)) { - printf("theta is nan. sumRGBSquare = %f, SqrModSquare = %f.\n",sumRGBSquare,SqrModSquare); + if (SC_OCL_SPOT_NAN && isnan(theta)) { + printf("theta is nan. sumRGBSquare = %f, SqrModSquare = %f.\n", + sumRGBSquare, SqrModSquare); return NAN; } @@ -92,8 +91,8 @@ float color_diff_RGB_Better(float3 rgb1, float3 rgb2) { const float3 S_t_rgb_vec3 = OnedDelta_rgb_vec3 / sumOnedDelta * S_rgb_vec3 * S_rgb_vec3; - - if(SC_OCL_SPOT_NAN&&have_nan(S_t_rgb_vec3)) { + + if (SC_OCL_SPOT_NAN && have_nan(S_t_rgb_vec3)) { printf("S_t_rgb_vec3 contains nan.\n"); return NAN; } @@ -108,13 +107,13 @@ float color_diff_RGB_Better(float3 rgb1, float3 rgb2) { S_rgb_vec3 * S_rgb_vec3 * delta_rgb_vec3 * delta_rgb_vec3 * w_vec3; const float part1 = sum3(SS_w_delta_delta_vec3) / sum3(w_vec3); - if(SC_OCL_SPOT_NAN&&isnan(part1)) { + if (SC_OCL_SPOT_NAN && isnan(part1)) { printf("part1 is nan.\n"); return NAN; } const float part2 = S_theta * S_ratio * theta * theta; - if(SC_OCL_SPOT_NAN&&isnan(part2)) { + if (SC_OCL_SPOT_NAN && isnan(part2)) { printf("part2 is nan.\n"); return NAN; } @@ -165,10 +164,9 @@ float color_diff_Lab94(float3 lab1_vec3, float3 lab2_vec3) { } float color_diff_Lab00(float3 lab1_vec3, float3 lab2_vec3) { - - const float kL = 1.0; - const float kC = 1.0; - const float kH = 1.0; + const float kL = 1.0f; + const float kC = 1.0f; + const float kH = 1.0f; const float L1 = lab1_vec3[0]; const float a1 = lab1_vec3[1]; const float b1 = lab1_vec3[2]; @@ -192,16 +190,14 @@ float color_diff_Lab00(float3 lab1_vec3, float3 lab2_vec3) { else h1p = atan2(b1, a1p); - if (h1p < 0) - h1p += 2 * M_PI; + if (h1p < 0) h1p += 2 * pi_fp32; if (b2 == 0 && a2p == 0) h2p = 0; else h2p = atan2(b2, a2p); - - if (h2p < 0) - h2p += 2 * M_PI; + + if (h2p < 0) h2p += 2 * pi_fp32; float dLp = L2 - L1; float dCp = C2p - C1p; @@ -233,20 +229,20 @@ float color_diff_Lab00(float3 lab1_vec3, float3 lab2_vec3) { mhp = (h1p + h2p - radians(360.0f)) / 2; } - float T = 1 - 0.17 * cos(mhp - radians(30.0f)) + 0.24 * cos(2 * mhp) + - 0.32 * cos(3 * mhp + radians(6.0f)) - - 0.20 * cos(4 * mhp - radians(63.0f)); + float T = 1 - 0.17f * cos(mhp - radians(30.0f)) + 0.24f * cos(2 * mhp) + + 0.32f * cos(3 * mhp + radians(6.0f)) - + 0.20f * cos(4 * mhp - radians(63.0f)); float dTheta = radians(30.0f) * exp(-square((mhp - radians(275.0f)) / radians(25.0f))); float RC = 2 * sqrt(pow(mCp, 7) / (pow(25.0f, 7.0f) + pow(mCp, 7.0f))); float square_mLp_minus_50 = square(mLp - 50); - float SL = 1 + 0.015 * square_mLp_minus_50 / sqrt(20 + square_mLp_minus_50); + float SL = 1 + 0.015f * square_mLp_minus_50 / sqrt(20 + square_mLp_minus_50); - float SC = 1 + 0.045 * mCp; + float SC = 1 + 0.045f * mCp; - float SH = 1 + 0.015 * mCp * T; + float SH = 1 + 0.015f * mCp * T; float RT = -RC * sin(2 * dTheta); @@ -257,51 +253,54 @@ float color_diff_Lab00(float3 lab1_vec3, float3 lab2_vec3) { return Diffsquare; } - -#define SC_MAKE_COLORDIFF_KERNEL_FUN(kfun_name, diff_fun) \ - __kernel void kfun_name( \ - __global const float *colorset_colors, const ushort colorset_size, \ - __global const float *unconverted_colors, \ - __global ushort *result_idx_dst, __global float *result_diff_dst) { \ - const size_t global_idx = get_global_id(0); \ - const float3 unconverted = {unconverted_colors[global_idx * 3 + 0], \ - unconverted_colors[global_idx * 3 + 1], \ - unconverted_colors[global_idx * 3 + 2]}; \ - if (true && have_nan(unconverted)) { \ - printf("Nan spotted at unconverted. Unconverted = {%f,%f,%f}, " \ - "get_global_id = %llu.\n", \ - unconverted[0], unconverted[1], unconverted[2], global_idx); \ - return; \ - } \ - \ - ushort result_idx = USHRT_MAX - 1; \ - float result_diff = FLT_MAX / 2; \ - \ - for (ushort idx = 0; idx < colorset_size; idx++) { \ - const float3 color_ava = {colorset_colors[idx * 3 + 0], \ - colorset_colors[idx * 3 + 1], \ - colorset_colors[idx * 3 + 2]}; \ - if (true && have_nan(color_ava)) { \ - printf("Nan spotted at color_ava. color_ava = {%f,%f,%f}, " \ - "get_global_id = %llu.\n", \ - color_ava[0], color_ava[1], color_ava[2], global_idx); \ - return; \ - } \ - \ - const float diff_sq = diff_fun(color_ava, unconverted); \ - if (true && isnan(diff_sq)) { \ - printf("Spotted nan at idx = %u.\n", (idx)); \ - return; \ - } \ - if (result_diff > diff_sq) { \ - /* this branch may be optimized */ \ - result_idx = idx; \ - result_diff = diff_sq; \ - } \ - } \ - \ - result_idx_dst[global_idx] = result_idx; \ - result_diff_dst[global_idx] = result_diff; \ +#define SC_MAKE_COLORDIFF_KERNEL_FUN(kfun_name, diff_fun) \ + __kernel void kfun_name( \ + __global const float *colorset_colors, const ushort colorset_size, \ + __global const float *unconverted_colors, \ + __global ushort *result_idx_dst, __global float *result_diff_dst) { \ + const size_t global_idx = get_global_id(0); \ + const float3 unconverted = {unconverted_colors[global_idx * 3 + 0], \ + unconverted_colors[global_idx * 3 + 1], \ + unconverted_colors[global_idx * 3 + 2]}; \ + if (true && have_nan(unconverted)) { \ + printf( \ + "Nan spotted at unconverted. Unconverted = {%f,%f,%f}, " \ + "get_global_id = %u.\n", \ + unconverted[0], unconverted[1], unconverted[2], \ + (unsigned int)global_idx); \ + return; \ + } \ + \ + ushort result_idx = USHRT_MAX - 1; \ + float result_diff = FLT_MAX / 2; \ + \ + for (ushort idx = 0; idx < colorset_size; idx++) { \ + const float3 color_ava = {colorset_colors[idx * 3 + 0], \ + colorset_colors[idx * 3 + 1], \ + colorset_colors[idx * 3 + 2]}; \ + if (true && have_nan(color_ava)) { \ + printf( \ + "Nan spotted at color_ava. color_ava = {%f,%f,%f}, " \ + "get_global_id = %u.\n", \ + color_ava[0], color_ava[1], color_ava[2], \ + (unsigned int)global_idx); \ + return; \ + } \ + \ + const float diff_sq = diff_fun(color_ava, unconverted); \ + if (true && isnan(diff_sq)) { \ + printf("Spotted nan at idx = %u.\n", (idx)); \ + return; \ + } \ + if (result_diff > diff_sq) { \ + /* this branch may be optimized */ \ + result_idx = idx; \ + result_diff = diff_sq; \ + } \ + } \ + \ + result_idx_dst[global_idx] = result_idx; \ + result_diff_dst[global_idx] = result_diff; \ } SC_MAKE_COLORDIFF_KERNEL_FUN(match_color_RGB, color_diff_RGB_XYZ) From 206181464d8c958820d6a7f733da5c45e24dfe3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 13:03:04 +0800 Subject: [PATCH 0487/1123] report opencl compilation errors --- VisualCraft/VCWind_gpu.cpp | 21 +++++++++++++++----- VisualCraftL/TokiVC.cpp | 23 ++++++++++++++++++++++ VisualCraftL/TokiVC.h | 17 ++++------------ VisualCraftL/VisualCraftL.h | 8 ++++++++ utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 19 ++++++++++++++++-- 5 files changed, 68 insertions(+), 20 deletions(-) diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index 6ab9801c..f6496bd3 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -222,11 +222,22 @@ QString VCWind::update_gpu_device(QPoint current_choice) noexcept { .arg(current_choice.x()) .arg(current_choice.y()); } - - if (!this->kernel->set_gpu_resource(plat, dev)) { - return VCWind::tr("设置 GPU 设备失败。,平台序号为%1,设备序号为%2") - .arg(current_choice.x()) - .arg(current_choice.y()); + { + std::string error_msg; + error_msg.resize(4096); + VCL_Kernel::gpu_options gpu_options; + VCL_string_deliver s{ + .data = error_msg.data(), .size = 0, .capacity = error_msg.size()}; + gpu_options.error_message = &s; + if (!this->kernel->set_gpu_resource(plat, dev, gpu_options)) { + error_msg.resize(s.size); + return VCWind::tr( + "设置 GPU " + "设备失败。平台序号为%1,设备序号为%2,详细错误信息:\n%3") + .arg(current_choice.x()) + .arg(current_choice.y()) + .arg(error_msg.data()); + } } VCL_release_device(dev); diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 877d75d3..12ba8618 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -737,3 +737,26 @@ void TokiVC::converted_image(uint32_t *dest, int64_t *rows, int64_t *cols, this->img_cvter.converted_image(dest, rows, cols, !write_dest_row_major); } + +bool TokiVC::set_gpu_resource(const VCL_GPU_Platform *p, + const VCL_GPU_Device *d, + const gpu_options &option) noexcept { + if (this->img_cvter.have_gpu_resource()) { + gpu_wrapper::gpu_interface::destroy(this->img_cvter.gpu_resource()); + } + auto platp = static_cast(p->pw); + auto devp = static_cast(d->dw); + + std::pair err; + auto gi = gpu_wrapper::gpu_interface::create(platp, devp, err); + if (gi == nullptr || !gi->ok_v()) { + err.second = fmt::format("{}, error code = {}", err.second, err.first); + write_to_string_deliver(err.second, option.error_message); + return false; + } else { + write_to_string_deliver("", option.error_message); + } + + this->img_cvter.set_gpu_resource(gi); + return this->img_cvter.gpu_resource()->ok_v(); +} \ No newline at end of file diff --git a/VisualCraftL/TokiVC.h b/VisualCraftL/TokiVC.h index a8e3a671..dc0a97c7 100644 --- a/VisualCraftL/TokiVC.h +++ b/VisualCraftL/TokiVC.h @@ -61,21 +61,12 @@ class TokiVC : public VCL_Kernel { bool set_gpu_resource(const VCL_GPU_Platform *p, const VCL_GPU_Device *d) noexcept override { - if (this->img_cvter.have_gpu_resource()) { - gpu_wrapper::gpu_interface::destroy(this->img_cvter.gpu_resource()); - } - auto platp = static_cast(p->pw); - auto devp = static_cast(d->dw); - - auto gi = gpu_wrapper::gpu_interface::create(platp, devp); - if (gi == nullptr || !gi->ok_v()) { - return false; - } - - this->img_cvter.set_gpu_resource(gi); - return this->img_cvter.gpu_resource()->ok_v(); + return this->set_gpu_resource(p, d, {}); } + bool set_gpu_resource(const VCL_GPU_Platform *p, const VCL_GPU_Device *d, + const gpu_options &option) noexcept override; + bool prefer_gpu() const noexcept override { return this->imgcvter_prefer_gpu; } diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index e4d11ced..0e5eb35f 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -270,6 +270,14 @@ class VCL_Kernel { const int (&weOffset)[3] = {0, 0, 0}, const char *utf8_Name = "", const char *const *const utf8_requiredMods = nullptr, const int requiredModsCount = 0) const noexcept = 0; + + struct gpu_options { + const uint64_t lib_version{SC_VERSION_U64}; + VCL_string_deliver *error_message{nullptr}; + }; + virtual bool set_gpu_resource(const VCL_GPU_Platform *, + const VCL_GPU_Device *, + const gpu_options &option) noexcept = 0; /* /// export map into Structure files (*.NBT) virtual void exportAsWESchem( diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index cee110f9..6ab968dc 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -26,6 +26,7 @@ This file is part of SlopeCraft. #include #include #include +#include extern "C" { extern const unsigned char ColorManip_cl_rc[]; @@ -141,9 +142,23 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { return; } - this->error = this->program.build(); + this->error = this->program.build( + "-cl-mad-enable -cl-unsafe-math-optimizations " + "-cl-single-precision-constant", + nullptr, nullptr); if (!this->ok()) { - this->err_msg = "Failed to build program."; + cl_int ec_get_build_log{CL_SUCCESS}; + auto build_log = this->program.getBuildInfo( + this->device, &ec_get_build_log); + if (ec_get_build_log == CL_SUCCESS) { + this->err_msg = + fmt::format("Failed to build program. Build log:\n{}", build_log); + } else { + this->err_msg = fmt::format( + "Failed to build program, and then failed to retrieve build log with " + "error code {}", + ec_get_build_log); + } return; } From e65ac15a5e09035d83113b0a5203bab1652d02cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 13:03:38 +0800 Subject: [PATCH 0488/1123] add test target for opencl source code --- utilities/GPUWrapper/CMakeLists.txt | 16 +++++++++------ utilities/GPUWrapper/OpenCL/CMakeLists.txt | 23 +++++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/utilities/GPUWrapper/CMakeLists.txt b/utilities/GPUWrapper/CMakeLists.txt index 479ea003..b21a1ede 100644 --- a/utilities/GPUWrapper/CMakeLists.txt +++ b/utilities/GPUWrapper/CMakeLists.txt @@ -6,19 +6,23 @@ add_library(GPUInterface STATIC target_include_directories(GPUInterface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_features(GPUInterface PUBLIC cxx_std_20) -if(${LINUX}) +include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) +find_package(fmt REQUIRED) +target_link_libraries(GPUInterface PUBLIC fmt::fmt) + +if (${LINUX}) set_target_properties(GPUInterface PROPERTIES TARGET_INDENPENDENT_CODE TRUE) -endif() +endif () -if(${SlopeCraft_GPU_API} STREQUAL "OpenCL") +if (${SlopeCraft_GPU_API} STREQUAL "OpenCL") add_subdirectory(OpenCL) target_compile_definitions(GPUInterface PUBLIC -DSLOPECRAFT_GPU_API="OpenCL") return() -endif() +endif () -if(${SlopeCraft_GPU_API} STREQUAL "None") +if (${SlopeCraft_GPU_API} STREQUAL "None") add_subdirectory(None) return() -endif() +endif () message(FATAL_ERROR "Invalid value for \"SlopeCraft_GPU_API\" : ${SlopeCraft_GPU_API}") \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 2b097ab0..34be996f 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -11,9 +11,9 @@ target_sources(GPUInterface PRIVATE GPU_interface.cpp) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() +endif () # convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) add_resource_config_time(ColorManip_cl_rc ColorDiff.cl) @@ -32,7 +32,7 @@ target_link_libraries(GPUInterface message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") -if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) +if (NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) target_compile_definitions(GPUInterface PRIVATE SLOPECRAFT_NO_CL_HPP) message(STATUS "Failed to find cl.hpp. This file doesn't exists in opencl include dir. SlopeCraft assumes that opencl.hpp exists, and will try to include it.") @@ -46,12 +46,21 @@ if(NOT EXISTS ${OpenCL_INCLUDE_DIR}/CL/cl.hpp) # message(STATUS "Manually found opencl_hpp_file = ${opencl_hpp_file}") file(GLOB_RECURSE all_cl_files "${OpenCL_INCLUDE_DIR}/CL/*") message(STATUS "All opencl headers: ${all_cl_files}") -else() +else () message(STATUS "Found opencl C++ header: ${OpenCL_INCLUDE_DIR}/CL/cl.hpp") -endif() +endif () target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) -if(${LINUX}) +if (${LINUX}) set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() \ No newline at end of file +endif () + +find_program(clang_exe NAMES "clang") +if (clang_exe) + set(binfile ${CMAKE_CURRENT_BINARY_DIR}/ColorDiff.bc) + add_custom_target(test_opencl_source ALL + COMMAND ${clang_exe} ${CMAKE_CURRENT_SOURCE_DIR}/ColorDiff.cl -c -o ${binfile} + SOURCES ColorDiff.cl + BYPRODUCTS ${binfile}) +endif () \ No newline at end of file From 0154970aaf586c7f8520a587c3fa0524ed36e22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 14:04:40 +0800 Subject: [PATCH 0489/1123] add slabs for andesite, granite and diorite --- Blocks/CustomBlocks.json | 63 ++++++++++++++++++ Blocks/CustomBlocks/andesite_slab.png | Bin 0 -> 1609 bytes Blocks/CustomBlocks/diorite_slab.png | Bin 0 -> 1756 bytes Blocks/CustomBlocks/granite.png | Bin 0 -> 335 bytes .../CustomBlocks/polished_andesite_slab.png | Bin 0 -> 1610 bytes .../polished_diorite.png | Bin Blocks/CustomBlocks/polished_diorite_slab.png | Bin 0 -> 1632 bytes .../polished_granite.png | Bin Blocks/CustomBlocks/polished_granite_slab.png | Bin 0 -> 1610 bytes Blocks/FixedBlocks.json | 18 ----- 10 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 Blocks/CustomBlocks/andesite_slab.png create mode 100644 Blocks/CustomBlocks/diorite_slab.png create mode 100644 Blocks/CustomBlocks/granite.png create mode 100644 Blocks/CustomBlocks/polished_andesite_slab.png rename Blocks/{FixedBlocks => CustomBlocks}/polished_diorite.png (100%) create mode 100644 Blocks/CustomBlocks/polished_diorite_slab.png rename Blocks/{FixedBlocks => CustomBlocks}/polished_granite.png (100%) create mode 100644 Blocks/CustomBlocks/polished_granite_slab.png diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 5dda93ed..90be600e 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -310,6 +310,24 @@ "version": 0, "idOld": "minecraft:stone_slab[half=top,variant=granite]" }, + { + "baseColor": 10, + "id": "minecraft:polished_granite", + "nameZH": "磨制花岗岩", + "nameEN": "Polished granite", + "icon": "polished_granite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_granite]" + }, + { + "baseColor": 10, + "id": "minecraft:polished_granite_slab[type=top,waterlogged=false]", + "nameZH": "磨制花岗岩台阶", + "nameEN": "Polished granite slab", + "icon": "polished_granite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=polished_granite]" + }, { "baseColor": 11, "id": "minecraft:andesite", @@ -319,6 +337,15 @@ "version": 0, "idOld": "minecraft:stone[variant=andesite]" }, + { + "baseColor": 11, + "id": "minecraft:andesite_slab[type=top,waterlogged=false]", + "nameZH": "安山岩台阶", + "nameEN": "Andesite slab", + "icon": "andesite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=andesite]" + }, { "baseColor": 11, "id": "minecraft:polished_andesite", @@ -328,6 +355,15 @@ "version": 0, "idOld": "minecraft:stone[variant=smooth_andesite]" }, + { + "baseColor": 11, + "id": "minecraft:polished_andesite_slab[type=top,waterlogged=false]", + "nameZH": "磨制安山岩台阶", + "nameEN": "Polished andesite slab", + "icon": "polished_andesite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=polished_andesite]" + }, { "baseColor": 14, "id": "minecraft:diorite", @@ -337,6 +373,33 @@ "version": 0, "idOld": "minecraft:stone[variant=diorite]" }, + { + "baseColor": 14, + "id": "minecraft:diorite_slab[type=top,waterlogged=false]", + "nameZH": "闪长岩台阶", + "nameEN": "Diorite slab", + "icon": "diorite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=diorite]" + }, + { + "baseColor": 14, + "id": "minecraft:polished_diorite", + "nameZH": "磨制闪长岩", + "nameEN": "Polished diorite", + "icon": "polished_diorite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_diorite]" + }, + { + "baseColor": 14, + "id": "minecraft:polished_diorite_slab[type=top,waterlogged=false]", + "nameZH": "磨制闪长岩台阶", + "nameEN": "Polished diorite slab", + "icon": "polished_diorite_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=polished_diorite]" + }, { "baseColor": 15, "id": "minecraft:red_sandstone", diff --git a/Blocks/CustomBlocks/andesite_slab.png b/Blocks/CustomBlocks/andesite_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..6a97365037b2c43b8e0f308e0cef03f51c2dd1de GIT binary patch literal 1609 zcmbVMTWl0n7@it!wlo+FJQyVDIO_#gW@mP1Z*%O3wcD~An9?j8X-!NxJ9Bn-vO9Ce znc42Pu|bItlqmXOVroMI+8VG*#0$o1T0+qW6dp7@P_4uVFfj;;8VpA3nY{%}mB=J# z&h0zjfB&EF@7uV1+3IB!MJ-Pz;wdt(aEGUr{5yVGgk)+n6N5HIwXbwX3pF-=H$~n4 zvz8uk2IS2^!MY!+ID`BZ-6Uv=>fBH*iV zLR&}r(#l9d5mjcxBXnm45CR=Jkgn)O!v+fT)?#33P zMSp-*cs@W!ML&$Gp=elGPY3y+!0`eX6j(k6!Vw@u>H5bIah93|sd#T)7}-fo-f>L8 zapiK^Ul#n>%5ecv6gfV~1%oU>u=cRwzzS>F-UdS)*@~r^j)o1|WrP`AawLYRTC+hn zo3w^q_Y?6LSAixM@bj)sRiLUgac0RXR)wnyhl)r?hGP?Kpoul}*ui!l{|j~V`UU~S zx3b)nv7|1#-V|XwJwwEdxgl7{U-LqW;7#1NbP znx+C2QL+$b!mI-MD9fXez{W%DX}GJ!}CsgX?MeH<$#H?ocQ>i>Md#nMP=!Qw6R zxCQ5?1W0H$3D$7EBDSKZ>Z_tgSF->>#m#PsQQWX1m8l3@W~2D5S2 zDMJf&<%qX#nob;1o^$K4W(W6A6RUUE)ocS!8iBiPwji=;HZf$7&SjAn^;=tXilSOt zlJTx|?8Qqj2MQkqEEa{l#(@U*G$jr!&tFBnsahKl{p; zgCKn>`QyU$<%JVR*MDmtp8jUBb;sQ7ntdJZk9xe+X>m846~74eP-BzXF-AN?{W`ku zogE*KubkYocl#J~TKx1Xn0RgGvyQ}j=dML=d*-7{R~EcSy%z`XSa<)_hrZ2sP543= zoNJ#yv1xv2eq(REGCX?U$?(A=XI|}9-}=Fd{_*FtlZRSXb)2_eI#-b&V0?GNxlU>R zo)1!|<|Ypvn>}0hypejrbHVEKt^H|_XY~8G4_tjewQ6U{+|>r()E~C?hxd+Oe7*lj eVer`0@9kf;?vE`#{rCa5*(ZDY;_p7Tedpig4IuLX literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/diorite_slab.png b/Blocks/CustomBlocks/diorite_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..4ca19dd9eb58a9f7e2997ed5c3678f8d25946353 GIT binary patch literal 1756 zcmbVN4NTNl9Pgn+rV?D-CZGwmvdBK}+H1Lk>$o}KWH3EGkAONCOZ)Dwa=mtKk2@HV zIFU{F<%pm#Kof#XU?FTomL+V|Su z|Ks=n>c0Hk=c1R!FGUa}Iw#v!2%jso6%`5Z3DY+j_;^st-l8DLvX$D>AR({ECYssAVD;Oq-_XD3|kIVv<$d-uNAv~@-&9>oE0lE*$KOp3EX^k zl?;liavf|{Icwpt4bPxy0U9b0fXbi&!Q)lvfE5esrQu$CjbmsKqLy2+bj=`IYR^YA zMH!$LgHg{Cgb_`#7?@NpImJXhg^~nG;RJ<~l%7bXO=g-(LFX?Fnv*#vU1-aiHwI5u z%&n>tjpKg5-{7YVqU^$r7K;TZNSq|~5TREpy($yXdzEzy8f-veWnNNw(Ti#tnKIF* zS~2Kqh=U-7)q0irIKhbF0Y<`&214T$1afQ`C;4Pg&^X89zyk!}RTYRehOv@cR7J%t z-bHoz^KAxTZ0+{2jXU}x2w@Y7y0HS%m=DMu(Tbx|0(c=%M4!xpjTO+%bs8Iq&XfV8 zin2o#Jqwx2UvL>ElMQAxsf71(qF;IZ76D*mRA9xltigQgNy=fQXp@OHl25|)5kv@T z7dhTpc^4>kI~3Lo$EeIb!5m9FMOk1VVP0Td0GGTj3=M~o&J;bO3=Ko?sGt{iJDuZI zRL0AK9Gew`oDDqB(I$>6qmqp&db87o5rOzbqQn3yL!4`9r)_A!o=M>zukY~!hkZ` zHacFrt8rIjwQe@r966o8l}XyaWbcalnTe}MY8y+p4SZU~jU(TPeYscJFM7fkRr~RDwYq)QweN;IyP)`koxX>+k9{;bTxgM%!2 zlYGtFVG&K+H`6z7ep8?7F9_sKfo|i`g zb9LY%B%R{Lfxxj$?x|D-{=nO+)}bPkqo`0YFHDZ;ZF8SU!DV>_Cjn!KxW^#jB@i>kBVhQN(cv?e72p002ovPDHLkV1l%Biq!xB literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/polished_andesite_slab.png b/Blocks/CustomBlocks/polished_andesite_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..015282fce005f64258fe206c218db28b8dae127e GIT binary patch literal 1610 zcmbVMTWB0r7@jm5V%lgxBQY8?Oh77jc5Zu{p<_%l(QM3a;%3{dbdjE&IlDV#=aQL8 zcQ>@QZm|$W2?%1-BHF%G&`?3NP>n&M1?fu=3$0c1Q1IReNexW{^~~OAC0gvjnRENj z_uv1i;mC8%P3=t>hBb%!r6`(P+|k&8{+-J=0h;bJ`(Ly%Z1aQesKaKCwPDyjSJhbD ziH8RT+0Z;dF_O@e*Gz=Qu6UbxG!ILnp>LRgp=1T%s6_FVAh3T-_3o~l}qy2jF1rt(HXd4rj4Ey#XHM?AEOrh6;z%i_tVPvb38m_90 zvtExM-#V)5ijlLQyyXFufCELsjT(v<$#OA<6MT%odY?k!qvHwwK**07LZq#ak%A{-V%y6pg6h9OBLkj)-d zRRop=ypIQdGMQBTB*S?*GUyNTq#Ter#fP?v465%XL!NLWTYazm&-X)?ib@M)@0!Og zI5#DPe$__7DpV?B1ddl$Srsp3fdFJTyG25F!wMCma;)C92g`rc=1OJtJ@Tk zdSbyh{+MQl4n5O$xbvZ6OZL52dv+%h>&ua|-5{BKto_8)p<{{mEzyD38XgrEJG7b8 z&M%9f{jh)O#^wvvU3L%MWAg`@X~CyQFWGjznGJ+=bBSxHPl#QX}2C zula>kbIVfa;Mw;h`R9M_IC<%V<-sS!J?#D0HqFNi-tdK;*FSper_G1I9!V?`Zyszr z^37av;ODi~q0yW4=@n+zVDf1t}yCEz6Lx(>=v9ta$MI1WO&B7E${}}o%zu2TY+`+r| z-o4NJe1Cs$e{avO_09J-69ln7+!c)C`A%!t*5UW&KmG!EYSOx%FbLxI4c2HN4jtJ< z5Nm&z;|Vhn=@vw!&_F^-NEZ|hqY0wDqo4tC5SnBXre)PnEuTI^k+S5c`rQ#Wq6J_^ z?kedpR_ck1r9sgrQ5`$T_JV*36lemnpk!4;DEO%|uYlLqXNDrn5OdH^by@<+M5LDt zARUrEnsbOO%aI-*4ZM=e<90qm@+|LUSSQ0f9jsSyw+T)US$!xhPM1Bo@O|o&&RMl!}AV|a2Q3^1Op&{zBX39t=999!Dr! zi&Sq-Ws-N%ZRErKvMQmxVZZJI3<4ASDJyC?UJl+F=bVC@6L{A)96pwY+_`kzqQ+u< ztpw4qDIDyKd#5f>&#DXT#?T%21jaY+IyyEnFgw36zc|GNuN@lt?d&)7d%s3oUS_?o zbl=wmcTWt&7N_4>bM(?xb9wvK;+MJmKR7aRcrpL%Xp%iYynO2NQp=1?NL0f+?>ElR zwanOm?CS>2R{}3~N5>}%BSmO?)j9l-d9v}*N!yG)s|5CLwLib|!q1C;t{r)5g#GrE z5PN-eT!=jr+R9Hx=F-1>Wgbs_p3Z*XX1i;jZG*d^ai4vG+;igNuRpu{qk*}^bC*^g zysb3*(z%0=dzX@*4x=9qfAMD1*`2|+9_V+SSa|QXqyZyj)xO8o5^ReZN`&-+O zojbS^YCZnp0XEU`_UQ|=pY&ajwYHyjoFD#fY2?f(vF*xhYryvCyVgG-9O?<4+&M7z EHwOMCNB{r; literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/polished_granite.png b/Blocks/CustomBlocks/polished_granite.png similarity index 100% rename from Blocks/FixedBlocks/polished_granite.png rename to Blocks/CustomBlocks/polished_granite.png diff --git a/Blocks/CustomBlocks/polished_granite_slab.png b/Blocks/CustomBlocks/polished_granite_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..92b488ab6ae3551c4ab91d1b63fe442bb39ef960 GIT binary patch literal 1610 zcmbVMTWs4@7^=SWKE{IbXiI}gaF4rNvy^`p6xbi z#if)XQ32v67#r}Ahe^{)i?ltIk%z5f4`>}sw7dZlPp$gUPJ&fzzy!y+X+wpHSvo$q z?|lFLpX%@H-PZ7M1BPMS;;~2q&CSl(dN=y-{PiyhP4^hFLl%ZLKHv-&cKnkEG3>5& zH92GtiTimOYNVvV6d((lfzTMXdr!fT{I&NHD33Uit-V+N=lds36_u8h zyJH@w;GC4;W2%LMHCC;NgWzy=l~eI@7VwhnWVb-bPFR6LRFBm=_CSR;p9P5YKf+ys zSukzqB@=`*$XmBfCkiP~IdxdEgZih5<-40|wgyLyz**K?5Zct67|>DYGEs|KT8^eL z%;kkd?9?%jYvGNr$?sklJ*PT8bANL!Fn4lpMLu$Lqy2jE!-X$zxba^u f&zxEPHr@VXQ)0(!;yUCeoo*kG_C;p9pP&32Ib0m$ literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks.json b/Blocks/FixedBlocks.json index 368ab8d6..137c6acf 100644 --- a/Blocks/FixedBlocks.json +++ b/Blocks/FixedBlocks.json @@ -317,15 +317,6 @@ "idOld": "minecraft:dirt[variant=coarse_dirt,snowy=false]", "endermanPickable": true }, - { - "baseColor": 10, - "id": "minecraft:polished_granite", - "nameZH": "磨制花岗岩", - "nameEN": "Polished granite", - "icon": "polished_granite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_granite]" - }, { "baseColor": 10, "id": "minecraft:jungle_planks", @@ -416,15 +407,6 @@ "idOld": "minecraft:planks[variant=oak]", "burnable": true }, - { - "baseColor": 14, - "id": "minecraft:polished_diorite", - "nameZH": "磨制闪长岩", - "nameEN": "Polished diorite", - "icon": "polished_diorite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_diorite]" - }, { "baseColor": 14, "id": "minecraft:quartz_block", From 29bb9468ada7429862a7cca3d66661b4a3941e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 14:26:14 +0800 Subject: [PATCH 0490/1123] add slabs for deepslate and blockstones --- Blocks/CustomBlocks.json | 56 ++++++++++++++++++ Blocks/CustomBlocks/blackstone_slab.png | Bin 0 -> 315 bytes .../CustomBlocks/cobbled_deepslate_slab.png | Bin 0 -> 346 bytes Blocks/CustomBlocks/deepslate_tiles_slab.png | Bin 0 -> 260 bytes Blocks/CustomBlocks/mud_bricks_slab.png | Bin 0 -> 394 bytes .../CustomBlocks/polished_blackstone_slab.png | Bin 0 -> 324 bytes .../CustomBlocks/polished_deepslate_slab.png | Bin 0 -> 309 bytes 7 files changed, 56 insertions(+) create mode 100644 Blocks/CustomBlocks/blackstone_slab.png create mode 100644 Blocks/CustomBlocks/cobbled_deepslate_slab.png create mode 100644 Blocks/CustomBlocks/deepslate_tiles_slab.png create mode 100644 Blocks/CustomBlocks/mud_bricks_slab.png create mode 100644 Blocks/CustomBlocks/polished_blackstone_slab.png create mode 100644 Blocks/CustomBlocks/polished_deepslate_slab.png diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 90be600e..58e58e28 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -450,6 +450,54 @@ "icon": "blackstone.png", "version": 16 }, + { + "baseColor": 29, + "id": "minecraft:blackstone_slab[type=top,waterlogged=false]", + "nameZH": "黑石台阶", + "nameEN": "Black stone slab", + "icon": "blackstone_slab.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:polished_blackstone_slab[type=top,waterlogged=false]", + "nameZH": "磨制黑石台阶", + "nameEN": "Polished black stone slab", + "icon": "polished_blackstone_slab.png", + "version": 16 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_bricks_slab[type=top,waterlogged=false]", + "nameZH": "深板岩砖台阶", + "nameEN": "Deepslate bricks slab", + "icon": "deepslate_bricks_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_tiles_slab[type=top,waterlogged=false]", + "nameZH": "深板岩瓦台阶", + "nameEN": "Deepslate tiles slab", + "icon": "deepslate_tiles_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:cobbled_deepslate_slab[type=top,waterlogged=false]", + "nameZH": "深板岩圆石台阶", + "nameEN": "Cobbled deepslate slab", + "icon": "cobbled_deepslate_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:polished_deepslate_slab[type=top,waterlogged=false]", + "nameZH": "磨制深板岩台阶", + "nameEN": "Polished deepslate slab", + "icon": "polished_deepslate_slab.png", + "version": 17 + }, { "baseColor": 29, "id": "minecraft:crying_obsidian", @@ -473,6 +521,14 @@ "nameEN": "Tuff", "icon": "tuff.png", "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:mud_bricks_slab[type=top,waterlogged=false]", + "nameZH": "泥砖台阶", + "nameEN": "Mud bricks slab", + "icon": "mud_bricks_slab.png", + "version": 19 } ] } \ No newline at end of file diff --git a/Blocks/CustomBlocks/blackstone_slab.png b/Blocks/CustomBlocks/blackstone_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..c8219f027bc0870299f3fb3ee5a2bd256d1e5af7 GIT binary patch literal 315 zcmV-B0mS}^P)M}8>&o+ z5Q+tcf;yuXOz&RKKOi!7%jjI9y|=*j-~}J#<{X41`p=8L#f;@(*W=p+TOhV8s8mv2-)UG z-I!637n3ELJ~-|k?g2QR0)24AXfYd&m?ABWEO|U3xo;$FBm}zn}(~G$aKw zaDWA5&sd@^$VhdjFr=VI1T=4VZ*MivGtbP+Q}n;U9}!p`kH;Cnd(Y+ag@~dog<%N! z4Iv_;aIQzGb%tY{D7^QKLy4Hv&wBAzGwdQ)A satGF0Vw^ai8?@dMLdVH7;FqSF7 zWrIps_l^Io_L~-1&eivP%yK_(VWAf9Dkg?ST2b%0<>p&3OmH#gaTc1$^yCg-WY3c| z?_E;L8dbivE1SJ$e_54$vUu*)AkjXRsQ2lY7!qWTPm0doY8(Fhm)nMkmg~N$Dsd?8 z`FY;B^le!zyP^FCK_`v>C(S$;z5jikU+3rKD^W$Z)$CqV3-0gP64(ax0fVQjpUXO@ GgeCwnWn~Kh literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/mud_bricks_slab.png b/Blocks/CustomBlocks/mud_bricks_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..38a1152fb2356cc226787ddfb89bcea81ce21a77 GIT binary patch literal 394 zcmV;50d@X~P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00009 za7bBm000XU000XU0RWnu7ytkP07*naR5*?8kUdVsFc5{mM2Yg}4N9@pv`F;ahs$so zPJ=kWQi72zIbO$Bq?jU!l_=#l6u22{-uQcOoP-d#<)k;g{s;UKK=$_f5&*OwQL5+t zQ}g_IM_CBkHjjf^k2r7mxLBSZ>ZoU{FxWsb#*W z1YLKE1I`+2wx&Zd@!3Lz6XzMv$*PY0|e%y|H9Y!DrJlZaC?OxY5UHYEvB0T_2 omG3~(Obd*IevzK0%DE0Bzhiuk-*6RP8UO$Q07*qoM6N<$f)gB?^#A|> literal 0 HcmV?d00001 diff --git a/Blocks/CustomBlocks/polished_blackstone_slab.png b/Blocks/CustomBlocks/polished_blackstone_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..a1a893a931930b67ccc5da6eab54fda2884ac2ca GIT binary patch literal 324 zcmV-K0lWT*P)ViL`v)JrDwYm#^x z;?W?1N*kR0A_Tk0B>g!BnpofzVlpa9k&_1URsdS^_QZ<&yN8(Ic}+v4D8;Y-&-pjR WorJ0EHtezh0000Io@X$B>h){EKUpx#^Su8lNqgk~oL=-Yh51S-lrg)oX}Zmi_rnO&f1QeRNvWMyj%4 zo~Ef;okCSj=@GwN$Pi*(*HmQzK#UO)u^wQz-5?@1PkVr03+IB2iKox|00000NkvXX Hu0mjfl~8}| literal 0 HcmV?d00001 From 0758e88961cfa252a1ba900146adc42d542e6510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 14:26:21 +0800 Subject: [PATCH 0491/1123] strip pngs --- Blocks/CustomBlocks/andesite_slab.png | Bin 1609 -> 335 bytes Blocks/CustomBlocks/diorite_slab.png | Bin 1756 -> 482 bytes Blocks/CustomBlocks/polished_andesite_slab.png | Bin 1610 -> 336 bytes Blocks/CustomBlocks/polished_diorite_slab.png | Bin 1632 -> 358 bytes Blocks/CustomBlocks/polished_granite_slab.png | Bin 1610 -> 336 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Blocks/CustomBlocks/andesite_slab.png b/Blocks/CustomBlocks/andesite_slab.png index 6a97365037b2c43b8e0f308e0cef03f51c2dd1de..73b3763d09e6654e5d5286352f4f88eb4ba9faf9 100644 GIT binary patch delta 11 ScmX@fbDn8}#bzT`aYg_dLIZIC literal 1609 zcmbVMTWl0n7@it!wlo+FJQyVDIO_#gW@mP1Z*%O3wcD~An9?j8X-!NxJ9Bn-vO9Ce znc42Pu|bItlqmXOVroMI+8VG*#0$o1T0+qW6dp7@P_4uVFfj;;8VpA3nY{%}mB=J# z&h0zjfB&EF@7uV1+3IB!MJ-Pz;wdt(aEGUr{5yVGgk)+n6N5HIwXbwX3pF-=H$~n4 zvz8uk2IS2^!MY!+ID`BZ-6Uv=>fBH*iV zLR&}r(#l9d5mjcxBXnm45CR=Jkgn)O!v+fT)?#33P zMSp-*cs@W!ML&$Gp=elGPY3y+!0`eX6j(k6!Vw@u>H5bIah93|sd#T)7}-fo-f>L8 zapiK^Ul#n>%5ecv6gfV~1%oU>u=cRwzzS>F-UdS)*@~r^j)o1|WrP`AawLYRTC+hn zo3w^q_Y?6LSAixM@bj)sRiLUgac0RXR)wnyhl)r?hGP?Kpoul}*ui!l{|j~V`UU~S zx3b)nv7|1#-V|XwJwwEdxgl7{U-LqW;7#1NbP znx+C2QL+$b!mI-MD9fXez{W%DX}GJ!}CsgX?MeH<$#H?ocQ>i>Md#nMP=!Qw6R zxCQ5?1W0H$3D$7EBDSKZ>Z_tgSF->>#m#PsQQWX1m8l3@W~2D5S2 zDMJf&<%qX#nob;1o^$K4W(W6A6RUUE)ocS!8iBiPwji=;HZf$7&SjAn^;=tXilSOt zlJTx|?8Qqj2MQkqEEa{l#(@U*G$jr!&tFBnsahKl{p; zgCKn>`QyU$<%JVR*MDmtp8jUBb;sQ7ntdJZk9xe+X>m846~74eP-BzXF-AN?{W`ku zogE*KubkYocl#J~TKx1Xn0RgGvyQ}j=dML=d*-7{R~EcSy%z`XSa<)_hrZ2sP543= zoNJ#yv1xv2eq(REGCX?U$?(A=XI|}9-}=Fd{_*FtlZRSXb)2_eI#-b&V0?GNxlU>R zo)1!|<|Ypvn>}0hypejrbHVEKt^H|_XY~8G4_tjewQ6U{+|>r()E~C?hxd+Oe7*lj eVer`0@9kf;?vE`#{rCa5*(ZDY;_p7Tedpig4IuLX diff --git a/Blocks/CustomBlocks/diorite_slab.png b/Blocks/CustomBlocks/diorite_slab.png index 4ca19dd9eb58a9f7e2997ed5c3678f8d25946353..06389e3025087c9a7033c09c119aac1459d94601 100644 GIT binary patch delta 11 Scmcb^`-pjh#bzVcRg3@}_5>^d literal 1756 zcmbVN4NTNl9Pgn+rV?D-CZGwmvdBK}+H1Lk>$o}KWH3EGkAONCOZ)Dwa=mtKk2@HV zIFU{F<%pm#Kof#XU?FTomL+V|Su z|Ks=n>c0Hk=c1R!FGUa}Iw#v!2%jso6%`5Z3DY+j_;^st-l8DLvX$D>AR({ECYssAVD;Oq-_XD3|kIVv<$d-uNAv~@-&9>oE0lE*$KOp3EX^k zl?;liavf|{Icwpt4bPxy0U9b0fXbi&!Q)lvfE5esrQu$CjbmsKqLy2+bj=`IYR^YA zMH!$LgHg{Cgb_`#7?@NpImJXhg^~nG;RJ<~l%7bXO=g-(LFX?Fnv*#vU1-aiHwI5u z%&n>tjpKg5-{7YVqU^$r7K;TZNSq|~5TREpy($yXdzEzy8f-veWnNNw(Ti#tnKIF* zS~2Kqh=U-7)q0irIKhbF0Y<`&214T$1afQ`C;4Pg&^X89zyk!}RTYRehOv@cR7J%t z-bHoz^KAxTZ0+{2jXU}x2w@Y7y0HS%m=DMu(Tbx|0(c=%M4!xpjTO+%bs8Iq&XfV8 zin2o#Jqwx2UvL>ElMQAxsf71(qF;IZ76D*mRA9xltigQgNy=fQXp@OHl25|)5kv@T z7dhTpc^4>kI~3Lo$EeIb!5m9FMOk1VVP0Td0GGTj3=M~o&J;bO3=Ko?sGt{iJDuZI zRL0AK9Gew`oDDqB(I$>6qmqp&db87o5rOzbqQn3yL!4`9r)_A!o=M>zukY~!hkZ` zHacFrt8rIjwQe@r966o8l}XyaWbcalnTe}MY8y+p4SZU~jU(TPeYscJFM7fkRr~RDwYq)QweN;IyP)`koxX>+k9{@QZm|$W2?%1-BHF%G&`?3NP>n&M1?fu=3$0c1Q1IReNexW{^~~OAC0gvjnRENj z_uv1i;mC8%P3=t>hBb%!r6`(P+|k&8{+-J=0h;bJ`(Ly%Z1aQesKaKCwPDyjSJhbD ziH8RT+0Z;dF_O@e*Gz=Qu6UbxG!ILnp>LRgp=1T%s6_FVAh3T-_3o~l}qy2jF1rt(HXd4rj4Ey#XHM?AEOrh6;z%i_tVPvb38m_90 zvtExM-#V)5ijlLQyyXFufCELsjT(v<$#OA<6MT%odY?k!qvHwwK**07LZq#ak%A{-V%y6pg6h9OBLkj)-d zRRop=ypIQdGMQBTB*S?*GUyNTq#Ter#fP?v465%XL!NLWTYazm&-X)?ib@M)@0!Og zI5#DPe$__7DpV?B1ddl$Srsp3fdFJTyG25F!wMCma;)C92g`rc=1OJtJ@Tk zdSbyh{+MQl4n5O$xbvZ6OZL52dv+%h>&ua|-5{BKto_8)p<{{mEzyD38XgrEJG7b8 z&M%9f{jh)O#^wvvU3L%MWAg`@X~CyQFWGjznGJ+=bBSxHPl#QX}2C zula>kbIVfa;Mw;h`R9M_IC<%V<-sS!J?#D0HqFNi-tdK;*FSper_G1I9!V?`Zyszr z^37av;ODi~q0yW4=@n+z literal 1632 zcmbVNe`p(39KW)4rj_B3&31^o^M=DPbH9=_$*o!KlDLL7U7JK2g+X8LUXru9d*|Jy z`2lUEcD9>VDf1t}yCEz6Lx(>=v9ta$MI1WO&B7E${}}o%zu2TY+`+r| z-o4NJe1Cs$e{avO_09J-69ln7+!c)C`A%!t*5UW&KmG!EYSOx%FbLxI4c2HN4jtJ< z5Nm&z;|Vhn=@vw!&_F^-NEZ|hqY0wDqo4tC5SnBXre)PnEuTI^k+S5c`rQ#Wq6J_^ z?kedpR_ck1r9sgrQ5`$T_JV*36lemnpk!4;DEO%|uYlLqXNDrn5OdH^by@<+M5LDt zARUrEnsbOO%aI-*4ZM=e<90qm@+|LUSSQ0f9jsSyw+T)US$!xhPM1Bo@O|o&&RMl!}AV|a2Q3^1Op&{zBX39t=999!Dr! zi&Sq-Ws-N%ZRErKvMQmxVZZJI3<4ASDJyC?UJl+F=bVC@6L{A)96pwY+_`kzqQ+u< ztpw4qDIDyKd#5f>&#DXT#?T%21jaY+IyyEnFgw36zc|GNuN@lt?d&)7d%s3oUS_?o zbl=wmcTWt&7N_4>bM(?xb9wvK;+MJmKR7aRcrpL%Xp%iYynO2NQp=1?NL0f+?>ElR zwanOm?CS>2R{}3~N5>}%BSmO?)j9l-d9v}*N!yG)s|5CLwLib|!q1C;t{r)5g#GrE z5PN-eT!=jr+R9Hx=F-1>Wgbs_p3Z*XX1i;jZG*d^ai4vG+;igNuRpu{qk*}^bC*^g zysb3*(z%0=dzX@*4x=9qfAMD1*`2|+9_V+SSa|QXqyZyj)xO8o5^ReZN`&-+O zojbS^YCZnp0XEU`_UQ|=pY&ajwYHyjoFD#fY2?f(vF*xhYryvCyVgG-9O?<4+&M7z EHwOMCNB{r; diff --git a/Blocks/CustomBlocks/polished_granite_slab.png b/Blocks/CustomBlocks/polished_granite_slab.png index 92b488ab6ae3551c4ab91d1b63fe442bb39ef960..3a82d4e8ddfb861f8b4961743b4da9c878d4eccb 100644 GIT binary patch delta 11 ScmX@bbAf4s#bzT`2}S@KSOatb literal 1610 zcmbVMTWs4@7^=SWKE{IbXiI}gaF4rNvy^`p6xbi z#if)XQ32v67#r}Ahe^{)i?ltIk%z5f4`>}sw7dZlPp$gUPJ&fzzy!y+X+wpHSvo$q z?|lFLpX%@H-PZ7M1BPMS;;~2q&CSl(dN=y-{PiyhP4^hFLl%ZLKHv-&cKnkEG3>5& zH92GtiTimOYNVvV6d((lfzTMXdr!fT{I&NHD33Uit-V+N=lds36_u8h zyJH@w;GC4;W2%LMHCC;NgWzy=l~eI@7VwhnWVb-bPFR6LRFBm=_CSR;p9P5YKf+ys zSukzqB@=`*$XmBfCkiP~IdxdEgZih5<-40|wgyLyz**K?5Zct67|>DYGEs|KT8^eL z%;kkd?9?%jYvGNr$?sklJ*PT8bANL!Fn4lpMLu$Lqy2jE!-X$zxba^u f&zxEPHr@VXQ)0(!;yUCeoo*kG_C;p9pP&32Ib0m$ From 7f1bd303795420054560d8e110cda4ce34ec5f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:17:11 +0800 Subject: [PATCH 0492/1123] fix wrong blocks --- Blocks/CustomBlocks.json | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json index 58e58e28..ea2fb56e 100644 --- a/Blocks/CustomBlocks.json +++ b/Blocks/CustomBlocks.json @@ -39,9 +39,9 @@ // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. "icon": "stone_slab.png", // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. - "version": 0, + "version": 14 // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string - "idOld": "minecraft:stone_slab[half=top,variant=stone]" + // needGlass means if this block must be setted on a solid block, default value is false // isGlowing means if the block glows, default value is false. // endermanPickable means if the block can be picked by enderman, default value is false @@ -274,7 +274,7 @@ "nameZH": "末地石砖台阶", "nameEN": "Endstone brick slab", "icon": "end_stone_bricks_slab.png", - "version": 0 + "version": 14 }, { "baseColor": 2, @@ -307,8 +307,7 @@ "nameZH": "花岗岩台阶", "nameEN": "Granite slab", "icon": "granite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=granite]" + "version": 14 }, { "baseColor": 10, @@ -325,8 +324,7 @@ "nameZH": "磨制花岗岩台阶", "nameEN": "Polished granite slab", "icon": "polished_granite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=polished_granite]" + "version": 14 }, { "baseColor": 11, @@ -343,8 +341,7 @@ "nameZH": "安山岩台阶", "nameEN": "Andesite slab", "icon": "andesite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=andesite]" + "version": 14 }, { "baseColor": 11, @@ -361,8 +358,7 @@ "nameZH": "磨制安山岩台阶", "nameEN": "Polished andesite slab", "icon": "polished_andesite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=polished_andesite]" + "version": 14 }, { "baseColor": 14, @@ -379,8 +375,7 @@ "nameZH": "闪长岩台阶", "nameEN": "Diorite slab", "icon": "diorite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=diorite]" + "version": 14 }, { "baseColor": 14, @@ -397,8 +392,7 @@ "nameZH": "磨制闪长岩台阶", "nameEN": "Polished diorite slab", "icon": "polished_diorite_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=polished_diorite]" + "version": 14 }, { "baseColor": 15, @@ -468,7 +462,7 @@ }, { "baseColor": 59, - "id": "minecraft:deepslate_bricks_slab[type=top,waterlogged=false]", + "id": "minecraft:deepslate_brick_slab[type=top,waterlogged=false]", "nameZH": "深板岩砖台阶", "nameEN": "Deepslate bricks slab", "icon": "deepslate_bricks_slab.png", @@ -476,7 +470,7 @@ }, { "baseColor": 59, - "id": "minecraft:deepslate_tiles_slab[type=top,waterlogged=false]", + "id": "minecraft:deepslate_tile_slab[type=top,waterlogged=false]", "nameZH": "深板岩瓦台阶", "nameEN": "Deepslate tiles slab", "icon": "deepslate_tiles_slab.png", @@ -524,7 +518,7 @@ }, { "baseColor": 44, - "id": "minecraft:mud_bricks_slab[type=top,waterlogged=false]", + "id": "minecraft:mud_brick_slab[type=top,waterlogged=false]", "nameZH": "泥砖台阶", "nameEN": "Mud bricks slab", "icon": "mud_bricks_slab.png", From d08ad63de4667aaef3c3ee0d7175020b96c593ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:17:42 +0800 Subject: [PATCH 0493/1123] add positional marking glasses to SCL's testing schem --- SlopeCraftL/TokiSlopeCraft_build.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 9213e396..14f2aa90 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -95,11 +95,11 @@ std::string TokiSlopeCraft::impl_make_tests( } int xSize = 0; - constexpr int zSize = 64, ySize = 1; + constexpr int zSize = 64, ySize = 2; for (const auto &it : blocks) { xSize = std::max(size_t(xSize), it.size()); } - test.resize(xSize, ySize, zSize); + test.resize(xSize + 1, ySize, zSize); test.set_zero(); for (uint8_t base = 0; base < 64; base++) { @@ -110,6 +110,7 @@ std::string TokiSlopeCraft::impl_make_tests( test(xPos, yPos, zPos) = blocks[base][idx] + 1; } + test(blocks[base].size(), 1, base) = 1; // glass block } SCL_errorFlag err; From 1224e2f7e1328e220bb95063326551109ea02a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:21:16 +0800 Subject: [PATCH 0494/1123] add prefer-slab to SCWind --- SlopeCraft/SCWind.h | 1 + SlopeCraft/SCWind.ui | 7 +++++++ SlopeCraft/SCWind_slots.cpp | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 34aab473..699a7aaf 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -61,6 +61,7 @@ class SCWind : public QMainWindow { void on_pb_prefer_glass_clicked() noexcept; void on_pb_prefer_planks_clicked() noexcept; void on_pb_prefer_logs_clicked() noexcept; + void on_pb_prefer_slabs_clicked() noexcept; void when_cvt_pool_selectionChanged() noexcept; void when_export_pool_selectionChanged() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 85906428..916ea290 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -293,6 +293,13 @@ + + + + 优先台阶 + + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index dfe0bdb0..9b5dc36c 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -204,6 +204,13 @@ void SCWind::on_pb_prefer_logs_clicked() noexcept { }); } +void SCWind::on_pb_prefer_slabs_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) -> int { + return impl_select_blk_by_id(blks, "_slab"); + }); +} + void SCWind::on_pb_cvt_current_clicked() noexcept { const auto sel = this->selected_cvt_task_idx(); From caf4423e0f94fd914921a2435204e907bebcd367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:21:34 +0800 Subject: [PATCH 0495/1123] fix wrong tips in tps wind --- SlopeCraft/TransparentStrategyWind.ui | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SlopeCraft/TransparentStrategyWind.ui b/SlopeCraft/TransparentStrategyWind.ui index 7086145b..784259a7 100644 --- a/SlopeCraft/TransparentStrategyWind.ui +++ b/SlopeCraft/TransparentStrategyWind.ui @@ -112,8 +112,7 @@ 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 ”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 -”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 -完成设置后,需重新导入图片。 +”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 true From 79b5a0c3cd5a86cf78d8beac1ad3663c7e9ce30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:33:07 +0800 Subject: [PATCH 0496/1123] show platform name before device name in VC's combobox --- VisualCraft/VCWind_gpu.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index f6496bd3..e73d4752 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -138,7 +138,9 @@ void VCWind::refresh_gpu_info() noexcept { twi->addChild(twi_device); - this->ui->combobox_select_device->addItem(devicename, QPoint(pid, did)); + this->ui->combobox_select_device->addItem( + QStringLiteral("%1 / %2").arg(platname, devicename), + QPoint(pid, did)); VCL_release_device(dev); } From 9a8ad4444bf05ac760fd07f46fde5aeb1c5faa96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:38:07 +0800 Subject: [PATCH 0497/1123] update translations --- SlopeCraft/others/SlopeCraft_en_US.ts | 309 ++++++++++++------------ VisualCraft/others/VisualCraft_en_US.ts | 16 +- 2 files changed, 165 insertions(+), 160 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 4e78bef1..70559666 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -262,283 +262,288 @@ Use logs - + 导入图像并转化 Load image and convert - + 原图 Original image - + 转化后 Converted image - + 删除 Delete - - + + 项目池 Task pool - + 添加 Add - + 转化算法 Convert algorithm - + 抖动 Dithering - + 转化当前图像 Convert current image - - - + + + 保存转化后图像 Save converted image - + 全部转化 Convert all - - + + 导出 Export - + Litematica - - + + 结构方块文件 Vanilla structure - + + 优先台阶 + Use slabs + + + 显示缩略图 - - + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - + 地图文件 Map data files - + 其他选项 Others - + 防火 Fire Proof - + 防末影人 Enderman Proof - + 连接蘑菇块 Connect mushroom blocks - + 压缩高度 Compress - + 有损压缩 Lossy Compression - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 搭桥 Glass Bridge - + 允许搭桥 Construct Glass Bridge - + layer(s) - + 搭桥间隔: Glass bridge interval: - + 投影区域名称 Region name - + 投影名称 Litematic name - + 用结构空位替代空气 Replace air with structure void - + offset - + WEOffset - - - - - - + + + + + + 0 - + 原理图名称 Name of schematic - + 依赖 mod 名称 Depend mods - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - + 垂直分割线 Vertical split line - + 水平分割线 Horizontal split line - + 大小与方块数量 Size and block count - + 大小: Size: - + 方块数量: Block count: - + 全部导出 Export all - + 预览 Preview - + 预览材料表 Material list - + 预览压缩效果 Compress effect - + 预构建三维结构 Construct 3d structure - + 地图画起始序号: Map beginning index: - + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 在下面的表格里可以看到每个图像对应的文件名。 @@ -547,93 +552,93 @@ Filenames of each image can be seen in the table below. - + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ @@ -809,144 +814,144 @@ Detailed information: %2 Failed to generate preset file "%1", detail: %2 - - - - - + + + + + 未选择图像 No image selected - - - - + + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - - + + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - - + + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - - - + + + 尚未构建三维结构 3d structure not built - - - + + + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -955,29 +960,29 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + 版权所有 © 2021-2023 SlopeCraft 开发者 Copyright © 2021-2023 SlopeCraft deveploers @@ -1042,38 +1047,38 @@ Click Ignore to skip, Retry to retry and Cancel to cancel Writing meta data - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: @@ -1111,56 +1116,54 @@ Click Ignore to skip, Retry to retry and Cancel to cancel 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 ”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 -”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 -完成设置后,需重新导入图片。 +”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 Transparency is hardly supported in map paintings. 3d maps and flat maps cannot implement transparent pixels. Although transparent pixels do exist in file-only maps, they just let the background of map/item go through. Thus it's necessary to deal with full/semi trasnparent pixels. "Replace with background" replace pixels with background color, while "Replace with air" with air. -"Compose with backgroundcolor" compose pixel's color with background color accroding to alpha value, and "Reserve color" simply ignore the alpha value, using its RGB directly. -You should load the image again after you confirmed these settings. +"Compose with backgroundcolor" compose pixel's color with background color accroding to alpha value, and "Reserve color" simply ignore the alpha value, using its RGB directly. - + 纯透明像素 Full transparent - + 替换为空气 Replace with air - - + + 替换为背景色 Replace with background - + 半透明像素 Semi-transparent - + 保留颜色 Reserve color - + 与背景色叠加 Compose with backgroundcolor - + 确定 OK - + 取消 Cancel - + 恢复默认设定 Restore to default diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 2019ad18..33094a94 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -858,7 +858,7 @@ If you select a block in "Avaliable blocks" page, the other page will Failed to retrieve device infomation, please check your deiver. OpenCL error code: %1 - + %1 这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft @@ -867,22 +867,24 @@ If you select a block in "Avaliable blocks" page, the other page will This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - + 创建 GPU 平台失败,平台序号为%1,设备序号为%2 Failed to create GPU platform, Platform index = %1, device index = %2 - + 创建 GPU 设备失败,平台序号为%1,设备序号为%2 Failed to create GPU device, Platform index = %1, device index = %2 - - 设置 GPU 设备失败。,平台序号为%1,设备序号为%2 - Failed to set GPU device. Platform index = %1, device index = %2 + + 设置 GPU 设备失败。平台序号为%1,设备序号为%2,详细错误信息: +%3 + Failed to set GPU device. Platform index = %1, device index = %2, detailed information: +%3 - + 设置计算设备失败 Failed to set compute device From efec1e697992023d6b5c1915f37ef5794a2bf538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 15:46:29 +0800 Subject: [PATCH 0498/1123] fix build without gpu --- utilities/GPUWrapper/None/GPU_interface.cpp | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/utilities/GPUWrapper/None/GPU_interface.cpp b/utilities/GPUWrapper/None/GPU_interface.cpp index 783ba06b..d6f06f87 100644 --- a/utilities/GPUWrapper/None/GPU_interface.cpp +++ b/utilities/GPUWrapper/None/GPU_interface.cpp @@ -4,8 +4,8 @@ const char *gpu_wrapper::api_name() noexcept { return "None"; } size_t gpu_wrapper::platform_num() noexcept { return 0; } -gpu_wrapper::platform_wrapper * -gpu_wrapper::platform_wrapper::create(size_t, int *) noexcept { +gpu_wrapper::platform_wrapper *gpu_wrapper::platform_wrapper::create( + size_t, int *) noexcept { return nullptr; } @@ -14,18 +14,24 @@ void gpu_wrapper::platform_wrapper::destroy( return; } -gpu_wrapper::device_wrapper * -gpu_wrapper::device_wrapper::create(platform_wrapper *, size_t, - int *) noexcept { +gpu_wrapper::device_wrapper *gpu_wrapper::device_wrapper::create( + platform_wrapper *, size_t, int *) noexcept { return nullptr; } void gpu_wrapper::device_wrapper::destroy(device_wrapper *) noexcept { return; } -gpu_wrapper::gpu_interface * -gpu_wrapper::gpu_interface::create(platform_wrapper *, - device_wrapper *) noexcept { +gpu_wrapper::gpu_interface *gpu_wrapper::gpu_interface::create( + platform_wrapper *, device_wrapper *) noexcept { return nullptr; } -void gpu_wrapper::gpu_interface::destroy(gpu_interface *) noexcept { return; } \ No newline at end of file +gpu_wrapper::gpu_interface *gpu_wrapper::gpu_interface::create( + gpu_wrapper::platform_wrapper *pw, gpu_wrapper::device_wrapper *dw, + std::pair &err) noexcept { + err.first = INT_MAX; + err.second = "VisualCraft is built without any GPU api."; + return nullptr; +} + +void gpu_wrapper::gpu_interface::destroy(gpu_interface *) noexcept { return; } From 7594dce77589983feb272b546e254c4e9dec6c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 16:06:00 +0800 Subject: [PATCH 0499/1123] fix build without gpu with gcc --- utilities/GPUWrapper/GPU_interface.h | 3 ++- utilities/GPUWrapper/None/GPU_interface.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/utilities/GPUWrapper/GPU_interface.h b/utilities/GPUWrapper/GPU_interface.h index c5be0b97..4732113b 100644 --- a/utilities/GPUWrapper/GPU_interface.h +++ b/utilities/GPUWrapper/GPU_interface.h @@ -26,7 +26,8 @@ This file is part of SlopeCraft. #include "../SC_GlobalEnums.h" #include #include -#include +#include +#include namespace gpu_wrapper { diff --git a/utilities/GPUWrapper/None/GPU_interface.cpp b/utilities/GPUWrapper/None/GPU_interface.cpp index d6f06f87..94844141 100644 --- a/utilities/GPUWrapper/None/GPU_interface.cpp +++ b/utilities/GPUWrapper/None/GPU_interface.cpp @@ -1,4 +1,5 @@ #include "../GPU_interface.h" +#include const char *gpu_wrapper::api_name() noexcept { return "None"; } From acd3dafc7f2bd16c684d35d7d1fa535126b8b877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 16:11:21 +0800 Subject: [PATCH 0500/1123] fix dithering with full-transparent pixels in VC --- utilities/ColorManip/imageConvert.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 3f0c282c..399301a0 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -555,7 +555,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t row = 0; row < this->rows(); row++) { if (is_dir_LR) for (int64_t col = 0; col < this->cols(); col++) { - if (::getA(this->_raw_image(row, col) <= 0)) { + if (::getA(this->_raw_image(row, col)) <= 0) { continue; } @@ -596,7 +596,7 @@ class ImageCvter : public GPU_wrapper_wrapper { } else for (int64_t col = this->cols() - 1; col >= 0; col--) { - if (::getA(this->_raw_image(row, col) <= 0)) { + if (::getA(this->_raw_image(row, col)) <= 0) { continue; } From f21d1629799cd35d5e0be9b10d7b4039e873ed45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 16:11:38 +0800 Subject: [PATCH 0501/1123] fix image preprocessing in SCL --- SlopeCraftL/imagePreprocess.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SlopeCraftL/imagePreprocess.cpp b/SlopeCraftL/imagePreprocess.cpp index 56504fd7..717d814c 100644 --- a/SlopeCraftL/imagePreprocess.cpp +++ b/SlopeCraftL/imagePreprocess.cpp @@ -60,6 +60,7 @@ void SCL_EXPORT SCL_preprocessImage(ARGB *data, const uint64_t imageSize, default: break; } + continue; } if (getA(data[i]) < 255) { // half transparent From cf9b1df24aae7d5c86cdb1a4e2386a7dfcd24617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 16:36:09 +0800 Subject: [PATCH 0502/1123] change export type automatically --- SlopeCraft/SCWind.cpp | 27 +++++++++++++++++++++++++++ SlopeCraft/SCWind.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index f2ee0f21..4830fa5e 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -418,6 +418,16 @@ void SCWind::when_version_buttons_toggled() noexcept { void SCWind::when_type_buttons_toggled() noexcept { this->when_blocklist_changed(); this->update_button_states(); + { + auto valid_buttons = this->valid_export_type_buttons(this->selected_type()); + for (auto btnp : valid_buttons) { + if (btnp->isChecked()) { + return; + } + } + valid_buttons[0]->click(); + } + // this->when_export_type_toggled(); } void SCWind::when_blocklist_changed() noexcept { @@ -461,6 +471,19 @@ std::array SCWind::export_type_buttons() return SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS; } +std::vector SCWind::valid_export_type_buttons( + SCL_mapTypes type) const noexcept { + switch (type) { + case SCL_mapTypes::Slope: + return {this->ui->rb_export_lite, this->ui->rb_export_nbt, + this->ui->rb_export_WE, this->ui->rb_export_fileonly}; + case SCL_mapTypes::Flat: + return SC_SLOPECRAFT_PREIVATEMACRO_EXPORT_TYPE_BUTTONS; + case SCL_mapTypes::FileOnly: + return {this->ui->rb_export_fileonly}; + } +} + std::array SCWind::preset_buttons_no_custom() noexcept { return {this->ui->rb_preset_vanilla, this->ui->rb_preset_cheap, this->ui->rb_preset_elegant, this->ui->rb_preset_shiny}; @@ -666,6 +689,10 @@ void SCWind::mark_all_task_unconverted() noexcept { } void SCWind::when_algo_btn_clicked() noexcept { + for (size_t i = 0; i < this->tasks.size(); i++) { + this->tasks[i].set_unconverted(); + } + this->cvt_pool_model->refresh(); this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 699a7aaf..3fc47d52 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -121,6 +121,8 @@ class SCWind : public QMainWindow { std::array export_type_buttons() noexcept; std::array export_type_buttons() const noexcept; + std::vector valid_export_type_buttons( + SCL_mapTypes type) const noexcept; std::array preset_buttons_no_custom() noexcept; From 03f4b1cffc4e3ffbb0637c382495ba32b94122d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 16:44:27 +0800 Subject: [PATCH 0503/1123] fix resizing of compress effect viewer --- SlopeCraft/CompressEffectViewer.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/CompressEffectViewer.ui b/SlopeCraft/CompressEffectViewer.ui index c6010e8b..678f56c2 100644 --- a/SlopeCraft/CompressEffectViewer.ui +++ b/SlopeCraft/CompressEffectViewer.ui @@ -11,7 +11,7 @@ - + 0 0 @@ -30,7 +30,7 @@ - + 0 0 From 9a30823bae1a855a01463303b16ce32b13289088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 17:32:29 +0800 Subject: [PATCH 0504/1123] fix compressed image displaying --- SlopeCraft/CompressEffectViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraft/CompressEffectViewer.cpp b/SlopeCraft/CompressEffectViewer.cpp index 18954c29..47a27b93 100644 --- a/SlopeCraft/CompressEffectViewer.cpp +++ b/SlopeCraft/CompressEffectViewer.cpp @@ -13,7 +13,7 @@ CompressEffectViewer::CompressEffectViewer(SCWind* parent) auto kernel = parent->kernel_ptr(); const int rows = kernel->getImageRows(); const int cols = kernel->getImageCols(); - QImage img{rows, cols, QImage::Format_ARGB32}; + QImage img{cols, rows, QImage::Format_ARGB32}; kernel->getCompressedImage( nullptr, nullptr, reinterpret_cast(img.scanLine(0)), false); From 8a3fd0bf496a0863bc6d2026bd44e723ac79b61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 17:33:13 +0800 Subject: [PATCH 0505/1123] fix material preview --- SlopeCraft/SCWind_slots.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 9b5dc36c..0ed2cc7e 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -374,6 +374,8 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { assert(taskopt.value() != nullptr); cvt_task &task = *taskopt.value(); + const ptrdiff_t index = &task - this->tasks.data(); + assert(index >= 0 && index < this->tasks.size()); if (!task.is_converted) [[unlikely]] { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); @@ -381,6 +383,7 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { } QString errtitle; QString errmsg; + this->kernel_set_image(index); // try to load cache [this, &errtitle, &errmsg]() { if (this->kernel->queryStep() >= SCL_step::builded) { From 0ff89a84f10dc99ae7a11bdeb1f09ae9bd2e8689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 17:50:23 +0800 Subject: [PATCH 0506/1123] add image replacing for SC --- SlopeCraft/SCWind.h | 4 +++ SlopeCraft/SCWind.ui | 7 +++++ SlopeCraft/SCWind_slots.cpp | 61 ++++++++++++++++++++++++++++++------- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 3fc47d52..c1c17719 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -50,6 +50,8 @@ class SCWind : public QMainWindow { private slots: void on_pb_add_image_clicked() noexcept; void on_pb_remove_image_clicked() noexcept; + void on_pb_replace_image_clicked() noexcept; + void on_cb_lv_cvt_icon_mode_clicked() noexcept; void on_cb_compress_lossy_toggled(bool checked) noexcept; @@ -108,6 +110,8 @@ class SCWind : public QMainWindow { SCL_language language{SCL_language::Chinese}; std::vector translators; + QString prev_load_image_dir{""}; + // QString fileonly_export_dir{""}; public: diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 916ea290..c48aa531 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -544,6 +544,13 @@ + + + + 替换 + + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 0ed2cc7e..37cdf62e 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -11,17 +11,20 @@ #include "TransparentStrategyWind.h" #include "CompressEffectViewer.h" -void SCWind::on_pb_add_image_clicked() noexcept { #ifdef WIN32 - const char *filter = "*.png;*.jpg"; +const char *SC_image_filter = "*.png;*.jpg"; #else - const char *filter = "*.png;;*.jpg"; +const char *SC_image_filter = "*.png;;*.jpg"; #endif - auto files = QFileDialog::getOpenFileNames(this, tr("选择图片"), "", filter); + +void SCWind::on_pb_add_image_clicked() noexcept { + auto files = QFileDialog::getOpenFileNames( + this, tr("选择图片"), this->prev_load_image_dir, SC_image_filter); if (files.empty()) { return; } + this->prev_load_image_dir = QFileInfo{files.front()}.dir().absolutePath(); std::optional strategy_opt{std::nullopt}; @@ -33,8 +36,7 @@ void SCWind::on_pb_add_image_clicked() noexcept { auto ret = QMessageBox::critical( this, tr("打开图像失败"), tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") - .arg(filename) - .arg(err), + .arg(filename, err), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); @@ -87,6 +89,42 @@ void SCWind::on_pb_remove_image_clicked() noexcept { emit this->image_changed(); } +void SCWind::on_pb_replace_image_clicked() noexcept { + auto selected = this->ui->lview_pool_cvt->selectionModel()->selectedIndexes(); + if (selected.empty()) { + QMessageBox::warning(this, tr("请选择将被替换的图像"), + tr("必须先选择一个或多个图像,然后才能替换它们。")); + return; + } + + const QString file = QFileDialog::getOpenFileName( + this, tr("选择图片"), this->prev_load_image_dir, SC_image_filter); + if (file.isEmpty()) { + return; + } + this->prev_load_image_dir = QFileInfo{file}.dir().absolutePath(); + QString err; + auto task = cvt_task::load(file, err); + if (!err.isEmpty()) { + auto ret = QMessageBox::critical( + this, tr("打开图像失败"), + tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") + .arg(file, err), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, + QMessageBox::StandardButton::Ignore}); + + if (ret == QMessageBox::Ignore) { + return; + } else { + abort(); + } + } + for (const auto &qmi : selected) { + this->tasks[qmi.row()] = task; + } + this->cvt_pool_model->refresh(); +} + void SCWind::on_cb_lv_cvt_icon_mode_clicked() noexcept { const bool is_icon_mode = this->ui->cb_lv_cvt_icon_mode->isChecked(); this->ui->lview_pool_cvt->setViewMode((is_icon_mode) @@ -521,10 +559,10 @@ void SCWind::on_pb_export_all_clicked() noexcept { break; } default: - QMessageBox::warning( - this, tr("你点错按钮了"), - tr("导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个" - "按钮,这可能是一个小小的 bug(特性)。")); + QMessageBox::warning(this, tr("你点错按钮了"), + tr("导出为纯文件地图画的按钮在另外一页。按理来说" + "你不应该能点击这个" + "按钮,这可能是一个小小的 bug(特性)。")); return; } } @@ -786,7 +824,8 @@ void SCWind::on_ac_clear_cache_triggered() noexcept { if (ret == QMessageBox::StandardButton::Ignore) { break; } - return; // QMessageBox::StandardButton::Cancel and for closing the dialog + return; // QMessageBox::StandardButton::Cancel and for closing the + // dialog } } } From 531b8230b689a4411eb4c88ed9b37f357bc5cfa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 17:54:08 +0800 Subject: [PATCH 0507/1123] update translation --- SlopeCraft/others/SlopeCraft_en_US.ts | 374 ++++++++++++++------------ 1 file changed, 196 insertions(+), 178 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 70559666..f72dc4ed 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -202,7 +202,7 @@ - + 保存当前预设 Save as preset @@ -283,7 +283,7 @@ - + 项目池 Task pool @@ -293,46 +293,46 @@ Add - + 转化算法 Convert algorithm - + 抖动 Dithering - + 转化当前图像 Convert current image - - - + + + 保存转化后图像 Save converted image - + 全部转化 Convert all - - + + 导出 Export - + Litematica - - + + 结构方块文件 Vanilla structure @@ -347,203 +347,208 @@ - - + + 替换 + Replace + + + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - + 地图文件 Map data files - + 其他选项 Others - + 防火 Fire Proof - + 防末影人 Enderman Proof - + 连接蘑菇块 Connect mushroom blocks - + 压缩高度 Compress - + 有损压缩 Lossy Compression - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 搭桥 Glass Bridge - + 允许搭桥 Construct Glass Bridge - + layer(s) - + 搭桥间隔: Glass bridge interval: - + 投影区域名称 Region name - + 投影名称 Litematic name - + 用结构空位替代空气 Replace air with structure void - + offset - + WEOffset - - - - - - + + + + + + 0 - + 原理图名称 Name of schematic - + 依赖 mod 名称 Depend mods - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - + 垂直分割线 Vertical split line - + 水平分割线 Horizontal split line - + 大小与方块数量 Size and block count - - + + 大小: Size: - - + + 方块数量: Block count: - + 全部导出 Export all - + 预览 Preview - + 预览材料表 Material list - + 预览压缩效果 Compress effect - + 预构建三维结构 Construct 3d structure - + 地图画起始序号: Map beginning index: - + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 在下面的表格里可以看到每个图像对应的文件名。 @@ -552,93 +557,93 @@ Filenames of each image can be seen in the table below. - + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ @@ -657,113 +662,113 @@ Detail information: %1 - + 设置方块列表失败 Failed to setup blocklist - + 您设置的方块列表可能存在错误 There may be errors in your blocklist - + 可用颜色数量:%1 Avaliable colors: %1 - + 应用预设失败 Failed to apply preset - + 转化图像失败 Failed to convert image - - + + 缓存失败 Failed to save cache - - + + 未能创建缓存文件,错误信息: %1 Failed to create cache directory, error info: %1 - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - + 保存图像失败 Failed to save image - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - + 构建三维结构失败 Failed to build 3d structure - + 构建三维结构时,出现错误。可能是因为尝试跳步。 An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - + 方块数量:%1 Block count: %1 - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - + SlopeCraft 出现错误 An error occurred to SlopeCraft - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -772,186 +777,199 @@ Detail information: Click Ok to ignore, and click Close to exit SlopeCraft. - + + 选择图片 Select Image - + + 打开图像失败 Failed to open image - + + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. Detailed information: %2 - + + 请选择将被替换的图像 + Please images to be replaced + + + + 必须先选择一个或多个图像,然后才能替换它们。 + You should select one or more images, and then replace them. + + + 选择预设文件 Select a preset file - + 解析预设文件失败 Failed to parse thes preset file - + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 - + 保存预设文件失败 Failed to save preset file - + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 - - - - - + + + + + 未选择图像 No image selected - - - - + + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - - + + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - - + + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - - - + + + 尚未构建三维结构 3d structure not built - - - + + + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -960,125 +978,125 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + 版权所有 © 2021-2023 SlopeCraft 开发者 Copyright © 2021-2023 SlopeCraft deveploers - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: From b3a8412092f4bafc822a19c3f387991eff15126b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 23 Aug 2023 18:12:58 +0800 Subject: [PATCH 0508/1123] update version number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbe51232..a01ec2cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.1.0) +set(SlopeCraft_version 5.2.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 787b870f1b649ae9e6442446037402da4cb14dd9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 26 Aug 2023 16:16:16 +0800 Subject: [PATCH 0509/1123] fix macos build with clang/libc++ --- utilities/ProcessBlockId/process_block_id.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/utilities/ProcessBlockId/process_block_id.cpp b/utilities/ProcessBlockId/process_block_id.cpp index 0307716d..f1917683 100644 --- a/utilities/ProcessBlockId/process_block_id.cpp +++ b/utilities/ProcessBlockId/process_block_id.cpp @@ -1,4 +1,5 @@ #include "process_block_id.h" +#include bool blkid::is_valid_id(std::string_view str) noexcept { if (str.find_first_of(':') != str.find_first_of(':')) { From 1822d5cc8f310dc9c62146801c428135e4485178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 1 Oct 2023 21:46:25 +0800 Subject: [PATCH 0510/1123] fix crashing in SlopeCraft --- utilities/ColorManip/imageConvert.hpp | 31 +++++++++++++++++++++---- utilities/MapImageCvter/MapImageCvter.h | 5 +++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 399301a0..88658040 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -197,6 +197,18 @@ class ImageCvter : public GPU_wrapper_wrapper { } else { this->_dithered_image = this->_raw_image; } + + // for (int64_t idx = 0; idx < this->_dithered_image.size(); idx++) { + // const auto current_color{this->_dithered_image(idx)}; + // if (getA(current_color) > 0) { + // continue; + // } + // const convert_unit key{current_color, this->algo}; + // if (!this->_color_hash.contains(key)) { + // this->_color_hash.emplace(key, uint8_t{0}); + // } + // } + ui.rangeSet(0, 100, 100); return true; // fill_coloridmat_by_hash(this->colorid_matrix); @@ -207,10 +219,16 @@ class ImageCvter : public GPU_wrapper_wrapper { result.setZero(this->rows(), this->cols()); for (int64_t idx = 0; idx < this->size(); idx++) { - auto it = this->_color_hash.find( - convert_unit(this->_dithered_image(idx), this->algo)); + const auto current_color = this->_dithered_image(idx); + + auto it = this->_color_hash.find(convert_unit(current_color, this->algo)); if (it == this->_color_hash.end()) { + if (getA(current_color) <= 0) { + result(idx) = 0; + continue; + } + abort(); } @@ -242,10 +260,13 @@ class ImageCvter : public GPU_wrapper_wrapper { assert(r >= 0 && r < this->rows()); assert(c >= 0 && c < this->cols()); - auto it = this->_color_hash.find( - convert_unit{this->_dithered_image(r, c), this->algo}); + const auto current_color = this->_dithered_image(r, c); + auto it = this->_color_hash.find(convert_unit{current_color, this->algo}); if (it == this->_color_hash.end()) { - abort(); + if (getA(current_color) > 0) { + abort(); + } + return 0; } return it->second.color_id(); } diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 57ef2710..863c5db8 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -134,7 +134,10 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { for (uint32_t color : colors_dithered_img) { auto it = this->color_hash().find(convert_unit{color, this->convert_algo()}); - assert(it != this->color_hash().end()); + if (it == this->color_hash().end()) { + assert(getA(color) <= 0); + continue; + } ar(it->first, it->second); } From 5f392f26395c23f03736a1d40cb097ba44e1b6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 1 Oct 2023 22:28:22 +0800 Subject: [PATCH 0511/1123] fix a warning --- SlopeCraft/SCWind.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 4830fa5e..d0398cbb 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -482,6 +482,7 @@ std::vector SCWind::valid_export_type_buttons( case SCL_mapTypes::FileOnly: return {this->ui->rb_export_fileonly}; } + return {}; } std::array SCWind::preset_buttons_no_custom() noexcept { From d4793dd3089768e1252aaceca0d890e2c5897746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 1 Oct 2023 23:03:31 +0800 Subject: [PATCH 0512/1123] try to fix windows build --- .github/workflows/build-dev-clang.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 73f68a4d..415c108d 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -34,6 +34,11 @@ jobs: where clang-cl clang --version + - name: Install ninja + run: | + choco install ninja + ninja --version + # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" From 037be28bbc4a0c05cf574e6664be17a4f092e6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 1 Oct 2023 23:12:23 +0800 Subject: [PATCH 0513/1123] try to fix windows build --- .github/workflows/build-dev-gcc.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 60108536..81a615f9 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -199,6 +199,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + + - name: Install ninja + run: | + choco install ninja + ninja --version + - name: Get short SHA run: | echo "GITHUB_SHA = $env:GITHUB_SHA" From 590cb7faee50b2974fa6199d9f52b8480978dc67 Mon Sep 17 00:00:00 2001 From: AbrasiveBoar902 <76773705+AbrasiveBoar902@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:59:35 +0800 Subject: [PATCH 0514/1123] Update build-dev-gcc.yml --- .github/workflows/build-dev-gcc.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 60108536..a673ce85 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -226,6 +226,11 @@ jobs: # gcc --version #- name: See Path # run: $env:path -split ';' + - name: Install ninja + run: | + choco install ninja + ninja --version + - name: Make dirs run: | mkdir bin @@ -364,4 +369,4 @@ jobs: # with: # name: gcc12-with-zlib,libzip,libpng # path: bin/mingw64 - # if-no-files-found: error \ No newline at end of file + # if-no-files-found: error From 87ef8f50789673677085104cd100e170a114fc82 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 2 Oct 2023 16:47:58 +0800 Subject: [PATCH 0515/1123] fix macos build with clang/libc++ --- SlopeCraft/SCWind.cpp | 2 ++ utilities/BlockListManager/BlockListManager.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index d0398cbb..fcc55c0a 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -130,6 +130,8 @@ SCWind::SCWind(QWidget *parent) this->ui->blm->set_version_callback( [this]() { return this->selected_version(); }); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + this->ui->blm->add_blocklist("./Blocks/FixedBlocks.json", "./Blocks/FixedBlocks"); this->ui->blm->add_blocklist("./Blocks/CustomBlocks.json", diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index d818b17e..178419b6 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -1,6 +1,7 @@ #include "BlockListManager.h" #include #include +#include extern std::string_view basecolor_names[64]; @@ -68,7 +69,9 @@ bool BlockListManager::impl_addblocklist( errmsg.resize(msg_len); + if (!errmsg.empty()) { + errmsg.append(QStringLiteral("\npwd: %1").arg(QFileInfo{"."}.absolutePath()).toLocal8Bit()); if (bli == nullptr) { QMessageBox::critical(dynamic_cast(this->parent()), tr("解析方块列表失败"), From a4860792b3084d5c69b4de321826866fff40729c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 2 Oct 2023 18:17:33 +0800 Subject: [PATCH 0516/1123] Remove macdeployqt for VC --- VisualCraft/install.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index cf481bfb..d9fc8e1b 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -70,8 +70,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL ) - QD_add_deployqt(VisualCraft - INSTALL_MODE INSTALL_DESTINATION .) + #QD_add_deployqt(VisualCraft + # INSTALL_MODE INSTALL_DESTINATION .) # Run macdeployqt at install time #install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) From 7af005d4a5a4b551a4f14f8e243759c2e33c6f73 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 2 Oct 2023 18:39:45 +0800 Subject: [PATCH 0517/1123] [mac] try to fix SlopeCraft icon --- SlopeCraft/CMakeLists.txt | 2 +- SlopeCraft/install.cmake | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 7a90d91a..68e45e36 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -87,7 +87,7 @@ target_include_directories(SlopeCraft PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(SlopeCraft PROPERTIES VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns + MACOSX_BUNDLE_ICON_FILE SlopeCraft.icns MACOSX_BUNDLE_GUI_IDENTIFIER "com.github.ToKiNoBug.SlopeCraft" MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index ef8e980e..afffaf37 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -26,10 +26,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") ) # Install icons - file(GLOB SlopeCraft_Icon - ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.icns) + set(SlopeCraft_Icon + ${CMAKE_SOURCE_DIR}/SlopeCraft/others/SlopeCraftIconNew.icns) install(FILES ${SlopeCraft_Icon} - DESTINATION SlopeCraft.app/Contents/Resources) + DESTINATION SlopeCraft.app/Contents/Resources + RENAME SlopeCraft.icns) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} From 8390177f8c9dbd25cdfa70885ec20a16de13ca34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 2 Oct 2023 22:21:03 +0800 Subject: [PATCH 0518/1123] [mac] disable gpu and vectorize by default --- CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a01ec2cc..ef861559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,9 +20,14 @@ endif () enable_testing() # configure options ----------------------------------------------------------- -set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") +if (NOT ${APPLE}) + set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") + option(SlopeCraft_vectorize "Compile with vectorization" ON) +else () + set(SlopeCraft_GPU_API "None" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") + option(SlopeCraft_vectorize "Compile with vectorization" OFF) +endif () -option(SlopeCraft_vectorize "Compile with vectorization" ON) option(SlopeCraft_update_ts_files "Update language files before build. If it is set to ON, everytime CMake reconfigure the project, all .ts files will be updated." OFF) From 786162829e0ddf0f6cca52fefbba8b6f3896d0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:13:45 +0800 Subject: [PATCH 0519/1123] remove SlopeCraft old gui files --- SlopeCraftMain/AiCvterParameterDialog.cpp | 90 - SlopeCraftMain/AiCvterParameterDialog.h | 54 - SlopeCraftMain/AiCvterParameterDialog.ui | 181 - SlopeCraftMain/BatchUi.cpp | 213 -- SlopeCraftMain/BatchUi.h | 78 - SlopeCraftMain/BatchUi.ui | 173 - SlopeCraftMain/CMakeLists.txt | 132 - SlopeCraftMain/MainWindow.cpp | 2039 ----------- SlopeCraftMain/MainWindow.h | 298 -- SlopeCraftMain/TaskBox.cpp | 41 - SlopeCraftMain/TaskBox.h | 127 - SlopeCraftMain/TaskBox.ui | 149 - SlopeCraftMain/install.cmake | 145 - SlopeCraftMain/main.cpp | 68 - SlopeCraftMain/mainwindow.ui | 4062 --------------------- SlopeCraftMain/previewwind.cpp | 106 - SlopeCraftMain/previewwind.h | 61 - SlopeCraftMain/previewwind.ui | 544 --- SlopeCraftMain/tpstrategywind.cpp | 102 - SlopeCraftMain/tpstrategywind.h | 76 - SlopeCraftMain/tpstrategywind.ui | 263 -- 21 files changed, 9002 deletions(-) delete mode 100644 SlopeCraftMain/AiCvterParameterDialog.cpp delete mode 100644 SlopeCraftMain/AiCvterParameterDialog.h delete mode 100644 SlopeCraftMain/AiCvterParameterDialog.ui delete mode 100644 SlopeCraftMain/BatchUi.cpp delete mode 100644 SlopeCraftMain/BatchUi.h delete mode 100644 SlopeCraftMain/BatchUi.ui delete mode 100644 SlopeCraftMain/CMakeLists.txt delete mode 100644 SlopeCraftMain/MainWindow.cpp delete mode 100644 SlopeCraftMain/MainWindow.h delete mode 100644 SlopeCraftMain/TaskBox.cpp delete mode 100644 SlopeCraftMain/TaskBox.h delete mode 100644 SlopeCraftMain/TaskBox.ui delete mode 100644 SlopeCraftMain/install.cmake delete mode 100644 SlopeCraftMain/main.cpp delete mode 100644 SlopeCraftMain/mainwindow.ui delete mode 100644 SlopeCraftMain/previewwind.cpp delete mode 100644 SlopeCraftMain/previewwind.h delete mode 100644 SlopeCraftMain/previewwind.ui delete mode 100644 SlopeCraftMain/tpstrategywind.cpp delete mode 100644 SlopeCraftMain/tpstrategywind.h delete mode 100644 SlopeCraftMain/tpstrategywind.ui diff --git a/SlopeCraftMain/AiCvterParameterDialog.cpp b/SlopeCraftMain/AiCvterParameterDialog.cpp deleted file mode 100644 index 8a6044d0..00000000 --- a/SlopeCraftMain/AiCvterParameterDialog.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "AiCvterParameterDialog.h" -#include "ui_AiCvterParameterDialog.h" - -#include "MainWindow.h" - -using namespace SlopeCraft; -AiCvterParameterDialog::AiCvterParameterDialog(QWidget *parent) - : QDialog(parent), ui(new Ui::AiCvterParameterDialog) { - ui->setupUi(this); - - MainWindow *wind = qobject_cast(parent); - Kernel *k = wind->kernelPtr(); - const AiCvterOpt *src = k->aiCvterOpt(); - - ui->crossoverProb->setValue(SCL_getCrossoverProb(src)); - ui->mutateProb->setValue(SCL_getMutationProb(src)); - ui->maxGeneration->setValue(SCL_getMaxGeneration(src)); - ui->popSize->setValue(SCL_getPopSize(src)); - - connect(ui->maxGeneration, &QSpinBox::valueChanged, this, - &AiCvterParameterDialog::updateMaxFailTimes); - connect(ui->maxFailTimes, &QSpinBox::valueChanged, this, - &AiCvterParameterDialog::updateMaxFailTimes); - connect(ui->enableFailTimes, &QCheckBox::clicked, this, - &AiCvterParameterDialog::updateMaxFailTimes); - - updateMaxFailTimes(); - ui->maxFailTimes->setValue(SCL_getMaxFailTimes(src)); - - ui->enableFailTimes->setChecked(SCL_getMaxFailTimes(src) < - SCL_getMaxGeneration(src)); -} - -AiCvterParameterDialog::~AiCvterParameterDialog() { delete ui; } - -void AiCvterParameterDialog::updateMaxFailTimes() { - ui->maxFailTimes->setMaximum(ui->maxGeneration->value()); - - ui->maxFailTimes->setEnabled(ui->enableFailTimes->isChecked()); - - if (!ui->enableFailTimes->isChecked()) { - ui->maxFailTimes->setValue(ui->maxGeneration->value()); - } -} - -void AiCvterParameterDialog::closeEvent(QCloseEvent *event) { - QDialog::closeEvent(event); - - deleteLater(); -} - -void AiCvterParameterDialog::on_buttonBox_accepted() { - AiCvterOpt *opt = SCL_createAiCvterOpt(); - SCL_setCrossoverProb(opt, ui->crossoverProb->value()); - SCL_setMaxFailTimes(opt, ui->maxFailTimes->value()); - SCL_setMaxGeneration(opt, ui->maxGeneration->value()); - SCL_setMutationProb(opt, ui->mutateProb->value()); - SCL_setPopSize(opt, ui->popSize->value()); - - MainWindow *wind = qobject_cast(parent()); - Kernel *k = wind->kernelPtr(); - - k->setAiCvterOpt(opt); -} - -void AiCvterParameterDialog::on_buttonBox_clicked(QAbstractButton *) { - deleteLater(); -} diff --git a/SlopeCraftMain/AiCvterParameterDialog.h b/SlopeCraftMain/AiCvterParameterDialog.h deleted file mode 100644 index 450c8686..00000000 --- a/SlopeCraftMain/AiCvterParameterDialog.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef AICVTERPARAMETERDIALOG_H -#define AICVTERPARAMETERDIALOG_H - -#include -#include - -namespace Ui { -class AiCvterParameterDialog; -} - -class MainWindow; - -class AiCvterParameterDialog : public QDialog { - Q_OBJECT - -public: - explicit AiCvterParameterDialog(QWidget *parent); - ~AiCvterParameterDialog(); - -protected: - void closeEvent(QCloseEvent *event) override; -private slots: - void updateMaxFailTimes(); - void on_buttonBox_accepted(); - - void on_buttonBox_clicked(QAbstractButton *button); - -private: - Ui::AiCvterParameterDialog *ui; -}; - -#endif // AICVTERPARAMETERDIALOG_H diff --git a/SlopeCraftMain/AiCvterParameterDialog.ui b/SlopeCraftMain/AiCvterParameterDialog.ui deleted file mode 100644 index 78bc0e41..00000000 --- a/SlopeCraftMain/AiCvterParameterDialog.ui +++ /dev/null @@ -1,181 +0,0 @@ - - - AiCvterParameterDialog - - - - 0 - 0 - 325 - 120 - - - - Ai转化器参数 - - - - - - 允许提前收敛 - - - true - - - - - - - 最大提前收敛代数: - - - 10 - - - 100 - - - 10 - - - - - - - 交叉概率: - - - - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.800000000000000 - - - - - - - - 150 - 0 - - - - - - - 种群数量: - - - 30 - - - 500 - - - 10 - - - 50 - - - - - - - - 150 - 0 - - - - 最大进化代数: - - - 50 - - - 3000 - - - 10 - - - 200 - - - - - - - 变异概率: - - - 3 - - - 1.000000000000000 - - - 0.001000000000000 - - - 0.010000000000000 - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - AiCvterParameterDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AiCvterParameterDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/SlopeCraftMain/BatchUi.cpp b/SlopeCraftMain/BatchUi.cpp deleted file mode 100644 index f9990c27..00000000 --- a/SlopeCraftMain/BatchUi.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "BatchUi.h" -#include "ui_BatchUi.h" - -#include "MainWindow.h" - -BatchUi::BatchUi(QWidget *parent) : QMainWindow(parent), ui(new Ui::BatchUi) { - ui->setupUi(this); - this->setAttribute(Qt::WA_QuitOnClose, false); - - // ui->setTypeLite->setChecked(false); - - connect(ui->setTypeData, &QRadioButton::clicked, this, - &BatchUi::onTaskTypeChanged); - connect(ui->setTypeLite, &QRadioButton::clicked, this, - &BatchUi::onTaskTypeChanged); - connect(ui->setTypeStructure, &QRadioButton::clicked, this, - &BatchUi::onTaskTypeChanged); - connect(ui->setDataFolder, &QLineEdit::textEdited, ui->setDataFolder, - &QLineEdit::textChanged); - connect(ui->setDataFolder, &QLineEdit::textChanged, this, - &BatchUi::checkExecutable); -} - -void BatchUi::closeEvent(QCloseEvent *event) { - QMainWindow::closeEvent(event); - delete this; -} - -BatchUi::~BatchUi() { delete ui; } - -void BatchUi::setTasks(const QStringList &fileNames) { - - taskBoxes.reserve(fileNames.size()); - - for (ushort idx = 0; idx < fileNames.size(); idx++) { - TaskBox *box = new TaskBox(this); - ui->scrollLayout->addWidget(box); - taskBoxes.emplace_back(box); - box->setTask(fileNames[idx]); - box->setMapBegSeqReadOnly(true); - - connect(box, &TaskBox::erase, this, &BatchUi::erased); - connect(box, &TaskBox::seqNumChanged, this, &BatchUi::onBoxSeqNumChanged); - } - qDebug("setTasks完毕"); - taskBoxes.front()->setMapBegSeq(0); - taskBoxes.front()->setMapBegSeqReadOnly(false); - onBoxSeqNumChanged(); - - emit ui->setTypeLite->clicked(); -} - -auto BatchUi::ptr2It(TaskBox *widgetPtr) const { - auto target = taskBoxes.begin(); - for (; target != taskBoxes.end(); ++target) { - if (*target == widgetPtr) { - return target; - } - } - return taskBoxes.end(); -} - -void BatchUi::erased(TaskBox *widgetPtr) { - ui->scrollLayout->removeWidget(widgetPtr); - - auto temp = ptr2It(widgetPtr); - taskBoxes.erase(temp); - widgetPtr->deleteLater(); - for (auto i : taskBoxes) { - i->setMapBegSeqReadOnly(true); - } - taskBoxes.front()->setMapBegSeqReadOnly(false); - onBoxSeqNumChanged(); -} - -void BatchUi::onBoxSeqNumChanged() { - uint32_t curBeg = taskBoxes.front()->begSeqNum(); - taskBoxes.front()->setMapBegSeq(curBeg); - for (size_t idx = 1; idx < taskBoxes.size(); idx++) { - taskBoxes[idx]->setMapBegSeq(curBeg + taskBoxes[idx - 1]->mapSize()); - curBeg += taskBoxes[idx - 1]->mapSize(); - } -} - -void BatchUi::onTaskTypeChanged() { - qDebug("void BatchUi::onTaskTypeChanged"); - if (ui->setTypeData->isChecked()) - TaskBox::taskType = TaskType::Data; - if (ui->setTypeLite->isChecked()) - TaskBox::taskType = TaskType::Litematica; - if (ui->setTypeStructure->isChecked()) - TaskBox::taskType = TaskType::Structure; - - ui->setDataFolder->setEnabled(TaskBox::taskType == TaskType::Data); - ui->BtnBrowseDataFolder->setEnabled(TaskBox::taskType == TaskType::Data); - ui->labelDenoteDstFolder->setEnabled(TaskBox::taskType == TaskType::Data); - - for (auto i : taskBoxes) { - i->updateTaskType(); - } - - checkExecutable(); -} - -void BatchUi::on_BtnBrowseDataFolder_clicked() { - QString path = QFileDialog::getExistingDirectory(this, tr("选择输出文件夹"), - ui->setDataFolder->text()); - if (path.isEmpty()) - return; - path.replace("\\\\", "/"); - path.replace('\\', '/'); - ui->setDataFolder->setText(path); -} - -MainWindow *BatchUi::wind() const { - return qobject_cast(parent()); -} - -SlopeCraft::Kernel *BatchUi::kernel() const { return wind()->kernelPtr(); } - -void BatchUi::checkExecutable() { - bool executable = true; - ui->LabelShowInfo->setText(""); - if (TaskBox::taskType == TaskType::Data) { - QString dstFolder = ui->setDataFolder->text(); - if (dstFolder.isEmpty() || !QDir(dstFolder).exists()) { - ui->LabelShowInfo->setText(tr("目标文件夹不可用")); - executable = false; - } - } else { - if (!kernel()->isVanilla()) { - ui->LabelShowInfo->setText(tr("主窗体中选择了纯文件地图画,冲突")); - executable = false; - } - } - - ui->LabelShowInfo->setText(tr("就绪")); - ui->BtnExecute->setEnabled(executable); -} - -void BatchUi::eraseAllTasks() { - for (auto widgetPtr : taskBoxes) { - - ui->scrollLayout->removeWidget(widgetPtr); - widgetPtr->deleteLater(); - } - taskBoxes.clear(); -} - -void BatchUi::on_BtnExecute_clicked() { - MainWindow::isBatchOperating = true; - for (size_t idx = 0; idx < taskBoxes.size(); idx++) { - TaskBox *curTask = taskBoxes[idx]; - if (curTask->mapSize() <= 0) { - continue; - } - QString prefix = tr("批量处理中:") + QString::number(idx + 1) + " / " + - QString::number(taskBoxes.size()) + '\n'; - ui->LabelShowInfo->setText(prefix); - - wind()->turnToPage(1); - wind()->preprocessImage(curTask->rawImgPath()); - wind()->kernelSetType(); - wind()->kernelSetImg(); - wind()->turnToPage(4); - - ui->LabelShowInfo->setText(prefix + tr("正在转化为地图画")); - wind()->on_Convert_clicked(); - - if (TaskBox::taskType != TaskType::Data) { - wind()->turnToPage(5); - ui->LabelShowInfo->setText(prefix + tr("正在构建三维结构")); - wind()->on_Build4Lite_clicked(); - ui->LabelShowInfo->setText(prefix + tr("正在导出三维结构")); - wind()->onExportLiteclicked(curTask->liteName()); - } else { - wind()->turnToPage(7); - ui->LabelShowInfo->setText(prefix + tr("正在导出地图文件")); - wind()->ui->InputDataIndex->setText( - QString::number(curTask->begSeqNum())); - wind()->onExportDataclicked(ui->setDataFolder->text()); - // export as data - } - } - eraseAllTasks(); - - ui->LabelShowInfo->setText(tr("批量处理完成")); - wind()->turnToPage(8); - qDebug("finished"); - MainWindow::isBatchOperating = false; -} diff --git a/SlopeCraftMain/BatchUi.h b/SlopeCraftMain/BatchUi.h deleted file mode 100644 index fa15b4de..00000000 --- a/SlopeCraftMain/BatchUi.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef BATCHUI_H -#define BATCHUI_H - -#include -#include -#include - -#include "TaskBox.h" -#include "ui_BatchUi.h" - -namespace Ui { -class BatchUi; -} - -class MainWindow; - -namespace SlopeCraft { -class Kernel; -} - -class BatchUi : public QMainWindow { - Q_OBJECT - -public: - explicit BatchUi(QWidget *parent); - ~BatchUi(); - void setTasks(const QStringList &); - -signals: - -protected: - void closeEvent(QCloseEvent *) override; - -private slots: - void erased(TaskBox *); - void onBoxSeqNumChanged(); - void onTaskTypeChanged(); - - void on_BtnExecute_clicked(); - - void on_BtnBrowseDataFolder_clicked(); - - void checkExecutable(); - - void eraseAllTasks(); - -private: - Ui::BatchUi *ui; - std::vector taskBoxes; - - auto ptr2It(TaskBox *widgetPtr) const; - MainWindow *wind() const; - SlopeCraft::Kernel *kernel() const; -}; - -#endif // BATCHUI_H diff --git a/SlopeCraftMain/BatchUi.ui b/SlopeCraftMain/BatchUi.ui deleted file mode 100644 index 9648cfcd..00000000 --- a/SlopeCraftMain/BatchUi.ui +++ /dev/null @@ -1,173 +0,0 @@ - - - BatchUi - - - - 0 - 0 - 640 - 480 - - - - - 640 - 0 - - - - SlopeCraft批量操作 - - - - - 0 - 0 - - - - - - - true - - - - - 0 - 0 - 620 - 353 - - - - - 0 - - - 0 - - - 0 - - - - - - - - - QFrame::StyledPanel - - - QFrame::Plain - - - - - - true - - - - - - - false - - - 开始执行 - - - - - - - - - 导出格式 - - - - - - - - 0 - 0 - - - - Litematica投影文件 - - - true - - - - - - - - 0 - 0 - - - - 原版结构方块文件 - - - - - - - - 0 - 0 - - - - 地图文件 - - - - - - - - - - - 地图文件输出位置 - - - - - - - false - - - false - - - - - - - false - - - 浏览 - - - - - - - - - - - diff --git a/SlopeCraftMain/CMakeLists.txt b/SlopeCraftMain/CMakeLists.txt deleted file mode 100644 index 49d753c5..00000000 --- a/SlopeCraftMain/CMakeLists.txt +++ /dev/null @@ -1,132 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(SlopeCraft_Main VERSION ${SlopeCraft_version} LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 17) - -include_directories( - ${CMAKE_SOURCE_DIR}/SlopeCraftL - ${CMAKE_SOURCE_DIR}/utilities/BlockListManager) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) - -set(SlopeCraftMain_windows_rc_file) - -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - message("Configuring on Windows. Adding rc file to " ${PROJECT_NAME}) - configure_file(others/SlopeCraft.rc.in others/SlopeCraft.rc) - set(SlopeCraftMain_windows_rc_file ${CMAKE_CURRENT_BINARY_DIR}/others/SlopeCraft.rc) -endif() - -set(SlopeCraftMain_header_files - AiCvterParameterDialog.h - BatchUi.h - TaskBox.h - MainWindow.h - previewwind.h - tpstrategywind.h -) - -set(SlopeCraftMain_source_files - - AiCvterParameterDialog.cpp - BatchUi.cpp - TaskBox.cpp - main.cpp - MainWindow.cpp - previewwind.cpp - tpstrategywind.cpp -) - -set(SlopeCraftMain_ui_files - - AiCvterParameterDialog.ui - BatchUi.ui - mainwindow.ui - previewwind.ui - TaskBox.ui - tpstrategywind.ui) - -set(SlopeCraftMain_ts_files - - others/SlopeCraft_en_US.ts) - -if(${SlopeCraft_update_ts_files}) - execute_process( - COMMAND ${SlopeCraft_Qt_lupdate_executable} ${SlopeCraftMain_header_files} ${SlopeCraftMain_source_files} ${SlopeCraftMain_ui_files} "-ts" ${SlopeCraftMain_ts_files} ${SlopeCraft_ts_flags} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) -endif() - -set(SlopeCraftMain_qrc_files - others/BlockTextures.qrc - others/Pics.qrc - - # others/SlopeCraft_translation.qrc -) - -set(SlopeCraftMain_project_sources - ${SlopeCraftMain_header_files} - ${SlopeCraftMain_source_files} - - ${SlopeCraftMain_ts_files} - ${SlopeCraftMain_ui_files} - ${SlopeCraftMain_qrc_files} - ${SlopeCraftMain_windows_rc_file} -) - -qt_add_executable(SlopeCraft - MANUAL_FINALIZATION - ${SlopeCraftMain_project_sources}) - -# execute_process(COMMAND "pause") -# qt_create_translation(SlopeCraftMain_qm_files ${CMAKE_CURRENT_SOURCE_DIR} ${SlopeCraftMain_ts_files}) -qt_add_lrelease(SlopeCraft TS_FILES ${SlopeCraftMain_ts_files} - QM_FILES_OUTPUT_VARIABLE SC_qm_files) - -qt_add_resources(SlopeCraft "SC_translations" - PREFIX "/i18n" - BASE ${CMAKE_CURRENT_BINARY_DIR} - FILES ${SC_qm_files}) - -# qt6_add_resources(SlopeCraft "translation" -# PREFIX "/i18n" -# FILES -# ${SlopeCraftMain_qm_files} -# ${CMAKE_SOURCE_DIR}/CMakeLists.txt) -target_link_libraries(SlopeCraft - PRIVATE - AdaptiveLabel - BlockListManager - SlopeCraftL - Qt6::Widgets - Qt6::Network - VersionDialog -) - -set_target_properties(SlopeCraft PROPERTIES - VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_ICON_FILE SlopeCraftIconNew.icns - MACOSX_BUNDLE_GUI_IDENTIFIER "com.github.ToKiNoBug.SlopeCraft" - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} - MACOSX_BUNDLE TRUE - WIN32_EXECUTABLE TRUE -) - -qt_finalize_executable(SlopeCraft) - -if(${WIN32}) - add_custom_target(SC_create_symlink_SC - COMMAND mklink SlopeCraftL.dll "..\\SlopeCraftL\\SlopeCraftL.dll" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS SlopeCraftL - COMMENT "Create symlink to SlopeCraftL.dll for SlopeCraft.exe") - add_dependencies(SC_create_all_symlinks SC_create_symlink_SC) -endif() - -include(install.cmake) \ No newline at end of file diff --git a/SlopeCraftMain/MainWindow.cpp b/SlopeCraftMain/MainWindow.cpp deleted file mode 100644 index 26ed7e32..00000000 --- a/SlopeCraftMain/MainWindow.cpp +++ /dev/null @@ -1,2039 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include -#include -#include -#include -#include - -#include "MainWindow.h" - -#include - -bool MainWindow::isBatchOperating = false; - -blockListPreset MainWindow::preset_vanilla; -blockListPreset MainWindow::preset_elegant; -blockListPreset MainWindow::preset_cheap; -blockListPreset MainWindow::preset_shiny; - -inline uint32_t inverseColor(uint32_t raw) noexcept { - const uint32_t ASeg = raw & (0xFF000000); - const uint32_t R = 255 - ((raw & 0x00FF0000) >> 16); - const uint32_t G = 255 - ((raw & 0x0000FF00) >> 8); - const uint32_t B = 255 - (raw & 0x000000FF); - - return ASeg | (R << 16) | (G << 8) | (B); -} - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), - ui(new Ui::MainWindow), - kernel(SlopeCraft::SCL_createKernel()) { - ui->setupUi(this); - - ui->label_show_version->setText( - ui->label_show_version->text().arg(QStringLiteral("v") + SC_VERSION_STR)); - - // qDebug("成功 setupUi"); - Collected = false; - - // qDebug("成功创建内核"); - kernel->setWindPtr(this); - kernel->setKeepAwake(keepAwake); - kernel->setProgressRangeSet(progressRangeSet); - kernel->setProgressAdd(progressAdd); - kernel->setAlgoProgressRangeSet(algoProgressRangeSet); - kernel->setAlgoProgressAdd(algoProgressAdd); - kernel->setReportError(showError); - kernel->setReportWorkingStatue(showWorkingStatue); - - proTracker = nullptr; - - ProductDir = ""; - - Manager = new BlockListManager( - (QHBoxLayout *)ui->scrollAreaWidgetContents->layout()); - - // qDebug("成功创建方块列表管理者"); - connect(Manager, &BlockListManager::switchToCustom, this, - &MainWindow::ChangeToCustom); - connect(Manager, &BlockListManager::blockListChanged, this, - &MainWindow::onBlockListChanged); - // connect(Kernel,SIGNAL(convertProgressSetRange(int,int,int))); - - ui->maxHeight->setValue(255); - - connect(ui->progressStart, &QPushButton::clicked, this, - &MainWindow::turnToPage0); - connect(ui->progressImPic, &QPushButton::clicked, this, - &MainWindow::turnToPage1); - connect(ui->progressType, &QPushButton::clicked, this, - &MainWindow::turnToPage2); - connect(ui->progressBL, &QPushButton::clicked, this, - &MainWindow::turnToPage3); - connect(ui->progressAdjPic, &QPushButton::clicked, this, - &MainWindow::turnToPage4); - connect(ui->progressExLite, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - connect(ui->progressExStructure, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - connect(ui->progressExWESchem, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - connect(ui->progressExFlatDiagram, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - // connect(ui->menuExMcF,&QAction::trigger,this,&MainWindow::turnToPage6); - connect(ui->progressExData, &QPushButton::clicked, this, - &MainWindow::turnToPage7); - - connect(ui->progressAbout, &QPushButton::clicked, this, - &MainWindow::turnToPage8); - connect(ui->actionAboutSlopeCraft, &QAction::triggered, this, - &MainWindow::turnToPage8); - connect(ui->actionChinese, &QAction::triggered, this, &MainWindow::turnCh); - connect(ui->actionEnglish, &QAction::triggered, this, &MainWindow::turnEn); - connect(ui->progressChinese, &QPushButton::clicked, this, - &MainWindow::turnCh); - connect(ui->progressEnglish, &QPushButton::clicked, this, - &MainWindow::turnEn); - connect(ui->actionToki, &QAction::triggered, this, &MainWindow::contactG); - connect(ui->actionDoki, &QAction::triggered, this, &MainWindow::contactB); - connect(ui->progressG, &QPushButton::clicked, this, &MainWindow::contactG); - connect(ui->progressB, &QPushButton::clicked, this, &MainWindow::contactB); - connect(ui->progressCheckUpdates, &QPushButton::clicked, this, - &MainWindow::checkVersion); - - connect(ui->contact, &QPushButton::clicked, this, &MainWindow::contactB); - connect(ui->contact, &QPushButton::clicked, this, &MainWindow::contactG); - connect(ui->actionReportBugs, &QAction::triggered, this, - &MainWindow::on_reportBugs_clicked); - connect(ui->actionCheckUpdates, &QAction::triggered, this, - &MainWindow::checkVersion); - - connect(ui->actionTestBlockList, &QAction::triggered, this, - &MainWindow::testBlockList); - connect(ui->actionSetBuildParameters, &QAction::triggered, this, - &MainWindow::turnToPage5); - connect(ui->action_export_avaliable_color_list, &QAction::triggered, this, - &MainWindow::exportAvailableColors); - - // qDebug("成功 connect 所有的菜单"); - - connect(ui->NextPage, &QPushButton::clicked, this, &MainWindow::turnToPage2); - connect(ui->NextPage2, &QPushButton::clicked, this, &MainWindow::turnToPage3); - connect(ui->NextPage3, &QPushButton::clicked, this, &MainWindow::turnToPage4); - connect(ui->ExLite, &QPushButton::clicked, this, &MainWindow::turnToPage5); - connect(ui->ExStructure, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - connect(ui->ExWESchem, &QPushButton::clicked, this, &MainWindow::turnToPage5); - connect(ui->ExportFlatDiagram, &QPushButton::clicked, this, - &MainWindow::turnToPage5); - - connect(ui->ExData, &QPushButton::clicked, this, &MainWindow::turnToPage7); - connect(ui->FinishExLite, &QPushButton::clicked, this, - &MainWindow::turnToPage8); - connect(ui->FinshExData, &QPushButton::clicked, this, - &MainWindow::turnToPage8); - connect(ui->Exit, &QPushButton::clicked, this, &MainWindow::close); - // qDebug("成功 connect 所有的翻页按钮"); - - connect(ui->isGame12, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame13, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame14, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame15, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame16, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame17, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame18, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - connect(ui->isGame19, &QRadioButton::toggled, this, - &MainWindow::onGameVerClicked); - - connect(ui->isMapCreative, &QRadioButton::toggled, this, - &MainWindow::onMapTypeClicked); - connect(ui->isMapSurvival, &QRadioButton::toggled, this, - &MainWindow::onMapTypeClicked); - /* - connect(ui->isMapWall,&QRadioButton::toggled, - this,&MainWindow::onMapTypeClicked);*/ - connect(ui->isMapFlat, &QRadioButton::toggled, this, - &MainWindow::onMapTypeClicked); - - connect(ui->isBLCreative, &QRadioButton::clicked, this, - &MainWindow::onPresetsClicked); - connect(ui->isBLSurvivalCheaper, &QRadioButton::clicked, this, - &MainWindow::onPresetsClicked); - connect(ui->isBLSurvivalBetter, &QRadioButton::clicked, this, - &MainWindow::onPresetsClicked); - connect(ui->isBLGlowing, &QRadioButton::clicked, this, - &MainWindow::onPresetsClicked); - - connect(ui->isColorSpaceRGBOld, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceRGB, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceHSV, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceLab94, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceLab00, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceXYZ, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->isColorSpaceAi, &QRadioButton::clicked, this, - &MainWindow::onAlgoClicked); - connect(ui->AllowDither, &QCheckBox::clicked, this, - &MainWindow::onAlgoClicked); - - connect(ui->actionStart, &QAction::triggered, ui->progressStart, - &QPushButton::clicked); - connect(ui->actionImportImage, &QAction::triggered, ui->progressImPic, - &QPushButton::clicked); - connect(ui->actionMapType, &QAction::triggered, ui->progressType, - &QPushButton::clicked); - connect(ui->actionBlockList, &QAction::triggered, ui->progressBL, - &QPushButton::clicked); - connect(ui->actionConvert, &QAction::triggered, ui->progressAdjPic, - &QPushButton::clicked); - connect(ui->actionExportLite, &QAction::triggered, ui->progressExLite, - &QPushButton::clicked); - connect(ui->actionExportNBT, &QAction::triggered, ui->progressExStructure, - &QPushButton::clicked); - connect(ui->actionExportWESchem, &QAction::triggered, ui->progressExWESchem, - &QPushButton::clicked); - connect(ui->actionExportData, &QAction::triggered, ui->progressExData, - &QPushButton::clicked); - - connect(ui->actionFinish, &QAction::triggered, ui->progressAbout, - &QPushButton::clicked); - connect(ui->actionSavePreset, &QAction::triggered, this, - &MainWindow::onActionSavePreset); - connect(ui->actionLoadPreset, &QAction::triggered, this, - &MainWindow::onActionLoadPreset); - connect(ui->actionAiCvterOption, &QAction::triggered, this, - &MainWindow::onActionAiCvterParameters); - - turnToPage(0); -} - -MainWindow::~MainWindow() { - SlopeCraft::SCL_destroyKernel(this->kernel); - delete Manager; - delete ui; -} - -void MainWindow::showPreview() { - if (kernel->queryStep() < SlopeCraft::step::builded) return; - - PreviewWind *preWind = new PreviewWind(this); - preWind->Src.resize(64); - preWind->BlockCount.resize(64); - - preWind->Src = Manager->getQRadioButtonList(); - - int totalNum = 0; - kernel->getBlockCounts(&totalNum, preWind->BlockCount.data()); - - // qDebug() << "去重前有:" << preWind->Src.size() << "个元素"; - auto iS = preWind->Src.begin(); - for (auto ib = preWind->BlockCount.begin(); - ib != preWind->BlockCount.end();) { - if (*iS == nullptr) { - ib = preWind->BlockCount.erase(ib); - iS = preWind->Src.erase(iS); - } - if (*ib > 0) { // if the block is used, keep it. otherwise erase it. - ib++; - iS++; - continue; - } - ib = preWind->BlockCount.erase(ib); - iS = preWind->Src.erase(iS); - } - - kernel->get3DSize(&preWind->size[0], &preWind->size[1], &preWind->size[2]); - - // qDebug() << "去重后有:" << preWind->Src.size() << "个元素"; - // preWind->Water=Blocks[12][0]; - preWind->Water = Manager->getQRadioButtonList()[12]; - // preWind->Src[1]=Blocks[1][0];preWind->BlockCount[1]=1919810; - EImage tempE; - tempE.resize(kernel->getImageRows(), kernel->getImageCols()); - int a, b; - kernel->getConvertedImage(&a, &b, tempE.data()); - - QImage temp = EImage2QImage(tempE); - - preWind->ShowMaterialList(); - - preWind->showConvertedImage(temp); - - preWind->show(); -} - -void MainWindow::keepAwake(void *) { QCoreApplication::processEvents(); } - -void MainWindow::loadBlockList() { - if (!Manager->setupFixedBlockList("./Blocks/FixedBlocks.json", - "./Blocks/FixedBlocks")) { - QMessageBox::critical(this, tr("SlopeCraft 无法加载必需方块列表"), - tr("SlopeCraft 必须退出")); - exit(1); - } - - if (!Manager->setupCustomBlockList("./Blocks/CustomBlocks.json", - "./Blocks/CustomBlocks")) { - auto ret = QMessageBox::critical( - this, tr("SlopeCraft 无法加载可选方块列表"), tr("此错误可以忽略"), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, - QMessageBox::StandardButton::Close}); - - if (ret == QMessageBox::StandardButton::Close) { - exit(1); - } - } - - QRgb colors[64]; - kernel->getBaseColorInARGB32(colors); - Manager->setLabelColors(colors); - // applyPre(BLBetter); - Manager->loadInternalPreset(preset_elegant); -} - -void MainWindow::InitializeAll() { - ui->LeftScroll->verticalScrollBar()->setStyleSheet( - "QScrollBar{width: 7px;margin: 0px 0 0px 0;background-color: rgba(255, " - "255, 255, 64);color: rgba(255, 255, 255, 128);}"); - static bool needInitialize = true; - if (needInitialize) { - needInitialize = false; - } - - try { - MainWindow::preset_vanilla = - load_preset("./Blocks/Presets/vanilla.sc_preset_json"); - MainWindow::preset_cheap = - load_preset("./Blocks/Presets/cheap.sc_preset_json"); - MainWindow::preset_elegant = - load_preset("./Blocks/Presets/elegant.sc_preset_json"); - MainWindow::preset_shiny = - load_preset("./Blocks/Presets/shiny.sc_preset_json"); - } catch (std::exception &e) { - QMessageBox::critical(this, tr("加载默认预设失败"), - tr("一个或多个内置的预设不能被解析。SlopeCraft " - "可能已经损坏,请重新安装。\n具体报错信息:\n%1") - .arg(e.what())); - exit(1); - } - - if (!Collected) { - loadBlockList(); - // qDebug("方块列表加载完毕"); - Manager->setVersion((unsigned char)SlopeCraft::gameVersion::MC17); - onPresetsClicked(); - Collected = true; - } -} - -void MainWindow::on_actionTutorial_triggered() { - QDesktopServices::openUrl(QUrl{"https://slopecraft.readthedocs.io/"}); -} - -void MainWindow::contactG() { - QDesktopServices::openUrl(QUrl("https://github.com/SlopeCraft/SlopeCraft")); -} - -void MainWindow::contactB() { - QDesktopServices::openUrl(QUrl("https://space.bilibili.com/351429231")); -} - -#ifndef tpSDestroyer -#define tpSDestroyer -tpS::~tpS() {} -#endif - -void MainWindow::turnToPage(int page) { - page %= 9; - QString newtitle = "SlopeCraft "; - - newtitle += SlopeCraft::SCL_getSCLVersion(); -#ifdef WIN32 - newtitle += " Copyright © 2021-2023 TokiNoBug "; // windowsf -#elif defined(_MAC) || defined(__APPLE__) - newtitle += - " Copyright © 2021-2023 TokiNoBug,AbrasiveBoar, Cubik65536 "; // macOs -#else - newtitle += " Copyright © 2021-2023 TokiNoBug "; // unknown platform -#endif - - switch (page) { - case 0: - newtitle += "Step 0 / 6"; - newtitle += " "; - newtitle += tr("开始"); - ui->stackedWidget->setCurrentIndex(page); - break; - - case 1: - newtitle += "Step 1 / 6"; - newtitle += " "; - newtitle += tr("导入图片"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 2: - newtitle += "Step 2 / 6"; - newtitle += " "; - newtitle += tr("设置地图画类型"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 3: - newtitle += "Step 3 / 6"; - newtitle += " "; - newtitle += tr("设置方块列表"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 4: - newtitle += "Step 4 / 6"; - newtitle += " "; - newtitle += tr("调整颜色"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 5: - newtitle += "Step 5 / 6"; - newtitle += " "; - newtitle += tr("导出为投影文件"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 6: - newtitle += "Step 5 / 6"; - newtitle += " "; - newtitle += tr("导出为 mcfunction"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 7: - newtitle += "Step 5 / 6"; - newtitle += " "; - newtitle += tr("导出为地图文件"); - ui->stackedWidget->setCurrentIndex(page); - break; - case 8: - newtitle += "Step 6 / 6"; - newtitle += " "; - newtitle += tr("结束"); - ui->stackedWidget->setCurrentIndex(page); - break; - default: - qDebug("尝试翻页错误"); - break; - } - this->setWindowTitle(newtitle); - updateEnables(); - return; -} - -void MainWindow::turnToPage0() { - turnToPage(0); - return; -} - -void MainWindow::turnToPage1() { - turnToPage(1); - return; -} - -void MainWindow::turnToPage2() { - turnToPage(2); - return; -} - -void MainWindow::turnToPage3() { - turnToPage(3); - return; -} - -void MainWindow::turnToPage4() { - turnToPage(4); - return; -} - -void MainWindow::turnToPage5() { - turnToPage(5); - return; -} - -void MainWindow::turnToPage6() { - turnToPage(6); - return; -} - -void MainWindow::turnToPage7() { - turnToPage(7); - return; -} - -void MainWindow::turnToPage8() { - turnToPage(8); - return; -} - -void MainWindow::updateEnables() { - bool temp = true; - ui->StartWithFlat->setEnabled(temp); - ui->StartWithNotVanilla->setEnabled(temp); - ui->StartWithNotVanilla->setEnabled(temp); - - temp = kernel->queryStep() >= SlopeCraft::step::wait4Image; - ui->actionTestBlockList->setEnabled(temp); - ui->action_export_avaliable_color_list->setEnabled(temp); - - temp = kernel->queryStep() >= SlopeCraft::step::convertionReady; - ui->Convert->setEnabled(temp); - ui->ShowRaw->setEnabled(temp); - // ui->Convert->setEnabled(temp); - - // //////////////// - temp = kernel->queryStep() >= SlopeCraft::step::converted; - ui->ShowAdjed->setEnabled(temp); - // ui->menuExport->setEnabled(temp); - // ui->ExData->setEnabled(temp); - ui->ExportData->setEnabled(temp); - // ui->actionExportData->setEnabled(temp); - // ui->progressEx->setEnabled(temp); - // ui->progressExData->setEnabled(temp); - - // //////////////// - temp = (!ui->isMapCreative->isChecked()) && - kernel->queryStep() >= SlopeCraft::step::converted; - ui->Build4Lite->setEnabled(temp); - // ui->actionExportLite->setEnabled(temp); - // ui->actionExportNBT->setEnabled(temp); - // ui->actionExportWESchem->setEnabled(temp); - // ui->ExLite->setEnabled(temp); - // ui->ExStructure->setEnabled(temp); - // ui->ExWESchem->setEnabled(temp); - // ui->progressExLite->setEnabled(temp); - // ui->progressExStructure->setEnabled(temp); - // ui->progressExFlatDiagram->setEnabled(temp); - // ui->progressExWESchem->setEnabled(temp); - - // //////////////// - temp = kernel->queryStep() >= SlopeCraft::step::builded; - ui->ExportLite->setEnabled(temp); - ui->ManualPreview->setEnabled(temp); - ui->ExportFlatDiagram->setEnabled(temp && (kernel->isFlat())); -} - -void MainWindow::on_StartWithSlope_clicked() { - ui->isMapSurvival->setChecked(true); - turnToPage(1); - onBlockListChanged(); -} - -void MainWindow::on_StartWithFlat_clicked() { - ui->isMapFlat->setChecked(true); - onBlockListChanged(); - turnToPage(1); -} - -void MainWindow::on_StartWithNotVanilla_clicked() { - ui->isMapCreative->setChecked(true); - onBlockListChanged(); - turnToPage(1); -} -/* -void MainWindow::on_StartWithWall_clicked() { - ui->isMapWall->setChecked(true); - onBlockListChanged(); - turnToPage(1); -} -*/ - -void MainWindow::preprocessImage(const QString &Path) { - if (!rawPic.load(Path)) { - QMessageBox::information(this, tr("打开图片失败"), - tr("要不试试换一张图片吧!")); - return; - } - bool needSearch = rawPic.hasAlphaChannel(); - rawPic = rawPic.convertToFormat(QImage::Format_ARGB32); - bool OriginHasTp = false; - if (needSearch) { - QRgb *CL = nullptr; - for (short r = 0; r < rawPic.height(); r++) { - CL = (QRgb *)rawPic.scanLine(r); - for (short c = 0; c < rawPic.width(); c++) { - if (qAlpha(CL[c]) < 255) { - r = rawPic.height() + 1; - OriginHasTp = true; - break; - } - } - } - } - - // ui->ShowRawPic->setPixmap(QPixmap::fromImage(rawPic)); - - ui->IntroPicInfo->setText(tr("图片尺寸:") + - QString::number(rawPic.height()) + "×" + - QString::number(rawPic.width()) + tr("像素")); - if (OriginHasTp) { - preProcess(Strategy.pTpS, Strategy.hTpS, Strategy.BGC); - ui->IntroPicInfo->setText( - ui->IntroPicInfo->text() + "\n" + - tr("图片中存在透明/" - "半透明像素,已处理,您可以点击“设置”重新选择处理透明/" - "半透明像素的方式。\n重新设置处理方式后,需要重新导入一次。")); - } else { - rawPic = rawPic.copy(); - } - ui->ShowRawPic->setPixmap(QPixmap::fromImage(rawPic)); - ui->ShowPic->setPixmap(QPixmap::fromImage(rawPic)); - - kernel->decreaseStep(SlopeCraft::step::nothing); - this->kernelSetType(); - this->kernelSetImg(); - this->updateEnables(); -} - -void MainWindow::on_ImportPic_clicked() { - QStringList userSelected = QFileDialog::getOpenFileNames( - this, tr("选择图片"), this->prevOpenedDir, - tr("图片 (*.png *.bmp *.jpg *.tif *.GIF )")); - - if (userSelected.isEmpty()) return; - - this->prevOpenedDir = QFileInfo(userSelected.front()).filePath(); - - if (userSelected.size() == 1) { - QString Path = userSelected.front(); - - if (Path.isEmpty()) { - return; - } - preprocessImage(Path); - - return; - } else { - auto bo = new BatchUi(this); - // qDebug("开始创建 BatchUi"); - bo->setTasks(userSelected); - bo->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); - bo->show(); - /* - connect(this,&MainWindow::mapTypeChanged, - batchOperator,&BatchUi::taskTypeUpdated); - */ - // qDebug("Mainwindow setTasks 完毕"); - return; - } -} - -void MainWindow::on_ImportSettings_clicked() { - auto transSubWind = new tpStrategyWind(this); - connect(transSubWind, &tpStrategyWind::Confirm, this, - &MainWindow::ReceiveTPS); - transSubWind->setVal(Strategy); - - transSubWind->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); - transSubWind->show(); -} - -void MainWindow::ReceiveTPS(tpS t) { - this->Strategy = t; - // qDebug("接收成功"); - // qDebug() << "pTpS=" << t.pTpS << ". hTpS=" << t.hTpS; -} - -QRgb ComposeColor(const QRgb front, const QRgb back) { - QRgb red = - (qRed(front) * qAlpha(front) + qRed(back) * (255 - qAlpha(front))) / 255; - QRgb green = - (qGreen(front) * qAlpha(front) + qGreen(back) * (255 - qAlpha(front))) / - 255; - QRgb blue = - (qBlue(front) * qAlpha(front) + qBlue(back) * (255 - qAlpha(front))) / - 255; - return qRgb(red, green, blue); -} - -inline void MainWindow::preProcess(char pureTpStrategy, char halfTpStrategy, - QRgb BGC) { - // qDebug("调用了 preProcess"); - // 透明像素处理策略:B->替换为背景色;A->空气;W->暂缓,等待处理 - // 半透明像素处理策略:B->替换为背景色;C->与背景色叠加;R->保留颜色;W->暂缓,等待处理 - // qDebug("Cpoied"); - bool hasTotalTrans = false; - if (pureTpStrategy != 'W' && halfTpStrategy != 'W') { - QRgb *CL = nullptr; - for (int r = 0; r < rawPic.height(); r++) { - CL = (QRgb *)rawPic.scanLine(r); - for (int c = 0; c < rawPic.width(); c++) { - if (qAlpha(CL[c]) >= 255) continue; - if (qAlpha(CL[c]) == 0) switch (pureTpStrategy) { - case 'B': - CL[c] = BGC; - continue; - case 'A': - if (!hasTotalTrans) { - // qDebug() << "发现纯透明像素"; - hasTotalTrans = true; - } - CL[c] = qRgba(0, 0, 0, 0); - continue; - } - - // qDebug("neeeee"); - switch (halfTpStrategy) { - case 'B': - CL[c] = BGC; - break; - case 'C': - CL[c] = ComposeColor(CL[c], BGC); - break; - case 'R': - CL[c] = qRgb(qRed(CL[c]), qGreen(CL[c]), qBlue(CL[c])); - } - } - } - } -} - -void MainWindow::onGameVerClicked() { - if (ui->isGame12->isChecked()) { - Manager->setVersion(12); - } - if (ui->isGame13->isChecked()) { - Manager->setVersion(13); - } - if (ui->isGame14->isChecked()) { - Manager->setVersion(14); - } - if (ui->isGame15->isChecked()) { - Manager->setVersion(15); - } - if (ui->isGame16->isChecked()) { - Manager->setVersion(16); - } - if (ui->isGame17->isChecked()) { - Manager->setVersion(17); - } - if (ui->isGame18->isChecked()) { - Manager->setVersion(18); - } - if (ui->isGame19->isChecked()) { - Manager->setVersion(19); - } - kernel->decreaseStep(SlopeCraft::step::nothing); - onBlockListChanged(); - - this->kernelSetType(); - if (!this->rawPic.isNull()) { - kernelSetImg(); - } - this->updateEnables(); -} - -void MainWindow::onMapTypeClicked() { - if (ui->isMapCreative->isChecked()) { - Manager->setEnabled(12, true); - } - if (ui->isMapFlat->isChecked()) { - Manager->setEnabled(12, true); - } - if (ui->isMapSurvival->isChecked()) { - Manager->setEnabled(12, false); - } - /* - if(ui->isMapWall->isChecked()) { - Manager->setEnabled(12,false); - }*/ - kernel->decreaseStep(SlopeCraft::step::nothing); - onBlockListChanged(); - - this->kernelSetType(); - if (!this->rawPic.isNull()) { - kernelSetImg(); - } - this->updateEnables(); -} - -void MainWindow::ChangeToCustom() { - ui->isBLCustom->setChecked(true); - kernel->decreaseStep(SlopeCraft::step::nothing); - updateEnables(); -} - -void MainWindow::onPresetsClicked() { - if (ui->isBLCreative->isChecked()) { - Manager->loadInternalPreset(preset_vanilla); - } - if (ui->isBLSurvivalCheaper->isChecked()) { - Manager->loadInternalPreset(preset_cheap); - } - if (ui->isBLSurvivalBetter->isChecked()) { - Manager->loadInternalPreset(preset_elegant); - } - if (ui->isBLGlowing->isChecked()) { - Manager->loadInternalPreset(preset_shiny); - } - - if (ui->isMapSurvival->isChecked()) Manager->setEnabled(12, false); - - kernel->decreaseStep(SlopeCraft::step::nothing); - - this->kernelSetType(); - if (!this->rawPic.isNull()) { - this->kernelSetImg(); - } - - updateEnables(); -} - -void MainWindow::onAlgoClicked() { - static SlopeCraft::convertAlgo lastChoice = - SlopeCraft::convertAlgo::RGB_Better; - static bool lastDither = false; - - SlopeCraft::convertAlgo now; - const bool nowDither = ui->AllowDither->isChecked(); - if (ui->isColorSpaceRGBOld->isChecked()) now = SlopeCraft::convertAlgo::RGB; - if (ui->isColorSpaceRGB->isChecked()) - now = SlopeCraft::convertAlgo::RGB_Better; - if (ui->isColorSpaceHSV->isChecked()) now = SlopeCraft::convertAlgo::HSV; - if (ui->isColorSpaceLab94->isChecked()) now = SlopeCraft::convertAlgo::Lab94; - if (ui->isColorSpaceLab00->isChecked()) now = SlopeCraft::convertAlgo::Lab00; - if (ui->isColorSpaceXYZ->isChecked()) now = SlopeCraft::convertAlgo::XYZ; - if (ui->isColorSpaceAi->isChecked()) now = SlopeCraft::convertAlgo::gaCvter; - - if (lastChoice == SlopeCraft::convertAlgo::gaCvter) kernelSetImg(); - - if ((lastChoice != now) || (lastDither != nowDither)) - kernel->decreaseStep(SlopeCraft::step::convertionReady); - - updateEnables(); - lastChoice = now; - lastDither = nowDither; -} - -void MainWindow::kernelSetType() { - SlopeCraft::mapTypes type = SlopeCraft::mapTypes::Slope; - { - if (ui->isMapCreative->isChecked()) type = SlopeCraft::mapTypes::FileOnly; - if (ui->isMapFlat->isChecked()) type = SlopeCraft::mapTypes::Flat; - if (ui->isMapSurvival->isChecked()) type = SlopeCraft::mapTypes::Slope; - /* - if(ui->isMapWall->isChecked()) - type=SlopeCraft::mapTypes::Wall;*/ - } - - SlopeCraft::gameVersion ver = SlopeCraft::gameVersion::MC19; - { - if (ui->isGame12->isChecked()) ver = SlopeCraft::gameVersion::MC12; - if (ui->isGame13->isChecked()) ver = SlopeCraft::gameVersion::MC13; - if (ui->isGame14->isChecked()) ver = SlopeCraft::gameVersion::MC14; - if (ui->isGame15->isChecked()) ver = SlopeCraft::gameVersion::MC15; - if (ui->isGame16->isChecked()) ver = SlopeCraft::gameVersion::MC16; - if (ui->isGame17->isChecked()) ver = SlopeCraft::gameVersion::MC17; - if (ui->isGame18->isChecked()) ver = SlopeCraft::gameVersion::MC18; - if (ui->isGame19->isChecked()) ver = SlopeCraft::gameVersion::MC19; - if (ui->isGame20->isChecked()) ver = SlopeCraft::gameVersion::MC20; - } - - bool allowedBaseColor[64]; - Manager->getEnableList(allowedBaseColor); - - std::array palette; - // const AbstractBlock * palette[64]; - Manager->getSimpleBlockList(palette.data()); - - kernel->setType(type, ver, allowedBaseColor, palette.data()); - const uint8_t *allowedMap; - int colorN = 0; - - SlopeCraft::SCL_getColorMapPtrs(nullptr, nullptr, nullptr, &allowedMap, - &colorN); - /* - cout<<"\n\nAllowedMap="; - for(int i=0;iisVanilla(); - emit mapTypeChanged(); -} - -void MainWindow::kernelSetImg() { - EImage rawImg = QImage2EImage(rawPic); - kernel->setRawImage(rawImg.data(), rawImg.rows(), rawImg.cols()); - // this->updateEnables(); -} - -EImage QImage2EImage(const QImage &qi) { - EImage ei; - if (qi.isNull() || qi.height() <= 0 || qi.width() <= 0) { - ei.setZero(0, 0); - return ei; - } - ei.setZero(qi.height(), qi.width()); - const QRgb *CL = nullptr; - for (int r = 0; r < ei.rows(); r++) { - CL = (const QRgb *)qi.scanLine(r); - for (int c = 0; c < ei.cols(); c++) ei(r, c) = CL[c]; - } - return ei; -} - -QImage EImage2QImage(const EImage &ei, ushort scale) { - QImage qi(ei.cols() * scale, ei.rows() * scale, - QImage::Format::Format_ARGB32); - QRgb *CL = nullptr; - for (int r = 0; r < qi.height(); r++) { - CL = (QRgb *)qi.scanLine(r); - for (int c = 0; c < qi.width(); c++) CL[c] = ei(r / scale, c / scale); - } - return qi; -} - -void MainWindow::progressRangeSet(void *p, int min, int max, int val) { - MainWindow *wind = (MainWindow *)p; - // 设置进度条的取值范围和值 - if (wind->proTracker == nullptr) { - qDebug("错误!proTracker==nullptr"); - return; - } - wind->proTracker->setRange(min, max); - wind->proTracker->setValue(val); -} - -void MainWindow::progressAdd(void *p, int deltaVal) { - MainWindow *wind = (MainWindow *)p; - if (wind->proTracker == nullptr) { - qDebug("错误!proTracker==nullptr"); - return; - } - wind->proTracker->setValue(deltaVal + wind->proTracker->value()); -} - -void MainWindow::algoProgressRangeSet(void *p, int min, int max, int val) { - MainWindow *wind = (MainWindow *)p; - wind->ui->algoBar->setRange(min, max); - wind->ui->algoBar->setValue(val); -} - -void MainWindow::algoProgressAdd(void *p, int deltaVal) { - MainWindow *wind = (MainWindow *)p; - wind->ui->algoBar->setValue(wind->ui->algoBar->value() + deltaVal); -} - -void MainWindow::on_Convert_clicked() { - if (kernel->queryStep() < SlopeCraft::step::wait4Image) { - // qDebug("setType again"); - onBlockListChanged(); - if (kernel->queryStep() < SlopeCraft::step::wait4Image) return; - } - - if (kernel->queryStep() < SlopeCraft::step::convertionReady) { - // qDebug("setImage again"); - kernelSetImg(); - if (kernel->queryStep() < SlopeCraft::step::convertionReady) return; - } - - SlopeCraft::convertAlgo now = SlopeCraft::convertAlgo::RGB; - bool nowDither = ui->AllowDither->isChecked(); - { - if (ui->isColorSpaceRGBOld->isChecked()) now = SlopeCraft::convertAlgo::RGB; - if (ui->isColorSpaceRGB->isChecked()) - now = SlopeCraft::convertAlgo::RGB_Better; - if (ui->isColorSpaceHSV->isChecked()) now = SlopeCraft::convertAlgo::HSV; - if (ui->isColorSpaceLab94->isChecked()) - now = SlopeCraft::convertAlgo::Lab94; - if (ui->isColorSpaceLab00->isChecked()) - now = SlopeCraft::convertAlgo::Lab00; - if (ui->isColorSpaceXYZ->isChecked()) now = SlopeCraft::convertAlgo::XYZ; - if (ui->isColorSpaceAi->isChecked()) now = SlopeCraft::convertAlgo::gaCvter; - } - - proTracker = ui->ShowProgressABbar; - - kernel->decreaseStep(SlopeCraft::step::convertionReady); - updateEnables(); - - bool temp = false; - ui->Convert->setEnabled(temp); // 防止用户在繁忙时重复操作 - ui->isColorSpaceHSV->setEnabled(temp); - ui->isColorSpaceRGB->setEnabled(temp); - ui->isColorSpaceLab94->setEnabled(temp); - ui->isColorSpaceLab00->setEnabled(temp); - ui->isColorSpaceXYZ->setEnabled(temp); - ui->isColorSpaceRGBOld->setEnabled(temp); - ui->isColorSpaceAi->setEnabled(temp); - ui->AllowDither->setEnabled(temp); - - std::clock_t startTime = std::clock(); - qDebug("Start to convert"); - kernel->convert(now, nowDither); - - qDebug() << "Convertion finished in " - << double(std::clock() - startTime) * 1000.0 / CLOCKS_PER_SEC - << " miliseconds."; - proTracker = nullptr; - - temp = true; - ui->Convert->setEnabled(temp); // 恢复锁定 - ui->isColorSpaceHSV->setEnabled(temp); - ui->isColorSpaceRGB->setEnabled(temp); - ui->isColorSpaceLab94->setEnabled(temp); - ui->isColorSpaceLab00->setEnabled(temp); - ui->isColorSpaceXYZ->setEnabled(temp); - ui->isColorSpaceRGBOld->setEnabled(temp); - ui->isColorSpaceAi->setEnabled(temp); - ui->AllowDither->setEnabled(temp); - on_ShowAdjed_clicked(); - updateEnables(); -} - -void MainWindow::on_ShowRaw_clicked() { - ui->ShowPic->setPixmap(QPixmap::fromImage(rawPic)); -} - -void MainWindow::on_ShowAdjed_clicked() { - EImage ei(kernel->getImageRows(), kernel->getImageCols()); - // int a, b; - kernel->getConvertedImage(nullptr, nullptr, ei.data()); - ui->ShowPic->setPixmap(QPixmap::fromImage(EImage2QImage(ei))); -} - -void MainWindow::on_ExData_clicked() { - int mapRows = ceil(kernel->getImageRows() / 128.0); - int mapCols = ceil(kernel->getImageCols() / 128.0); - int mapCounts = mapRows * mapCols; - ui->ShowDataRows->setText(QString::number(mapRows)); - ui->ShowDataCols->setText(QString::number(mapCols)); - ui->ShowDataCounts->setText(QString::number(mapCounts)); - ui->InputDataIndex->setText("0"); -} - -void MainWindow::on_ExportFlatDiagram_clicked() { - const QString path = - QFileDialog::getSaveFileName(this, "保存为平面示意图", "", "*.png"); - - if (path.isEmpty()) return; - - ui->ExportFlatDiagram->setEnabled(false); - ui->progressExFlatDiagram->setEnabled(false); - ui->ExportLite->setEnabled(false); - ui->progressExLite->setEnabled(false); - - this->proTracker = ui->ShowProgressExLite; - // ui->ShowProgressExLite->setValue(0); - - constexpr int charHeight = 14; - constexpr int charWidth = 10; - constexpr int charSpace = 1; - constexpr int leftSpace = 2; - constexpr int topSpace = 2; - - /* - here [] means an blank pixel - left border : [][]char[]char[]...char[]Blocks - - top border : - [] - [] - char - [] - char - [] - ... - char - [] - Blocks - */ - - const int buildRows = kernel->getZRange(); - const int buildCols = kernel->getXRange(); - - /// pixel rows and cols of single block - constexpr int blockRowsCols = 16; - - const int numberRowsDigits = std::ceil(std::log10(1e-2 + buildRows)); - const int numberColsDigits = std::ceil(std::log10(1e-2 + buildCols)); - - const int leftBorderWidth = - leftSpace + numberColsDigits * (charWidth + charSpace); - const int topBorderWidth = - topSpace + numberRowsDigits * (charHeight + charSpace); - - /// the height of exported image - const int diagramRows = blockRowsCols * buildRows + topBorderWidth; - /// the width of exported image - const int diagramCols = blockRowsCols * buildCols + leftBorderWidth; - - // progress bar range: 0~ rows + cols + pixNum + rows + cols + pixNum/10 - const int progressMax = buildRows + buildCols + buildRows * buildCols + - buildRows + buildCols + buildRows * buildCols / 10; - // ui->ShowProgressExLite->setRange(0,progressMax); - progressRangeSet(this, 0, progressMax, 0); - - using blockEImg_t = - Eigen::Array; - std::vector blockImgs16; - blockImgs16.reserve(64); - - // fill blockImgs16 with images of each block - { - auto tokiBlockList = Manager->getTokiBlockList(); - for (auto tokiBlock : tokiBlockList) { - if (tokiBlock == nullptr) { - break; - } - QImage tempImg = tokiBlock->getTarget() - ->icon() - .pixmap(blockRowsCols, blockRowsCols) - .toImage() - .convertToFormat(QImage::Format_ARGB32); - Eigen::Map map( - reinterpret_cast(tempImg.scanLine(0))); - SlopeCraft::SCL_preprocessImage(map.data(), map.size()); - blockImgs16.emplace_back(map); - } - } - - using charEImg_t = - Eigen::Array; - - std::vector numberImgs(10); - // fill numberImgs with images of each number - { - QImage tempImg = QImage(":/new/Pic/MCStyledNumbers.png") - .convertToFormat(QImage::Format_ARGB32); - Eigen::Map< - Eigen::Array> - mappedTempImg(reinterpret_cast(tempImg.scanLine(0)), - tempImg.height(), tempImg.width()); - for (int idx = 0; idx < 10; idx++) { - numberImgs[idx] = - mappedTempImg.block(0, idx * charWidth); - } - } - // cout<<"Size of blockImgs16 = "< - EDiagram; - - EDiagram.setConstant(diagramRows, diagramCols, 0xFFFFFFFFU); - - // write row numbers - for (int row = 0; row < buildRows; row++) { - const std::string str = std::to_string(row); - - const int rowOffset = - topBorderWidth + blockRowsCols * row + (blockRowsCols - charHeight) / 2; - // cout<<"\n\nrowOffset = "<= (int)str.size()) break; - - // the reverse idx - const char curChar = str[str.size() - 1 - invIdx]; - const int curCharIdx = curChar - '0'; - - const int colOffset = - leftBorderWidth - (invIdx + 1) * (charWidth + charSpace); - - // cout<<"colOffset = "<(rowOffset, colOffset) = - numberImgs[curCharIdx]; - } - } - - progressAdd(this, buildRows); - keepAwake(this); - // cout<= (int)str.size()) break; - const int curCharIdx = str[str.size() - 1 - invIdx] - '0'; - - const int rowOffset = - topBorderWidth - (invIdx + 1) * (charHeight + charSpace); - EDiagram.block(rowOffset, colOffset) = - numberImgs[curCharIdx]; - } - } - - progressAdd(this, buildCols); - keepAwake(this); - - const Eigen::TensorMap> build( - kernel->getBuild(), kernel->getXRange(), kernel->getHeight(), - kernel->getZRange()); - - static constexpr int reportInterval = 512; - - // fill diagram with blocks - for (int bRow = 0; bRow < buildRows; bRow++) { - constexpr int yPos = 0; - const int rowOffset = topBorderWidth + blockRowsCols * bRow; - const int zPos = bRow; - for (int bCol = 0; bCol < buildCols; bCol++) { - const int xPos = bCol; - const int eleIdx = &build(xPos, yPos, zPos) - build.data(); - - if (eleIdx % reportInterval == 0) { - progressAdd(this, reportInterval); - keepAwake(this); - } - - if (build(xPos, yPos, zPos) <= 0) continue; - - const int blockIdx = build(xPos, yPos, zPos) - 1; - - const int colOffset = leftBorderWidth + blockRowsCols * bCol; - - EDiagram.block(rowOffset, colOffset) = - blockImgs16[blockIdx]; - } - } - - // draw horizontal lines - for (int lineRows = 1; lineRows < buildRows; lineRows += 16) { - const int row = topBorderWidth + blockRowsCols * lineRows; - for (int col = leftBorderWidth; col < diagramCols; col++) { - EDiagram(row, col) = inverseColor(EDiagram(row, col)); - } - } - progressAdd(this, buildRows); - - // draw vertical lines - for (int lineCols = 1; lineCols < buildCols; lineCols += 16) { - const int col = leftBorderWidth + blockRowsCols * lineCols; - for (int row = topBorderWidth; row < diagramRows; row++) { - // if((row-topBorderWidth)%(blockRowsCols*16)==0) continue; - - EDiagram(row, col) = inverseColor(EDiagram(row, col)); - } - } - progressAdd(this, buildCols); - keepAwake(this); - - QImage(reinterpret_cast(EDiagram.data()), diagramCols, diagramRows, - QImage::Format_ARGB32) - .save(path); - - progressRangeSet(this, 0, progressMax, progressMax); - keepAwake(this); - - this->proTracker = nullptr; - - ui->FinishExLite->setEnabled(true); - - this->ProductDir = path; - - ProductDir = ProductDir.replace('\\', '/'); - ProductDir = ProductDir.left(ProductDir.lastIndexOf('/')); - - ui->seeExported->setEnabled(true); - - updateEnables(); -} - -// Page5 - -void MainWindow::on_Build4Lite_clicked() { - bool naturalCompress = ui->AllowNaturalOpti->isChecked(); - bool forcedCompress = ui->AllowForcedOpti->isChecked(); - SlopeCraft::compressSettings cS; - if (naturalCompress) { - if (forcedCompress) - cS = SlopeCraft::compressSettings::Both; - else - cS = SlopeCraft::compressSettings::NaturalOnly; - } else { - if (forcedCompress) - cS = SlopeCraft::compressSettings::ForcedOnly; - else - cS = SlopeCraft::compressSettings::noCompress; - } - - bool allowBridge = ui->allowGlassBridge->isChecked(); - SlopeCraft::glassBridgeSettings gBS = - allowBridge ? SlopeCraft::glassBridgeSettings::withBridge - : SlopeCraft::glassBridgeSettings::noBridge; - - kernel->decreaseStep(SlopeCraft::step::converted); - ui->ExportLite->setEnabled(false); - ui->FinishExLite->setEnabled(false); - ui->ManualPreview->setEnabled(false); - - proTracker = ui->ShowProgressExLite; - qDebug() << "ui->maxHeight->value()=" << ui->maxHeight->value(); - kernel->build( - cS, ui->maxHeight->value(), gBS, ui->glassBridgeInterval->value(), - ui->allowAntiFire->isChecked(), ui->allowAntiEnderman->isChecked()); - - int size3D[3], total; - - kernel->get3DSize(&size3D[0], &size3D[1], &size3D[2]); - total = kernel->getBlockCounts(); - ui->ShowLiteBlocks->setText(QString::number(total)); - ui->ShowLiteXYZ->setText(QString::fromStdString( - "X:" + std::to_string(size3D[0]) + " × Y:" + std::to_string(size3D[1]) + - " × Z:" + std::to_string(size3D[2]))); - proTracker = nullptr; - updateEnables(); - if (!isBatchOperating) showPreview(); -} - -void MainWindow::on_ManualPreview_clicked() { showPreview(); } - -void MainWindow::on_ExportLite_clicked() { onExportLiteclicked(""); } - -void MainWindow::onExportLiteclicked(QString path) { - std::string FileName; - if (path.isEmpty()) { - QStringList suffixes({tr("投影文件 (*.litematic)"), - tr("结构方块文件 (*.nbt)"), - tr("WorldEdit 原理图 (*.schem)")}); - - const int first_format_idx = ui->tabExport3DInfo->currentIndex(); - - QString suffix = suffixes[first_format_idx]; - - for (int idx = 0; idx < suffixes.size(); idx++) { - if (idx != first_format_idx) { - suffix += ";;"; - suffix += suffixes[idx]; - } - } - - FileName = QFileDialog::getSaveFileName(this, tr("导出为投影/结构方块文件"), - "", suffix) - .toLocal8Bit() - .data(); - } else { - FileName = path.toLocal8Bit().data(); - } - // std::string unCompressed; - char failed_file_name[512] = ""; - if (FileName.empty()) return; - const bool putLitematic = - (FileName.substr(FileName.length() - strlen(".litematic")) == - ".litematic"); - const bool putStructure = - (FileName.substr(FileName.length() - strlen(".nbt")) == ".nbt"); - const bool putWESchem = - (FileName.substr(FileName.length() - strlen(".schem")) == ".schem"); - - if (!putLitematic && !putStructure && !putWESchem) { - qDebug("Invalid save file name : "); - qDebug() << FileName.data(); - return; - } - // qDebug("开始导出投影"); - // cout << FileName << endl; - - ui->FinishExLite->setEnabled(false); - ui->seeExported->setEnabled(false); - ui->Build4Lite->setEnabled(false); - - this->proTracker = ui->ShowProgressExLite; - - if (putStructure) - kernel->exportAsStructure(FileName.data(), failed_file_name); - else if (putLitematic) - kernel->exportAsLitematic( - FileName.data(), ui->InputLiteName->text().toUtf8().data(), - (ui->InputRegionName->text() + tr("(xz 坐标=-65±128×整数)")) - .toUtf8() - .data(), - failed_file_name); - - else { - int offset[3] = {0, 0, 0}, weOffset[3] = {0, 0, 0}; - QString dependModsListString = ui->schem_required_mods->toPlainText(); - QStringList modList = dependModsListString.split('\n'); - - std::vector stdStrList(modList.size()); - std::vector charPtrs; - for (int idx = 0; idx < int(stdStrList.size()); idx++) { - stdStrList[idx] = modList[idx].toUtf8().data(); - charPtrs.emplace_back(stdStrList[idx].data()); - } - - const std::array offsetSrc( - {ui->schem_offsetX, ui->schem_offsetY, ui->schem_offsetZ}); - const std::array weOffsetSrc( - {ui->schem_weOffsetX, ui->schem_weOffsetY, ui->schem_weOffsetZ}); - - for (int d = 0; d < 3; d++) { - bool ok = true; - int result = offsetSrc[d]->text().toInt(&ok); - if (ok) offset[d] = result; - - result = weOffsetSrc[d]->text().toInt(&ok); - if (ok) weOffset[d] = result; - } - - kernel->exportAsWESchem(FileName.data(), offset, weOffset, - ui->schem_name->text().toUtf8().data(), - charPtrs.data(), charPtrs.size(), failed_file_name); - } - - if (std::strlen(failed_file_name) <= 0) { - // success - // qDebug("压缩成功"); - ProductDir = QString::fromLocal8Bit(FileName.data()); - ProductDir = ProductDir.replace('\\', '/'); - ProductDir = ProductDir.left(ProductDir.lastIndexOf('/')); - - qDebug() << "ProductDir=" << ProductDir; - - } else { - qDebug("Failed to export."); - QMessageBox::warning( - this, tr("投影文件导出失败"), - tr("这可能是汉字编码错误造成的。请检查路径中是否有汉字") + '\n' + - tr("错误信息:") + '\n' + failed_file_name); - return; - }; - - ui->FinishExLite->setEnabled(true); - ui->seeExported->setEnabled(true); - ui->Build4Lite->setEnabled(true); - - updateEnables(); - this->proTracker = nullptr; - // success - // qDebug("导出为投影成功"); - return; -} - -constexpr inline int ceil_to_128(int x) noexcept { - const bool add_1 = (x % 128) > 0; - x = x / 128; - if (add_1) { - x += 1; - } - return std::max(1, x); -} - -int MainWindow::mapRows() const noexcept { - return ceil_to_128(this->kernel->getImageRows()); -} -int MainWindow::mapCols() const noexcept { - return ceil_to_128(this->kernel->getImageCols()); -} -int MainWindow::mapCount() const noexcept { - return this->mapRows() * this->mapCols(); -} - -void MainWindow::on_InputDataIndex_textChanged() { - bool isIndexValid = false; - const int indexStart = ui->InputDataIndex->toPlainText().toInt(&isIndexValid); - isIndexValid = isIndexValid && (indexStart >= 0); - if (isIndexValid) { - if (this->mapCount() == 1) - ui->ShowDataFileName->setText( - QStringLiteral("map_%1.dat").arg(indexStart)); - else - ui->ShowDataFileName->setText( - QStringLiteral("map_%1.dat ~ map_%2.dat") - .arg(indexStart) - .arg(indexStart + this->mapCount() - 1)); - ui->ExportData->setEnabled(true); - return; - } - - ui->ShowDataFileName->setText( - tr("你输入的起始序号不可用,请输入大于等于 0 的整数!")); - ui->ExportData->setEnabled(false); - return; -} - -void MainWindow::on_ExportData_clicked() { onExportDataclicked(""); } - -std::vector MainWindow::existingMapDataFiles( - QString prefix) const noexcept { - std::vector ret; - ret.reserve(this->mapCount()); - const int start_number = this->ui->InputDataIndex->toPlainText().toInt(); - if (prefix.back() == '/' || prefix.back() == '\\') { - } else { - prefix += '/'; - } - - for (int idx = start_number; idx < this->mapCount() + start_number; idx++) { - QString filename = QStringLiteral("map_%1.dat").arg(idx); - QString abs_filename = prefix + filename; - if (!QFile(abs_filename).exists()) { - continue; - } - ret.emplace_back(filename); - } - - return ret; -} - -void MainWindow::onExportDataclicked(QString path) { - bool isIndexValid = false; - const int indexStart = ui->InputDataIndex->toPlainText().toInt(&isIndexValid); - isIndexValid = isIndexValid && (indexStart >= 0); - if (!isIndexValid) { - QMessageBox::information(this, tr("你输入的起始序号不可用"), - tr("请输入大于等于 0 的整数!")); - return; - } - QString FolderPath; - - if (path.isEmpty()) - FolderPath = (QFileDialog::getExistingDirectory( - this, tr("请选择导出的文件夹"), this->prevOpenedDir)); - else - FolderPath = path; - - if (FolderPath.isEmpty()) { - QMessageBox::information(this, tr("你选择的文件夹不存在!"), - tr("你可以选择存档中的 data 文件夹")); - return; - } - this->prevOpenedDir = FolderPath; - - { - auto files_to_be_covered = this->existingMapDataFiles(FolderPath); - if (files_to_be_covered.size() > 0) { - QString files{files_to_be_covered.front()}; - for (size_t idx = 1; idx < files_to_be_covered.size(); idx++) { - files += ';' + files_to_be_covered[idx]; - } - - auto ret = QMessageBox::warning( - this, tr("导出时将会覆盖部分地图文件"), - tr("%1 " - "个文件将被覆盖:\n%" - "2\n\n点击\"Yes\"将继续并覆盖这些文件,点击\"No\"将撤销本次操作。") - .arg(files_to_be_covered.size()) - .arg(files), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, - QMessageBox::StandardButton::No}); - if (ret == QMessageBox::StandardButton::No) { - return; - } - } - } - - ui->InputDataIndex->setEnabled(false); - ui->ExportData->setEnabled(false); - ui->FinshExData->setEnabled(false); - ui->ExportData->setText(tr("请稍等")); - - proTracker = ui->ShowProgressExData; - - FolderPath = FolderPath.replace('\\', '/'); - ProductDir = FolderPath; - - kernel->exportAsData(FolderPath.toLocal8Bit().data(), indexStart, - //&fileCount,unCompressedBuffers.data() - nullptr, nullptr); - // qDebug("导出地图文件成功"); - - ui->InputDataIndex->setEnabled(true); - ui->ExportData->setEnabled(true); - ui->FinshExData->setEnabled(true); - ui->ExportData->setText(tr("导出")); - proTracker = nullptr; - updateEnables(); -} - -void MainWindow::turnCh() { switchLan(Language::ZH); } - -void MainWindow::turnEn() { switchLan(Language::EN); } - -void MainWindow::switchLan(Language lang) { - emit Manager->translate(lang); - - if (lang == Language::EN) { - QString msg{""}; - - if (!this->trans_SC.load(":/i18n/SlopeCraft_en_US.qm")) { - msg += QStringLiteral("Failed to load translation file \"%1\"\n") - .arg(":/i18n/SlopeCraft_en_US.qm"); - } - if (!this->trans_BLM.load(":/i18n/BlockListManager_en_US.qm")) { - msg += QStringLiteral("Failed to load translation file \"%1\"\n") - .arg(":/i18n/BlockListManager_en_US.qm"); - } - if (!this->trans_VD.load(":/i18n/VersionDialog_en_US.qm")) { - msg += QStringLiteral("Failed to load translation file \"%1\"\n") - .arg(":/i18n/VersionDialog_en_US.qm"); - } - - if (!msg.isEmpty()) { - QMessageBox::warning(this, "Failed to load translation.", msg); - return; - } - - qApp->installTranslator(&this->trans_SC); - qApp->installTranslator(&this->trans_BLM); - qApp->installTranslator(&this->trans_VD); - ui->retranslateUi(this); - // qDebug("Changed language to English"); - } else { - qApp->removeTranslator(&this->trans_SC); - qApp->removeTranslator(&this->trans_BLM); - qApp->removeTranslator(&this->trans_VD); - ui->retranslateUi(this); - // qDebug("Changed language to Chinese"); - } - return; -} - -void MainWindow::on_allowGlassBridge_stateChanged(int arg1) { - ui->glassBridgeInterval->setEnabled(arg1); -} - -void MainWindow::showError(void *p, SlopeCraft::errorFlag error, - const char *msg) { - MainWindow *wind = (MainWindow *)p; - QString title, text; - bool isFatal = false; - - const QString detail = - (msg == nullptr) ? ("") - : (tr("\n具体信息:") + QString::fromStdString(msg)); - - switch (error) { - case SlopeCraft::errorFlag::NO_ERROR_OCCUR: - return; - case SlopeCraft::errorFlag::UNKNOWN_MAJOR_GAME_VERSION: - title = tr("未知游戏版本"); - text = detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_BLOCK_PALETTE_OVERFLOW: - title = tr("导出原理图失败"); - text = tr("方块种类超出上限。") + detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_WRONG_EXTENSION: - title = tr("导出原理图失败"); - text = tr("错误的文件扩展名") + detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS: - title = tr("导出原理图失败"); - text = tr("三维结构中存在错误的方块") + detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE: - title = tr("导出原理图失败"); - text = tr("无法创建/打开文件") + detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_MC12_NOT_SUPPORTED: - title = tr("导出 WorldEdit 原理图失败"); - text = tr("不支持导出 1.12 " - "WorldEdit 原理图(.schematic 格式),仅支持.schem 格式") + - detail; - break; - case SlopeCraft::errorFlag::EXPORT_SCHEM_STRUCTURE_REQUIRES_AIR: - title = tr("导出原版结构方块文件失败"); - text = tr("导出时指定不使用结构空位表示空气,但方块列表中不包含空气。") + - detail; - break; - - case SlopeCraft::errorFlag::EMPTY_RAW_IMAGE: - title = tr("转化原图为地图画时出错"); - text = tr("原图为空!你可能没有导入原图!"); - break; - case SlopeCraft::errorFlag::DEPTH_3_IN_VANILLA_MAP: - title = tr("构建高度矩阵时出现错误"); - text = tr( - "原版地图画不允许出现第三个阴影(不存在的几何关系不可能生存实装!)\n" - "请检查你的地图画类型,纯文件地图画不可以导出为投影!"); - break; - case SlopeCraft::errorFlag::HASTY_MANIPULATION: - title = tr("跳步操作"); - text = tr("SlopeCraft 不允许你跳步操作,请按照左侧竖边栏的顺序操作!"); - break; - case SlopeCraft::errorFlag::LOSSYCOMPRESS_FAILED: - title = tr("有损压缩失败"); - text = - tr("在构建高度矩阵时,有损压缩失败,没能将地图画压缩到目标高度。 \ - 这可能是因为地图画行数过大。 \ - 尝试启用无损压缩,或者提高最大允许高度"); - break; - case SlopeCraft::errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14: - title = tr("最大允许高度太小了"); - text = tr("有损压缩的最大允许不要低于 14,否则很容易压缩失败"); - break; - case SlopeCraft::errorFlag::USEABLE_COLOR_TOO_FEW: - title = tr("允许使用的颜色过少"); - text = tr("你应该勾选启用尽可能多的基色,颜色太少是不行的!"); - break; - case SlopeCraft::errorFlag::FAILED_TO_COMPRESS: - title = tr("导出时 Gzip 压缩文件失败"); - text = tr("这可能是因为路径中含有中文字符!"); - break; - case SlopeCraft::errorFlag::FAILED_TO_REMOVE: - title = tr("删除临时文件失败"); - text = tr("这可能是因为路径中含有中文字符!"); - break; - } - if (isFatal) - QMessageBox::warning(wind, title, text + detail, - QMessageBox::StandardButton::Ok, - QMessageBox::StandardButton::NoButton); - else { - QMessageBox::critical(wind, title, text + detail, - QMessageBox::StandardButton::Close); - emit wind->ui->Exit->clicked(); - } - wind->updateEnables(); - return; -} - -void MainWindow::showWorkingStatue(void *p, SlopeCraft::workStatues statue) { - MainWindow *wind = (MainWindow *)p; - QString title = wind->windowTitle(); - const char spacer[] = " | "; - if (title.contains(spacer)) { - title = title.left(title.lastIndexOf(spacer)); - } - - if (statue != SlopeCraft::workStatues::none) title += spacer; - - switch (statue) { - case SlopeCraft::workStatues::none: - break; - case SlopeCraft::workStatues::buidingHeighMap: - title += tr("正在构建高度矩阵"); - break; - case SlopeCraft::workStatues::building3D: - title += tr("正在构建三维结构"); - break; - case SlopeCraft::workStatues::collectingColors: - title += tr("正在收集整张图片的颜色"); - break; - case SlopeCraft::workStatues::compressing: - title += tr("正在压缩立体地图画"); - break; - case SlopeCraft::workStatues::constructingBridges: - title += tr("正在为立体地图画搭桥"); - break; - case SlopeCraft::workStatues::converting: - title += tr("正在匹配颜色"); - break; - case SlopeCraft::workStatues::dithering: - title += tr("正在使用抖动仿色"); - break; - case SlopeCraft::workStatues::flippingToWall: - title += tr("正在将平板地图画变为墙面地图画"); - break; - case SlopeCraft::workStatues::writing3D: - title += tr("正在写入三维结构"); - break; - case SlopeCraft::workStatues::writingBlockPalette: - title += tr("正在写入方块列表"); - break; - case SlopeCraft::workStatues::writingMapDataFiles: - title += tr("正在写入地图数据文件"); - break; - case SlopeCraft::workStatues::writingMetaInfo: - title += tr("正在写入基础信息"); - break; - } - - wind->setWindowTitle(title); - return; -} - -void MainWindow::on_seeExported_clicked() { - if (ProductDir.isEmpty()) { - return; - } - qDebug() << "ProductDir=" << ProductDir; - QDesktopServices::openUrl(QUrl::fromLocalFile(ProductDir)); -} - -void MainWindow::on_AllowForcedOpti_stateChanged(int arg1) { - ui->maxHeight->setEnabled(arg1); -} - -void MainWindow::on_reportBugs_clicked() { - QUrl url("https://github.com/SlopeCraft/SlopeCraft/issues/new/choose"); - QDesktopServices::openUrl(url); -} - -void MainWindow::checkVersion() { - // QtConcurrent::run(grabVersion,this); - grabVersion(false); - return; -} - -void MainWindow::grabVersion(bool isAuto) { - VersionDialog::start_network_request( - this, "SlopeCraft", - QUrl("https://api.github.com/repos/SlopeCraft/SlopeCraft/releases"), - networkManager(), !isAuto); -} - -void MainWindow::onBlockListChanged() { - // qDebug("onBlockListChanged"); - if (kernel->queryStep() < SlopeCraft::step::nothing) { - return; - } - - this->kernelSetType(); - if (!this->rawPic.isNull()) { - this->kernelSetImg(); - } - this->updateEnables(); - - ushort colorCount = kernel->getColorCount(); - ui->IntroColorCount->setText(tr("可用") + QString::number(colorCount) + - tr("种颜色")); -} - -void MainWindow::closeEvent(QCloseEvent *event) { - emit closed(); - qDebug("closed Signal emitted"); - QMainWindow::closeEvent(event); - exit(0); -} - -void MainWindow::keyPressEvent(QKeyEvent *event) { - switch (event->key()) { - case Qt::Key::Key_F5: { - QString destName = QFileDialog::getSaveFileName( - this, tr("保存截屏"), "", - tr("图片 (*.jpg *.jpeg *.tif *.bmp *.png)")); - - if (destName.isEmpty()) { - break; - } - - QPixmap pix = this->grab(); - pix.save(destName); - break; - } - default: - break; - } - - QMainWindow::keyPressEvent(event); -} - -void MainWindow::on_ExImage_clicked() { - QPixmap image = ui->ShowPic->pixmap(); - - if (image.isNull()) { - return; - } - - QString savePath = QFileDialog::getSaveFileName(this, tr("保存当前显示图片"), - "./", tr("图片 (*.png)")); - - if (savePath.isEmpty()) { - return; - } - - image.save(savePath); -} - -void MainWindow::selectBlockByString(const std::string &key) { - std::vector tbcs; - Manager->getTokiBaseColors(&tbcs); - - for (uint8_t baseColor = 0; baseColor < tbcs.size(); baseColor++) { - std::vector tbs; - tbcs[baseColor]->getTokiBlockList(tbs); - for (uint16_t idx = 0; idx < tbs.size(); idx++) { - std::string curBlockId = tbs[idx]->getSimpleBlock()->getId(); - if (curBlockId.find(key) != std::string::npos) { - Manager->setSelected(baseColor, idx); - continue; - } - } - } -} - -void MainWindow::onActionSavePreset() { - QString dst = QFileDialog::getSaveFileName( - this, tr("保存预设"), "", - QStringLiteral("*") + MainWindow::sc_preset_extension); - if (dst.isEmpty()) return; - - auto preset = this->Manager->currentPreset(); - - QString content = serialize_preset(preset); - - QFile ofile(dst); - if (!ofile.open(QFile::OpenMode::enum_type::WriteOnly)) { - QMessageBox::warning(this, tr("保存预设文件失败"), - tr("无法创建文件\"%1\"").arg(dst)); - return; - } - - ofile.write(content.toUtf8()); - ofile.close(); -} - -void MainWindow::onActionLoadPreset() { - QString src = QFileDialog::getOpenFileName( - this, tr("选择预设文件"), this->prevOpenedDir, - QStringLiteral("*") + MainWindow::sc_preset_extension); - if (src.isEmpty()) return; - - this->prevOpenedDir = QFileInfo(src).filePath(); - QString err; - auto preset = load_preset(src, err); - if (!err.isEmpty()) { - QMessageBox::warning(this, tr("加载预设失败"), err); - return; - } - - this->Manager->loadPreset(preset); -} - -void MainWindow::onActionAiCvterParameters() { - auto acpDialog = new AiCvterParameterDialog(this); - acpDialog->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); - acpDialog->show(); -} - -void MainWindow::on_FirstConcrete_clicked() { selectBlockByString("concrete"); } - -void MainWindow::on_FirstWool_clicked() { selectBlockByString("wool"); } - -void MainWindow::on_FirstStainedGlass_clicked() { - selectBlockByString("stained_glass"); -} - -void MainWindow::testBlockList() { - std::vector ptr_buffer; - std::vector base_buffer; - - const int buffSize = Manager->getBlockNum(); - ptr_buffer.resize(buffSize + 1); - base_buffer.resize(buffSize + 1); - - Manager->getBlockPtrs(ptr_buffer.data(), base_buffer.data()); - - QString targetName = QFileDialog::getSaveFileName( - this, tr("测试方块列表的结构文件"), "", "*.nbt"); - if (targetName.isEmpty()) { - return; - } - - char failed_file_name[512] = ""; - kernel->makeTests(ptr_buffer.data(), base_buffer.data(), - targetName.toLocal8Bit().data(), failed_file_name); - if (std::string_view(failed_file_name).empty()) { - // cerr<<"Success"<tabExport3DInfo->setCurrentIndex(0); -} - -void MainWindow::on_ExStructure_clicked() { - ui->tabExport3DInfo->setCurrentIndex(1); -} - -void MainWindow::on_ExWESchem_clicked() { - ui->tabExport3DInfo->setCurrentIndex(2); -} - -void MainWindow::exportAvailableColors() { - constexpr int basecolors_per_row = 4; - constexpr int basecolors_per_col = 16; - - static_assert(basecolors_per_row * basecolors_per_col == 64); - - constexpr int row_pixels = basecolors_per_row * 4; - constexpr int col_pixels = basecolors_per_col * 1; - - static_assert(row_pixels * col_pixels == 256); - - const QString dest_file = - QFileDialog::getSaveFileName(this, tr("保存颜色表"), "", "*.png"); - - if (dest_file.isEmpty()) { - return; - } - - QImage img(row_pixels, col_pixels, QImage::Format::Format_ARGB32); - - if (img.isNull()) { - QMessageBox::warning(this, tr("保存颜色表失败"), tr("分配内存失败")); - return; - } - - img.fill(0x00FFFFFFU); - - Eigen::Map< - Eigen::Array> - map(reinterpret_cast(img.scanLine(0)), row_pixels, - col_pixels); - - uint32_t argb_colors[256]; - uint8_t map_colors[256]; - const int available_colors = kernel->getColorCount(); - kernel->getAvailableColors(argb_colors, map_colors); - - for (int cidx = 0; cidx < available_colors; cidx++) { - /* - const int basecolor = (map_colors[cidx] / 4); - const int shade = (map_colors[cidx] % 4); - const int pixel_row = basecolor / basecolors_per_col; - const int pixel_col = (basecolor % basecolors_per_col) * 4 + shade; - */ - map(map_colors[cidx]) = argb_colors[cidx]; - } - - if (img.save(dest_file)) { - this->ProductDir = dest_file; - } - return; -} - -QNetworkAccessManager &MainWindow::networkManager() noexcept { - static QNetworkAccessManager manager; - return manager; -} \ No newline at end of file diff --git a/SlopeCraftMain/MainWindow.h b/SlopeCraftMain/MainWindow.h deleted file mode 100644 index f7e39816..00000000 --- a/SlopeCraftMain/MainWindow.h +++ /dev/null @@ -1,298 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -// #define dispDerivative -// #define putDitheredImg -// #define putMapData -// #define putBlockList -#include "ui_mainwindow.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -// #define SLOPECRAFTL_WITH_AICVETR -#include "SlopeCraftL.h" - -#include "AiCvterParameterDialog.h" -#include "BatchUi.h" -#include "BlockListManager.h" -#include "previewwind.h" -#include "tpstrategywind.h" - -#include - -class MainWindow; - -using std::cout, std::endl, std::cerr; - -#include -#include - -// class ColorSet; - -QT_BEGIN_NAMESPACE -namespace Ui { -class MainWindow; -} -QT_END_NAMESPACE - -class tpStrategyWind; - -#ifndef TPS__ -#define TPS__ -class tpS { - public: - tpS(char _pTpS = 'B', char _hTpS = 'C', QRgb _BGC = qRgb(220, 220, 220)) { - pTpS = _pTpS; - hTpS = _hTpS; - BGC = _BGC; - } - ~tpS(); - char pTpS; - char hTpS; - QRgb BGC; -}; -#endif - -class MainWindow : public QMainWindow { - Q_OBJECT - friend class BatchUi; - - public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - - // 初始化方块列表用 - void InitializeAll(); - - static constexpr char sc_preset_extension[] = ".sc_preset_json"; - - signals: - void mapTypeChanged(); - - void closed(); - - protected: - void closeEvent(QCloseEvent *) override; - void keyPressEvent(QKeyEvent *) override; - - public: - inline void preProcess(char pureTpStrategy = 'B', char halfTpStrategy = 'C', - QRgb BGC = qRgb(220, 220, 220)); - - inline auto kernelPtr() const { return kernel; } - - static QNetworkAccessManager &networkManager() noexcept; - - public slots: - void ReceiveTPS(tpS); - // 透明像素处理策略:B->替换为背景色;A->空气;W->暂缓,等待处理 - // 半透明像素处理策略:B->替换为背景色;C->与背景色叠加;R->保留颜色;W->暂缓,等待处理 - - void showPreview(); - // 语言槽 - void turnCh(); - void turnEn(); - - void checkVersion(); - - void grabVersion(bool isAuto = true); - - private slots: - - // void when_network_finished(QNetworkReply *reply, bool is_manually); - - void on_actionTutorial_triggered(); - - void contactG(); - void contactB(); - // 翻页的自定义槽 - void turnToPage0(); - void turnToPage1(); - void turnToPage2(); - void turnToPage3(); - void turnToPage4(); - void turnToPage5(); - void turnToPage6(); - void turnToPage7(); - void turnToPage8(); - - // for Page0 - void on_StartWithSlope_clicked(); - void on_StartWithFlat_clicked(); - void on_StartWithNotVanilla_clicked(); - - // for Page1 - void on_ImportPic_clicked(); - void on_ImportSettings_clicked(); - - // for Page2 - void onGameVerClicked(); - void onMapTypeClicked(); - - // for Page3 - // 应用预设方块列表的自定义槽 - void ChangeToCustom(); - void onPresetsClicked(); - void onBlockListChanged(); - - void onActionSavePreset(); - void onActionLoadPreset(); - - void exportAvailableColors(); - - // for Page4 - void onAlgoClicked(); - void on_Convert_clicked(); - void on_ShowRaw_clicked(); - void on_ShowAdjed_clicked(); - void on_ExData_clicked(); - void on_ExportFlatDiagram_clicked(); - // void on_ExFlatDiagram_clicked(); - - void onActionAiCvterParameters(); - - void on_ExLite_clicked(); - - void on_ExStructure_clicked(); - - void on_ExWESchem_clicked(); - - // for Page5 - void on_Build4Lite_clicked(); - void on_ManualPreview_clicked(); - void on_ExportLite_clicked(); - void onExportLiteclicked(QString); - void on_allowGlassBridge_stateChanged(int arg1); - - // for Page7 - void on_InputDataIndex_textChanged(); - void on_ExportData_clicked(); - void onExportDataclicked(QString); - - void on_seeExported_clicked(); - - void on_AllowForcedOpti_stateChanged(int arg1); - - void on_reportBugs_clicked(); - - // void on_StartWithWall_clicked(); - - void on_ExImage_clicked(); - - void on_FirstConcrete_clicked(); - - void on_FirstWool_clicked(); - - void on_FirstStainedGlass_clicked(); - - void testBlockList(); - - private: - Ui::MainWindow *ui; - - SlopeCraft::Kernel *const kernel; - BlockListManager *Manager; - - QImage rawPic; - - static bool isBatchOperating; - - static blockListPreset preset_vanilla; - static blockListPreset preset_elegant; - static blockListPreset preset_cheap; - static blockListPreset preset_shiny; - - tpS Strategy; - - QString prevOpenedDir{"./"}; - QString ProductDir; - QTranslator trans_SC; - QTranslator trans_BLM; - QTranslator trans_VD; - bool Collected; - QProgressBar *proTracker; - - // void applyPre(ushort*BL); - - private: - void loadBlockList(); - void turnToPage(int); - void updateEnables(); - void preprocessImage(const QString &); - void switchLan(Language); - void kernelSetType(); - void kernelSetImg(); - - void selectBlockByString(const std::string &); - - static void progressRangeSet(void *, int min, int max, - int val); // 设置进度条的取值范围和值 - static void progressAdd(void *, int deltaVal); - static void keepAwake(void *); - - static void showError(void *, SlopeCraft::errorFlag, const char *errInfo); - static void showWorkingStatue(void *, SlopeCraft::workStatues); - - static void algoProgressRangeSet(void *, int min, int max, int val); - static void algoProgressAdd(void *, int deltaVal); - - int mapRows() const noexcept; - int mapCols() const noexcept; - int mapCount() const noexcept; - - std::vector existingMapDataFiles(QString prefix) const noexcept; -}; - -using EImage = Eigen::ArrayXX; - -EImage QImage2EImage(const QImage &); -QImage EImage2QImage(const EImage &, ushort scale = 1); -#endif // MAINWINDOW_H diff --git a/SlopeCraftMain/TaskBox.cpp b/SlopeCraftMain/TaskBox.cpp deleted file mode 100644 index b337c601..00000000 --- a/SlopeCraftMain/TaskBox.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TaskBox.h" - -TaskType TaskBox::taskType = TaskType::Litematica; - -TaskBox::TaskBox(QWidget *parent) : QWidget(parent), ui(new Ui::TaskBox) { - ui->setupUi(this); - mapCols = 0; - mapRows = 0; -} - -TaskBox::~TaskBox() { delete ui; } - -void TaskBox::on_browseImage_clicked() { - QString imgPath = QFileDialog::getOpenFileName( - this, tr("选择图片"), "./", tr("图片(*.png *.bmp *.jpg *.tif *.GIF )")); - if (imgPath.isEmpty()) - return; - setTask(imgPath); -} diff --git a/SlopeCraftMain/TaskBox.h b/SlopeCraftMain/TaskBox.h deleted file mode 100644 index efb28c86..00000000 --- a/SlopeCraftMain/TaskBox.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TASKBOX_H -#define TASKBOX_H - -#include "ui_TaskBox.h" -#include -#include - -namespace Ui { -class TaskBox; -} - -class BatchUi; - -enum TaskType { Litematica, Structure, Data }; - -class TaskBox : public QWidget { - Q_OBJECT - // friend class BatchUi; -public: - explicit TaskBox(QWidget *parent = nullptr); - ~TaskBox(); - - static TaskType taskType; - - inline int32_t mapSize() const { return mapRows * mapCols; } - - inline void updateTaskType() { - ui->liteName->setText(rawImgPath() + liteSuffix()); - ui->DenoteLiteName->setEnabled(taskType != TaskType::Data); - ui->liteName->setEnabled(taskType != TaskType::Data); - ui->setMapBegSeq->setEnabled(taskType == TaskType::Data); - } - - void setTask(const QString &rawImg) { - QImage img; - int32_t prevMapSize = mapSize(); - if (!img.load(rawImg)) { - mapRows = 0; - mapCols = 0; - ui->preView->setPixmap(QPixmap()); - ui->preView->setText(tr("图片格式损坏")); - } - mapRows = std::ceil(img.height() / 128.0); - mapCols = std::ceil(img.width() / 128.0); - ui->preView->setPixmap(QPixmap::fromImage(img.scaledToWidth(128))); - ui->preView->setText(""); - ui->imageName->setText(rawImg); - - updateTaskType(); - - if (prevMapSize != mapSize() && taskType == Data) { - emit seqNumChanged(this); - } - } - - inline QString rawImgPath() const { return ui->imageName->text(); } - - inline QString liteName() const { return ui->liteName->text(); } - - inline int32_t begSeqNum() const { return ui->setMapBegSeq->value(); } - - inline static const char *liteSuffix() { - switch (taskType) { - case TaskType::Litematica: - return ".litematic"; - case TaskType::Structure: - return ".nbt"; - default: - return ".ERROR_TASK_TYPE"; - } - } - - inline void setMapBegSeqReadOnly(bool mbsro) { - ui->setMapBegSeq->setReadOnly(mbsro); - } - - inline void setMapBegSeq(int32_t mbs) { - ui->setMapBegSeq->setValue(mbs); - ui->setMapBegSeq->setSuffix(" ~ " + QString::number(mbs + mapSize() - 1)); - } - -signals: - void erase(TaskBox *); - void seqNumChanged(TaskBox *); - -private slots: - void on_imageName_editingFinished() { setTask(ui->imageName->text()); } - - void on_setMapBegSeq_valueChanged(int) { - if (!ui->setMapBegSeq->isReadOnly()) { - emit seqNumChanged(this); - } - } - - void on_BtnErase_clicked() { emit erase(this); } - - void on_browseImage_clicked(); - -private: - Ui::TaskBox *ui; - int16_t mapRows; - int16_t mapCols; -}; - -#endif // TASKBOX_H diff --git a/SlopeCraftMain/TaskBox.ui b/SlopeCraftMain/TaskBox.ui deleted file mode 100644 index c9b114cc..00000000 --- a/SlopeCraftMain/TaskBox.ui +++ /dev/null @@ -1,149 +0,0 @@ - - - TaskBox - - - - 0 - 0 - 500 - 132 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 6 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 浏览 - - - - - - - - 123 - 123 - - - - true - - - QFrame::StyledPanel - - - - - - true - - - - - - - - - - - 0 - 0 - - - - 投影/结构文件名 - - - - - - - 0 - - - - - × - - - Qt::NoArrow - - - - - - - - - true - - - ~ - - - 占用的地图序号: - - - 65535 - - - - - - - - 0 - 0 - - - - - 0 - 22 - - - - FileName - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - diff --git a/SlopeCraftMain/install.cmake b/SlopeCraftMain/install.cmake deleted file mode 100644 index 5daa80a9..00000000 --- a/SlopeCraftMain/install.cmake +++ /dev/null @@ -1,145 +0,0 @@ - -file(GLOB SlopeCraft_install_jsons - "${CMAKE_SOURCE_DIR}/Blocks/*.json" - "${CMAKE_SOURCE_DIR}/Blocks/*.md") - -file(GLOB SlopeCraft_install_png_fixedblocks - "${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks/*.png") - -file(GLOB SlopeCraft_install_png_customblocks - "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") - -file(GLOB SlopeCraft_install_presets - "${CMAKE_CURRENT_SOURCE_DIR}/others/*.sc_preset_json") - -set(AppName SlopeCraft) -configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake - @ONLY) - -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") - # Install for macOS - # Install app - install(TARGETS SlopeCraft - RUNTIME DESTINATION . - BUNDLE DESTINATION . - ) - - # Install icons - file(GLOB SlopeCraft_Icon - ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.icns) - install(FILES ${SlopeCraft_Icon} - DESTINATION SlopeCraft.app/Contents/Resources) - - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks) - file(COPY ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks) - - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) - file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) - - # Install presets - install(FILES ${SlopeCraft_install_presets} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/Presets) - file(COPY ${SlopeCraft_install_presets} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) - return() -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Windows") - # Install app - install(TARGETS SlopeCraft - RUNTIME DESTINATION . - ) - - # Run windeployqt at build time - add_custom_target(Windeployqt-SlopeCraft ALL - COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS SlopeCraft) - - # Run windeployqt at install time - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} - DESTINATION Blocks) - file(COPY ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) - - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION Blocks/CustomBlocks) - file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) - - # Install presets - install(FILES ${SlopeCraft_install_presets} - DESTINATION Blocks/Presets) - file(COPY ${SlopeCraft_install_presets} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) - - return() -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - # set_target_properties(SlopeCraft PROPERTIES INSTALL_RPATH "../lib") - # Install for Linux - # Install app - install(TARGETS SlopeCraft - RUNTIME DESTINATION bin - ) - - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} - DESTINATION bin/Blocks) - file(COPY ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) - - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION bin/Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION bin/Blocks/CustomBlocks) - file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) - - file(GLOB SlopeCraft_Icon ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.png) - - install(FILES ${SlopeCraft_Icon} - DESTINATION bin/icons) - - # Install presets - install(FILES ${SlopeCraft_install_presets} - DESTINATION bin/Blocks/Presets) - file(COPY ${SlopeCraft_install_presets} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/Presets) - - # Install platforms and imageformats plugins - include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) - - return() -endif() - -message(WARNING "No rule to install SlopeCraft and images, because the system is not Windows, linux or MacOS.") diff --git a/SlopeCraftMain/main.cpp b/SlopeCraftMain/main.cpp deleted file mode 100644 index c3d7c35b..00000000 --- a/SlopeCraftMain/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright © 2021-2022 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/ToKiNoBug - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "MainWindow.h" - -#include -#include -#include - -int main(int argc, char *argv[]) { - QApplication a(argc, argv); - - const QStringList uiLanguages = QLocale::system().uiLanguages(); - - // qDebug() << uiLanguages; - - // qDebug() << "当前运行路径:" << QCoreApplication::applicationDirPath(); - // QString DirPath=QCoreApplication::applicationDirPath()+'/'; - QDir::setCurrent(QCoreApplication::applicationDirPath()); - - const QStringList ZHLang = {"zh-CN", "zh", "zh-Hans-CN"}; - - bool isZH = false; - for (auto it = ZHLang.cbegin(); it != ZHLang.cend(); it++) { - if (uiLanguages.contains(*it)) { - isZH = true; - break; - } - } - - MainWindow w; - w.show(); - - if (isZH) - w.turnCh(); - else - w.turnEn(); - - w.InitializeAll(); - - if (isZH) - w.turnCh(); - else - w.turnEn(); - - w.grabVersion(true); - - return a.exec(); -} diff --git a/SlopeCraftMain/mainwindow.ui b/SlopeCraftMain/mainwindow.ui deleted file mode 100644 index 2274c618..00000000 --- a/SlopeCraftMain/mainwindow.ui +++ /dev/null @@ -1,4062 +0,0 @@ - - - TokiNoBug - MainWindow - - - - 0 - 0 - 960 - 540 - - - - - 0 - 0 - - - - - 960 - 540 - - - - - 16777215 - 16777215 - - - - - - - SlopeCraft v5.0.1 Copyright © 2021-2023 TokiNoBug - - - - others/SlopeCraftIconNew.icoothers/SlopeCraftIconNew.ico - - - - - - - 128 - 128 - - - - true - - - QTabWidget::Rounded - - - true - - - - - 0 - 0 - - - - QWidget#centralwidget{border-image: url(":/new/Pic/BG4.png");} - - - - QLayout::SetNoConstraint - - - 4 - - - 4 - - - 4 - - - 4 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - #LeftScroll ,#LeftScrollArea{ - background-color: rgba(255, 255, 255, 0); -} - -QPushButton:enabled{ - border:2px; - border-radius:10px; - padding:2px 4px; - background-color: rgba(255, 255, 255,128); - color: rgb(0, 0, 0); - font: 9pt "微软雅黑"; -} - -QPushButton:!enabled{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(191, 191,191,128); -color: rgb(64, 64, 64); -font: 9pt "微软雅黑"; -} - -QPushButton:hover{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(255, 255, 255,191); -color: rgb(0, 0, 0); -font: 9pt "微软雅黑"; -} - -QPushButton:pressed{ -border:2px; -border-radius:10px; -padding:2px 4px; -background-color: rgba(255, 255, 255,223); -border-style: inset; -border-color: rgb(235, 235, 235); -color: rgb(0, 0, 0); -font: 9pt "微软雅黑"; -} - -/**/ - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - true - - - Qt::AlignCenter - - - - - 0 - 0 - 152 - 757 - - - - - 0 - 0 - - - - - 0 - 0 - - - - false - - - - - - - 9 - - - 5 - - - 5 - - - 9 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:700; color:#ffffff;">地图画</span></p></body></html> - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - 开始 - - - - :/new/Textures/Slope/block/grass_block.png:/new/Textures/Slope/block/grass_block.png - - - - - - - - 100 - 30 - - - - 导入图片 - - - - :/new/Textures/Slope/items/book.png:/new/Textures/Slope/items/book.png - - - - - - - true - - - - 100 - 30 - - - - - - - 地图画类型 - - - - :/new/Textures/Slope/items/map.png:/new/Textures/Slope/items/map.png - - - - - - - - 100 - 30 - - - - 方块列表 - - - - :/new/Textures/Slope/block/waxed_cut_copper.png:/new/Textures/Slope/block/waxed_cut_copper.png - - - - - - - - 100 - 30 - - - - 调整颜色 - - - - :/new/Textures/Slope/items/amethyst_shard.png:/new/Textures/Slope/items/amethyst_shard.png - - - - - - - - 100 - 30 - - - - 导出为 - - - - :/new/Textures/Slope/items/iron_pickaxe.png:/new/Textures/Slope/items/iron_pickaxe.png - - - - - - - 0 - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 平面示意图 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 地图文件 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 投影文件 - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - 结构文件 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 90 - 25 - - - - WE原理图 - - - - - - - - - - 100 - 30 - - - - 完成 - - - - :/new/Textures/Slope/items/diamond.png:/new/Textures/Slope/items/diamond.png - - - - - - - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">语言/Languages</span></p></body></html> - - - - - - - - 0 - 30 - - - - 简体中文 - - - - - - - - 0 - 30 - - - - English - - - - - - - <html><head/><body><p><br/><span style=" font-weight:700; color:#ffffff;">联系作者</span></p></body></html> - - - - - - - - 0 - 30 - - - - GitHub - - - - - - - - 0 - 30 - - - - BiliBili - - - - - - - - 0 - 30 - - - - 检查更新 - - - - - - - - 0 - 30 - - - - 反馈Bug - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - 0 - 0 - - - - - 30 - 0 - - - - - - - /*QWidget#PageEnd{border-image: url(:/new/Pic/BG4.png);}*/ - -QWidget#PageStart,#PageEnd{ - background-color: rgba(255, 255, 255, 0); -} - - -QWidget#PageImPic,#PageType,#PageBL,#PageAdjPic,#PageExLite,#PageExMcF,#PageExDat{ -background-color:#f0f0f0; -border:2px solid gray -} - -QPushButton:enabled{ -border:2px; -border-radius:10px; -border-style:groove; -border-color: rgb(136, 136, 136); -color: rgb(0, 0, 0); -padding:2px 4px; -background-color: rgb(225, 225, 225); -} - -QPushButton:hover{ -border:2px; -border-radius:10px; -border-style:solid; -border-color: rgb(136, 136, 136); -color: rgb(0, 0, 0); -padding:2px 4px; -background-color: rgb(241, 241, 241); -} - -QPushButton:!enabled{ -border:2px; -border-radius:10px; -border-style:groove; -border-color: rgb(136, 136, 136); -color: rgb(80, 80, 80); -padding:2px 4px; -background-color: rgb(193, 193, 193); -} - -QCommandLinkButton:enabled{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,128); -font: 11pt "微软雅黑"; -} - -QCommandLinkButton:hover{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,191); -font: 11pt "微软雅黑"; -} -QCommandLinkButton:pressed{ -color: rgb(0, 0, 0); -border:0px; -background-color: rgba(255, 255, 255,223); -font: 11pt "微软雅黑"; -} - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - - - - - - - - 30 - - - - - - 0 - 0 - - - - - 20 - false - - - - <html><head/><body><p><span style=" font-size:16pt; font-weight:700; color:#ffff7f;">Copyright © 2021-2023 TokiNoBug</span></p></body></html> - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - - - 0 - 0 - - - - - MV Boli - 26 - false - - - - <html><head/><body><p><span style=" font-size:40pt; color:#ffffff;">SlopeCraft</span><span style=" color:#ffffff;"> %1</span></p></body></html> - - - Qt::AlignBottom|Qt::AlignHCenter - - - - - - - - - 0 - - - 0 - - - - - QLayout::SetDefaultConstraint - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Flat.png - - - true - - - - - - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建平板地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">传统的地图画样式</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - - 260 - 195 - - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_3D.png - - - true - - - - - - - - 微软雅黑 - 11 - false - false - - - - - - - - - - - - - 创建立体地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">原版生存的最高画质</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 16777215 - 195 - - - - false - - - QFrame::StyledPanel - - - 2 - - - - - - :/new/Pic/cover_Data.png - - - true - - - - - - - true - - - - 0 - 40 - - - - - 微软雅黑 - 11 - false - false - - - - 创建纯文件地图画 - - - - - - - 2 - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="center"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">地图画质的极限!但需要修改存档。</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - - - - - - - 0 - 0 - - - - - 65536 - 65536 - - - - false - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - #ShowRawPic{background-image: url(:/new/Pic/Transparent.png);} - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 9 - - - - Qt::LeftToRight - - - false - - - 导入图片 - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p>第一步,点击“导入图片“按钮,选择你要制作为地图画的图片。</p><p>图片的长宽(以像素为单位)最好是128的整倍数。</p><p>如果要生存实装,那么图片不要太大,我推荐128×128或者256×256。</p></body></html> - - - Qt::AutoText - - - true - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - - 0 - 0 - - - - - 100 - 30 - - - - - - - 透明度相关设置 - - - 设置 - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 5 - 2 - - - - - 10 - - - - 下一步 - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - - - backgroundcolor: rgb(255, 255, 255); - - - <html><head/><body><p align="justify">第二步,选择好你要什么样的地图画。</p><p align="justify">请选择好地图画对应的游戏版本,以及地图画的类型。</p><p align="justify">立体地图画如右图,是我们的核心功能;</p><p align="justify">平板地图画颜色相对少,但更容易建造;</p><p align="justify">纯文件地图画拥有最丰富的的颜色,但不可建造。</p></body></html> - - - true - - - - - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 10 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - 0 - - - - - 9 - - - - 游戏版本 - - - - - - - 9 - - - - 1.15 - - - false - - - - - - - - 9 - - - - 1.16 - - - false - - - - - - - true - - - - - - 1.17 - - - true - - - - - - - - - - 1.13 - - - - - - - - - - 1.12 - - - - - - - - - - 1.14 - - - - - - - 1.18 - - - - - - - 1.19 - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - - - - true - - - - - - - - 0 - 0 - - - - - - - :/new/Pic/BG3.png - - - true - - - - - - - - 0 - 0 - - - - - 10 - - - - 地图画类型 - - - - - - - 9 - - - - 立体地图画 - - - true - - - - - - - - 9 - - - - 平板地图画 - - - - - - - - 9 - - - - 纯文件地图画 - - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - - - - 10 - - - - 预设方块列表 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 9 - - - - 适合创造 - - - Vanilla - - - - - - - - 9 - - - - 适合生存早期 - - - Cheap - - - - - - - - 9 - - - - 适合生存后期 - - - Elegant - - - true - - - - - - - - 9 - - - - 适合光影 - - - Shiny - - - - - - - - 9 - - - - 自定义 - - - Custom - - - - - - - - - - - 0 - 0 - - - - - - - - - - true - - - - - - - 6 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 100 - 30 - - - - - 100 - 30 - - - - - 9 - - - - 下一步 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 0 - - - - - 0 - - - - - - 0 - 0 - - - - - 120 - 0 - - - - - - - <html><head/><body><p align="justify">第三步,给每一种颜色设置对应的方块,我们有四种预设。</p><p align="justify">你也可以在右侧的滚动条里自定义。每一列方块对应一种颜色,每种颜色只能选择一种方块。你也可以勾掉启用,禁用任何一种颜色。</p></body></html> - - - true - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先混凝土 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先羊毛 - - - - - - - - 0 - 25 - - - - - 9 - - - - 优先染色玻璃 - - - - - - - - - true - - - QFrame::Box - - - 2 - - - Qt::ScrollBarAlwaysOn - - - true - - - - - 0 - 0 - 16 - 16 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - 3 - - - 0 - - - 0 - - - 0 - - - 1 - - - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 0 - - - - - 0 - 15 - - - - Qt::DefaultContextMenu - - - - - - - - - false - - - - - - 1 - - - 0 - - - Qt::AlignCenter - - - %p% - - - - - - - 0 - - - - - - 0 - 0 - - - - - 100 - 40 - - - - - 32767 - 16777215 - - - - - 9 - - - - 转换为地图画 - - - false - - - - - - - - 0 - 0 - - - - - 80 - 40 - - - - - 150 - 1000 - - - - - - - 保存当前图片 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示地图画 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 16777215 - 16777215 - - - - 导出为 -原版结构文件 - - - - - - - - 0 - 0 - - - - - 100 - 20 - - - - - 150 - 16777215 - - - - - 9 - - - - 显示原图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 32767 - - - - - - - 导出为 -地图文件 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - 导出为 -WorldEdit原理图 - - - - - - - true - - - - 0 - 0 - - - - - 80 - 30 - - - - - 150 - 16777215 - - - - - 9 - - - - - - - 导出为 -Litematica投影 - - - - - - - - 0 - 0 - - - - - 0 - 100 - - - - 第四步,调整颜色。地图支持的颜色有限,你的图片必须也只能由地图允许的颜色组成。 -六种算法对应不同的调整颜色的方式,你可以挨个试一试。如果开启“抖动仿色”,SlopeCraft会尝试用相近的颜色混合,更好的贴近原图。 -调整颜色可能会比较慢,下面的进度条指示了进度。 - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 150 - 300 - - - - - 9 - - - - 算法 - - - - 2 - - - 4 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 9 - - - - RGB欧式距离 - - - RGB - - - - - - - - 0 - 0 - - - - - - - 更好的RGB色差公式 - - - RGB+ - - - true - - - - - - - - 0 - 0 - - - - - 9 - - - - 不是简单的欧式距离 - - - HSV - - - - - - - - 0 - 0 - - - - - 9 - - - - Lab1994公式 - - - Lab94 - - - false - - - - - - - - 0 - 0 - - - - - - - Lab2000公式 - - - Lab00 - - - - - - - - 0 - 0 - - - - - 9 - - - - XYZ欧式距离 - - - XYZ - - - - - - - - 0 - 0 - - - - 遗传算法 - - - GACvter - - - - - - - - 0 - 0 - - - - - - - 用分辨率换颜色 - - - 抖动仿色 - - - - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 440 - 440 - - - - true - - - QFrame::StyledPanel - - - - - - :/new/Pic/BG2.png - - - false - - - Qt::AlignCenter - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - QFrame::NoFrame - - - 其他选项 - - - - - - - 搭桥 - - - - - - - 方便建造,耗费玻璃 - - - 允许搭桥 - - - - - - - - - - 降低总高度,破坏连续性 - - - - - - - - - 无损压缩 - - - true - - - - - - - Qt::Horizontal - - - - - - - 用玻璃包围防火方块 - - - 防火 - - - - - - - - - - QFrame::NoFrame - - - 压缩高度 - - - - - - - true - - - 用玻璃包围可偷方块 - - - 防末影人 - - - false - - - - - - - true - - - - - - 降低总高度,微调颜色 - - - 智能有损压缩 - - - true - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="justify">最后一步,将立体地图画导出为投影文件,这很方便生存实装,是不是?</p><p align="justify">左侧的三个栏是投影文件的一些属性,空着不填也完全没问题。</p><p align="justify">如果您启用了“允许压缩高度”,SlopeCraft会在构建三维结构时尝试依据地图绘制的规律压缩立体地图画的高度,这可以有效避免超过限高(但未必能成功)。</p><p align="justify">下面的两个栏显示了立体地图画的信息,以供参考。</p><p align="justify">这个过程可能会很慢,请关注进度条</p></body></html> - - - true - - - - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - Qt::Horizontal - - - - - - - - - - 投影尺寸 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - - - QFrame::StyledPanel - - - - - - - - - - true - - - - - - QAbstractSpinBox::UpDownArrows - - - - - - QAbstractSpinBox::CorrectToNearestValue - - - 最大允许高度: - - - 14 - - - 32767 - - - 255 - - - - - - - false - - - - - - 搭桥间隔: - - - 4 - - - - - - - - - - 总方块数 - - - - - - - - - - - - - 0 - - - - Litematica - - - - - - - 9 - - - - 投影名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - 9 - - - - 投影区域名称 - - - - - - - Pixel Paint by SlopeCraft - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Structure - - - - - - 节省大量存储空间 - - - - - - - - - 用结构空位代替 - - - true - - - - - - - 空气处理方式 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - WorldEdit - - - - - - 0 - - - - - - - WEOffset(X,Y,Z) - - - - - - - 0 - - - - - - - 0 - - - - - - - 0 - - - - - - - offset(X,Y,Z) - - - - - - - 0 - - - - - - - 原理图名称 - - - - - - - 0 - - - - - - - 依赖mod名称 - - - - - - - - - - Pixel Paint by SlopeCraft - - - - - - - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 20 - - - - - 10 - - - - 结束 - - - - - - - - - - 0 - 0 - - - - 1 - - - 0 - - - Qt::AlignCenter - - - false - - - Qt::Vertical - - - false - - - %p% - - - - - - - 0 - - - Qt::Vertical - - - - - - - - - false - - - - 0 - 0 - - - - - 100 - 30 - - - - 导出平面示意图 - - - - - - - false - - - - 100 - 30 - - - - - - - 导出三维结构 - - - - - - - false - - - - 0 - 30 - - - - 预览 - - - - - - - false - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 0 - - - 12 - - - - - 地图画起点坐标 - - - - - - - 地图画尺寸 - - - - - - - Y - - - - - - - X - - - - - - - 总命令数 - - - - - - - Z - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 200 - 30 - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - 1 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - -64 - - - - - - - - - 0 - - - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 0 - - - -1 - - - Qt::Vertical - - - - - - - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - 0 - 30 - - - - - - - 构建三维结构 - - - - - - - - - - 0 - 0 - - - - - - - <html><head/><body><p align="justify">最后一步,导出为mcfunction!</p><p align="justify">如果你不想导出为投影文件,也可以使用mc自带的数据包。</p><p align="justify">导出的文件是一个mc中的“函数”,是数据包的一部分。</p><p align="justify">你可以在单机存档中使用/reload命令来加载它,用/function命令调用它。</p><p align="justify">如果地图画很大,超过了一个mcfunction的命令数,那么会将全部的命令分散在多个mcfuntion中。</p><p align="justify">在导出前,你需要指定地图画的起点坐标,它是xyz负方向的方块的坐标。</p><p align="justify">(如果不知道要放在哪里,请使用默认值-64,1,-64)</p></body></html> - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - 16777215 - 60 - - - - - - - - - - - - - 0 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -hr { height: 1px; border-width: 0; } -li.unchecked::marker { content: "\2610"; } -li.checked::marker { content: "\2612"; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:6px; margin-bottom:6px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Microsoft YaHei UI'; font-size:9pt;">0</span></p></body></html> - - - - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - map_0.dat - - - Qt::AlignCenter - - - - - - - - 0 - 30 - - - - QFrame::StyledPanel - - - QFrame::Plain - - - 1 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - <html><head/><body><p align="justify">最后一步,导出为地图文件。</p><p align="justify">地图文件的文件名形如map_3.dat,是minecraft用于存储地图内容的文件。其中3表示地图文件的序号,地图的序号从0开始。</p><p align="justify">地图文件存储于存档中的data文件夹下,你需要一定的权限才能修改它们。如果你既不是单机游戏,又不是服主,那你应该选择导出为投影,而不是地图文件。</p><p align="justify">每张地图只能显示128×128的画面,大图片可能会有多个地图,对应多个地图文件。它们会占用连续的一段序号。</p><p align="justify">例如,你可以使用/give @s filled_map{map:3}来获得map_3.dat的地图。</p><p align="justify">1.12版请使用/give @p filled_map 1 3</p><p align="justify">这种方法适合以最高画质展示大图片,但不适合服务器。</p></body></html> - - - true - - - - - - - 0 - - - - - false - - - - 100 - 20 - - - - - 10 - - - - 完成 - - - - - - - 0 - - - - - 1 - - - 0 - - - Qt::Vertical - - - %p% - - - - - - - - - false - - - - 100 - 30 - - - - - 0 - 0 - - - - - 10 - - - - 导出 - - - - - - - - - 导出的文件名 - - - - - - - - 0 - 0 - - - - 地图文件起始序号 - - - - - - - 地图画行数 - - - - - - - 地图画列数 - - - - - - - 地图文件数量 - - - - - - - - - - - - 0 - 30 - - - - - - - 查看导出的文件 - - - - - - - true - - - - 0 - 30 - - - - - - - 联系作者 - - - - - - - - 0 - 30 - - - - - - - 退出 - - - - - - - - - - background-color: rgba(0, 0, 0, 48); - - - <html><head/><body><p align="center"><span style=" font-size:16pt; font-weight:700; color:#ffffff;">地图画生成完毕!</span><br/></p><p align="center"><span style=" font-size:11pt; font-weight:700; color:#ffffff;">关于SlopeCraft</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">感谢你使用SlopeCraft,我是开发者TokiNoBug。SlopeCraft是由我开发的一款立体地图画生成器,主要用于在minecraft中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你正在使用的是SlopeCraft的第三代版本,在开发时使用了Qt,zlib和eigen,对上述库的开发者表示感谢。也感谢Mojang,整个软件就是为minecraft而设计的。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">AbrasiveBoar902(PopChrono)为本软件的设计和优化贡献了不少力量,并编写了基于SlopeCraftL核心的全新界面;Cubik65536和67au为本软件在MacOS和Linux的适配做出了贡献。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">你可以访问:</span><a href="https://github.com/ToKiNoBug/SlopeCraft/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">SlopeCraft的github</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://github.com/ToKiNoBug/"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的github主页</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">,</span><a href="https://space.bilibili.com/351429231"><span style=" font-weight:700; text-decoration: underline; color:#ffffff;">我的bilibili</span></a><span style=" font-size:10pt; font-weight:700; color:#ffffff;">。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">本软件遵循GPL-3.0及以后版本(GPL-3.0 or later)协议开放源代码。</span></p><p align="justify"><span style=" font-size:10pt; font-weight:700; color:#ffffff;">Copyright © 2021-2022 TokiNoBug</span></p></body></html> - - - true - - - 20 - - - - - - - - - - - - - 0 - 0 - 960 - 27 - - - - - 关于 - - - - 联系作者 - - - - - - - - - - - - - - - - - - - - Languages - - - - - - - 地图画 - - - - 导出为 - - - - - - - - - - - - - - - - - 高级 - - - - 批量操作 - - - - - - 方块列表预设 - - - - - - - - - - - - - - - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - 转到页面 - - - - - false - - - 导出为投影文件 - - - 导出为投影文件 - - - 导出为投影文件 - - - - - false - - - 导出为mcfunction - - - 导出为mcfunction - - - - - false - - - true - - - 导出为地图文件 - - - - - false - - - 关于SlopeCraft - - - - - 简体中文 - - - - - English - - - - - GitHub - - - - - BiliBili - - - - - 反馈Bug - - - - - false - - - 检查更新 - - - 检查更新 - - - 检查更新 - - - - - 开始 - - - - - 导入图片 - - - - - 地图画类型 - - - - - 方块列表 - - - - - 调整颜色 - - - - - 投影文件 - - - - - 结构文件 - - - - - 地图文件 - - - - - 完成 - - - - - false - - - 测试方块列表 - - - - - 设置导出参数 - - - - - 保存预设 - - - - - 加载预设 - - - - - GACvter参数 - - - GACvter参数 - - - GACvter参数 - - - - - 输出当前颜色表 - - - - - WE原理图 - - - - - 使用教程 - - - - - - AdaptiveLabel - QLabel -

AdaptiveLabel.h
- - - - isMapSurvival - isMapFlat - isGame16 - isBLSurvivalCheaper - isBLSurvivalBetter - isBLGlowing - isBLCustom - NextPage3 - FirstConcrete - FirstWool - FirstStainedGlass - scrollArea - isColorSpaceRGBOld - isColorSpaceHSV - isColorSpaceLab94 - isColorSpaceXYZ - FinishExLite - ExportLite - NWPosY - NWPosX - NWPosZ - FinishMcF - _ExportMcF - isBLCreative - NextPage2 - - - - - - - diff --git a/SlopeCraftMain/previewwind.cpp b/SlopeCraftMain/previewwind.cpp deleted file mode 100644 index 31af361f..00000000 --- a/SlopeCraftMain/previewwind.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "previewwind.h" -#include "ui_previewwind.h" - -PreviewWind::PreviewWind(QWidget *parent) - : QMainWindow(parent), ui(new Ui::PreviewWind) { - ui->setupUi(this); - this->setAttribute(Qt::WA_QuitOnClose, false); -} - -PreviewWind::~PreviewWind() { delete ui; } - -QString blockCount2string(int count, int setCount) { - if (count > 0 && count <= (setCount - 1)) - return QString::number(count) + QObject::tr("个"); - if (count >= (setCount * 27)) - return QString::number(count / (setCount * 27)) + QObject::tr("盒") + - blockCount2string(count % (setCount * 27)); - if (count >= setCount && count < (setCount * 27)) - return QString::number(count / setCount) + QObject::tr("组") + - blockCount2string(count % setCount); - return ""; -} - -void PreviewWind::ShowMaterialList() { - TotalBlockCount = 0; - - for (auto i = BlockCount.begin(); i != BlockCount.end(); i++) { - TotalBlockCount += *i; - } - - ui->Size->setText(QString::number(size[0]) + "×" + QString::number(size[1]) + - "×" + QString::number(size[2])); - - ui->Volume->setText(QString::number(size[0] * size[1] * size[2])); - - ui->BlockCount->setText(QString::number(TotalBlockCount)); - - auto area = ui->MaterialArea; - QLabel *iconShower, *idShower, *countShower; - QLabel *Spacer; - int rows = area->columnCount(), colOffset = 0; - - for (int i = 0; i < (signed)Src.size(); i++) { - area->addWidget(iconShower = new QLabel("Test1"), rows, colOffset); - area->addWidget(idShower = new QLabel("Test2"), rows, colOffset); - area->addWidget(countShower = new QLabel("Test3"), rows, colOffset + 1); - - auto icon = Src[i]->icon(); - auto iconsize = Src[i]->iconSize(); - auto pixmap = icon.pixmap(iconsize); - iconShower->setPixmap(pixmap); - - iconShower->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - idShower->setText(" " + Src[i]->text()); - countShower->setText(QString::number(BlockCount[i])); - countShower->setAlignment(Qt::AlignHCenter); - CountLabel.push_back(countShower); - colOffset = 2 * (!colOffset); - rows += i % 2; - } - - area->addWidget(Spacer = new QLabel(""), area->rowCount(), 0); - Spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); -} - -void PreviewWind::on_SwitchUnit_clicked(bool checked) { - if (checked) - for (int i = 0; i < (signed)BlockCount.size(); i++) { - if (Src[i] == Water) { - CountLabel[i]->setText(blockCount2string(BlockCount[i], 1)); - continue; - } - CountLabel[i]->setText(blockCount2string(BlockCount[i])); - } - else { - for (int i = 0; i < (signed)BlockCount.size(); i++) { - CountLabel[i]->setText(QString::number(BlockCount[i])); - } - } -} - -void PreviewWind::showConvertedImage(const QImage &img) { - ui->showImg->setPixmap(QPixmap::fromImage(img)); -} diff --git a/SlopeCraftMain/previewwind.h b/SlopeCraftMain/previewwind.h deleted file mode 100644 index 4b84988b..00000000 --- a/SlopeCraftMain/previewwind.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef PREVIEWWIND_H -#define PREVIEWWIND_H - -#include -#include -#include -#include -#include -#include - -namespace Ui { -class PreviewWind; -} - -class PreviewWind : public QMainWindow { - Q_OBJECT - - public: - explicit PreviewWind(QWidget *parent = nullptr); - - std::vector Src; - std::vector BlockCount; - std::vector CountLabel; - const QRadioButton *Water; - int size[3]; - int TotalBlockCount; - void ShowMaterialList(); - void showConvertedImage(const QImage &); - ~PreviewWind(); - - private slots: - void on_SwitchUnit_clicked(bool checked); - - private: - Ui::PreviewWind *ui; -}; - -QString blockCount2string(int, int = 64); -#endif // PREVIEWWIND_H diff --git a/SlopeCraftMain/previewwind.ui b/SlopeCraftMain/previewwind.ui deleted file mode 100644 index 11f258a4..00000000 --- a/SlopeCraftMain/previewwind.ui +++ /dev/null @@ -1,544 +0,0 @@ - - - PreviewWind - - - - 0 - 0 - 590 - 482 - - - - 预览投影文件 - - - - - 500 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 460 - 460 - - - - 0 - - - - 材料表 - - - - 10 - - - - - 方块 - - - Qt::AlignCenter - - - - - - - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - 投影尺寸 - - - Qt::AlignCenter - - - - - - - /*background-color: rgba(255, 255, 255,0);*/ - - - QFrame::NoFrame - - - QFrame::Plain - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 566 - 329 - - - - true - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 5 - - - 5 - - - 10 - - - - - - - - - - - 数量 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 24 - - - - 总方块数 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - 总体积 - - - Qt::AlignCenter - - - - - - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 120 - 215 - - - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - - - 120 - 120 - 120 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 120 - 215 - - - - - - - - false - - - 方块 - - - false - - - Qt::AlignCenter - - - - - - - 数量 - - - Qt::AlignCenter - - - - - - - - - - QFrame::StyledPanel - - - - - - - - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - - 0 - 24 - - - - - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - 切换单位 - - - - - - - - true - - - 预览地图画 - - - - - - true - - - - 0 - 0 - - - - - 414 - 414 - - - - true - - - QFrame::StyledPanel - - - - - - true - - - - - - - true - - - - 0 - 0 - - - - - 57 - 10 - - - - - 140 - 16777215 - - - - 如果使用了有损压缩,上一步生成的地图画可能会被轻微的修改 - - - true - - - - - - - - - - - - - diff --git a/SlopeCraftMain/tpstrategywind.cpp b/SlopeCraftMain/tpstrategywind.cpp deleted file mode 100644 index 552590a2..00000000 --- a/SlopeCraftMain/tpstrategywind.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TpStrategyWind_CPP -#define TpStrategyWind_CPP -#include "tpstrategywind.h" -#include "MainWindow.h" -#include "ui_tpstrategywind.h" -#include -#include -tpStrategyWind::tpStrategyWind(QWidget *parent) - : QMainWindow(parent), ui(new Ui::tpStrategyWind) { - ui->setupUi(this); - BackGroundColor = qRgb(220, 220, 220); - this->setAttribute(Qt::WA_QuitOnClose, false); -} - -void tpStrategyWind::setVal(tpS t) { - if (t.pTpS == 'B') - ui->isPureB->setChecked(true); - else - ui->isPureA->setChecked(true); - - if (t.hTpS == 'B') - ui->isHB->setChecked(true); - else if (t.hTpS == 'C') - ui->isHS->setChecked(true); - else - ui->isHR->setChecked(true); - - QPalette temp; - QColor Temp(qRed(t.BGC), qGreen(t.BGC), qBlue(t.BGC)); - temp.setColor(QPalette::Window, Temp); - ui->ShowBGCCustom->setPalette(temp); - ui->ShowBGCCustom->setAutoFillBackground(true); -} - -void tpStrategyWind::closeEvent(QCloseEvent *event) { - emit destroyed(); - delete this; - event->accept(); -} - -tpStrategyWind::~tpStrategyWind() { - qDebug("子窗口析构"); - delete ui; -} - -void tpStrategyWind::on_Confirm_clicked() { - grabTpSInfo(); - emit Confirm(tpS(pTpS, hTpS, BackGroundColor)); - qDebug("传值完成"); - close(); -} - -void tpStrategyWind::grabTpSInfo() { - pTpS = (ui->isPureB->isChecked()) ? 'B' : 'A'; - - hTpS = (ui->isHB->isChecked()) ? 'B' : ((ui->isHR->isChecked()) ? 'R' : 'C'); - if (ui->isBGCWhite->isChecked()) - BackGroundColor = qRgb(255, 255, 255); - else if (ui->isBGCGray->isChecked()) - BackGroundColor = qRgb(220, 220, 220); - qDebug("抓取完成"); -} - -void tpStrategyWind::on_isBGCCustom_clicked() { - QColor Temp = QColorDialog::getColor(); - if (!Temp.isValid()) return; - BackGroundColor = qRgb(Temp.red(), Temp.green(), Temp.blue()); - QPalette temp; - temp.setColor(QPalette::Window, Temp); - ui->ShowBGCCustom->setPalette(temp); - ui->ShowBGCCustom->setAutoFillBackground(true); -} - -void tpStrategyWind::on_Reset_clicked() { - ui->isPureB->setChecked(true); - ui->isHS->setChecked(true); - ui->isBGCGray->setChecked(true); -} - -#endif diff --git a/SlopeCraftMain/tpstrategywind.h b/SlopeCraftMain/tpstrategywind.h deleted file mode 100644 index 554f72f6..00000000 --- a/SlopeCraftMain/tpstrategywind.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TPSTRATEGYWIND_H -#define TPSTRATEGYWIND_H - -#include - -namespace Ui { -class tpStrategyWind; -} -class MainWindow; - -#ifndef TPS__ -#define TPS__ -class tpS { -public: - tpS(char _pTpS = 'B', char _hTpS = 'C', QRgb _BGC = qRgb(220, 220, 220)) { - pTpS = _pTpS; - hTpS = _hTpS; - BGC = _BGC; - } - ~tpS(); - char pTpS; - char hTpS; - QRgb BGC; -}; -#endif - -class tpStrategyWind : public QMainWindow { - Q_OBJECT - -public: - explicit tpStrategyWind(QWidget *parent = nullptr); - ~tpStrategyWind(); - MainWindow *parent; - char pTpS; - char hTpS; - QRgb BackGroundColor; - void setVal(tpS); - -protected: - void closeEvent(QCloseEvent *event) override; - -private: - Ui::tpStrategyWind *ui; -signals: - void Confirm(tpS); -public slots: - void grabTpSInfo(); -private slots: - void on_Confirm_clicked(); - void on_isBGCCustom_clicked(); - void on_Reset_clicked(); -}; - -#endif // TPSTRATEGYWIND_H diff --git a/SlopeCraftMain/tpstrategywind.ui b/SlopeCraftMain/tpstrategywind.ui deleted file mode 100644 index a6257ce3..00000000 --- a/SlopeCraftMain/tpstrategywind.ui +++ /dev/null @@ -1,263 +0,0 @@ - - - tpStrategyWind - - - - 0 - 0 - 520 - 324 - - - - - 520 - 324 - - - - 透明像素处理策略 - - - - - 5 - - - 5 - - - 5 - - - 5 - - - 3 - - - 0 - - - - - 12 - - - 6 - - - 6 - - - 0 - - - - - 确定 - - - - - - - 取消 - - - - - - - 恢复默认设定 - - - - - - - - - - 0 - 0 - - - - 地图画中几乎不能使用透明像素。立体地图画和平板地图画都不能实现纯透明像素,纯文件地图画虽然理论上支持透明像素,但只会透出地图/物品展示框的背景色。因此有必要对透明/半透明像素进行处理。 -”替换为背景色“会将像素替换为背景色;”替换为空气“将像素替换为空气。 -”与背景色叠加“会按照像素的透明度与背景色叠加;“保留颜色”会忽视半透明像素的透明度,直接使用它们的颜色。 -完成设置后,需重新导入图片。 - - - true - - - 4 - - - - - - - 纯透明像素 - - - - - - 替换为空气 - - - - - - - 替换为背景色 - - - true - - - - - - - - - - 背景色 - - - - - - 高级灰(#DCDCDC) - - - true - - - - - - - - 20 - 20 - - - - - 20 - 16777215 - - - - background-color: rgb(255, 255, 255); - - - QFrame::StyledPanel - - - - - - - - - - 自定义 - - - - - - - QFrame::StyledPanel - - - - - - - - - - background-color: rgb(220, 220, 220); - - - QFrame::StyledPanel - - - - - - - - - - 纯白(#FFFFFF) - - - - - - - - - - 半透明像素 - - - - - - 保留颜色 - - - - - - - 与背景色叠加 - - - true - - - - - - - 替换为背景色 - - - - - - - - - - - - - Cancel - clicked() - tpStrategyWind - close() - - - 259 - 309 - - - 259 - 161 - - - - - From d165c197da1c70555825702a9e60d46a9a9f2198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:23:13 +0800 Subject: [PATCH 0520/1123] [win-clang] try to install deps with vcpkg --- .github/workflows/build-dev-clang.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 415c108d..fe75967b 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -39,6 +39,11 @@ jobs: choco install ninja ninja --version + - name: Install zlib, libpng and libzip with vcpkg + run: | + vcpkg install zlib libpng libzip --triplet=x64-windows + dir %VCPKG_INSTALLATION_ROOT%/install + # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" From c27b990d42f57d7c4a2fd034f688a7c3dd77fe47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:30:30 +0800 Subject: [PATCH 0521/1123] [win-clang] try to install deps with vcpkg --- .github/workflows/build-dev-clang.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index fe75967b..69141606 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -41,8 +41,11 @@ jobs: - name: Install zlib, libpng and libzip with vcpkg run: | + dir C:\vcpkg\installed vcpkg install zlib libpng libzip --triplet=x64-windows - dir %VCPKG_INSTALLATION_ROOT%/install + dir C:\vcpkg\installed\x64-windows + rd /s /q C:\vcpkg\installed\x64-windows\debug + # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" From 6e2daec19f8d809481f79a11fbb8733c9f5ad11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:32:50 +0800 Subject: [PATCH 0522/1123] [win-clang] try to install deps with vcpkg --- .github/workflows/build-dev-clang.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 69141606..517075d8 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -28,6 +28,10 @@ jobs: echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" + - name: Check vcpkg + run: | + dir C:\vcpkg + - name: check clang run: | where clang @@ -41,7 +45,7 @@ jobs: - name: Install zlib, libpng and libzip with vcpkg run: | - dir C:\vcpkg\installed + dir C:\vcpkg vcpkg install zlib libpng libzip --triplet=x64-windows dir C:\vcpkg\installed\x64-windows rd /s /q C:\vcpkg\installed\x64-windows\debug From 4fe8e271d2d724286bcf37cc5457058e16b54c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:38:10 +0800 Subject: [PATCH 0523/1123] [win-clang] try to install deps with vcpkg --- .github/workflows/build-dev-clang.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 517075d8..aa5879e8 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -47,7 +47,9 @@ jobs: run: | dir C:\vcpkg vcpkg install zlib libpng libzip --triplet=x64-windows + dir C:\vcpkg\installed dir C:\vcpkg\installed\x64-windows + dir C:\vcpkg\installed\x64-windows\debug rd /s /q C:\vcpkg\installed\x64-windows\debug From 371b9ab039d192f299e3d612ab2155012cb87001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 20:56:26 +0800 Subject: [PATCH 0524/1123] [win-clang] try to install deps with vcpkg --- .github/workflows/build-dev-clang.yml | 98 +++++++++++++-------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index aa5879e8..3c81abd2 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -43,14 +43,14 @@ jobs: choco install ninja ninja --version - - name: Install zlib, libpng and libzip with vcpkg + - name: Install deps with vcpkg run: | dir C:\vcpkg - vcpkg install zlib libpng libzip --triplet=x64-windows + vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 dir C:\vcpkg\installed dir C:\vcpkg\installed\x64-windows dir C:\vcpkg\installed\x64-windows\debug - rd /s /q C:\vcpkg\installed\x64-windows\debug + rd /s/q C:\vcpkg\installed\x64-windows\debug # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" @@ -73,51 +73,51 @@ jobs: mkdir 3rdParty mkdir bin/dependencies - - name: Build and install zlib - run: | - $basedir=(pwd).path.replace("\\","/") - echo "basedir = $basedir" - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/madler/zlib.git - cd zlib - git checkout v1.2.13 - cd $basedir - mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" - cmake --build bin/build-zlib --parallel - cmake --install bin/build-zlib - - - name: Build and install libzip - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/nih-at/libzip.git - cd libzip - git checkout v1.9.2 - cd $basedir - mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false - cmake --build bin/build-libzip --parallel - cmake --install bin/build-libzip - - - name: Build and install libpng - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/glennrp/libpng.git - cd libpng - git checkout v1.6.39 - cd $basedir - mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false - cmake --build bin/build-libpng --parallel - cmake --install bin/build-libpng - - - name: Install Eigen3 - run: vcpkg install --triplet=x64-windows eigen3 + # - name: Build and install zlib + # run: | + # $basedir=(pwd).path.replace("\\","/") + # echo "basedir = $basedir" + # $BUILD_TYPE=$env:BUILD_TYPE + # cd 3rdParty + # git clone https://github.com/madler/zlib.git + # cd zlib + # git checkout v1.2.13 + # cd $basedir + # mkdir bin/build-zlib + # cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" + # cmake --build bin/build-zlib --parallel + # cmake --install bin/build-zlib + # + # - name: Build and install libzip + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $BUILD_TYPE=$env:BUILD_TYPE + # cd 3rdParty + # git clone https://github.com/nih-at/libzip.git + # cd libzip + # git checkout v1.9.2 + # cd $basedir + # mkdir bin/build-libzip + # cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false + # cmake --build bin/build-libzip --parallel + # cmake --install bin/build-libzip + # + # - name: Build and install libpng + # run: | + # $basedir=(pwd).path.replace("\\","/") + # $BUILD_TYPE=$env:BUILD_TYPE + # cd 3rdParty + # git clone https://github.com/glennrp/libpng.git + # cd libpng + # git checkout v1.6.39 + # cd $basedir + # mkdir bin/build-libpng + # cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false + # cmake --build bin/build-libpng --parallel + # cmake --install bin/build-libpng + + # - name: Install Eigen3 + # run: vcpkg install --triplet=x64-windows eigen3 - name: Download Qt6.5.0-msvc-shared and extract run: | @@ -134,7 +134,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;D:/a/SlopeCraft/SlopeCraft/bin/dependencies;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build shell: cmd From 1a56609c74521a9379a3535df0f07a7f9981e15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 21:04:53 +0800 Subject: [PATCH 0525/1123] try to fix windows-clang build --- .github/workflows/build-dev-clang.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 3c81abd2..4398b151 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -44,6 +44,7 @@ jobs: ninja --version - name: Install deps with vcpkg + shell: cmd run: | dir C:\vcpkg vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 From cac210bdffe68309f1fb3b8b3b32f50e98faf960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 22:16:46 +0800 Subject: [PATCH 0526/1123] try to fix windows-clang build --- .github/workflows/build-dev-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 4398b151..4c094eb1 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -51,7 +51,7 @@ jobs: dir C:\vcpkg\installed dir C:\vcpkg\installed\x64-windows dir C:\vcpkg\installed\x64-windows\debug - rd /s/q C:\vcpkg\installed\x64-windows\debug + # rd /s/q C:\vcpkg\installed\x64-windows\debug # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" From 40776ab0d9299b25a822eac75294e5f7afcf55a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 3 Oct 2023 23:26:47 +0800 Subject: [PATCH 0527/1123] remove redundant steps in windows-clang build --- .github/workflows/build-dev-clang.yml | 73 ++------------------------- 1 file changed, 3 insertions(+), 70 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 4c094eb1..51d95616 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -28,16 +28,6 @@ jobs: echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" - - name: Check vcpkg - run: | - dir C:\vcpkg - - - name: check clang - run: | - where clang - where clang-cl - clang --version - - name: Install ninja run: | choco install ninja @@ -45,17 +35,7 @@ jobs: - name: Install deps with vcpkg shell: cmd - run: | - dir C:\vcpkg - vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 - dir C:\vcpkg\installed - dir C:\vcpkg\installed\x64-windows - dir C:\vcpkg\installed\x64-windows\debug - # rd /s/q C:\vcpkg\installed\x64-windows\debug - - - # Invoke-Expression "& 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat'" - + run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 - name: Checkout repository uses: actions/checkout@v2 @@ -72,53 +52,6 @@ jobs: mkdir bin mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty - mkdir bin/dependencies - - # - name: Build and install zlib - # run: | - # $basedir=(pwd).path.replace("\\","/") - # echo "basedir = $basedir" - # $BUILD_TYPE=$env:BUILD_TYPE - # cd 3rdParty - # git clone https://github.com/madler/zlib.git - # cd zlib - # git checkout v1.2.13 - # cd $basedir - # mkdir bin/build-zlib - # cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" - # cmake --build bin/build-zlib --parallel - # cmake --install bin/build-zlib - # - # - name: Build and install libzip - # run: | - # $basedir=(pwd).path.replace("\\","/") - # $BUILD_TYPE=$env:BUILD_TYPE - # cd 3rdParty - # git clone https://github.com/nih-at/libzip.git - # cd libzip - # git checkout v1.9.2 - # cd $basedir - # mkdir bin/build-libzip - # cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false - # cmake --build bin/build-libzip --parallel - # cmake --install bin/build-libzip - # - # - name: Build and install libpng - # run: | - # $basedir=(pwd).path.replace("\\","/") - # $BUILD_TYPE=$env:BUILD_TYPE - # cd 3rdParty - # git clone https://github.com/glennrp/libpng.git - # cd libpng - # git checkout v1.6.39 - # cd $basedir - # mkdir bin/build-libpng - # cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="Release" -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX="$basedir/bin/dependencies" -DCMAKE_PREFIX_PATH="$basedir/bin/dependencies" -DPNG_SHARED:BOOL=true -DPNG_STATIC:BOOL=false - # cmake --build bin/build-libpng --parallel - # cmake --install bin/build-libpng - - # - name: Install Eigen3 - # run: vcpkg install --triplet=x64-windows eigen3 - name: Download Qt6.5.0-msvc-shared and extract run: | @@ -215,7 +148,7 @@ jobs: # - name: Compress as zip # run: | # cd ./build/install -# zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* +# zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* # # - name: Get short SHA # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -223,4 +156,4 @@ jobs: # uses: actions/upload-artifact@v2 # with: # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang -# path: build/install/SlopeCraft-5.1.0-macos.zip \ No newline at end of file +# path: build/install/SlopeCraft*.zip \ No newline at end of file From 57f74b5d728dec985be81f7f1e9149b6aa3bc7eb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 6 Oct 2023 10:01:10 +0800 Subject: [PATCH 0528/1123] fix retrieving cpu name on linux --- VisualCraft/VCWind_gpu.cpp | 90 ++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index e73d4752..f93cabb5 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -26,49 +26,72 @@ This file is part of SlopeCraft. #include #include - +#include #include "VCWind.h" #include "ui_VCWind.h" -#ifdef _MSC_VER -#include +QString get_cpu_name(bool &error) noexcept { + QProcess proc{0}; + error = true; + +#ifdef WIN32 + const char *command = "wmic cpu get name"; +#elif defined(__linux__) + const char *command = "sh -c \"cat /proc/cpuinfo | grep name\""; #else -#include +#warning "Unknown OS" #endif -std::string get_cpu_name(bool &error) noexcept { - int buffer[5]; - uint8_t *const buffer_cptr = reinterpret_cast(buffer); - constexpr uint32_t input[3] = {0x80000002, 0x80000003, 0x80000004}; + proc.startCommand(command); + if (!proc.waitForStarted()) { + return {}; + } + if (!proc.waitForFinished()) { + return {}; + } - char str[1024] = ""; + QString output = QString::fromUtf8(proc.readAllStandardOutput()); - error = false; - for (auto i : input) { - memset(buffer, 0, sizeof(buffer)); - try { -#ifdef _MSC_VER - __cpuid(buffer, i); -#else - __cpuid(i, buffer[0], buffer[1], buffer[2], buffer[3]); -#endif +#ifdef WIN32 + output = output.remove(QChar{'\r'}); + auto splitted = output.split('\n'); + if (splitted.size() < 2) { + return {}; + } - } catch (std::exception &e) { - strcpy(str, "Instruction cpuid failed. Detail : "); - strcpy(str, e.what()); - error = true; - return str; - } - if constexpr (false) { - for (size_t o = 0; o < 4 * sizeof(uint32_t); o++) { - std::cout << (int)buffer_cptr[o] << ", "; - } - std::cout << std::endl; - } + if (splitted[0].remove(QChar{' '}) != QStringLiteral("Name")) { + return {}; + } + + const auto cpu_name = splitted[1]; + +#elif defined(__linux__) + + output.remove('\t'); - strcat(str, reinterpret_cast(buffer_cptr)); + auto spilitted = output.split('\n'); + if (spilitted.size() <= 0) { + return {}; + } + const auto line0 = spilitted[0]; + if (!line0.contains(':')) { + return {}; } - return str; + auto line0_splitted = line0.split(':'); + if (line0_splitted.size() != 2) { + return {}; + } + if (line0_splitted[0].remove(' ') != "modelname") { + return {}; + } + const auto cpu_name = line0_splitted[1]; + +#else +#warning "Unknown OS" + QString cpu_name{}; +#endif + error = false; + return cpu_name; } void VCWind::refresh_gpu_info() noexcept { @@ -79,7 +102,8 @@ void VCWind::refresh_gpu_info() noexcept { { bool error = false; - QString text("CPU : " + QString::fromUtf8(get_cpu_name(error))); + QString text("CPU : " + get_cpu_name(error)); + // QString text("CPU : " +); QTreeWidgetItem *cpu = new QTreeWidgetItem; cpu->setText(0, text); if (error) { From 5fb22b5dffa00605047a0e71892d545ebaebf48e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 6 Oct 2023 10:01:25 +0800 Subject: [PATCH 0529/1123] fix gpu boosting and vectorization on other platforms --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef861559..ece83766 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,12 +20,13 @@ endif () enable_testing() # configure options ----------------------------------------------------------- -if (NOT ${APPLE}) +if (NOT APPLE) set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") option(SlopeCraft_vectorize "Compile with vectorization" ON) else () set(SlopeCraft_GPU_API "None" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") option(SlopeCraft_vectorize "Compile with vectorization" OFF) + message(STATUS "GPU boosting and vectorization have been disabled on mac") endif () From ccbda0cbc41ded7c23dd625d38398ef94c513e2c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 6 Oct 2023 11:07:04 +0800 Subject: [PATCH 0530/1123] [mac] remove macdeployqt for vccl --- vccl/deploy_qt_for_vccl_macos.cmake.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index f8ef54db..8cff1c97 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -1,11 +1,11 @@ # This script should run during installtion -message(STATUS "Running macdeployqt for @AppName@ ...") -execute_process( - COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" - WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/@vccl_prefix@" - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY) +#message(STATUS "Running macdeployqt for @AppName@ ...") +#execute_process( +# COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" +# WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/@vccl_prefix@" +# OUTPUT_QUIET +# COMMAND_ERROR_IS_FATAL ANY) file(CREATE_LINK "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl" From 9f888adac70394bebdd1333c4ba56c1006267f04 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 6 Oct 2023 11:07:21 +0800 Subject: [PATCH 0531/1123] get cpu name on macos --- VisualCraft/VCWind_gpu.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index f93cabb5..7aa28b50 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -38,8 +38,12 @@ QString get_cpu_name(bool &error) noexcept { const char *command = "wmic cpu get name"; #elif defined(__linux__) const char *command = "sh -c \"cat /proc/cpuinfo | grep name\""; +#elif defined(__APPLE__) + const char * command="sysctl machdep.cpu.brand_string"; #else -#warning "Unknown OS" +#warning Unknown OS + const char * command=nullptr; + return {}; #endif proc.startCommand(command); @@ -86,6 +90,23 @@ QString get_cpu_name(bool &error) noexcept { } const auto cpu_name = line0_splitted[1]; +#elif defined(__APPLE__) + output.remove('\n'); + auto split_out=output.split(':'); + if (split_out.size()<2) { + return {}; + } + if (split_out[0]!="machdep.cpu.brand_string") { + return {}; + } + auto cpu_name=split_out[1]; + cpu_name.remove('\t'); + while(cpu_name.front()==' ') { + cpu_name.removeFirst(); + } + while(cpu_name.back()==' ') { + cpu_name.removeLast(); + } #else #warning "Unknown OS" QString cpu_name{}; @@ -95,7 +116,7 @@ QString get_cpu_name(bool &error) noexcept { } void VCWind::refresh_gpu_info() noexcept { - this->ui->sb_threads->setValue(std::thread::hardware_concurrency()); + this->ui->sb_threads->setValue((int)std::thread::hardware_concurrency()); this->ui->tw_gpu->clear(); this->ui->combobox_select_device->clear(); From 90136f36e877e1be52a2f62e6e21dd75aeafcb8f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 6 Oct 2023 11:08:09 +0800 Subject: [PATCH 0532/1123] fix gpu boosting and vectorization --- CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ece83766..37e29c1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,13 +20,14 @@ endif () enable_testing() # configure options ----------------------------------------------------------- -if (NOT APPLE) - set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") - option(SlopeCraft_vectorize "Compile with vectorization" ON) -else () +if (${APPLE}) set(SlopeCraft_GPU_API "None" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") option(SlopeCraft_vectorize "Compile with vectorization" OFF) - message(STATUS "GPU boosting and vectorization have been disabled on mac") + message(STATUS "GPU boosting and vectorization have been disabled on mac by default") + +else () + set(SlopeCraft_GPU_API "OpenCL" CACHE STRING "API used to compute. Valid values : OpenCL, None. Metal may be supported.") + option(SlopeCraft_vectorize "Compile with vectorization" ON) endif () From f18f6bfc063df7cafee27ef83a1aa13b387a7dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 12 Oct 2023 20:09:43 +0800 Subject: [PATCH 0533/1123] [NN] image preprocessing --- py/test1/preprocess.py | 188 +++++++++++++++++++++++++++++++++++++++++ py/test1/test_load.py | 22 +++++ 2 files changed, 210 insertions(+) create mode 100644 py/test1/preprocess.py create mode 100644 py/test1/test_load.py diff --git a/py/test1/preprocess.py b/py/test1/preprocess.py new file mode 100644 index 00000000..18c98aa5 --- /dev/null +++ b/py/test1/preprocess.py @@ -0,0 +1,188 @@ +import cv2 +import os +import pathlib +import argparse +import numpy as np +import multiprocessing as mp +import zipfile +import time +import hashlib +import tomllib +import tomli_w +from typing import Any +import torch +import torch.utils.data + + +def cut_image(input_img: cv2.typing.MatLike, + row_size: int, + col_size: int) -> list[cv2.typing.MatLike]: + result = [] + rows = input_img.shape[0] + cols = input_img.shape[1] + rows = rows - rows % row_size + cols = cols - cols % col_size + + for r in range(0, rows, row_size): + for c in range(0, cols, col_size): + result.append(input_img[r:r + row_size, c:c + col_size]) + + return result + + +def process_dir(source_dir: str, archive_name: str, cutted_rows: int, cutted_cols: int) -> dict[str, Any]: + read_counter: int = 0 + write_counter: int = 0 + duplicate_counter: int = 0 + archive = zipfile.ZipFile(archive_name, mode='w', compression=zipfile.ZIP_STORED) + + hash_set = set() + + for filepath, _, filenames in os.walk(source_dir): + for filename in filenames: + abs_filename = os.path.join(filepath, filename) + + if not os.path.isfile(abs_filename): + raise RuntimeError(f"Non existing file {abs_filename}") + + if filename == ".nomedia": + continue + + img = cv2.imdecode(np.fromfile(abs_filename, dtype=np.uint8), cv2.IMREAD_COLOR) + if img is None: + print(f"Failed to read {abs_filename}, skip and continue.") + continue + + read_counter += 1 + + if read_counter % 100 == 0: + print(f"{read_counter} images read, {write_counter} images generated.") + + cut_imgs = cut_image(img, cutted_rows, cutted_cols) + + for cut_img in cut_imgs: + core_filename = f"{write_counter:014}.jpg" + ok, encoded = cv2.imencode(".jpg", cut_img) + if not ok: + raise RuntimeError(f"Failed to encode {core_filename}") + + encoded_bytes = encoded.tobytes() + img_hash = hashlib.sha1() + img_hash.update(encoded_bytes) + + img_hash = img_hash.hexdigest() + if img_hash in hash_set: + duplicate_counter += 1 + continue + + hash_set.add(img_hash) + write_counter += 1 + archive.writestr(core_filename, encoded_bytes) + + archive.close() + print(f"{read_counter} images read, {duplicate_counter} duplicated images removed., {write_counter} images " + f"generated") + + return {'original_images': read_counter, + 'generated_images': write_counter, + 'source_dir': source_dir, + 'rows': cutted_rows, + 'cols': cutted_cols} + + +def parse_shape_str(shape_str: str) -> tuple[int, int]: + split = shape_str.split('x') + if len(split) != 2: + raise RuntimeError(f"Invalid shape string {shape_str}") + + result = [0, 0] + for idx in range(0, 2): + temp = int(split[idx]) + if temp <= 0: + raise RuntimeError(f"Invalid shape: {temp}") + result[idx] = temp + + return result[0], result[1] + + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument("--source-dir", type=str, required=True, nargs='+') + parser.add_argument("--out-dir", type=str, default="preprocessed") + parser.add_argument("--shape", type=str, default="128x128", nargs='+') + + args = vars(parser.parse_args()) + + out_dir = args["out_dir"] + os.makedirs(out_dir, exist_ok=True) + + source_dirs: list[str] = args["source_dir"] + + shapes = [] + for shape_str in args["shape"]: + shapes.append(parse_shape_str(shape_str)) + + # metainfos = dict() + + for src_dir_name in source_dirs: + print(f"Processing images in {src_dir_name}...") + for shape in shapes: + print(f"Cutting with shape str = {shape}...") + cut_rows = shape[1] + cut_cols = shape[0] + + filename_stem = f"{pathlib.Path(src_dir_name).stem}-{cut_cols}x{cut_rows}" + + archive_name = os.path.join(out_dir, f"{filename_stem}.zip") + abs_time = time.time() + info = process_dir(src_dir_name, archive_name, cut_rows, cut_cols) + seconds = time.time() - abs_time + print(f"Finished in {seconds} seconds") + + tomli_w.dump(info, open(os.path.join(out_dir, f"{filename_stem}.toml"), "wb")) + + # metainfos[archive_name] = info + + # tomli_w.dump(metainfos, open(os.path.join(out_dir, "total_info.toml"), 'wb')) + + +class ZipDataSet(torch.utils.data.Dataset): + config: dict[str, Any] + zip: zipfile.ZipFile + + def __init__(self, zip_file: str): + config_file = zip_file.removesuffix(".zip") + ".toml" + if not os.path.isfile(config_file): + raise RuntimeError(f"Expected {config_file} as the config file for {zip_file}, but doesn't exist.") + + self.config = tomllib.load(open(config_file, "rb")) + print(f"Loading {zip_file}...") + self.zip = zipfile.ZipFile(zip_file) + + def __len__(self) -> int: + return len(self.zip.filelist) + + def decode_image(self, zip_info: zipfile.ZipInfo) -> torch.Tensor: + encoded = self.zip.read(name=zip_info) + encoded_nparr = np.frombuffer(encoded, dtype=np.uint8) + image = cv2.imdecode(encoded_nparr, flags=cv2.IMREAD_COLOR) + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + + image = np.array(image, dtype=np.float32) / 255 + + tensor = torch.from_numpy(image) + tensor = torch.permute(tensor, dims=[2, 0, 1]) + return tensor + + def __getitem__(self, item) -> torch.Tensor: + return self.decode_image(self.zip.filelist[item]) + + # def __iter__(self): + # for zip_info in self.zip.filelist: + # tensor=self.decode_image(zip_info) + # yield tensor + + +if __name__ == "__main__": + main() diff --git a/py/test1/test_load.py b/py/test1/test_load.py new file mode 100644 index 00000000..960a2dfa --- /dev/null +++ b/py/test1/test_load.py @@ -0,0 +1,22 @@ +import preprocess as pp +import random +import matplotlib.pyplot as plt +import torch.utils.data +import os + + +def main(): + dS = pp.ZipDataSet("preprocessed/埃罗芒阿-128x128.zip") + + dL = torch.utils.data.DataLoader(dS, batch_size=64, + shuffle=True, + pin_memory=True, + num_workers=0) + + for batch_index, img in enumerate(dL): + pass + print(f"Batch {batch_index}") + + +if __name__ == "__main__": + main() From 8f9303477bc7aeb4d28d803bb963e7c9e67fa0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 12 Oct 2023 20:10:05 +0800 Subject: [PATCH 0534/1123] [NN] ignore some binary files --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1d645c9d..7da3463c 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,6 @@ Testing Makefile cmake_install.cmake install_manifest.txt -compile_commands.json CTestTestfile.cmake _deps @@ -76,3 +75,7 @@ binaries/* ### CLion ### .idea/* cmake-build-* + +### PyCharm ### +py/preprocessed +py/outputs From e0e30386ec1ba0d62e2d4617beded27cca8e0dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 12 Oct 2023 21:15:08 +0800 Subject: [PATCH 0535/1123] [NN] fix typo --- py/test1/preprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/test1/preprocess.py b/py/test1/preprocess.py index 18c98aa5..fb7c434a 100644 --- a/py/test1/preprocess.py +++ b/py/test1/preprocess.py @@ -147,7 +147,7 @@ def main(): # tomli_w.dump(metainfos, open(os.path.join(out_dir, "total_info.toml"), 'wb')) -class ZipDataSet(torch.utils.data.Dataset): +class ZipDataset(torch.utils.data.Dataset): config: dict[str, Any] zip: zipfile.ZipFile From ff8d3480ab3047ba3b0bc4d33b3f18abbe7a67a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Thu, 12 Oct 2023 21:16:02 +0800 Subject: [PATCH 0536/1123] [NN] split dataset --- py/test1/split_dataset.py | 109 ++++++++++++++++++++++++++++++++++++++ py/test1/test_load.py | 10 ++-- 2 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 py/test1/split_dataset.py diff --git a/py/test1/split_dataset.py b/py/test1/split_dataset.py new file mode 100644 index 00000000..f1808b03 --- /dev/null +++ b/py/test1/split_dataset.py @@ -0,0 +1,109 @@ +import os +import pathlib +from typing import Any +import preprocess as pp +import zipfile +import argparse +import random +import tomli_w + + +def picked_count(size: int, ratio: float, max_count: int) -> int: + assert max_count != 0 + if max_count < 0: + return int(size * ratio) + return min(max_count, int(size * ratio)) + + +def export_subdataset(filename: str, src: zipfile.ZipFile, filelist: list[zipfile.ZipInfo], metainfo: dict[str, Any]): + dst = zipfile.ZipFile(filename, 'w', compression=zipfile.ZIP_STORED) + for info in filelist: + content = src.read(info) + dst.writestr(info.filename, data=content) + dst.close() + + config_filename = filename.removesuffix(".zip") + ".toml" + tomli_w.dump(metainfo, open(config_filename, "wb")) + + +def split_dataset(source: str, + train_dir: str, test_dir: str, validate_dir: str, + test_ratio: float, test_max_count: int, + validate_ratio: float, validate_max_count: int): + src_ds = pp.ZipDataset(source) + src = src_ds.zip + + filelist = src.filelist.copy() + random.shuffle(filelist) + + test_count = picked_count(len(filelist), test_ratio, test_max_count) + validate_count = picked_count(len(filelist), validate_ratio, validate_max_count) + + counter: int = 0 + + metainfo: dict[str, Any] = src_ds.config + metainfo['parent'] = source + metainfo.pop('original_images') + + metainfo['generated_images'] = test_count + metainfo['usage'] = 'test' + export_subdataset(os.path.join(test_dir, os.path.basename(source)), + src=src, + filelist=filelist[counter:counter + test_count], + metainfo=metainfo + ) + counter += test_count + + metainfo['generated_images'] = validate_count + metainfo['usage'] = 'validate' + export_subdataset(os.path.join(validate_dir, os.path.basename(source)), + src=src, + filelist=filelist[counter:counter + validate_count], + metainfo=metainfo + ) + counter += validate_count + + metainfo['generated_images'] = len(src.filelist) - validate_count - test_count + metainfo['usage'] = 'train' + export_subdataset(os.path.join(train_dir, os.path.basename(source)), + src=src, + filelist=filelist[counter:len(src.filelist)], + metainfo=metainfo + ) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("source", type=str, nargs='+') + parser.add_argument("--out-dir", type=str) + parser.add_argument("--test-ratio", "--tr", type=float) + parser.add_argument("--test-max-count", "--tmc", type=int, required=False, default=-1) + parser.add_argument("--validate-ratio", "--vr", type=float) + parser.add_argument("--validate-max-count", "--vmc", type=int, required=False, default=-1) + args = parser.parse_args() + + out_dir = args.out_dir + train_dir = os.path.join(out_dir, "train") + test_dir = os.path.join(out_dir, "test") + validate_dir = os.path.join(out_dir, "validate") + + os.makedirs(train_dir, exist_ok=True) + os.makedirs(test_dir, exist_ok=True) + os.makedirs(validate_dir, exist_ok=True) + + for src in args.source: + print(f"Splitting {src}...") + split_dataset(src, + train_dir=train_dir, + test_dir=test_dir, + validate_dir=validate_dir, + + test_ratio=args.test_ratio, + test_max_count=args.test_max_count, + + validate_ratio=args.validate_ratio, + validate_max_count=args.validate_max_count) + + +if __name__ == "__main__": + main() diff --git a/py/test1/test_load.py b/py/test1/test_load.py index 960a2dfa..d609ee49 100644 --- a/py/test1/test_load.py +++ b/py/test1/test_load.py @@ -3,17 +3,21 @@ import matplotlib.pyplot as plt import torch.utils.data import os +import argparse def main(): - dS = pp.ZipDataSet("preprocessed/埃罗芒阿-128x128.zip") + parser = argparse.ArgumentParser() + parser.add_argument("input", type=str) + args = parser.parse_args() - dL = torch.utils.data.DataLoader(dS, batch_size=64, + ds = pp.ZipDataset(args.input) + dl = torch.utils.data.DataLoader(ds, batch_size=64, shuffle=True, pin_memory=True, num_workers=0) - for batch_index, img in enumerate(dL): + for batch_index, img in enumerate(dl): pass print(f"Batch {batch_index}") From 559137dda67f21739f0f47b40a09f7b67a995ad2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 12 Oct 2023 23:58:31 +0800 Subject: [PATCH 0537/1123] [NN] allow single-thread prefetching --- py/test1/preprocess.py | 9 +++++++-- py/test1/test_load.py | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/py/test1/preprocess.py b/py/test1/preprocess.py index fb7c434a..c7d59a6f 100644 --- a/py/test1/preprocess.py +++ b/py/test1/preprocess.py @@ -1,3 +1,4 @@ +import copy import cv2 import os import pathlib @@ -158,13 +159,17 @@ def __init__(self, zip_file: str): self.config = tomllib.load(open(config_file, "rb")) print(f"Loading {zip_file}...") - self.zip = zipfile.ZipFile(zip_file) + self.zip = zipfile.ZipFile(zip_file, mode='r') def __len__(self) -> int: return len(self.zip.filelist) + @staticmethod + def read_image_binary(zip_info: zipfile.ZipInfo, zip_obj: zipfile.ZipFile) -> bytes: + return zip_obj.read(name=zip_info) + def decode_image(self, zip_info: zipfile.ZipInfo) -> torch.Tensor: - encoded = self.zip.read(name=zip_info) + encoded = self.read_image_binary(zip_info, self.zip) encoded_nparr = np.frombuffer(encoded, dtype=np.uint8) image = cv2.imdecode(encoded_nparr, flags=cv2.IMREAD_COLOR) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) diff --git a/py/test1/test_load.py b/py/test1/test_load.py index d609ee49..01b35107 100644 --- a/py/test1/test_load.py +++ b/py/test1/test_load.py @@ -12,12 +12,13 @@ def main(): args = parser.parse_args() ds = pp.ZipDataset(args.input) - dl = torch.utils.data.DataLoader(ds, batch_size=64, + dl = torch.utils.data.DataLoader(ds, batch_size=1024, shuffle=True, pin_memory=True, - num_workers=0) + num_workers=0 if os.name == 'nt' else 1) for batch_index, img in enumerate(dl): + img = img.to('cuda') pass print(f"Batch {batch_index}") From d07d7b54a470db51febcdc46f0c527e92d520ae6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 13 Oct 2023 10:37:07 +0800 Subject: [PATCH 0538/1123] [NN] prefetch images with multiple processes --- py/test1/preprocess.py | 34 ++++++++++++++++++++++++++++++++-- py/test1/split_dataset.py | 5 ++++- py/test1/test_load.py | 6 +++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/py/test1/preprocess.py b/py/test1/preprocess.py index c7d59a6f..ff1be214 100644 --- a/py/test1/preprocess.py +++ b/py/test1/preprocess.py @@ -1,4 +1,6 @@ import copy +import io + import cv2 import os import pathlib @@ -165,11 +167,11 @@ def __len__(self) -> int: return len(self.zip.filelist) @staticmethod - def read_image_binary(zip_info: zipfile.ZipInfo, zip_obj: zipfile.ZipFile) -> bytes: + def read_image_binary(zip_info: zipfile.ZipInfo) -> bytes: return zip_obj.read(name=zip_info) def decode_image(self, zip_info: zipfile.ZipInfo) -> torch.Tensor: - encoded = self.read_image_binary(zip_info, self.zip) + encoded = self.read_image_binary(zip_info) encoded_nparr = np.frombuffer(encoded, dtype=np.uint8) image = cv2.imdecode(encoded_nparr, flags=cv2.IMREAD_COLOR) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) @@ -189,5 +191,33 @@ def __getitem__(self, item) -> torch.Tensor: # yield tensor +class MPZipDataset(ZipDataset): + major_pid: int + zip_dict: dict[int, zipfile.ZipFile] + + def __init__(self, zip_file: str, major_pid: int = os.getpid()): + super().__init__(zip_file) + self.major_pid = os.getpid() + self.zip_dict = {} + + def select_zip_obj(self) -> zipfile.ZipFile: + pid = os.getpid() + if pid == self.major_pid: + return self.zip + + if pid not in self.zip_dict: + print(f"Reloading {self.zip.filename} for process {pid}...") + # new_zip = zipfile.ZipFile(self.zip.filename, mode='r') + new_zip = self.zip + new_zip.fp = io.open(self.zip.filename,self.zip.fp.mode) + self.zip_dict[pid] = new_zip + + return self.zip_dict[pid] + + # @override + def read_image_binary(self, zip_info: zipfile.ZipInfo) -> bytes: + return self.select_zip_obj().read(zip_info) + + if __name__ == "__main__": main() diff --git a/py/test1/split_dataset.py b/py/test1/split_dataset.py index f1808b03..e5196ee9 100644 --- a/py/test1/split_dataset.py +++ b/py/test1/split_dataset.py @@ -15,7 +15,10 @@ def picked_count(size: int, ratio: float, max_count: int) -> int: return min(max_count, int(size * ratio)) -def export_subdataset(filename: str, src: zipfile.ZipFile, filelist: list[zipfile.ZipInfo], metainfo: dict[str, Any]): +def export_subdataset(filename: str, + src: zipfile.ZipFile, + filelist: list[zipfile.ZipInfo], + metainfo: dict[str, Any]): dst = zipfile.ZipFile(filename, 'w', compression=zipfile.ZIP_STORED) for info in filelist: content = src.read(info) diff --git a/py/test1/test_load.py b/py/test1/test_load.py index 01b35107..8984ad12 100644 --- a/py/test1/test_load.py +++ b/py/test1/test_load.py @@ -11,11 +11,11 @@ def main(): parser.add_argument("input", type=str) args = parser.parse_args() - ds = pp.ZipDataset(args.input) - dl = torch.utils.data.DataLoader(ds, batch_size=1024, + ds = pp.MPZipDataset(args.input) + dl = torch.utils.data.DataLoader(ds, batch_size=64, shuffle=True, pin_memory=True, - num_workers=0 if os.name == 'nt' else 1) + num_workers=0 if os.name == 'nt' else 8) for batch_index, img in enumerate(dl): img = img.to('cuda') From a75c20da42efb4c17fa16f87e423326cd4c5da63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 14 Oct 2023 10:29:58 +0800 Subject: [PATCH 0539/1123] [CI] test self-hosted action --- .github/workflows/build-dev-clang.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 51d95616..d3cf1f9c 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -103,6 +103,23 @@ jobs: if-no-files-found: error + + macos-build-m2: + runs-on: self-hosted + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + + steps: + - name: pwd + run: pwd + + + # macos-build: # runs-on: macos-latest # strategy: From 2d5f6351fdd09e2c3cddddb19b8c250391f12355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 14 Oct 2023 10:32:22 +0800 Subject: [PATCH 0540/1123] [CI] test self-hosted action --- .github/workflows/build-dev-clang.yml | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index d3cf1f9c..da34b82b 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -118,6 +118,35 @@ jobs: - name: pwd run: pwd + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build and Install + run: | + cd build + cmake --build . --parallel + cmake --install . + cd install + # chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + # chmod +x MapViewer.app/Contents/MacOS/MapViewer + # chmod +x imageCutter.app/Contents/MacOS/imageCutter + # chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + # chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd ./build/install + zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang + path: build/install/SlopeCraft*.zip + # macos-build: From e5ea55437de7301e5936b489c2443955f4fcdc7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 14 Oct 2023 10:38:52 +0800 Subject: [PATCH 0541/1123] [CI] test self-hosted action --- .github/workflows/build-dev-clang.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index da34b82b..02223e2a 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -122,22 +122,14 @@ jobs: uses: actions/checkout@v2 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build and Install + - name: Build run: | cd build cmake --build . --parallel - cmake --install . - cd install - # chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - # chmod +x MapViewer.app/Contents/MacOS/MapViewer - # chmod +x imageCutter.app/Contents/MacOS/imageCutter - # chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - # chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl - # chmod +x vccl.app/Contents/MacOS/vccl - - name: Compress as zip + - name: CPack run: | - cd ./build/install - zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* + cd build + cpack -G ZIP - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -145,7 +137,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang - path: build/install/SlopeCraft*.zip + path: build/SlopeCraft*.zip From 608c07a7a72eec63342007d6b1a2d356510f80c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 14 Oct 2023 20:28:09 +0800 Subject: [PATCH 0542/1123] append processor arch to cpack package name --- cpack/make-packs.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 2cc6c32f..04c26b16 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -7,9 +7,13 @@ set(CPACK_PACKAGE_VENDOR "SlopeCraft group") set(CPACK_PACKAGE_CONTACT https://github.com/SlopeCraft) set(CPACK_PACKAGE_HOMEPAGE_URL https://github.com/SlopeCraft) -if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") +if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME}-debug) -endif() +endif () + +if (${APPLE}) + set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_OSX_ARCHITECTURES}") +endif () include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) From 3c7d99bf26e4bd4079aee005635fdabcdd1893b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 14 Oct 2023 20:44:16 +0800 Subject: [PATCH 0543/1123] fix macos package name --- cpack/make-packs.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 04c26b16..583aec0d 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -12,7 +12,11 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") endif () if (${APPLE}) - set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_OSX_ARCHITECTURES}") + set(cpu_arch ${CMAKE_SYSTEM_PROCESSOR}) + if (${cpu_arch} STREQUAL "AMD64") + set(cpu_arch "x86_64") + endif () + set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${cpu_arch}") endif () include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) From 88d524c62fb1dee0627a8ed713b4094c3e145883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sun, 15 Oct 2023 22:05:05 +0800 Subject: [PATCH 0544/1123] rewrite color diff of RGB and RGB+ with xsimd --- cmake/configure_xsimd.cmake | 10 + utilities/ColorManip/CMakeLists.txt | 17 +- utilities/ColorManip/ColorDiff.cpp | 526 +++++++++++++++++----------- utilities/ColorManip/ColorManip.h | 9 +- 4 files changed, 348 insertions(+), 214 deletions(-) create mode 100644 cmake/configure_xsimd.cmake diff --git a/cmake/configure_xsimd.cmake b/cmake/configure_xsimd.cmake new file mode 100644 index 00000000..88392b2b --- /dev/null +++ b/cmake/configure_xsimd.cmake @@ -0,0 +1,10 @@ +include(FetchContent) + +FetchContent_Declare(xsimd + GIT_REPOSITORY https://github.com/xtensor-stack/xsimd.git + GIT_TAG 11.1.0 + OVERRIDE_FIND_PACKAGE) + +FetchContent_MakeAvailable(xsimd) + +find_package(xsimd REQUIRED) \ No newline at end of file diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 5950b2e0..24c83c40 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -10,7 +10,9 @@ find_package(Heu REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_xsimd.cmake) find_package(cereal REQUIRED) +find_package(xsimd REQUIRED) add_library(ColorManip @@ -42,14 +44,15 @@ target_link_libraries(ColorManip PRIVATE target_link_libraries(ColorManip PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen - cereal::cereal) + cereal::cereal + xsimd) # target_compile_options(ColorManip BEFORE PUBLIC "-std=c++17") target_compile_options(ColorManip PRIVATE ${SlopeCraft_vectorize_flags}) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(ColorManip PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() +endif () # ColorManip links to GPUInterface target_link_libraries(ColorManip PUBLIC GPUInterface) @@ -57,7 +60,7 @@ target_include_directories(ColorManip INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) find_package(OpenCL 3.0) -if(${OpenCL_FOUND}) +if (${OpenCL_FOUND}) add_executable(test_init_program tests/test_init_program.cpp) target_link_libraries(test_init_program PRIVATE OpenMP::OpenMP_CXX ColorManip) @@ -67,9 +70,9 @@ if(${OpenCL_FOUND}) include(${CMAKE_SOURCE_DIR}/cmake/configure_cli11.cmake) target_include_directories(test_algo PRIVATE ${cli11_include_dir}) - foreach(_algo r R H X l L) + foreach (_algo r R H X l L) add_test(NAME test_algo_${_algo} COMMAND test_algo --algo ${_algo} --platform-idx 0 --device-idx 0 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endforeach(_algo r R H X l L) -endif() + endforeach (_algo r R H X l L) +endif () diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 2e9a0c02..5f6121d5 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -22,6 +22,7 @@ This file is part of SlopeCraft. #include "ColorManip.h" #include +#include #include "newTokiColor.hpp" inline float square(float x) { return x * x; } @@ -90,27 +91,9 @@ float color_diff_HSV(float h1, float s1, float v1, float h2, float s2, return dX * dX + dY * dY + dZ * dZ; } -#ifdef SC_VECTORIZE_AVX2 -#include -#include - -constexpr int num_float_per_m256 = 256 / 32; - -union alignas(32) f32_i32 { - float f32[8]; - int i32[8]; - __m256i m256i; -}; - -inline void take_abs_f32_8(float *p) noexcept { - for (size_t i = 0; i < 8; i++) { - p[i] = std::abs(p[i]); - } -} - -// #warning rua~ -#endif // SC_VECTORIZE_AVX2 - +// using selected_arch = xsimd::default_arch; +using batch_t = xsimd::batch; +constexpr size_t batch_size = batch_t::size; void colordiff_RGB_batch(std::span r1p, std::span g1p, std::span b1p, std::span rgb2, @@ -119,53 +102,38 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, assert(g1p.size() == b1p.size()); assert(b1p.size() == dest.size()); - const int color_count = r1p.size(); - -#ifdef SC_VECTORIZE_AVX2 - const __m256 r2 = _mm256_set1_ps(rgb2[0]); - const __m256 g2 = _mm256_set1_ps(rgb2[1]); - const __m256 b2 = _mm256_set1_ps(rgb2[2]); + const size_t color_count = r1p.size(); - for (int i = 0; i + num_float_per_m256 <= color_count; - i += num_float_per_m256) { - const int offset = i; - __m256 r1 = _mm256_load_ps(r1p.data() + offset); - __m256 g1 = _mm256_load_ps(g1p.data() + offset); - __m256 b1 = _mm256_load_ps(b1p.data() + offset); + const size_t vec_size = color_count - color_count % batch_size; - __m256 dr = _mm256_sub_ps(r1, r2); - __m256 dg = _mm256_sub_ps(g1, g2); - __m256 db = _mm256_sub_ps(b1, b2); + const float r2{rgb2[0]}, g2{rgb2[1]}, b2{rgb2[2]}; - dr = _mm256_mul_ps(dr, dr); - dg = _mm256_mul_ps(dg, dg); - db = _mm256_mul_ps(db, db); + for (size_t idx = 0; idx < vec_size; idx += batch_size) { + batch_t r1{batch_t ::load_aligned(r1p.data() + idx)}; + batch_t g1{batch_t ::load_aligned(g1p.data() + idx)}; + batch_t b1{batch_t ::load_aligned(b1p.data() + idx)}; - _mm256_store_ps(dest.data() + offset, - _mm256_add_ps(dr, _mm256_add_ps(dg, db))); + auto dr = r1 - r2; + auto dg = g1 - g2; + auto db = b1 - b2; + batch_t diff = dr * dr + dg * dg + db * db; + diff.store_aligned(dest.data() + idx); } - const int loop_start = - (color_count / num_float_per_m256) * num_float_per_m256; -#else - const int loop_start = 0; -#endif - for (int i = loop_start; i < color_count; i++) { - dest[i] = square(r1p[i] - rgb2[0]) + square(g1p[i] - rgb2[1]) + - square(b1p[i] - rgb2[2]); + for (size_t idx = vec_size; idx < color_count; idx++) { + const float r1 = r1p[idx], g1 = g1p[idx], b1 = b1p[idx]; + const float dr = r1 - r2; + const float dg = g1 - g2; + const float db = b1 - b2; + auto diff = dr * dr + dg * dg + db * db; + dest[idx] = diff; } } -#define SC_PRIVATE_MARCO_assert_if_nan(vec) \ - { \ - alignas(32) std::array temp; \ - { \ - _mm256_store_ps(temp.data(), (vec)); \ - for (float f : temp) { \ - assert(!std::isnan(f)); \ - assert(f >= 0); \ - } \ - } \ +inline void assert_if_nan(batch_t val) noexcept { + for (size_t i = 0; i < batch_size; i++) { + assert(!std::isnan(val.get(i))); } +} void colordiff_RGBplus_batch(std::span r1p, std::span g1p, @@ -178,180 +146,332 @@ void colordiff_RGBplus_batch(std::span r1p, std::fill(dest.begin(), dest.end(), NAN); - const int color_count = r1p.size(); - const float _r2 = c3[0], _g2 = c3[1], _b2 = c3[2]; -#ifdef SC_VECTORIZE_AVX2 + const size_t color_count = r1p.size(); + const size_t vec_size = color_count - color_count % batch_size; + const float r2 = c3[0], g2 = c3[1], b2 = c3[2]; - const __m256 r2 = _mm256_set1_ps(_r2), g2 = _mm256_set1_ps(_g2), - b2 = _mm256_set1_ps(_b2); - const __m256 thre = _mm256_set1_ps(threshold); + // const batch_t r2{_r2}, g2{_g2}, b2{_b2}; - const float rr_plus_gg_plus_bb_2 = (_r2 * _r2 + _g2 * _g2 + _b2 * _b2); + // const batch_t thre_{threshold}; + + const float rr_plus_gg_plus_bb_2 = (r2 * r2 + g2 * g2 + b2 * b2); constexpr float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; - for (int i = 0; i + num_float_per_m256 <= color_count; - i += num_float_per_m256) { - __m256 r1 = _mm256_load_ps(r1p.data() + i); - __m256 g1 = _mm256_load_ps(g1p.data() + i); - __m256 b1 = _mm256_load_ps(b1p.data() + i); + for (size_t i = 0; i < vec_size; i += batch_size) { + batch_t r1{batch_t ::load_aligned(r1p.data() + i)}; + batch_t g1{batch_t ::load_aligned(g1p.data() + i)}; + batch_t b1{batch_t ::load_aligned(b1p.data() + i)}; - __m256 deltaR = _mm256_sub_ps(r1, r2); - __m256 deltaG = _mm256_sub_ps(g1, g2); - __m256 deltaB = _mm256_sub_ps(b1, b2); + auto deltaR = r1 - r2; + auto deltaG = g1 - g2; + auto deltaB = b1 - b2; - __m256 SqrModSquare; + batch_t SqrModSquare; { - const __m256 temp_r = _mm256_mul_ps(r1, r1); - const __m256 temp_g = _mm256_mul_ps(g1, g1); - const __m256 temp_b = _mm256_mul_ps(b1, b1); - - const __m256 rr_plus_gg_plus_bb_1 = - _mm256_add_ps(temp_r, _mm256_add_ps(temp_g, temp_b)); + const batch_t rr_plus_gg_plus_bb_1 = r1 * r1 + g1 * g1 + b1 * b1; - SqrModSquare = _mm256_mul_ps(rr_plus_gg_plus_bb_1, - _mm256_set1_ps(rr_plus_gg_plus_bb_2)); - SqrModSquare = _mm256_sqrt_ps(SqrModSquare); + SqrModSquare = rr_plus_gg_plus_bb_1 * rr_plus_gg_plus_bb_2; + SqrModSquare = xsimd::sqrt(SqrModSquare); } - SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); + assert_if_nan(SqrModSquare); - __m256 sigma_rgb; - { - __m256 temp1 = _mm256_add_ps(r1, g1); - __m256 temp2 = _mm256_add_ps(g1, _mm256_set1_ps(_r2 + _g2 + _b2)); - sigma_rgb = - _mm256_mul_ps(_mm256_add_ps(temp1, temp2), _mm256_set1_ps(1.0f / 3)); - } - __m256 sigma_rgb_plus_thre = - _mm256_add_ps(sigma_rgb, _mm256_set1_ps(threshold)); + const batch_t sigma_rgb = (r1 + g1 + b1 + r2 + g2 + b2) * float(1.0f / 3); - const __m256 r1_plus_r2 = _mm256_add_ps(r1, r2); - const __m256 g1_plus_g2 = _mm256_add_ps(g1, g2); - const __m256 b1_plus_b2 = _mm256_add_ps(b1, b2); - __m256 S_r, S_g, S_b; - { - const __m256 m256_1f = _mm256_set1_ps(1.0f); - __m256 temp_r = _mm256_div_ps(r1_plus_r2, sigma_rgb_plus_thre); - __m256 temp_g = _mm256_div_ps(g1_plus_g2, sigma_rgb_plus_thre); - __m256 temp_b = _mm256_div_ps(b1_plus_b2, sigma_rgb_plus_thre); - - S_r = _mm256_min_ps(temp_r, m256_1f); - S_g = _mm256_min_ps(temp_g, m256_1f); - S_b = _mm256_min_ps(temp_b, m256_1f); - } + const batch_t sigma_rgb_plus_thre = sigma_rgb + threshold; - __m256 sumRGBsquare; + const batch_t r1_plus_r2 = r1 + r2; + const batch_t g1_plus_g2 = g1 + g2; + const batch_t b1_plus_b2 = b1 + b2; + batch_t S_r, S_g, S_b; { - __m256 r1r2 = _mm256_mul_ps(r1, r2); - __m256 g1g2 = _mm256_mul_ps(g1, g2); - __m256 b1b2 = _mm256_mul_ps(b1, b2); - sumRGBsquare = _mm256_add_ps(r1r2, _mm256_add_ps(g1g2, b1b2)); + batch_t temp_r = r1_plus_r2 / sigma_rgb_plus_thre; + batch_t temp_g = g1_plus_g2 / sigma_rgb_plus_thre; + batch_t temp_b = b1_plus_b2 / sigma_rgb_plus_thre; + + S_r = min(temp_r, batch_t{1.0f}); + S_g = min(temp_g, batch_t{1.0f}); + S_b = min(temp_b, batch_t{1.0f}); } - __m256 theta; + const batch_t sumRGBsquare = r1 * r2 + g1 * g2 + b1 * b2; + + batch_t theta; { - __m256 temp1 = - _mm256_div_ps(sumRGBsquare, _mm256_add_ps(SqrModSquare, thre)); - //__m256 _mm256_rsqrt_ps (__m256 a) - /* - __m256 temp1 = _mm256_mul_ps( - sumRGBsquare, _mm256_rsqrt_ps(_mm256_add_ps(SqrModSquare, thre))); - */ - temp1 = _mm256_div_ps(temp1, _mm256_set1_ps(1.01f)); - __m256 temp2; - { - alignas(32) float arr[8]; - _mm256_store_ps(arr, temp1); - for (float &f : arr) { - f = std::acos(f); - assert(!std::isnan(f)); - } - temp2 = _mm256_load_ps(arr); - } - //__m256 temp2 = _mm256_acos_ps__manually(temp1); - theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0 / M_PI)); + batch_t temp1 = sumRGBsquare / (SqrModSquare + threshold); + + temp1 /= 1.01f; + const batch_t temp2 = acos(temp1); + // batch_t temp2 = _mm256_acos_ps__manually(temp1); + theta = temp2 * float(2.0 / M_PI); } alignas(32) float arr[8]; - __m256 OnedDeltaR = - _mm256_div_ps((_mm256_store_ps(arr, deltaR), take_abs_f32_8(arr), - _mm256_load_ps(arr)), - _mm256_add_ps(r1_plus_r2, thre)); - __m256 OnedDeltaG = - _mm256_div_ps((_mm256_store_ps(arr, deltaG), take_abs_f32_8(arr), - _mm256_load_ps(arr)), - _mm256_add_ps(g1_plus_g2, thre)); - __m256 OnedDeltaB = - _mm256_div_ps((_mm256_store_ps(arr, deltaB), take_abs_f32_8(arr), - _mm256_load_ps(arr)), - _mm256_add_ps(b1_plus_b2, thre)); - - __m256 sumOnedDelta = _mm256_add_ps(_mm256_add_ps(OnedDeltaR, OnedDeltaG), - _mm256_add_ps(OnedDeltaB, thre)); - - __m256 S_tr = _mm256_div_ps( - OnedDeltaR, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_r, S_r))); - __m256 S_tg = _mm256_div_ps( - OnedDeltaG, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_g, S_g))); - __m256 S_tb = _mm256_div_ps( - OnedDeltaB, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_b, S_b))); - - __m256 S_theta = _mm256_add_ps(S_tr, _mm256_add_ps(S_tg, S_tb)); - - __m256 S_ratio; + const batch_t OnedDeltaR = abs(deltaR) / (r1_plus_r2 * thre); + const batch_t OnedDeltaG = abs(deltaG) / (g1_plus_g2 * thre); + const batch_t OnedDeltaB = abs(deltaB) / (b1_plus_b2 * thre); + + const batch_t sumOnedDelta = OnedDeltaR + OnedDeltaG + OnedDeltaB + thre; + + batch_t S_tr = OnedDeltaR / (sumOnedDelta * (S_r * S_r)); + batch_t S_tg = OnedDeltaG / (sumOnedDelta * (S_g * S_g)); + batch_t S_tb = OnedDeltaB / (sumOnedDelta * (S_b * S_b)); + + batch_t S_theta = S_tr + S_tg + S_tb; + + batch_t S_ratio; { - __m256 max_r = _mm256_max_ps(r1, r2); - __m256 max_g = _mm256_max_ps(g1, g2); - __m256 max_b = _mm256_max_ps(b1, b2); - S_ratio = _mm256_max_ps(max_r, _mm256_max_ps(max_g, max_b)); + batch_t max_r = max(r1, {r2}); + batch_t max_g = max(g1, {g2}); + batch_t max_b = max(b1, {b2}); + S_ratio = max(max_r, max(max_g, max_b)); } - - __m256 diff; + /* + * + const float result = + (S_r * S_r * w_r * deltaR * deltaR + S_g * S_g * w_g * deltaG * + deltaG + S_b * S_b * w_b * deltaB * deltaB) / (w_r + w_g + w_b) + S_theta * + S_ratio * theta * theta; + * */ + batch_t diff; { - __m256 temp_r = _mm256_mul_ps( - _mm256_mul_ps(_mm256_mul_ps(S_r, S_r), _mm256_mul_ps(deltaR, deltaR)), - _mm256_set1_ps(w_r)); - __m256 temp_g = _mm256_mul_ps( - _mm256_mul_ps(_mm256_mul_ps(S_g, S_g), _mm256_mul_ps(deltaG, deltaG)), - _mm256_set1_ps(w_g)); - __m256 temp_b = _mm256_mul_ps( - _mm256_mul_ps(_mm256_mul_ps(S_b, S_b), _mm256_mul_ps(deltaB, deltaB)), - _mm256_set1_ps(w_b)); - __m256 wr_plus_wr_plus_wb = _mm256_set1_ps(w_r + w_b + w_g); - __m256 temp_X = - _mm256_div_ps(_mm256_add_ps(_mm256_add_ps(temp_r, temp_g), temp_b), - wr_plus_wr_plus_wb); - - __m256 temp_Y = _mm256_mul_ps(_mm256_mul_ps(S_theta, S_ratio), - _mm256_mul_ps(theta, theta)); - - diff = _mm256_add_ps(temp_X, temp_Y); - if (true) { - alignas(32) float temp[8]; - _mm256_store_ps(temp, - diff); // this line crashes on win11, the address of - // temp[7] is 0xfffffffff. I can't understand - // this, maybe a compiler-error? - for (float f : temp) { - assert(!std::isnan(f)); - assert(f >= 0); - } - } + batch_t temp_r = S_r * S_r * deltaR * deltaR * w_r; + batch_t temp_g = S_g * S_g * deltaG * deltaG * w_g; + batch_t temp_b = S_b * S_b * deltaB * deltaB * w_b; + batch_t wr_plus_wr_plus_wb{w_r + w_b + w_g}; + batch_t temp_X = (temp_r + temp_g + temp_b) / wr_plus_wr_plus_wb; + + batch_t temp_Y = S_theta * S_ratio * theta * theta; + + diff = temp_X + temp_Y; } + diff.store_aligned(dest.data() + i); + } - _mm256_store_ps(dest.data() + i, diff); + for (size_t i = vec_size; i < color_count; i++) { + dest[i] = color_diff_RGB_plus(r1p[i], g1p[i], b1p[i], r2, g2, b2); } +} - const int loop_start = - (color_count / num_float_per_m256) * num_float_per_m256; -#else - const int loop_start = 0; -#endif +#ifdef SC_VECTORIZE_AVX2 +#include +#include + +constexpr int num_float_per_m256 = 256 / 32; + +union alignas(32) f32_i32 { + float f32[8]; + int i32[8]; + __m256i m256i; +}; - for (int i = loop_start; i < color_count; i++) { - dest[i] = color_diff_RGB_plus(r1p[i], g1p[i], b1p[i], _r2, _g2, _b2); +inline void take_abs_f32_8(float *p) noexcept { + for (size_t i = 0; i < 8; i++) { + p[i] = std::abs(p[i]); } } +// #warning rua~ +#endif // SC_VECTORIZE_AVX2 + +#define SC_PRIVATE_MARCO_assert_if_nan(vec) \ + { \ + alignas(32) std::array temp; \ + { \ + _mm256_store_ps(temp.data(), (vec)); \ + for (float f : temp) { \ + assert(!std::isnan(f)); \ + assert(f >= 0); \ + } \ + } \ + } + +// void colordiff_RGBplus_batch(std::span r1p, +// std::span g1p, +// std::span b1p, +// std::span c3, +// std::span dest) noexcept { +// assert(r1p.size() == g1p.size()); +// assert(g1p.size() == b1p.size()); +// assert(b1p.size() == dest.size()); +// +// std::fill(dest.begin(), dest.end(), NAN); +// +// const int color_count = r1p.size(); +// const float _r2 = c3[0], _g2 = c3[1], _b2 = c3[2]; +// #ifdef SC_VECTORIZE_AVX2 +// +// const __m256 r2 = _mm256_set1_ps(_r2), g2 = _mm256_set1_ps(_g2), +// b2 = _mm256_set1_ps(_b2); +// const __m256 thre = _mm256_set1_ps(threshold); +// +// const float rr_plus_gg_plus_bb_2 = (_r2 * _r2 + _g2 * _g2 + _b2 * _b2); +// constexpr float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; +// +// for (int i = 0; i + num_float_per_m256 <= color_count; +// i += num_float_per_m256) { +// __m256 r1 = _mm256_load_ps(r1p.data() + i); +// __m256 g1 = _mm256_load_ps(g1p.data() + i); +// __m256 b1 = _mm256_load_ps(b1p.data() + i); +// +// __m256 deltaR = _mm256_sub_ps(r1, r2); +// __m256 deltaG = _mm256_sub_ps(g1, g2); +// __m256 deltaB = _mm256_sub_ps(b1, b2); +// +// __m256 SqrModSquare; +// { +// const __m256 temp_r = _mm256_mul_ps(r1, r1); +// const __m256 temp_g = _mm256_mul_ps(g1, g1); +// const __m256 temp_b = _mm256_mul_ps(b1, b1); +// +// const __m256 rr_plus_gg_plus_bb_1 = +// _mm256_add_ps(temp_r, _mm256_add_ps(temp_g, temp_b)); +// +// SqrModSquare = _mm256_mul_ps(rr_plus_gg_plus_bb_1, +// _mm256_set1_ps(rr_plus_gg_plus_bb_2)); +// SqrModSquare = _mm256_sqrt_ps(SqrModSquare); +// } +// SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); +// +// __m256 sigma_rgb; +// { +// __m256 temp1 = _mm256_add_ps(r1, g1); +// __m256 temp2 = _mm256_add_ps(g1, _mm256_set1_ps(_r2 + _g2 + _b2)); +// sigma_rgb = +// _mm256_mul_ps(_mm256_add_ps(temp1, temp2), _mm256_set1_ps(1.0f / +// 3)); +// } +// __m256 sigma_rgb_plus_thre = +// _mm256_add_ps(sigma_rgb, _mm256_set1_ps(threshold)); +// +// const __m256 r1_plus_r2 = _mm256_add_ps(r1, r2); +// const __m256 g1_plus_g2 = _mm256_add_ps(g1, g2); +// const __m256 b1_plus_b2 = _mm256_add_ps(b1, b2); +// __m256 S_r, S_g, S_b; +// { +// const __m256 m256_1f = _mm256_set1_ps(1.0f); +// __m256 temp_r = _mm256_div_ps(r1_plus_r2, sigma_rgb_plus_thre); +// __m256 temp_g = _mm256_div_ps(g1_plus_g2, sigma_rgb_plus_thre); +// __m256 temp_b = _mm256_div_ps(b1_plus_b2, sigma_rgb_plus_thre); +// +// S_r = _mm256_min_ps(temp_r, m256_1f); +// S_g = _mm256_min_ps(temp_g, m256_1f); +// S_b = _mm256_min_ps(temp_b, m256_1f); +// } +// +// __m256 sumRGBsquare; +// { +// __m256 r1r2 = _mm256_mul_ps(r1, r2); +// __m256 g1g2 = _mm256_mul_ps(g1, g2); +// __m256 b1b2 = _mm256_mul_ps(b1, b2); +// sumRGBsquare = _mm256_add_ps(r1r2, _mm256_add_ps(g1g2, b1b2)); +// } +// +// __m256 theta; +// { +// __m256 temp1 = +// _mm256_div_ps(sumRGBsquare, _mm256_add_ps(SqrModSquare, thre)); +// //__m256 _mm256_rsqrt_ps (__m256 a) +// /* +// __m256 temp1 = _mm256_mul_ps( +// sumRGBsquare, _mm256_rsqrt_ps(_mm256_add_ps(SqrModSquare, thre))); +// */ +// temp1 = _mm256_div_ps(temp1, _mm256_set1_ps(1.01f)); +// __m256 temp2; +// { +// alignas(32) float arr[8]; +// _mm256_store_ps(arr, temp1); +// for (float &f : arr) { +// f = std::acos(f); +// assert(!std::isnan(f)); +// } +// temp2 = _mm256_load_ps(arr); +// } +// //__m256 temp2 = _mm256_acos_ps__manually(temp1); +// theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0 / M_PI)); +// } +// +// alignas(32) float arr[8]; +// __m256 OnedDeltaR = +// _mm256_div_ps((_mm256_store_ps(arr, deltaR), take_abs_f32_8(arr), +// _mm256_load_ps(arr)), +// _mm256_add_ps(r1_plus_r2, thre)); +// __m256 OnedDeltaG = +// _mm256_div_ps((_mm256_store_ps(arr, deltaG), take_abs_f32_8(arr), +// _mm256_load_ps(arr)), +// _mm256_add_ps(g1_plus_g2, thre)); +// __m256 OnedDeltaB = +// _mm256_div_ps((_mm256_store_ps(arr, deltaB), take_abs_f32_8(arr), +// _mm256_load_ps(arr)), +// _mm256_add_ps(b1_plus_b2, thre)); +// +// __m256 sumOnedDelta = _mm256_add_ps(_mm256_add_ps(OnedDeltaR, +// OnedDeltaG), +// _mm256_add_ps(OnedDeltaB, thre)); +// +// __m256 S_tr = _mm256_div_ps( +// OnedDeltaR, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_r, S_r))); +// __m256 S_tg = _mm256_div_ps( +// OnedDeltaG, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_g, S_g))); +// __m256 S_tb = _mm256_div_ps( +// OnedDeltaB, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_b, S_b))); +// +// __m256 S_theta = _mm256_add_ps(S_tr, _mm256_add_ps(S_tg, S_tb)); +// +// __m256 S_ratio; +// { +// __m256 max_r = _mm256_max_ps(r1, r2); +// __m256 max_g = _mm256_max_ps(g1, g2); +// __m256 max_b = _mm256_max_ps(b1, b2); +// S_ratio = _mm256_max_ps(max_r, _mm256_max_ps(max_g, max_b)); +// } +// +// __m256 diff; +// { +// __m256 temp_r = _mm256_mul_ps( +// _mm256_mul_ps(_mm256_mul_ps(S_r, S_r), _mm256_mul_ps(deltaR, +// deltaR)), _mm256_set1_ps(w_r)); +// __m256 temp_g = _mm256_mul_ps( +// _mm256_mul_ps(_mm256_mul_ps(S_g, S_g), _mm256_mul_ps(deltaG, +// deltaG)), _mm256_set1_ps(w_g)); +// __m256 temp_b = _mm256_mul_ps( +// _mm256_mul_ps(_mm256_mul_ps(S_b, S_b), _mm256_mul_ps(deltaB, +// deltaB)), _mm256_set1_ps(w_b)); +// __m256 wr_plus_wr_plus_wb = _mm256_set1_ps(w_r + w_b + w_g); +// __m256 temp_X = +// _mm256_div_ps(_mm256_add_ps(_mm256_add_ps(temp_r, temp_g), temp_b), +// wr_plus_wr_plus_wb); +// +// __m256 temp_Y = _mm256_mul_ps(_mm256_mul_ps(S_theta, S_ratio), +// _mm256_mul_ps(theta, theta)); +// +// diff = _mm256_add_ps(temp_X, temp_Y); +// if (true) { +// alignas(32) float temp[8]; +// _mm256_store_ps(temp, +// diff); // this line crashes on win11, the address of +// // temp[7] is 0xfffffffff. I can't understand +// // this, maybe a compiler-error? +// for (float f : temp) { +// assert(!std::isnan(f)); +// assert(f >= 0); +// } +// } +// } +// +// _mm256_store_ps(dest.data() + i, diff); +// } +// +// const int loop_start = +// (color_count / num_float_per_m256) * num_float_per_m256; +// #else +// const int loop_start = 0; +// #endif +// +// for (int i = loop_start; i < color_count; i++) { +// dest[i] = color_diff_RGB_plus(r1p[i], g1p[i], b1p[i], _r2, _g2, _b2); +// } +// } + void colordiff_HSV_batch(std::span h1p, std::span s1p, std::span v1p, std::span hsv2, diff --git a/utilities/ColorManip/ColorManip.h b/utilities/ColorManip/ColorManip.h index d6b8e083..19e0f9fc 100644 --- a/utilities/ColorManip/ColorManip.h +++ b/utilities/ColorManip/ColorManip.h @@ -78,7 +78,8 @@ void colordiff_RGB_batch(std::span r1, std::span g1, std::span rgb2, std::span dest) noexcept; -void colordiff_RGBplus_batch(std::span r1, std::span g1, +void colordiff_RGBplus_batch(std::span r1, + std::span g1, std::span b1, std::span rgb2, std::span dest) noexcept; @@ -89,8 +90,8 @@ void colordiff_HSV_batch(std::span h1, std::span s1, std::span dest) noexcept; void colordiff_Lab94_batch(std::span l1, std::span a1, - std::span b1, - std::span lab2, - std::span dest) noexcept; + std::span b1, + std::span lab2, + std::span dest) noexcept; #endif \ No newline at end of file From 522ad4da8a83342e15da6fa604a8c5d6b2f518ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 16 Oct 2023 12:58:15 +0800 Subject: [PATCH 0545/1123] fix macos packaging --- vccl/deploy_qt_for_vccl_macos.cmake.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 8cff1c97..04b7913e 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -1,21 +1,21 @@ -# This script should run during installtion +# This script should run during installation #message(STATUS "Running macdeployqt for @AppName@ ...") #execute_process( # COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" -# WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/@vccl_prefix@" +# WORKING_DIRECTORY "@vccl_prefix@" # OUTPUT_QUIET # COMMAND_ERROR_IS_FATAL ANY) file(CREATE_LINK "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl" - "@CMAKE_INSTALL_PREFIX@/vccl" + "vccl" SYMBOLIC) file(CREATE_LINK "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl-config.json" - "@CMAKE_INSTALL_PREFIX@/vccl-config.json" + "vccl-config.json" SYMBOLIC) file(CREATE_LINK "./@vccl_prefix@/vccl.app/Contents/MacOS/Blocks_VCL" - "@CMAKE_INSTALL_PREFIX@/Blocks_VCL" + "Blocks_VCL" SYMBOLIC) From 645f88e6423c30196a8d251811409298285b1a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 16 Oct 2023 13:13:48 +0800 Subject: [PATCH 0546/1123] fix macos packaging --- vccl/install.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vccl/install.cmake b/vccl/install.cmake index b78dde5b..ec6917c0 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -66,6 +66,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) # Do not run deploy_qt.cmake, but a specialied one - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake + DESTINATION .) return() endif () \ No newline at end of file From fa2ea504cdba96d48c2acfb2e08bf2413c31ddd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 16 Oct 2023 16:19:22 +0800 Subject: [PATCH 0547/1123] try to fix macos packaging --- vccl/deploy_qt_for_vccl_macos.cmake.in | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 04b7913e..797fcd0e 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -7,15 +7,17 @@ # OUTPUT_QUIET # COMMAND_ERROR_IS_FATAL ANY) +message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") + file(CREATE_LINK - "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl" + "@vccl_prefix@/vccl.app/Contents/MacOS/vccl" "vccl" SYMBOLIC) file(CREATE_LINK - "./@vccl_prefix@/vccl.app/Contents/MacOS/vccl-config.json" + "@vccl_prefix@/vccl.app/Contents/MacOS/vccl-config.json" "vccl-config.json" SYMBOLIC) file(CREATE_LINK - "./@vccl_prefix@/vccl.app/Contents/MacOS/Blocks_VCL" + "@vccl_prefix@/vccl.app/Contents/MacOS/Blocks_VCL" "Blocks_VCL" SYMBOLIC) From 409712faabb4aa6b266431fffca2453a195e3e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 16 Oct 2023 16:50:51 +0800 Subject: [PATCH 0548/1123] vectorize HSV color diff with xsimd --- utilities/ColorManip/ColorDiff.cpp | 241 +++++------------------------ 1 file changed, 37 insertions(+), 204 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 5f6121d5..b98ba9a3 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -252,6 +252,43 @@ void colordiff_RGBplus_batch(std::span r1p, } } +void colordiff_HSV_batch(std::span h1p, std::span s1p, + std::span v1p, + std::span hsv2, + std::span dest) noexcept { + assert(h1p.size() == s1p.size()); + assert(s1p.size() == v1p.size()); + assert(v1p.size() == dest.size()); + + const size_t color_count = h1p.size(); + const size_t vec_size = color_count - color_count % batch_size; + + const float h2 = hsv2[0]; + const float s2 = hsv2[1]; + const float v2 = hsv2[2]; + + for (size_t idx = 0; idx < vec_size; idx += batch_size) { + const batch_t h1 = batch_t::load_aligned(h1p.data() + idx); + const batch_t s1 = batch_t::load_aligned(s1p.data() + idx); + const batch_t v1 = batch_t::load_aligned(v1p.data() + idx); + auto sv_1 = s1 * v1; + auto sv_2 = s2 * v2; + + const auto dX = 50.0f * (cos(h1) * sv_1 - std::cos(h2) * sv_2); + const auto dY = 50.0f * (sin(h1) * sv_1 - std::sin(h2) * sv_2); + const auto dZ = 50.0f * (v1 - v2); + + const auto diff = dX * dX + dY * dY + dZ * dZ; + diff.store_aligned(dest.data() + idx); + } + + for (size_t idx = vec_size; idx < color_count; idx++) { + const float diff = + color_diff_HSV(hsv2[0], hsv2[1], hsv2[2], h1p[idx], s1p[idx], v1p[idx]); + dest[idx] = diff; + } +} + #ifdef SC_VECTORIZE_AVX2 #include #include @@ -285,210 +322,6 @@ inline void take_abs_f32_8(float *p) noexcept { } \ } -// void colordiff_RGBplus_batch(std::span r1p, -// std::span g1p, -// std::span b1p, -// std::span c3, -// std::span dest) noexcept { -// assert(r1p.size() == g1p.size()); -// assert(g1p.size() == b1p.size()); -// assert(b1p.size() == dest.size()); -// -// std::fill(dest.begin(), dest.end(), NAN); -// -// const int color_count = r1p.size(); -// const float _r2 = c3[0], _g2 = c3[1], _b2 = c3[2]; -// #ifdef SC_VECTORIZE_AVX2 -// -// const __m256 r2 = _mm256_set1_ps(_r2), g2 = _mm256_set1_ps(_g2), -// b2 = _mm256_set1_ps(_b2); -// const __m256 thre = _mm256_set1_ps(threshold); -// -// const float rr_plus_gg_plus_bb_2 = (_r2 * _r2 + _g2 * _g2 + _b2 * _b2); -// constexpr float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; -// -// for (int i = 0; i + num_float_per_m256 <= color_count; -// i += num_float_per_m256) { -// __m256 r1 = _mm256_load_ps(r1p.data() + i); -// __m256 g1 = _mm256_load_ps(g1p.data() + i); -// __m256 b1 = _mm256_load_ps(b1p.data() + i); -// -// __m256 deltaR = _mm256_sub_ps(r1, r2); -// __m256 deltaG = _mm256_sub_ps(g1, g2); -// __m256 deltaB = _mm256_sub_ps(b1, b2); -// -// __m256 SqrModSquare; -// { -// const __m256 temp_r = _mm256_mul_ps(r1, r1); -// const __m256 temp_g = _mm256_mul_ps(g1, g1); -// const __m256 temp_b = _mm256_mul_ps(b1, b1); -// -// const __m256 rr_plus_gg_plus_bb_1 = -// _mm256_add_ps(temp_r, _mm256_add_ps(temp_g, temp_b)); -// -// SqrModSquare = _mm256_mul_ps(rr_plus_gg_plus_bb_1, -// _mm256_set1_ps(rr_plus_gg_plus_bb_2)); -// SqrModSquare = _mm256_sqrt_ps(SqrModSquare); -// } -// SC_PRIVATE_MARCO_assert_if_nan(SqrModSquare); -// -// __m256 sigma_rgb; -// { -// __m256 temp1 = _mm256_add_ps(r1, g1); -// __m256 temp2 = _mm256_add_ps(g1, _mm256_set1_ps(_r2 + _g2 + _b2)); -// sigma_rgb = -// _mm256_mul_ps(_mm256_add_ps(temp1, temp2), _mm256_set1_ps(1.0f / -// 3)); -// } -// __m256 sigma_rgb_plus_thre = -// _mm256_add_ps(sigma_rgb, _mm256_set1_ps(threshold)); -// -// const __m256 r1_plus_r2 = _mm256_add_ps(r1, r2); -// const __m256 g1_plus_g2 = _mm256_add_ps(g1, g2); -// const __m256 b1_plus_b2 = _mm256_add_ps(b1, b2); -// __m256 S_r, S_g, S_b; -// { -// const __m256 m256_1f = _mm256_set1_ps(1.0f); -// __m256 temp_r = _mm256_div_ps(r1_plus_r2, sigma_rgb_plus_thre); -// __m256 temp_g = _mm256_div_ps(g1_plus_g2, sigma_rgb_plus_thre); -// __m256 temp_b = _mm256_div_ps(b1_plus_b2, sigma_rgb_plus_thre); -// -// S_r = _mm256_min_ps(temp_r, m256_1f); -// S_g = _mm256_min_ps(temp_g, m256_1f); -// S_b = _mm256_min_ps(temp_b, m256_1f); -// } -// -// __m256 sumRGBsquare; -// { -// __m256 r1r2 = _mm256_mul_ps(r1, r2); -// __m256 g1g2 = _mm256_mul_ps(g1, g2); -// __m256 b1b2 = _mm256_mul_ps(b1, b2); -// sumRGBsquare = _mm256_add_ps(r1r2, _mm256_add_ps(g1g2, b1b2)); -// } -// -// __m256 theta; -// { -// __m256 temp1 = -// _mm256_div_ps(sumRGBsquare, _mm256_add_ps(SqrModSquare, thre)); -// //__m256 _mm256_rsqrt_ps (__m256 a) -// /* -// __m256 temp1 = _mm256_mul_ps( -// sumRGBsquare, _mm256_rsqrt_ps(_mm256_add_ps(SqrModSquare, thre))); -// */ -// temp1 = _mm256_div_ps(temp1, _mm256_set1_ps(1.01f)); -// __m256 temp2; -// { -// alignas(32) float arr[8]; -// _mm256_store_ps(arr, temp1); -// for (float &f : arr) { -// f = std::acos(f); -// assert(!std::isnan(f)); -// } -// temp2 = _mm256_load_ps(arr); -// } -// //__m256 temp2 = _mm256_acos_ps__manually(temp1); -// theta = _mm256_mul_ps(temp2, _mm256_set1_ps(2.0 / M_PI)); -// } -// -// alignas(32) float arr[8]; -// __m256 OnedDeltaR = -// _mm256_div_ps((_mm256_store_ps(arr, deltaR), take_abs_f32_8(arr), -// _mm256_load_ps(arr)), -// _mm256_add_ps(r1_plus_r2, thre)); -// __m256 OnedDeltaG = -// _mm256_div_ps((_mm256_store_ps(arr, deltaG), take_abs_f32_8(arr), -// _mm256_load_ps(arr)), -// _mm256_add_ps(g1_plus_g2, thre)); -// __m256 OnedDeltaB = -// _mm256_div_ps((_mm256_store_ps(arr, deltaB), take_abs_f32_8(arr), -// _mm256_load_ps(arr)), -// _mm256_add_ps(b1_plus_b2, thre)); -// -// __m256 sumOnedDelta = _mm256_add_ps(_mm256_add_ps(OnedDeltaR, -// OnedDeltaG), -// _mm256_add_ps(OnedDeltaB, thre)); -// -// __m256 S_tr = _mm256_div_ps( -// OnedDeltaR, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_r, S_r))); -// __m256 S_tg = _mm256_div_ps( -// OnedDeltaG, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_g, S_g))); -// __m256 S_tb = _mm256_div_ps( -// OnedDeltaB, _mm256_mul_ps(sumOnedDelta, _mm256_mul_ps(S_b, S_b))); -// -// __m256 S_theta = _mm256_add_ps(S_tr, _mm256_add_ps(S_tg, S_tb)); -// -// __m256 S_ratio; -// { -// __m256 max_r = _mm256_max_ps(r1, r2); -// __m256 max_g = _mm256_max_ps(g1, g2); -// __m256 max_b = _mm256_max_ps(b1, b2); -// S_ratio = _mm256_max_ps(max_r, _mm256_max_ps(max_g, max_b)); -// } -// -// __m256 diff; -// { -// __m256 temp_r = _mm256_mul_ps( -// _mm256_mul_ps(_mm256_mul_ps(S_r, S_r), _mm256_mul_ps(deltaR, -// deltaR)), _mm256_set1_ps(w_r)); -// __m256 temp_g = _mm256_mul_ps( -// _mm256_mul_ps(_mm256_mul_ps(S_g, S_g), _mm256_mul_ps(deltaG, -// deltaG)), _mm256_set1_ps(w_g)); -// __m256 temp_b = _mm256_mul_ps( -// _mm256_mul_ps(_mm256_mul_ps(S_b, S_b), _mm256_mul_ps(deltaB, -// deltaB)), _mm256_set1_ps(w_b)); -// __m256 wr_plus_wr_plus_wb = _mm256_set1_ps(w_r + w_b + w_g); -// __m256 temp_X = -// _mm256_div_ps(_mm256_add_ps(_mm256_add_ps(temp_r, temp_g), temp_b), -// wr_plus_wr_plus_wb); -// -// __m256 temp_Y = _mm256_mul_ps(_mm256_mul_ps(S_theta, S_ratio), -// _mm256_mul_ps(theta, theta)); -// -// diff = _mm256_add_ps(temp_X, temp_Y); -// if (true) { -// alignas(32) float temp[8]; -// _mm256_store_ps(temp, -// diff); // this line crashes on win11, the address of -// // temp[7] is 0xfffffffff. I can't understand -// // this, maybe a compiler-error? -// for (float f : temp) { -// assert(!std::isnan(f)); -// assert(f >= 0); -// } -// } -// } -// -// _mm256_store_ps(dest.data() + i, diff); -// } -// -// const int loop_start = -// (color_count / num_float_per_m256) * num_float_per_m256; -// #else -// const int loop_start = 0; -// #endif -// -// for (int i = loop_start; i < color_count; i++) { -// dest[i] = color_diff_RGB_plus(r1p[i], g1p[i], b1p[i], _r2, _g2, _b2); -// } -// } - -void colordiff_HSV_batch(std::span h1p, std::span s1p, - std::span v1p, - std::span hsv2, - std::span dest) noexcept { - assert(h1p.size() == s1p.size()); - assert(s1p.size() == v1p.size()); - assert(v1p.size() == dest.size()); - - const int color_count = h1p.size(); - - for (int idx = 0; idx < color_count; idx++) { - const float diff = - color_diff_HSV(hsv2[0], hsv2[1], hsv2[2], h1p[idx], s1p[idx], v1p[idx]); - dest[idx] = diff; - } -} - void colordiff_Lab94_batch(std::span l1p, std::span a1p, std::span b1p, From 50a22cc9a0c06f80e74eac56bbf75c8b2ecbf3cd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 17 Oct 2023 16:34:45 +0800 Subject: [PATCH 0549/1123] fix macos installation of vccl --- vccl/deploy_qt_for_vccl_macos.cmake.in | 13 ++++++++++++- vccl/install.cmake | 7 +++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 797fcd0e..4d709085 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -1,5 +1,16 @@ # This script should run during installation +set(this_script_file @deployqt_vccl_script@) +option(install_mode "" ON) + +if(install_mode) + execute_process(COMMAND ${CMAKE_COMMAND} -Dinstall_mode:BOOL=false -P ${this_script_file} + WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} + COMMAND_ERROR_IS_FATAL ANY + ) + return() +endif() + #message(STATUS "Running macdeployqt for @AppName@ ...") #execute_process( # COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" @@ -7,7 +18,7 @@ # OUTPUT_QUIET # COMMAND_ERROR_IS_FATAL ANY) -message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") +# message(WARNING "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") file(CREATE_LINK "@vccl_prefix@/vccl.app/Contents/MacOS/vccl" diff --git a/vccl/install.cmake b/vccl/install.cmake index ec6917c0..be207e1e 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -49,8 +49,11 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") set(vccl_prefix vccl-contents) + set(deployqt_vccl_script ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) find_program(SlopeCraft_Qt_macdeployqt_executable macdeployqt REQUIRED) - configure_file(deploy_qt_for_vccl_macos.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake) + configure_file(deploy_qt_for_vccl_macos.cmake.in + ${deployqt_vccl_script} + @ONLY) include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS vccl @@ -66,7 +69,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) # Do not run deploy_qt.cmake, but a specialied one - install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt_for_vccl_macos.cmake + install(SCRIPT ${deployqt_vccl_script} DESTINATION .) return() endif () \ No newline at end of file From 8534c147fda40239808b8fccd5bb667dea4969ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 11:34:50 +0800 Subject: [PATCH 0550/1123] change the way of introducing xsimd --- cmake/configure_xsimd.cmake | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cmake/configure_xsimd.cmake b/cmake/configure_xsimd.cmake index 88392b2b..325550c6 100644 --- a/cmake/configure_xsimd.cmake +++ b/cmake/configure_xsimd.cmake @@ -1,10 +1,15 @@ -include(FetchContent) +find_package(xsimd QUIET) +if (NOT ${xsimd_FOUND}) + message(FATAL_ERROR "xsimd is not installed. You may install it with vcpkg") +endif () -FetchContent_Declare(xsimd - GIT_REPOSITORY https://github.com/xtensor-stack/xsimd.git - GIT_TAG 11.1.0 - OVERRIDE_FIND_PACKAGE) - -FetchContent_MakeAvailable(xsimd) - -find_package(xsimd REQUIRED) \ No newline at end of file +#include(FetchContent) +# +#FetchContent_Declare(xsimd +# GIT_REPOSITORY https://github.com/xtensor-stack/xsimd.git +# GIT_TAG 11.1.0 +# OVERRIDE_FIND_PACKAGE) +# +#FetchContent_MakeAvailable(xsimd) +# +#find_package(xsimd REQUIRED) \ No newline at end of file From 5c11bb0e48d28d2fbbe36ef52e14d15c3e580994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 13:41:13 +0800 Subject: [PATCH 0551/1123] rewrite cie 94 with xsimd --- utilities/ColorManip/ColorDiff.cpp | 120 ++++++++--------------------- 1 file changed, 32 insertions(+), 88 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index b98ba9a3..9b265517 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -205,7 +205,6 @@ void colordiff_RGBplus_batch(std::span r1p, theta = temp2 * float(2.0 / M_PI); } - alignas(32) float arr[8]; const batch_t OnedDeltaR = abs(deltaR) / (r1_plus_r2 * thre); const batch_t OnedDeltaG = abs(deltaG) / (g1_plus_g2 * thre); const batch_t OnedDeltaB = abs(deltaB) / (b1_plus_b2 * thre); @@ -289,39 +288,6 @@ void colordiff_HSV_batch(std::span h1p, std::span s1p, } } -#ifdef SC_VECTORIZE_AVX2 -#include -#include - -constexpr int num_float_per_m256 = 256 / 32; - -union alignas(32) f32_i32 { - float f32[8]; - int i32[8]; - __m256i m256i; -}; - -inline void take_abs_f32_8(float *p) noexcept { - for (size_t i = 0; i < 8; i++) { - p[i] = std::abs(p[i]); - } -} - -// #warning rua~ -#endif // SC_VECTORIZE_AVX2 - -#define SC_PRIVATE_MARCO_assert_if_nan(vec) \ - { \ - alignas(32) std::array temp; \ - { \ - _mm256_store_ps(temp.data(), (vec)); \ - for (float f : temp) { \ - assert(!std::isnan(f)); \ - assert(f >= 0); \ - } \ - } \ - } - void colordiff_Lab94_batch(std::span l1p, std::span a1p, std::span b1p, @@ -333,55 +299,42 @@ void colordiff_Lab94_batch(std::span l1p, assert(a1p.size() == b1p.size()); assert(b1p.size() == dest.size()); - const int color_count = l1p.size(); + const size_t color_count = l1p.size(); + const size_t vec_size = color_count - color_count % batch_size; -#ifdef SC_VECTORIZE_AVX2 - const __m256 L2 = _mm256_set1_ps(c3[0]); - const __m256 a2 = _mm256_set1_ps(c3[1]); - const __m256 b2 = _mm256_set1_ps(c3[2]); + const float L2 = c3[0]; + const float a2 = c3[1]; + const float b2 = c3[2]; //__m256 C1_2; - __m256 SC_2, sqrt_C1_2; - { - // float L = c3[0]; - float a = c3[1]; - float b = c3[2]; - float _C1_2 = a * a + b * b; - float _SC_2 = (sqrt(_C1_2) * 0.045f + 1.0f) * (sqrt(_C1_2) * 0.045f + 1.0f); - - // C1_2 = _mm256_set1_ps(_C1_2); - SC_2 = _mm256_set1_ps(_SC_2); - sqrt_C1_2 = _mm256_set1_ps(sqrt(_C1_2)); - } + const float sqrt_C1_2 = sqrt(a2 * a2 + b2 * b2); + const float SC_2 = square(sqrt_C1_2 * 0.045f + 1.0f); - for (int i = 0; i + num_float_per_m256 <= color_count; - i += num_float_per_m256) { - __m256 L1 = _mm256_load_ps(l1p.data() + i); - __m256 a1 = _mm256_load_ps(a1p.data() + i); - __m256 b1 = _mm256_load_ps(b1p.data() + i); - // auto deltaL_2 = (Allowed->lab(0) - L).square(); + for (size_t i = 0; i < vec_size; i += batch_size) { + batch_t L1 = batch_t::load_aligned(l1p.data() + i); + batch_t a1 = batch_t::load_aligned(a1p.data() + i); + batch_t b1 = batch_t::load_aligned(b1p.data() + i); - __m256 deltaL_2; + batch_t deltaL_2; { - __m256 Ldiff = _mm256_sub_ps(L1, L2); - deltaL_2 = _mm256_mul_ps(Ldiff, Ldiff); + batch_t Ldiff = L1 - L2; + deltaL_2 = (Ldiff * Ldiff); } - __m256 C2_2 = _mm256_add_ps(_mm256_mul_ps(a1, a1), _mm256_mul_ps(b1, b1)); + batch_t C2_2 = ((a1 * a1) + (b1 * b1)); - __m256 deltaCab_2; + batch_t deltaCab_2; { - __m256 temp = _mm256_sub_ps(sqrt_C1_2, _mm256_sqrt_ps(C2_2)); - deltaCab_2 = _mm256_mul_ps(temp, temp); + batch_t temp = (sqrt_C1_2 - sqrt(C2_2)); + deltaCab_2 = (temp * temp); } - __m256 deltaHab_2; + batch_t deltaHab_2; { - __m256 a_diff = _mm256_sub_ps(a1, a2); - __m256 b_diff = _mm256_sub_ps(b1, b2); + batch_t a_diff = (a1 - a2); + batch_t b_diff = (b1 - b2); - deltaHab_2 = _mm256_add_ps(_mm256_mul_ps(a_diff, a_diff), - _mm256_mul_ps(b_diff, b_diff)); - deltaHab_2 = _mm256_sub_ps(deltaHab_2, deltaCab_2); + deltaHab_2 = ((a_diff * a_diff) + (b_diff * b_diff)); + deltaHab_2 = (deltaHab_2 - deltaCab_2); } // constexpr float SL = 1; @@ -389,31 +342,22 @@ void colordiff_Lab94_batch(std::span l1p, // constexpr float K1 = 0.045f; constexpr float K2 = 0.015f; - __m256 SH_2; + batch_t SH_2; { - __m256 temp = - _mm256_add_ps(_mm256_mul_ps(_mm256_sqrt_ps(C2_2), _mm256_set1_ps(K2)), - _mm256_set1_ps(1.0f)); - SH_2 = _mm256_mul_ps(temp, temp); + batch_t temp = ((sqrt(C2_2) * K2) + 1.0f); + SH_2 = (temp * temp); } - __m256 diff; + batch_t diff; { - __m256 temp_C = _mm256_div_ps(deltaCab_2, SC_2); - __m256 temp_H = _mm256_div_ps(deltaHab_2, SH_2); - diff = _mm256_add_ps(deltaL_2, _mm256_add_ps(temp_C, temp_H)); + batch_t temp_C = (deltaCab_2 / SC_2); + batch_t temp_H = (deltaHab_2 / SH_2); + diff = (deltaL_2 + (temp_C + temp_H)); } - _mm256_store_ps(dest.data() + i, diff); + diff.store_aligned(dest.data() + i); } - const int loop_start = - (color_count / num_float_per_m256) * num_float_per_m256; -#else - const int loop_start = 0; - -#endif - { const float L = c3[0]; const float a = c3[1]; @@ -422,7 +366,7 @@ void colordiff_Lab94_batch(std::span l1p, const float _SC_2 = (sqrt(_C1_2) * 0.045f + 1.0f) * (sqrt(_C1_2) * 0.045f + 1.0f); - for (int i = loop_start; i < color_count; i++) { + for (size_t i = vec_size; i < color_count; i++) { // auto deltaL_2 = (Allowed->lab(0) - L).square(); const float deltaL_2 = (l1p[i] - L) * (l1p[i] - L); From bbcefba01ac19216fdce967183059e5416c2baf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 14:16:51 +0800 Subject: [PATCH 0552/1123] enable neon --- CMakeLists.txt | 14 +------------- cmake/select_vectorize_flag.cmake | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 cmake/select_vectorize_flag.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 37e29c1a..dcaf14dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,19 +83,7 @@ if (NOT ${SlopeCraft_vectorize}) endif () if (${SlopeCraft_vectorize}) - include(CheckCXXCompilerFlag) - add_definitions("-DSC_VECTORIZE_AVX2") - - if (${MSVC}) - set(SlopeCraft_vectorize_flags "/arch:AVX2") - else () - set(SlopeCraft_vectorize_flags -mavx -mavx2 -mfma) - endif () - - message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) - add_compile_options(${SlopeCraft_vectorize_flags}) - - # list(APPEND SlopeCraft_vectorize_flags "-O3") + include(cmake/select_vectorize_flag.cmake) endif () if (${WIN32}) diff --git a/cmake/select_vectorize_flag.cmake b/cmake/select_vectorize_flag.cmake new file mode 100644 index 00000000..fdf90ced --- /dev/null +++ b/cmake/select_vectorize_flag.cmake @@ -0,0 +1,24 @@ + +include(CheckCXXCompilerFlag) +#add_definitions("-DSC_VECTORIZE_AVX2") + +message(STATUS "System processor arch = ${CMAKE_SYSTEM_PROCESSOR}") + +if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") + if (${MSVC}) + set(SlopeCraft_vectorize_flags "/arch:AVX2") + else () + set(SlopeCraft_vectorize_flags -mavx -mavx2 -mfma) + endif () +elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64") + set(SlopeCraft_vectorize_flags -mfpu=neon) + # if (${APPLE}) + # set(SlopeCraft_vectorize_flags -mcpu=apple-m1 -mfpu=neon) + # endif () +else () + message(WARNING "Unknown cpu arch, using -march=native") +endif () + + +message(STATUS "Vectorize using " ${SlopeCraft_vectorize_flags}) +add_compile_options(${SlopeCraft_vectorize_flags}) \ No newline at end of file From fc92cf42f79e0e8131ad2b4b8113e82abb82e367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 14:28:53 +0800 Subject: [PATCH 0553/1123] update github actions --- .github/workflows/build-dev-clang.yml | 2 +- .github/workflows/build-dev-gcc.yml | 63 +++++---------------------- 2 files changed, 11 insertions(+), 54 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 02223e2a..07c7762a 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -35,7 +35,7 @@ jobs: - name: Install deps with vcpkg shell: cmd - run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 + run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 xsimd - name: Checkout repository uses: actions/checkout@v2 diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 8996e58b..1cd087c9 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -31,6 +31,7 @@ jobs: run: | brew install libpng brew install qt@6 + brew install xsimd - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH @@ -90,8 +91,8 @@ jobs: - name: Install cmake, ninja run: sudo apt install cmake ninja-build - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + - name: Install libzip, libpng, Eigen3, and xsimd + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libxsimd-dev - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools @@ -222,21 +223,11 @@ jobs: echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - #- name: See environment - # run: where.exe cmake ninja 7z clang gcc vcpkg - #- name: See versions - # run: | - # cmake --version - # ninja --version - # clang --version - # gcc --version - #- name: See Path - # run: $env:path -split ';' - name: Install ninja run: | choco install ninja ninja --version - + - name: Make dirs run: | mkdir bin @@ -253,48 +244,14 @@ jobs: # gcc installation dir: bin/mingw64 # gcc.exe: bin/mingw64/bin/gcc.exe # g++.exe: bin/mingw64/bin/g++.exe - - name: Build and install zlib - run: | - $basedir=(pwd).path.replace("\\","/") - echo "basedir = $basedir" - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/madler/zlib.git - cd zlib - git checkout v1.2.13 - cd $basedir - mkdir bin/build-zlib - cmake -S 3rdParty/zlib -B bin/build-zlib -G Ninja -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" - cmake --build bin/build-zlib --parallel - cmake --install bin/build-zlib - - - name: Build and install libzip + - name: Install deps with vcpkg run: | $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/nih-at/libzip.git - cd libzip - git checkout v1.9.2 - cd $basedir - mkdir bin/build-libzip - cmake -S 3rdParty/libzip -B bin/build-libzip -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" -DBUILD_SHARED_LIBS=true -DLIBZIP_DO_INSTALL=true -DENABLE_BZIP2=false -DENABLE_LZMA=false -DENABLE_ZSTD=false - cmake --build bin/build-libzip --parallel - cmake --install bin/build-libzip - - - name: Build and install libpng - run: | - $basedir=(pwd).path.replace("\\","/") - $BUILD_TYPE=$env:BUILD_TYPE - cd 3rdParty - git clone https://github.com/glennrp/libpng.git - cd libpng - git checkout v1.6.39 - cd $basedir - mkdir bin/build-libpng - cmake -S 3rdParty/libpng -B bin/build-libpng -G Ninja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_INSTALL_PREFIX="$basedir/bin/mingw64" -DCMAKE_PREFIX_PATH="$basedir/bin/mingw64" - cmake --build bin/build-libpng --parallel - cmake --install bin/build-libpng + $GPU_API=$env:GPU_API + $env:path=$env:NEW_PATH + echo "env:path = $env:path" + vcpkg install --triplet=x64-mingw-dynamic zlib libpng libzip eigen3 xsimd - name: Download Qt6.4.0-gcc12-shared and extract run: | @@ -313,7 +270,7 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared;C:/vcpkg/installed/x64-mingw-dynamic" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - name: CMake build run: | From b5446689698211e6dd864746df30f5fea082e2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 14:56:40 +0800 Subject: [PATCH 0554/1123] [CI] fix gcc build --- .github/workflows/build-dev-gcc.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 1cd087c9..d48db2bf 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -91,8 +91,19 @@ jobs: - name: Install cmake, ninja run: sudo apt install cmake ninja-build - - name: Install libzip, libpng, Eigen3, and xsimd - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libxsimd-dev + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install xsimd + run: | + cd build + git clone https://github.com/xtensor-stack/xsimd.git + cd xsimd + git checkout 11.1.0 + cmake -S . -B build-xsimd + sudo cmake --install ./build-xsimd + cd .. + rm -rf ./* - name: Install qt6 run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools @@ -266,7 +277,7 @@ jobs: $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API - $env:path=$env:NEW_PATH + $env:path="$basedir/bin/mingw64/bin;$env:path" echo "env:path = $env:path" mkdir build mkdir install From 214970a45a2d91b858653323afadcf9119b3a63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 15:08:30 +0800 Subject: [PATCH 0555/1123] [CI] try to fix gcc-windows build --- .github/workflows/build-dev-gcc.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index d48db2bf..bf57c068 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -243,7 +243,7 @@ jobs: run: | mkdir bin mkdir bin/mingw64 - mkdir bin/Qt6.4.0-gcc12-shared + mkdir bin/Qt6.5.0-gcc11-shared-offical mkdir 3rdParty - name: Download mingw64 and extract @@ -264,14 +264,14 @@ jobs: echo "env:path = $env:path" vcpkg install --triplet=x64-mingw-dynamic zlib libpng libzip eigen3 xsimd - - name: Download Qt6.4.0-gcc12-shared and extract + - name: Download Qt6.5.0-gcc11-shared-offical and extract run: | cmd - curl -JL -o bin/Qt6.4.0-gcc12-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.4.0-gcc12-shared-native.7z" - 7z x -o"bin/Qt6.4.0-gcc12-shared" bin/Qt6.4.0-gcc12-shared.7z + curl -JL -o bin/Qt6.5.0-gcc11-shared-offical.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-gcc11-shared-offical.7z" + 7z x -o"bin/Qt6.5.0-gcc11-shared-offical" bin/Qt6.5.0-gcc11-shared-offical.7z exit - tree /f bin/Qt6.4.0-gcc12-shared - # Qt installation dir: bin/Qt6.4.0-gcc12-shared + tree /f bin/Qt6.5.0-gcc11-shared-offical + # Qt installation dir: bin/Qt6.5.0-gcc11-shared-offical - name: CMake configure run: | $basedir=(pwd).path.replace("\\","/") @@ -281,7 +281,7 @@ jobs: echo "env:path = $env:path" mkdir build mkdir install - cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.4.0-gcc12-shared;C:/vcpkg/installed/x64-mingw-dynamic" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE + cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_C_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/gcc.exe" -DCMAKE_CXX_COMPILER:FILEPATH="$basedir/bin/mingw64/bin/g++.exe" -DCMAKE_PREFIX_PATH:PATH="$basedir/bin/Qt6.5.0-gcc11-shared-offical;C:/vcpkg/installed/x64-mingw-dynamic" -DCMAKE_INSTALL_PREFIX:PATH="$basedir/install" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DSlopeCraft_GPU_API:STRING="$GPU_API" -DSlopeCraft_vectorize:BOOL=$VECTORIZE - name: CMake build run: | From f0869cd0095c017792f79bf330fd8243264d58af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 15:24:41 +0800 Subject: [PATCH 0556/1123] [CI] enable opencl to windows build --- .github/workflows/build-dev-clang.yml | 6 +++++- .github/workflows/build-dev-gcc.yml | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 07c7762a..813ee2a1 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None ] + gpu_api: [ None, OpenCL ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL @@ -37,6 +37,10 @@ jobs: shell: cmd run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 xsimd + - name: Install OpenCL with vcpkg + if: matrix.gpu_api == 'OpenCL' + run: vcpkg install opencl --triplet=x64-windows + - name: Checkout repository uses: actions/checkout@v2 diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index bf57c068..0e4dd62e 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -193,7 +193,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None ] + gpu_api: [ None , OpenCL ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL @@ -264,6 +264,17 @@ jobs: echo "env:path = $env:path" vcpkg install --triplet=x64-mingw-dynamic zlib libpng libzip eigen3 xsimd + + - name: Install OpenCL with vcpkg + if: matrix.gpu_api == 'OpenCL' + run: | + $basedir=(pwd).path.replace("\\","/") + $BUILD_TYPE=$env:BUILD_TYPE + $GPU_API=$env:GPU_API + $env:path=$env:NEW_PATH + echo "env:path = $env:path" + vcpkg install opencl --triplet=x64-mingw-dynamic + - name: Download Qt6.5.0-gcc11-shared-offical and extract run: | cmd From 1558596ad8bc799ba66d3bdb497b02ff879c7368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 15:32:51 +0800 Subject: [PATCH 0557/1123] [CI] pack macos-gcc build with cpack --- .github/workflows/build-dev-gcc.yml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index 0e4dd62e..fefe310c 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -7,7 +7,7 @@ on: - dev jobs: - macos-build: + macos-build-intel: runs-on: macos-latest strategy: matrix: @@ -40,22 +40,15 @@ jobs: uses: actions/checkout@v2 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build and Install + - name: Build run: | cd build cmake --build . --parallel - cmake --install . - cd install - chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - chmod +x MapViewer.app/Contents/MacOS/MapViewer - chmod +x imageCutter.app/Contents/MacOS/imageCutter - chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl # chmod +x vccl.app/Contents/MacOS/vccl - - name: Compress as zip + - name: CPack run: | - cd ./build/install - zip -9 -r -y SlopeCraft-5.1.0-macos.zip ./* + cd ./build + cpack -G ZIP - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -63,7 +56,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - path: build/install/SlopeCraft-5.1.0-macos.zip + path: build/SlopeCraft*.zip linux-build: runs-on: ubuntu-latest From 092195ee08619896f14b3cf8e3c05c5e1f11e6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 15:33:33 +0800 Subject: [PATCH 0558/1123] [CI] add clang-macos-intel build --- .github/workflows/build-dev-clang.yml | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml index 813ee2a1..8f77a8f2 100644 --- a/.github/workflows/build-dev-clang.yml +++ b/.github/workflows/build-dev-clang.yml @@ -107,6 +107,57 @@ jobs: if-no-files-found: error + macos-build-intel: + runs-on: macos-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: brew upgrade & update + run: | + brew upgrade + brew update + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng + brew install qt@6 + brew install xsimd + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build + run: | + cd build + cmake --build . --parallel + # chmod +x vccl.app/Contents/MacOS/vccl + - name: CPack + run: | + cd ./build + cpack -G ZIP + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang + path: build/SlopeCraft*.zip + macos-build-m2: runs-on: self-hosted From f90b01b74364c73e32eef705bf9fe0d983f835e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 15:58:42 +0800 Subject: [PATCH 0559/1123] [CI] hide windows-gcc build with opencl --- .github/workflows/build-dev-gcc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/build-dev-gcc.yml index fefe310c..0e331232 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/build-dev-gcc.yml @@ -186,7 +186,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None , OpenCL ] + gpu_api: [ None ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL From 3819f9c28d010070767bb340f52e94ab8c006c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Wed, 18 Oct 2023 22:19:21 +0800 Subject: [PATCH 0560/1123] add framework for vk support --- utilities/GPUWrapper/CMakeLists.txt | 8 +++++--- utilities/GPUWrapper/Vulkan/CMakeLists.txt | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 utilities/GPUWrapper/Vulkan/CMakeLists.txt diff --git a/utilities/GPUWrapper/CMakeLists.txt b/utilities/GPUWrapper/CMakeLists.txt index b21a1ede..0ec0e4fa 100644 --- a/utilities/GPUWrapper/CMakeLists.txt +++ b/utilities/GPUWrapper/CMakeLists.txt @@ -18,9 +18,11 @@ if (${SlopeCraft_GPU_API} STREQUAL "OpenCL") add_subdirectory(OpenCL) target_compile_definitions(GPUInterface PUBLIC -DSLOPECRAFT_GPU_API="OpenCL") return() -endif () - -if (${SlopeCraft_GPU_API} STREQUAL "None") +elseif (${SlopeCraft_GPU_API} STREQUAL "Vulkan") + add_subdirectory(Vulkan) + target_compile_definitions(GPUInterface PUBLIC -DSLOPECRAFT_GPU_API="Vulkan") + return() +elseif (${SlopeCraft_GPU_API} STREQUAL "None") add_subdirectory(None) return() endif () diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt new file mode 100644 index 00000000..7c2a27a7 --- /dev/null +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -0,0 +1 @@ +find_package(Vulkan REQUIRED) \ No newline at end of file From 00711155542c2fbebd41352ac446af9a1ea8706e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 21 Oct 2023 23:29:20 +0800 Subject: [PATCH 0561/1123] recombine github actions --- .github/workflows/build-dev-clang.yml | 252 ------------------ .github/workflows/linux-build.yml | 131 +++++++++ .github/workflows/macos-build-arm64.yml | 100 +++++++ .github/workflows/macos-build-x86_64.yml | 110 ++++++++ .../{build-dev-gcc.yml => windows-build.yml} | 220 +++++---------- 5 files changed, 413 insertions(+), 400 deletions(-) delete mode 100644 .github/workflows/build-dev-clang.yml create mode 100644 .github/workflows/linux-build.yml create mode 100644 .github/workflows/macos-build-arm64.yml create mode 100644 .github/workflows/macos-build-x86_64.yml rename .github/workflows/{build-dev-gcc.yml => windows-build.yml} (57%) diff --git a/.github/workflows/build-dev-clang.yml b/.github/workflows/build-dev-clang.yml deleted file mode 100644 index 8f77a8f2..00000000 --- a/.github/workflows/build-dev-clang.yml +++ /dev/null @@ -1,252 +0,0 @@ -name: clang build(for windows and macos) (macos build is hidden) -on: - pull_request: - push: - branches: - - main - - dev - -jobs: - - windows-build: - runs-on: windows-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL ] - vectorize: [ true, false ] - exclude: - - gpu_api: OpenCL - vectorize: false - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - VECTORIZE: ${{ matrix.vectorize }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo "env:BUILD_TYPE = $env:BUILD_TYPE" - echo "env:GPU_API = $env:GPU_API" - - - name: Install ninja - run: | - choco install ninja - ninja --version - - - name: Install deps with vcpkg - shell: cmd - run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 xsimd - - - name: Install OpenCL with vcpkg - if: matrix.gpu_api == 'OpenCL' - run: vcpkg install opencl --triplet=x64-windows - - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Get short SHA - run: | - echo "GITHUB_SHA = $env:GITHUB_SHA" - $short_sha=$env:GITHUB_SHA.substring(0,7) - echo "short_sha = $short_sha" - echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - - name: make dirs - run: | - mkdir bin - mkdir bin/Qt6.5.0-msvc-shared - mkdir 3rdParty - - - name: Download Qt6.5.0-msvc-shared and extract - run: | - cmd - curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared.7z" - 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z - exit - tree /f bin/Qt6.5.0-msvc-shared - # Qt installation dir: bin/Qt6.5.0-msvc-shared - - - name: CMake configure - shell: cmd - run: | - mkdir build - mkdir install - set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - - - name: CMake build - shell: cmd - run: | - tree ./build - cmake --build ./build --parallel 10 - - - name: CMake install - shell: cmd - run: | - cmake --install ./build - - - name: Make zip and 7z packs with CPack - run: | - $basedir=(pwd).path.replace("\\","/") - cd ./build - cpack -G ZIP -B "$basedir/pack" - cpack -G 7Z -B "$basedir/pack" - - #- name: Upload zip pack - # uses: actions/upload-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-zip - # path: pack/SlopeCraft*.zip - # if-no-files-found: error - - - name: Upload 7z pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z - path: pack/SlopeCraft*.7z - if-no-files-found: error - - - macos-build-intel: - runs-on: macos-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: brew upgrade & update - run: | - brew upgrade - brew update - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: | - brew install libpng - brew install qt@6 - brew install xsimd - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build - run: | - cd build - cmake --build . --parallel - # chmod +x vccl.app/Contents/MacOS/vccl - - name: CPack - run: | - cd ./build - cpack -G ZIP - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang - path: build/SlopeCraft*.zip - - - macos-build-m2: - runs-on: self-hosted - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - - steps: - - name: pwd - run: pwd - - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build - run: | - cd build - cmake --build . --parallel - - name: CPack - run: | - cd build - cpack -G ZIP - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang - path: build/SlopeCraft*.zip - - - -# macos-build: -# runs-on: macos-latest -# strategy: -# matrix: -# build_type: [ Debug, Release ] -# gpu_api: [ None ] -# env: -# BUILD_TYPE: ${{ matrix.build_type }} -# GPU_API: ${{ matrix.gpu_api }} -# steps: -# - name: brew update -# run: brew update -# - name: echo matrix variables (build_type = ${{ matrix.build_type }}) -# run: | -# echo $BUILD_TYPE -# echo $GPU_API -# - name: Install build system -# run: brew install ninja cmake -# - name: Install dependencies -# run: | -# brew install libpng qt@6 eigen -# brew reinstall libomp -# - name: Add /usr/local/lib to PATH -# run: echo "/usr/local/lib" >> $GITHUB_PATH -# - name: Check PATH -# run: echo $PATH -# - name: Checkout repository -# uses: actions/checkout@v2 -# - name: Configure CMake -# run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -# - name: Build and Install -# run: | -# cd build -# cmake --build . --parallel -# cmake --install . -# cd install -# chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft -# chmod +x MapViewer.app/Contents/MacOS/MapViewer -# chmod +x imageCutter.app/Contents/MacOS/imageCutter -# chmod +x VisualCraft.app/Contents/MacOS/VisualCraft -# chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl -# # chmod +x vccl.app/Contents/MacOS/vccl -# - name: Compress as zip -# run: | -# cd ./build/install -# zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* -# -# - name: Get short SHA -# run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV -# - name: Upload Artifacts -# uses: actions/upload-artifact@v2 -# with: -# name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang -# path: build/install/SlopeCraft*.zip \ No newline at end of file diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml new file mode 100644 index 00000000..3de48e65 --- /dev/null +++ b/.github/workflows/linux-build.yml @@ -0,0 +1,131 @@ +name: Linux build +on: + pull_request: + push: + branches: + - main + - dev + +jobs: + gcc: + runs-on: ubuntu-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None, OpenCL ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: apt update + run: sudo apt update + + - name: Make directories + run: mkdir build install pack + + #- name: List installed + # run: apt list --installed + + - name: Install cmake, ninja + run: sudo apt install cmake ninja-build + + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install xsimd + run: | + cd build + git clone https://github.com/xtensor-stack/xsimd.git + cd xsimd + git checkout 11.1.0 + cmake -S . -B build-xsimd + sudo cmake --install ./build-xsimd + cd .. + rm -rf ./* + + - name: Install qt6 + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + + - name: Install additional qt-related packages + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install OpenCL sdk + if: matrix.gpu_api == 'OpenCL' + run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + + - name: See clinfo + if: matrix.gpu_api == 'OpenCL' + run: clinfo + + - name: Install xz (Release as tar.xz) + run: sudo apt install xz-utils + + - name: Checkout repository + uses: actions/checkout@v2 + + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + + - name: CMake build + run: cmake --build ./build --parallel + + - name: CMake install + run: cmake --install ./build + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + + - name: Make deb and tar.xz packs with cpack + run: | + cd build + cpack -G DEB -B ../pack + cpack -G TXZ -B ../pack + cd .. + + - name: Upload deb pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-deb + path: pack/SlopeCraft*.deb + if-no-files-found: error + + - name: Upload tar.xz pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-tar-xz + path: pack/SlopeCraft*.tar.xz + if-no-files-found: error + + - name: Run CTest + if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure + - name: Test deb pack + run: sudo dpkg -i ./pack/*.deb + + # linux-test-deb: + # runs-on: ubunut-latest + # needs: linux-build + # strategy: + # matrix: + # build_type: [Debug, Release] + # gpu_api: [None, OpenCL] + # steps: + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Download deb + # uses: actions/download-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + # + # - name: ls + # run: ls . + # + # - name: Try installing deb + # run: sudo dpkg -i ./*.deb diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml new file mode 100644 index 00000000..788e1c72 --- /dev/null +++ b/.github/workflows/macos-build-arm64.yml @@ -0,0 +1,100 @@ +name: macos build(for m-series CPUs) +on: + pull_request: + push: + branches: + - main + - dev + +jobs: + clang: + runs-on: self-hosted + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + + steps: + - name: pwd + run: pwd + + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build + run: | + cd build + cmake --build . --parallel + - name: CPack + run: | + cd build + cpack -G ZIP + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang + path: build/SlopeCraft*.zip + + + + # macos-build: + # runs-on: macos-latest + # strategy: + # matrix: + # build_type: [ Debug, Release ] + # gpu_api: [ None ] + # env: + # BUILD_TYPE: ${{ matrix.build_type }} + # GPU_API: ${{ matrix.gpu_api }} + # steps: + # - name: brew update + # run: brew update + # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + # run: | + # echo $BUILD_TYPE + # echo $GPU_API + # - name: Install build system + # run: brew install ninja cmake + # - name: Install dependencies + # run: | + # brew install libpng qt@6 eigen + # brew reinstall libomp + # - name: Add /usr/local/lib to PATH + # run: echo "/usr/local/lib" >> $GITHUB_PATH + # - name: Check PATH + # run: echo $PATH + # - name: Checkout repository + # uses: actions/checkout@v2 + # - name: Configure CMake + # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + # - name: Build and Install + # run: | + # cd build + # cmake --build . --parallel + # cmake --install . + # cd install + # chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft + # chmod +x MapViewer.app/Contents/MacOS/MapViewer + # chmod +x imageCutter.app/Contents/MacOS/imageCutter + # chmod +x VisualCraft.app/Contents/MacOS/VisualCraft + # chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl + # # chmod +x vccl.app/Contents/MacOS/vccl + # - name: Compress as zip + # run: | + # cd ./build/install + # zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* + # + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # - name: Upload Artifacts + # uses: actions/upload-artifact@v2 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang + # path: build/install/SlopeCraft*.zip \ No newline at end of file diff --git a/.github/workflows/macos-build-x86_64.yml b/.github/workflows/macos-build-x86_64.yml new file mode 100644 index 00000000..8d245184 --- /dev/null +++ b/.github/workflows/macos-build-x86_64.yml @@ -0,0 +1,110 @@ +name: macos build(for intel CPUs) +on: + pull_request: + push: + branches: + - main + - dev + +jobs: + gcc: + runs-on: macos-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: brew upgrade & update + run: | + brew upgrade + brew update + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng + brew install qt@6 + brew install xsimd + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build + run: | + cd build + cmake --build . --parallel + # chmod +x vccl.app/Contents/MacOS/vccl + - name: CPack + run: | + cd ./build + cpack -G ZIP + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc + path: build/SlopeCraft*.zip + + clang: + runs-on: macos-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: brew upgrade & update + run: | + brew upgrade + brew update + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng + brew install qt@6 + brew install xsimd + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Checkout repository + uses: actions/checkout@v2 + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + - name: Build + run: | + cd build + cmake --build . --parallel + # chmod +x vccl.app/Contents/MacOS/vccl + - name: CPack + run: | + cd ./build + cpack -G ZIP + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v2 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang + path: build/SlopeCraft*.zip \ No newline at end of file diff --git a/.github/workflows/build-dev-gcc.yml b/.github/workflows/windows-build.yml similarity index 57% rename from .github/workflows/build-dev-gcc.yml rename to .github/workflows/windows-build.yml index 0e331232..62716a9c 100644 --- a/.github/workflows/build-dev-gcc.yml +++ b/.github/workflows/windows-build.yml @@ -1,4 +1,4 @@ -name: gcc build(for windows, linux and macos) +name: windows build on: pull_request: push: @@ -7,181 +7,105 @@ on: - dev jobs: - macos-build-intel: - runs-on: macos-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: brew upgrade & update - run: | - brew upgrade - brew update - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: | - brew install libpng - brew install qt@6 - brew install xsimd - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v2 - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - - name: Build - run: | - cd build - cmake --build . --parallel - # chmod +x vccl.app/Contents/MacOS/vccl - - name: CPack - run: | - cd ./build - cpack -G ZIP - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v2 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - path: build/SlopeCraft*.zip - - linux-build: - runs-on: ubuntu-latest + clang: + runs-on: windows-latest strategy: matrix: build_type: [ Debug, Release ] gpu_api: [ None, OpenCL ] + vectorize: [ true, false ] + exclude: + - gpu_api: OpenCL + vectorize: false env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} + VECTORIZE: ${{ matrix.vectorize }} steps: - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | - echo $BUILD_TYPE - echo $GPU_API - - name: apt update - run: sudo apt update + echo "env:BUILD_TYPE = $env:BUILD_TYPE" + echo "env:GPU_API = $env:GPU_API" - - name: Make directories - run: mkdir build install pack + - name: Install ninja + run: | + choco install ninja + ninja --version - #- name: List installed - # run: apt list --installed + - name: Install deps with vcpkg + shell: cmd + run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 xsimd - - name: Install cmake, ninja - run: sudo apt install cmake ninja-build + - name: Install OpenCL with vcpkg + if: matrix.gpu_api == 'OpenCL' + run: vcpkg install opencl --triplet=x64-windows - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + - name: Checkout repository + uses: actions/checkout@v2 - - name: Install xsimd + - name: Get short SHA run: | - cd build - git clone https://github.com/xtensor-stack/xsimd.git - cd xsimd - git checkout 11.1.0 - cmake -S . -B build-xsimd - sudo cmake --install ./build-xsimd - cd .. - rm -rf ./* - - - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - - name: Install additional qt-related packages - run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev - # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install OpenCL sdk - if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo - - - name: See clinfo - if: matrix.gpu_api == 'OpenCL' - run: clinfo + echo "GITHUB_SHA = $env:GITHUB_SHA" + $short_sha=$env:GITHUB_SHA.substring(0,7) + echo "short_sha = $short_sha" + echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - name: Install xz (Release as tar.xz) - run: sudo apt install xz-utils + - name: make dirs + run: | + mkdir bin + mkdir bin/Qt6.5.0-msvc-shared + mkdir 3rdParty - - name: Checkout repository - uses: actions/checkout@v2 + - name: Download Qt6.5.0-msvc-shared and extract + run: | + cmd + curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared.7z" + 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z + exit + tree /f bin/Qt6.5.0-msvc-shared + # Qt installation dir: bin/Qt6.5.0-msvc-shared - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + shell: cmd + run: | + mkdir build + mkdir install + set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build - run: cmake --build ./build --parallel + shell: cmd + run: | + tree ./build + cmake --build ./build --parallel 10 - name: CMake install - run: cmake --install ./build - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + shell: cmd + run: | + cmake --install ./build - - name: Make deb and tar.xz packs with cpack + - name: Make zip and 7z packs with CPack run: | - cd build - cpack -G DEB -B ../pack - cpack -G TXZ -B ../pack - cd .. + $basedir=(pwd).path.replace("\\","/") + cd ./build + cpack -G ZIP -B "$basedir/pack" + cpack -G 7Z -B "$basedir/pack" - - name: Upload deb pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-deb - path: pack/SlopeCraft*.deb - if-no-files-found: error + #- name: Upload zip pack + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-zip + # path: pack/SlopeCraft*.zip + # if-no-files-found: error - - name: Upload tar.xz pack + - name: Upload 7z pack uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-tar-xz - path: pack/SlopeCraft*.tar.xz + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z + path: pack/SlopeCraft*.7z if-no-files-found: error - - name: Run CTest - if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') - run: | - cd ./build - ctest -j20 --output-on-failure --stop-on-failure - - name: Test deb pack - run: sudo dpkg -i ./pack/*.deb - - # linux-test-deb: - # runs-on: ubunut-latest - # needs: linux-build - # strategy: - # matrix: - # build_type: [Debug, Release] - # gpu_api: [None, OpenCL] - # steps: - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - # - name: Download deb - # uses: actions/download-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb - # - # - name: ls - # run: ls . - # - # - name: Try installing deb - # run: sudo dpkg -i ./*.deb - - windows-build: + gcc: runs-on: windows-latest strategy: matrix: @@ -318,10 +242,10 @@ jobs: #- name: Upload zip pack # uses: actions/upload-artifact@v3 - # with: + # with: # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-zip # path: pack/SlopeCraft*.zip - # if-no-files-found: error + # if-no-files-found: error - name: Upload 7z pack uses: actions/upload-artifact@v3 @@ -338,7 +262,7 @@ jobs: # with: # name: all_files_on_D.txt # path: bin/all_files_on_D.txt - # if-no-files-found: error + # if-no-files-found: error @@ -347,4 +271,4 @@ jobs: # with: # name: gcc12-with-zlib,libzip,libpng # path: bin/mingw64 - # if-no-files-found: error + # if-no-files-found: error From db17a3ed3a4a36c3d3550a2f2c49b22fd08d5a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 11:48:23 -0400 Subject: [PATCH 0562/1123] ci: Optimize CI names --- .github/workflows/linux-build.yml | 2 +- .github/workflows/macos-build-arm64.yml | 2 +- .../workflows/{macos-build-x86_64.yml => macos-build-x64.yml} | 2 +- .github/workflows/windows-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{macos-build-x86_64.yml => macos-build-x64.yml} (99%) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 3de48e65..4e358ce9 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -1,4 +1,4 @@ -name: Linux build +name: Linux Build on: pull_request: push: diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 788e1c72..19210727 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -1,4 +1,4 @@ -name: macos build(for m-series CPUs) +name: macOS (Apple Silicon) Build on: pull_request: push: diff --git a/.github/workflows/macos-build-x86_64.yml b/.github/workflows/macos-build-x64.yml similarity index 99% rename from .github/workflows/macos-build-x86_64.yml rename to .github/workflows/macos-build-x64.yml index 8d245184..5065177e 100644 --- a/.github/workflows/macos-build-x86_64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -1,4 +1,4 @@ -name: macos build(for intel CPUs) +name: macOS (x64) Build on: pull_request: push: diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 62716a9c..32dee7e1 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -1,4 +1,4 @@ -name: windows build +name: Windows Build on: pull_request: push: From 70c0f79ed70ef3efd9ab77257fc34fcfb7ceeb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 12:33:38 -0400 Subject: [PATCH 0563/1123] ci(macos-build-x64): Add clang check --- .github/workflows/macos-build-x64.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 5065177e..83efd0b3 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -19,12 +19,16 @@ jobs: steps: - name: brew upgrade & update run: | - brew upgrade brew update + brew upgrade - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE echo $GPU_API + - name: Install LLVM clang + run: brew install llvm + - name: Check clang + run: clang --version - name: Install Ninja build system run: brew install ninja - name: Install dependencies @@ -70,8 +74,8 @@ jobs: steps: - name: brew upgrade & update run: | - brew upgrade brew update + brew upgrade - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE @@ -107,4 +111,4 @@ jobs: uses: actions/upload-artifact@v2 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang - path: build/SlopeCraft*.zip \ No newline at end of file + path: build/SlopeCraft*.zip From dc4ecac242a47c16f3640dba3dbf03606bf9186e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 12:42:24 -0400 Subject: [PATCH 0564/1123] ci(macos-build-x64): Disable brew update --- .github/workflows/macos-build-x64.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 83efd0b3..5b65cb14 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -17,10 +17,10 @@ jobs: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} steps: - - name: brew upgrade & update - run: | - brew update - brew upgrade + # - name: brew upgrade & update + # run: | + # brew update + # brew upgrade - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE @@ -72,10 +72,10 @@ jobs: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} steps: - - name: brew upgrade & update - run: | - brew update - brew upgrade + # - name: brew upgrade & update + # run: | + # brew update + # brew upgrade - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE From a81abd629a9e2f4ec7c1d0f307189b93c61e06db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 12:43:50 -0400 Subject: [PATCH 0565/1123] ci(macos-build-x64): Fix --- .github/workflows/macos-build-x64.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 5b65cb14..f43b1a03 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -25,10 +25,6 @@ jobs: run: | echo $BUILD_TYPE echo $GPU_API - - name: Install LLVM clang - run: brew install llvm - - name: Check clang - run: clang --version - name: Install Ninja build system run: brew install ninja - name: Install dependencies @@ -76,6 +72,10 @@ jobs: # run: | # brew update # brew upgrade + - name: Install LLVM clang + run: brew install llvm + - name: Check clang + run: clang --version - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE From 15bf95e6e735f6f84813059f8970160672fcf1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 12:50:44 -0400 Subject: [PATCH 0566/1123] ci(macos-build-x64): Use LLVM clang --- .github/workflows/macos-build-x64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index f43b1a03..e774fc1f 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -75,7 +75,7 @@ jobs: - name: Install LLVM clang run: brew install llvm - name: Check clang - run: clang --version + run: /usr/local/opt/llvm/bin/clang --version - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE @@ -94,7 +94,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - name: Build run: | cd build From 03fcb721ad4f3c1f53444a59eb361e6764f16352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sat, 21 Oct 2023 13:10:44 -0400 Subject: [PATCH 0567/1123] ci: Update `actions/checkout` and `actions/upload-artifact` --- .github/workflows/linux-build.yml | 2 +- .github/workflows/macos-build-arm64.yml | 8 ++++---- .github/workflows/macos-build-x64.yml | 8 ++++---- .github/workflows/windows-build.yml | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 4e358ce9..693c960e 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -65,7 +65,7 @@ jobs: run: sudo apt install xz-utils - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: CMake configure run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 19210727..7c6b8bf1 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -22,7 +22,7 @@ jobs: run: pwd - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - name: Build @@ -37,7 +37,7 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang path: build/SlopeCraft*.zip @@ -71,7 +71,7 @@ jobs: # - name: Check PATH # run: echo $PATH # - name: Checkout repository - # uses: actions/checkout@v2 + # uses: actions/checkout@v4 # - name: Configure CMake # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar # - name: Build and Install @@ -94,7 +94,7 @@ jobs: # - name: Get short SHA # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV # - name: Upload Artifacts - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang # path: build/install/SlopeCraft*.zip \ No newline at end of file diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index e774fc1f..5ffc1709 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -37,7 +37,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - name: Build @@ -53,7 +53,7 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc path: build/SlopeCraft*.zip @@ -92,7 +92,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - name: Build @@ -108,7 +108,7 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang path: build/SlopeCraft*.zip diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 32dee7e1..951a928f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -41,7 +41,7 @@ jobs: run: vcpkg install opencl --triplet=x64-windows - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Get short SHA run: | @@ -126,7 +126,7 @@ jobs: echo "env:GPU_API = $env:GPU_API" - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install ninja From cd05ed97a582e09a6a74cbf1c0aa4a07f5cb0adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Sun, 22 Oct 2023 21:55:12 -0400 Subject: [PATCH 0568/1123] ci(macos): Apply `OSX_DEPLOYMENT_TARGET` --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 7c6b8bf1..f107f01d 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 5ffc1709..705252e8 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -39,7 +39,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build @@ -94,7 +94,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build From 042477da750033569263f9c52801bff041d0f9a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 23 Oct 2023 16:01:01 +0800 Subject: [PATCH 0569/1123] add linux-clang build --- .github/workflows/linux-build.yml | 123 ++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 693c960e..bff1b3b6 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -129,3 +129,126 @@ jobs: # # - name: Try installing deb # run: sudo dpkg -i ./*.deb + + clang: + runs-on: ubuntu-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None, OpenCL ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: apt update + run: sudo apt update + + - name: Make directories + run: mkdir build install pack + + #- name: List installed + # run: apt list --installed + + - name: Install clang, cmake, ninja + run: sudo apt install clang cmake ninja-build + + - name: Install libzip, libpng, Eigen3 + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + + - name: Install xsimd + run: | + cd build + git clone https://github.com/xtensor-stack/xsimd.git + cd xsimd + git checkout 11.1.0 + cmake -S . -B build-xsimd + sudo cmake --install ./build-xsimd + cd .. + rm -rf ./* + + - name: Install qt6 + run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + + - name: Install additional qt-related packages + run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + - name: Install OpenCL sdk + if: matrix.gpu_api == 'OpenCL' + run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + + - name: See clinfo + if: matrix.gpu_api == 'OpenCL' + run: clinfo + + - name: Install xz (Release as tar.xz) + run: sudo apt install xz-utils + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: CMake configure + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + + - name: CMake build + run: cmake --build ./build --parallel + + - name: CMake install + run: cmake --install ./build + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + + - name: Make deb and tar.xz packs with cpack + run: | + cd build + cpack -G DEB -B ../pack + cpack -G TXZ -B ../pack + cd .. + + - name: Upload deb pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-deb + path: pack/SlopeCraft*.deb + if-no-files-found: error + + - name: Upload tar.xz pack + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-tar-xz + path: pack/SlopeCraft*.tar.xz + if-no-files-found: error + + - name: Run CTest + if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') + run: | + cd ./build + ctest -j20 --output-on-failure --stop-on-failure + - name: Test deb pack + run: sudo dpkg -i ./pack/*.deb + + # linux-test-deb: + # runs-on: ubunut-latest + # needs: linux-build + # strategy: + # matrix: + # build_type: [Debug, Release] + # gpu_api: [None, OpenCL] + # steps: + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Download deb + # uses: actions/download-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-deb + # + # - name: ls + # run: ls . + # + # - name: Try installing deb + # run: sudo dpkg -i ./*.deb From 2d2e87a528036c168f41235fff9a96422ccd0e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 23 Oct 2023 16:08:53 +0800 Subject: [PATCH 0570/1123] [CI] fix linux-clang build --- .github/workflows/linux-build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index bff1b3b6..b488859f 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -153,11 +153,11 @@ jobs: #- name: List installed # run: apt list --installed - - name: Install clang, cmake, ninja - run: sudo apt install clang cmake ninja-build + - name: Install clang-15, cmake, ninja + run: sudo apt install clang-15 cmake ninja-build - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + - name: Install libzip, libpng, Eigen3, openmp + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libomp5-15 - name: Install xsimd run: | @@ -191,7 +191,7 @@ jobs: uses: actions/checkout@v4 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-15 -DCMAKE_CXX_COMPILER:FILEPATH=clang++-15 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - name: CMake build run: cmake --build ./build --parallel From 1da9ead4c565466b7d8471d75d9bbcf256af83bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 23 Oct 2023 16:26:08 +0800 Subject: [PATCH 0571/1123] [CI] hide linux-clang build --- .github/workflows/linux-build.yml | 200 +++++++++++++++--------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index b488859f..bf178e5d 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -130,106 +130,106 @@ jobs: # - name: Try installing deb # run: sudo dpkg -i ./*.deb - clang: - runs-on: ubuntu-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: apt update - run: sudo apt update - - - name: Make directories - run: mkdir build install pack - - #- name: List installed - # run: apt list --installed - - - name: Install clang-15, cmake, ninja - run: sudo apt install clang-15 cmake ninja-build - - - name: Install libzip, libpng, Eigen3, openmp - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libomp5-15 - - - name: Install xsimd - run: | - cd build - git clone https://github.com/xtensor-stack/xsimd.git - cd xsimd - git checkout 11.1.0 - cmake -S . -B build-xsimd - sudo cmake --install ./build-xsimd - cd .. - rm -rf ./* - - - name: Install qt6 - run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools - - - name: Install additional qt-related packages - run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev - # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install OpenCL sdk - if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo - - - name: See clinfo - if: matrix.gpu_api == 'OpenCL' - run: clinfo - - - name: Install xz (Release as tar.xz) - run: sudo apt install xz-utils - - - name: Checkout repository - uses: actions/checkout@v4 - - - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-15 -DCMAKE_CXX_COMPILER:FILEPATH=clang++-15 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE - - - name: CMake build - run: cmake --build ./build --parallel - - - name: CMake install - run: cmake --install ./build - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - - name: Make deb and tar.xz packs with cpack - run: | - cd build - cpack -G DEB -B ../pack - cpack -G TXZ -B ../pack - cd .. - - - name: Upload deb pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-deb - path: pack/SlopeCraft*.deb - if-no-files-found: error - - - name: Upload tar.xz pack - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-tar-xz - path: pack/SlopeCraft*.tar.xz - if-no-files-found: error - - - name: Run CTest - if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') - run: | - cd ./build - ctest -j20 --output-on-failure --stop-on-failure - - name: Test deb pack - run: sudo dpkg -i ./pack/*.deb + # clang: + # runs-on: ubuntu-latest + # strategy: + # matrix: + # build_type: [ Debug, Release ] + # gpu_api: [ None, OpenCL ] + # env: + # BUILD_TYPE: ${{ matrix.build_type }} + # GPU_API: ${{ matrix.gpu_api }} + # steps: + # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + # run: | + # echo $BUILD_TYPE + # echo $GPU_API + # - name: apt update + # run: sudo apt update + # + # - name: Make directories + # run: mkdir build install pack + # + # #- name: List installed + # # run: apt list --installed + # + # - name: Install clang-15, cmake, ninja + # run: sudo apt install clang-15 cmake ninja-build + # + # - name: Install libzip, libpng, Eigen3, openmp + # run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libomp5-15 + # + # - name: Install xsimd + # run: | + # cd build + # git clone https://github.com/xtensor-stack/xsimd.git + # cd xsimd + # git checkout 11.1.0 + # cmake -S . -B build-xsimd + # sudo cmake --install ./build-xsimd + # cd .. + # rm -rf ./* + # + # - name: Install qt6 + # run: sudo apt install libqt6widgets6 libqt6gui6 libqt6network6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools + # + # - name: Install additional qt-related packages + # run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev + # # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically + # - name: Install OpenCL sdk + # if: matrix.gpu_api == 'OpenCL' + # run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + # + # - name: See clinfo + # if: matrix.gpu_api == 'OpenCL' + # run: clinfo + # + # - name: Install xz (Release as tar.xz) + # run: sudo apt install xz-utils + # + # - name: Checkout repository + # uses: actions/checkout@v4 + # + # - name: CMake configure + # run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-15 -DCMAKE_CXX_COMPILER:FILEPATH=clang++-15 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + # + # - name: CMake build + # run: cmake --build ./build --parallel + # + # - name: CMake install + # run: cmake --install ./build + # + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # + # - name: Make deb and tar.xz packs with cpack + # run: | + # cd build + # cpack -G DEB -B ../pack + # cpack -G TXZ -B ../pack + # cd .. + # + # - name: Upload deb pack + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-deb + # path: pack/SlopeCraft*.deb + # if-no-files-found: error + # + # - name: Upload tar.xz pack + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-clang-tar-xz + # path: pack/SlopeCraft*.tar.xz + # if-no-files-found: error + # + # - name: Run CTest + # if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') + # run: | + # cd ./build + # ctest -j20 --output-on-failure --stop-on-failure + # - name: Test deb pack + # run: sudo dpkg -i ./pack/*.deb # linux-test-deb: # runs-on: ubunut-latest From 5f60eeaa31e590b76d16b0cd05c8c7d24baaf60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 23 Oct 2023 22:13:54 +0800 Subject: [PATCH 0572/1123] Fixed loading build cache with dithering in SC --- SlopeCraftL/TokiSlopeCraft.h | 2 +- SlopeCraftL/TokiSlopeCraft_cache.cpp | 7 +++++-- utilities/MapImageCvter/MapImageCvter.h | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index b93d23ea..0dc10491 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -446,7 +446,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { }; static std::string build_hash_filename_of( std::string_view build_dir) noexcept; - bool exmaine_build_cache(const build_options &opt, + bool examine_build_cache(const build_options &opt, std::span expected_sha3_512, build_cache_ir *ir) const noexcept; bool load_build_cache(const build_options &opt) noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 4e18938e..560ef5f9 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -325,10 +325,13 @@ void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { return; } -bool TokiSlopeCraft::exmaine_build_cache( +bool TokiSlopeCraft::examine_build_cache( const build_options &opt, std::span expected_sha3_512, build_cache_ir *ir) const noexcept { assert(this->kernelStep >= SCL_step::converted); + + // this->build_task_hash_of(this->mapPic,this->schem_block_id_list(),opt); + const std::string build_dir = build_dir_of(this->current_convert_dir(), to_short_hash(expected_sha3_512)); @@ -373,7 +376,7 @@ bool TokiSlopeCraft::load_build_cache(const build_options &opt) noexcept { build_cache_ir ir; - if (!this->exmaine_build_cache(opt, expected_hash, &ir)) { + if (!this->examine_build_cache(opt, expected_hash, &ir)) { return false; } diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 863c5db8..19dbdcb3 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -118,6 +118,7 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { assert(this->_raw_image.cols() == this->_dithered_image.cols()); ar(this->_raw_image); ar(this->algo); + ar(this->dither); // ar(this->_color_hash); ar(this->_dithered_image); // save required colorset @@ -148,6 +149,7 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { void load(archive &ar) { ar(this->_raw_image); ar(this->algo); + ar(this->dither); // ar(this->_color_hash); ar(this->_dithered_image); From 85e63bcf6ea7d8a15017442b03e42f2509630e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Mon, 23 Oct 2023 22:20:45 +0800 Subject: [PATCH 0573/1123] Fixed implementation of RGB+ with xsimd --- utilities/ColorManip/ColorDiff.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 9b265517..36f20ee7 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -211,9 +211,9 @@ void colordiff_RGBplus_batch(std::span r1p, const batch_t sumOnedDelta = OnedDeltaR + OnedDeltaG + OnedDeltaB + thre; - batch_t S_tr = OnedDeltaR / (sumOnedDelta * (S_r * S_r)); - batch_t S_tg = OnedDeltaG / (sumOnedDelta * (S_g * S_g)); - batch_t S_tb = OnedDeltaB / (sumOnedDelta * (S_b * S_b)); + batch_t S_tr = OnedDeltaR / sumOnedDelta * (S_r * S_r); + batch_t S_tg = OnedDeltaG / sumOnedDelta * (S_g * S_g); + batch_t S_tb = OnedDeltaB / sumOnedDelta * (S_b * S_b); batch_t S_theta = S_tr + S_tg + S_tb; From d23db56c84e6d3ec22e97aafea22647c74b654eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Tue, 24 Oct 2023 02:23:21 -0400 Subject: [PATCH 0574/1123] ci(macos): Run CMake Install --- .github/workflows/macos-build-arm64.yml | 6 ++++-- .github/workflows/macos-build-x64.yml | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index f107f01d..6e207bd0 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,14 +24,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build cmake --build . --parallel + - name: CMake Install + run: cmake --install . - name: CPack run: | - cd build + cd install cpack -G ZIP - name: Get short SHA diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 705252e8..50d816de 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -44,10 +44,12 @@ jobs: run: | cd build cmake --build . --parallel + - name: CMake Install + run: cmake --install . # chmod +x vccl.app/Contents/MacOS/vccl - name: CPack run: | - cd ./build + cd install cpack -G ZIP - name: Get short SHA @@ -99,10 +101,12 @@ jobs: run: | cd build cmake --build . --parallel + - name: CMake Install + run: cmake --install . # chmod +x vccl.app/Contents/MacOS/vccl - name: CPack run: | - cd ./build + cd install cpack -G ZIP - name: Get short SHA From 20f1dd97f9c2cae8d1400e5752bcae3b21c93e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 24 Oct 2023 18:04:16 +0800 Subject: [PATCH 0575/1123] [CI] fix macos CI --- .github/workflows/macos-build-arm64.yml | 8 +++++--- .github/workflows/macos-build-x64.yml | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 6e207bd0..03a854e1 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -29,12 +29,14 @@ jobs: run: | cd build cmake --build . --parallel - - name: CMake Install - run: cmake --install . - name: CPack run: | - cd install + cd build cpack -G ZIP + - name: Test installation + run: | + cd build + cmake --install . - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 50d816de..d4b55231 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -44,13 +44,15 @@ jobs: run: | cd build cmake --build . --parallel - - name: CMake Install - run: cmake --install . - # chmod +x vccl.app/Contents/MacOS/vccl - name: CPack run: | - cd install + cd build cpack -G ZIP + - name: Test installation + run: | + cd build + cmake --install . + # chmod +x vccl.app/Contents/MacOS/vccl - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV @@ -101,14 +103,15 @@ jobs: run: | cd build cmake --build . --parallel - - name: CMake Install - run: cmake --install . - # chmod +x vccl.app/Contents/MacOS/vccl - name: CPack run: | - cd install + cd build cpack -G ZIP + - name: Test installation + run: cmake --install . + # chmod +x vccl.app/Contents/MacOS/vccl + - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts From 79c3a50b919d96f30e20f9b00caf08cbab4a80c2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 24 Oct 2023 22:21:35 +0800 Subject: [PATCH 0576/1123] restore qt deployment for macos --- MapViewer/install.cmake | 17 ++++------------- SlopeCraft/install.cmake | 4 ++++ VisualCraft/install.cmake | 20 ++------------------ imageCutter/install.cmake | 3 +++ vccl/deploy_qt_for_vccl_macos.cmake.in | 12 ++++++------ 5 files changed, 19 insertions(+), 37 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 761d1684..13dd5e6a 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -18,19 +18,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") BUILD_MODE INSTALL_MODE INSTALL_DESTINATION .) - # # Run windeployqt at build time - # add_custom_target(Windeployqt-MapViewer - # COMMAND ${SlopeCraft_Qt_windeployqt_executable} MapViewer.exe ${SlopeCraft_windeployqt_flags_build} - # COMMAND_EXPAND_LISTS - # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # DEPENDS MapViewer) - # add_dependencies(SC_deploy_all Windeployqt-MapViewer) - # - # # Run windeployqt at install time - # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - # - # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) - return() endif () @@ -57,6 +44,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") file(GLOB MapViewer_Icon ${CMAKE_SOURCE_DIR}/MapViewer/others/MapViewer.icns) install(FILES ${MapViewer_Icon} DESTINATION MapViewer.app/Contents/Resources) + + QD_add_deployqt(MapViewer + INSTALL_MODE INSTALL_DESTINATION .) + return() endif () diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index afffaf37..fa44fbac 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -55,6 +55,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/Presets) file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) + + QD_add_deployqt(SlopeCraft + INSTALL_MODE INSTALL_DESTINATION .) + return() endif () diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index d9fc8e1b..a3d1e9b5 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -1,8 +1,5 @@ set(AppName VisualCraft) -#configure_file(${CMAKE_SOURCE_DIR}/cmake/deploy_qt.cmake.in -# ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake -# @ONLY) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft @@ -23,16 +20,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") INSTALL_MODE INSTALL_DESTINATION . IGNORE VisualCraftL.dll libVisualCraftL.dll) - # # Run windeployqt at build time - # add_custom_target(Windeployqt-VisualCraft - # COMMAND ${SlopeCraft_Qt_windeployqt_executable} VisualCraft.exe ${SlopeCraft_windeployqt_flags_build} - # COMMAND_EXPAND_LISTS - # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # DEPENDS VisualCraft) - # add_dependencies(SC_deploy_all Windeployqt-VisualCraft) - # - # # Run windeployqt at install time - # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) return() endif () @@ -70,11 +57,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL ) - #QD_add_deployqt(VisualCraft - # INSTALL_MODE INSTALL_DESTINATION .) - - # Run macdeployqt at install time - #install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) + QD_add_deployqt(VisualCraft + INSTALL_MODE INSTALL_DESTINATION .) return() endif () \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 88c323dd..7d137318 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -56,6 +56,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${imageCutter_Icon} DESTINATION imageCutter.app/Contents/Resources) + QD_add_deployqt(imageCutter + INSTALL_MODE INSTALL_DESTINATION .) + return() endif () diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 4d709085..2d8fc87b 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -11,12 +11,12 @@ if(install_mode) return() endif() -#message(STATUS "Running macdeployqt for @AppName@ ...") -#execute_process( -# COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" -# WORKING_DIRECTORY "@vccl_prefix@" -# OUTPUT_QUIET -# COMMAND_ERROR_IS_FATAL ANY) +message(STATUS "Running macdeployqt for @AppName@ ...") +execute_process( + COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" + WORKING_DIRECTORY "@vccl_prefix@" + OUTPUT_QUIET + COMMAND_ERROR_IS_FATAL ANY) # message(WARNING "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") From 2fb7f9c25d7c914bb3f41d21f0fc4784880f8f66 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 24 Oct 2023 22:23:52 +0800 Subject: [PATCH 0577/1123] [CI] fix macos-x64-clang build --- .github/workflows/macos-build-x64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index d4b55231..07bd9f4a 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -109,7 +109,9 @@ jobs: cpack -G ZIP - name: Test installation - run: cmake --install . + run: | + cd build + cmake --install . # chmod +x vccl.app/Contents/MacOS/vccl - name: Get short SHA From 5b57ef8dd833f57c2a873736ac55cef1493976f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Tue, 24 Oct 2023 11:02:08 -0400 Subject: [PATCH 0578/1123] ci(macos-build-arm64) --- .github/workflows/macos-build-arm64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 03a854e1..27d16cdb 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build @@ -101,4 +101,4 @@ jobs: # uses: actions/upload-artifact@v3 # with: # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang - # path: build/install/SlopeCraft*.zip \ No newline at end of file + # path: build/install/SlopeCraft*.zip From c574c402b8d6fe3ef8679cd52844d94050426d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Tue, 24 Oct 2023 23:14:22 +0800 Subject: [PATCH 0579/1123] remove Qt depolyment for macos --- MapViewer/install.cmake | 10 +++++----- SlopeCraft/install.cmake | 10 +++++----- VisualCraft/install.cmake | 10 +++++----- imageCutter/install.cmake | 10 +++++----- vccl/deploy_qt_for_vccl_macos.cmake.in | 16 ++++++++-------- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 13dd5e6a..7f1f5f78 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -6,7 +6,7 @@ set(AppName MapViewer) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS MapViewer RUNTIME DESTINATION . - ) + ) QD_add_deployqt(MapViewer BUILD_MODE @@ -26,7 +26,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS MapViewer RUNTIME DESTINATION bin BUNDLE DESTINATION lib - ) + ) # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) @@ -37,7 +37,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS MapViewer RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icon for macOS # MapViewer.app @@ -45,8 +45,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${MapViewer_Icon} DESTINATION MapViewer.app/Contents/Resources) - QD_add_deployqt(MapViewer - INSTALL_MODE INSTALL_DESTINATION .) + # QD_add_deployqt(MapViewer + # INSTALL_MODE INSTALL_DESTINATION .) return() endif () diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index fa44fbac..d2692095 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -23,7 +23,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS SlopeCraft RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icons set(SlopeCraft_Icon @@ -56,8 +56,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) - QD_add_deployqt(SlopeCraft - INSTALL_MODE INSTALL_DESTINATION .) + # QD_add_deployqt(SlopeCraft + # INSTALL_MODE INSTALL_DESTINATION .) return() endif () @@ -66,7 +66,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") # Install app install(TARGETS SlopeCraft RUNTIME DESTINATION . - ) + ) # # Run windeployqt at build time # add_custom_target(Windeployqt-SlopeCraft @@ -123,7 +123,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") # Install app install(TARGETS SlopeCraft RUNTIME DESTINATION bin - ) + ) # Install FixedBlocks.json, CustomBlocks.json and README.md install(FILES ${SlopeCraft_install_jsons} diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index a3d1e9b5..8662d95a 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -4,7 +4,7 @@ set(AppName VisualCraft) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft RUNTIME DESTINATION . - ) + ) install(FILES vc-config.json DESTINATION .) @@ -26,7 +26,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS VisualCraft RUNTIME DESTINATION bin - ) + ) install(FILES vc-config.json DESTINATION bin) @@ -56,9 +56,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install zips. In vccl-config.json or vc-config.json, they are referred like ./Blocks_VCL/Vanilla_1_19_3.zip install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL - ) - QD_add_deployqt(VisualCraft - INSTALL_MODE INSTALL_DESTINATION .) + ) + # QD_add_deployqt(VisualCraft + # INSTALL_MODE INSTALL_DESTINATION .) return() endif () \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 7d137318..78babad9 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -6,7 +6,7 @@ set(AppName imageCutter) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS imageCutter RUNTIME DESTINATION . - ) + ) QD_add_deployqt(imageCutter BUILD_MODE @@ -37,7 +37,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS imageCutter RUNTIME DESTINATION bin BUNDLE DESTINATION lib - ) + ) # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) @@ -48,7 +48,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS imageCutter RUNTIME DESTINATION . BUNDLE DESTINATION . - ) + ) # Install icon for macOS file(GLOB imageCutter_Icon @@ -56,8 +56,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${imageCutter_Icon} DESTINATION imageCutter.app/Contents/Resources) - QD_add_deployqt(imageCutter - INSTALL_MODE INSTALL_DESTINATION .) + # QD_add_deployqt(imageCutter + # INSTALL_MODE INSTALL_DESTINATION .) return() endif () diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 2d8fc87b..602aaad7 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -3,20 +3,20 @@ set(this_script_file @deployqt_vccl_script@) option(install_mode "" ON) -if(install_mode) +if (install_mode) execute_process(COMMAND ${CMAKE_COMMAND} -Dinstall_mode:BOOL=false -P ${this_script_file} WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX} COMMAND_ERROR_IS_FATAL ANY ) return() -endif() +endif () -message(STATUS "Running macdeployqt for @AppName@ ...") -execute_process( - COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" - WORKING_DIRECTORY "@vccl_prefix@" - OUTPUT_QUIET - COMMAND_ERROR_IS_FATAL ANY) +#message(STATUS "Running macdeployqt for @AppName@ ...") +#execute_process( +# COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" +# WORKING_DIRECTORY "@vccl_prefix@" +# OUTPUT_QUIET +# COMMAND_ERROR_IS_FATAL ANY) # message(WARNING "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") From 3644ba87d14107716beee5618507cbc73ddde0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Tue, 24 Oct 2023 11:46:27 -0400 Subject: [PATCH 0580/1123] feat: Add user used install script for macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] Signed-off-by: Qian Qian "Cubik"‎ --- SlopeCraft-install-macOS.zsh | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 SlopeCraft-install-macOS.zsh diff --git a/SlopeCraft-install-macOS.zsh b/SlopeCraft-install-macOS.zsh new file mode 100755 index 00000000..3f21631b --- /dev/null +++ b/SlopeCraft-install-macOS.zsh @@ -0,0 +1,55 @@ +#!/usr/bin/env zsh + +if [[ $OSTYPE != darwin* ]]; then + echo "This script can ONLY be used on macOS!" + exit 1 +fi + +# Check if Homebrew is installed +which -s brew + +if [[ $? != 0 ]] ; then + # Install Homebrew + echo "Installing Homebrew" + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +else + echo "Updating Homebrew" + brew update +fi + +echo "Installing dependencies" +brew install git +brew install llvm + +if [[ $CPUTYPE == arm64 ]]; then + echo "Configuring LLVM Clang for Apple Silicon Macs" + alias clang=/opt/homebrew/opt/llvm/bin/clang + alias clang++=/opt/homebrew/opt/llvm/bin/clang++ +else + echo "Configuring LLVM Clang for Intel Macs" + alias clang=/usr/local/opt/llvm/bin/clang + alias clang++=/usr/local/opt/llvm/bin/clang++ +fi + +brew install cmake ninja +brew install qt +brew install zlib libpng libzip xsimd + +echo "Cloning git repo" +cd ~ +git clone https://github.com/SlopeCraft/SlopeCraft.git && cd SlopeCraft + +echo "Configuring CMake... This step might take a while." +cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DCMAKE_BUILD_TYPE=Release + +echo "Building... This step might take a while." +cd build +cmake --build . --parallel + +echo "Installing and Deploying" +cmake --install . +cd install +macdeployqt *.app + +echo "Get your app files at $(pwd)!" + From 774db11ec89a4b894c5157387a1562f2a25c9f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=AB?= Date: Sat, 4 Nov 2023 16:15:24 +0800 Subject: [PATCH 0581/1123] introduce kompute Signed-off-by: ToKiNoBug --- cmake/configure_fmtlib.cmake | 4 ++-- cmake/configure_kompute.cmake | 16 ++++++++++++++ utilities/GPUWrapper/Vulkan/CMakeLists.txt | 25 +++++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 cmake/configure_kompute.cmake diff --git a/cmake/configure_fmtlib.cmake b/cmake/configure_fmtlib.cmake index f989424c..8fc820d5 100644 --- a/cmake/configure_fmtlib.cmake +++ b/cmake/configure_fmtlib.cmake @@ -11,7 +11,7 @@ if (NOT ${fmt_FOUND}) FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG "9.1.0" + GIT_TAG "10.1.1" OVERRIDE_FIND_PACKAGE # QUIET false @@ -19,7 +19,7 @@ if (NOT ${fmt_FOUND}) # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args ) - message(STATUS "Downaloding and building fmtlib......") + message(STATUS "Downaloding......") FetchContent_MakeAvailable(fmt) find_package(fmt REQUIRED) diff --git a/cmake/configure_kompute.cmake b/cmake/configure_kompute.cmake new file mode 100644 index 00000000..33cd72d0 --- /dev/null +++ b/cmake/configure_kompute.cmake @@ -0,0 +1,16 @@ +include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) + +find_package(Vulkan REQUIRED) + +set(KOMPUTE_OPT_USE_BUILT_IN_FMT OFF) +set(KOMPUTE_OPT_USE_BUILT_IN_GOOGLE_TEST OFF) +set(KOMPUTE_OPT_USE_BUILT_IN_VULKAN_HEADER OFF) +FetchContent_Declare(kompute + GIT_REPOSITORY https://github.com/SlopeCraft/kompute + GIT_TAG 72459d97a9ddbe3651d8449b2f8476151a7cb25d + OVERRIDE_FIND_PACKAGE) + +message(STATUS "Downaloding SlopeCraft/kompute......") +FetchContent_MakeAvailable(kompute) + +find_package(kompute REQUIRED) \ No newline at end of file diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index 7c2a27a7..5b1772fe 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -1 +1,24 @@ -find_package(Vulkan REQUIRED) \ No newline at end of file +find_package(Vulkan + COMPONENTS glslc + REQUIRED) + +include(${CMAKE_SOURCE_DIR}/cmake/configure_kompute.cmake) +find_package(kompute REQUIRED) + +target_sources(GPUInterface PRIVATE GPU_interface.cpp) +target_link_libraries(GPUInterface PUBLIC + Vulkan::Vulkan + kompute::kompute) +target_compile_features(GPUInterface PRIVATE cxx_std_20) + +get_target_property(glslc_exe Vulkan::glslc LOCATION) +message(STATUS "glslc found at ${glslc_exe}") + +set(shader_filename "${CMAKE_CURRENT_BINARY_DIR}/compute.spv") +add_custom_target(GPUInterface_shader ALL + COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${shader_filename} + SOURCES compute.glsl + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + BYPRODUCTS ${shader_filename} + COMMENT "Building compute shader ${shader_filename}") +add_dependencies(GPUInterface GPUInterface_shader) \ No newline at end of file From fd87709a98db5eca856c7c117bce2e6e3dbbb473 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 4 Nov 2023 16:16:23 +0800 Subject: [PATCH 0582/1123] write compute shader Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/compute.glsl | 337 +++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 utilities/GPUWrapper/Vulkan/compute.glsl diff --git a/utilities/GPUWrapper/Vulkan/compute.glsl b/utilities/GPUWrapper/Vulkan/compute.glsl new file mode 100644 index 00000000..15bd6853 --- /dev/null +++ b/utilities/GPUWrapper/Vulkan/compute.glsl @@ -0,0 +1,337 @@ +#version 450 +#extension GL_EXT_shader_8bit_storage: enable +#extension GL_EXT_shader_16bit_storage: enable + +#extension GL_EXT_debug_printf: enable + +#define NAN float(0.0f / 0.0f) +#define pi_fp32 float(radians(180)) + +//struct task_info { +// uint task_num; +// uint colorset_size; +// //uint16_t algo; +//}; + +const uint ALGO_RGB = 114; +const uint ALGO_RGB_BETTER = 82; +const uint ALGO_HSV = 72; +const uint ALGO_LAB94 = 108; +const uint ALGO_LAB00 = 76; +const uint ALGO_XYZ = 88; + +const bool SC_OCL_SPOT_NAN = true; + +layout (binding = 0) readonly buffer bufOpt { + uint task_num; + uint colorset_size; + uint8_t algo; +} option; +layout (binding = 1) readonly buffer bufCC { + float colorset_colors[]; +}; +layout (binding = 2) readonly buffer bufUC { + float unconverted_colors[]; +}; +layout (binding = 3) writeonly buffer bufRID { + uint16_t result_idx_dst[]; +}; +layout (binding = 4) writeonly buffer bufRDD { + float result_diff_dst[]; +}; + + +bool have_nan(vec3 v) { + bool ret = false; + for (uint i = 0; i < 3; i++) { + ret = ret || isnan(v[i]); + } + return ret; +} + +float norm2(vec3 v) { return dot(v, v); } +float sum3(vec3 v) { return v[0] + v[1] + v[2]; } +float square(float s) { return s * s; } +vec3 square_vec3(vec3 v) { return v * v; } + + + +float color_diff_RGB_XYZ(vec3 RGB1, vec3 RGB2); +float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2); +float color_diff_HSV(vec3 hsv1_vec3, vec3 hsv2_vec3); +float color_diff_Lab94(vec3 lab1_vec3, vec3 lab2_vec3); +float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3); + +void compute(const uint global_idx); + +void main() { + + const uint global_idx = gl_GlobalInvocationID.x; + compute(global_idx); +} + + +void compute(const uint global_idx) { + const vec3 unconverted = { unconverted_colors[global_idx * 3 + 0], + unconverted_colors[global_idx * 3 + 1], + unconverted_colors[global_idx * 3 + 2] }; + + + uint result_idx = 65535 - 1; + float result_diff = 1e30 / 2; + + for (uint idx = 0; idx < option.colorset_size; idx++) { + const vec3 color_ava = { colorset_colors[idx * 3 + 0], + colorset_colors[idx * 3 + 1], + colorset_colors[idx * 3 + 2] }; + if (true && have_nan(color_ava)) { + debugPrintfEXT( + "Nan spotted at color_ava. color_ava = {%f,%f,%f}, get_global_id = %u.n", + color_ava[0], color_ava[1], color_ava[2], + uint(global_idx)); + return; + } + + float diff_sq = 0; + + /* + +float color_diff_RGB_XYZ(vec3 RGB1, vec3 RGB2); +float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2); +float color_diff_HSV(vec3 hsv1_vec3, vec3 hsv2_vec3); +float color_diff_Lab94(vec3 lab1_vec3, vec3 lab2_vec3); +float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3); +*/ + switch (uint(option.algo)) { + case ALGO_RGB_BETTER: + diff_sq = color_diff_RGB_Better(color_ava, unconverted); + break; + case ALGO_HSV: + diff_sq = color_diff_HSV(color_ava, unconverted); + break; + case ALGO_LAB94: + diff_sq = color_diff_Lab94(color_ava, unconverted); + break; + case ALGO_LAB00: + diff_sq = color_diff_Lab00(color_ava, unconverted); + break; + default: + diff_sq = color_diff_RGB_XYZ(color_ava, unconverted); + + } + if (true && isnan(diff_sq)) { + debugPrintfEXT("Spotted nan at idx = %u.n", (idx)); + return; + } + if (result_diff > diff_sq) { + /* this branch may be optimized */ + result_idx = idx; + result_diff = diff_sq; + } + } + + result_idx_dst[global_idx] = uint16_t(result_idx); + result_diff_dst[global_idx] = result_diff; + +} + +float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2) { + const float w_r = 1.0f, w_g = 2.0f, w_b = 1.0f; + const vec3 w_vec3 = { w_r, w_g, w_b }; + const float thre = 1e-4f; + const vec3 one_vec3 = { 1, 1, 1 }; + + const float SqrModSquare = norm2(rgb1) * norm2(rgb2); + + const vec3 delta_rgb_vec3 = rgb1 - rgb2; + + const float SigmaRGB = (sum3(rgb1) + sum3(rgb2)) / 3.0f; + const vec3 S_rgb_vec3 = min((rgb1 + rgb2) / (SigmaRGB + thre), one_vec3); + + if (SC_OCL_SPOT_NAN && have_nan(S_rgb_vec3)) { + debugPrintfEXT("S_rgb_vec3 contains nan.\n"); + return NAN; + } + + const float sumRGBSquare = dot(rgb1, rgb2); + + const float theta = 2.0f / pi_fp32 * + acos((sumRGBSquare / sqrt(SqrModSquare + thre)) / 1.01f); + + if (SC_OCL_SPOT_NAN && isnan(theta)) { + debugPrintfEXT("theta is nan. sumRGBSquare = %f, SqrModSquare = %f.\n", + sumRGBSquare, SqrModSquare); + return NAN; + } + + const vec3 OnedDelta_rgb_vec3 = abs(delta_rgb_vec3) / (rgb1 + rgb2 + thre); + + const float sumOnedDelta = sum3(OnedDelta_rgb_vec3) + thre; + + const vec3 S_t_rgb_vec3 = + OnedDelta_rgb_vec3 / sumOnedDelta * S_rgb_vec3 * S_rgb_vec3; + + if (SC_OCL_SPOT_NAN && have_nan(S_t_rgb_vec3)) { + debugPrintfEXT("S_t_rgb_vec3 contains nan.\n"); + return NAN; + } + + const float S_theta = sum3(S_t_rgb_vec3); + + const vec3 rgb_max_vec3 = max(rgb1, rgb2); + const float S_ratio = + max(rgb_max_vec3[0], max(rgb_max_vec3[1], rgb_max_vec3[2])); + + const vec3 SS_w_delta_delta_vec3 = + S_rgb_vec3 * S_rgb_vec3 * delta_rgb_vec3 * delta_rgb_vec3 * w_vec3; + + const float part1 = sum3(SS_w_delta_delta_vec3) / sum3(w_vec3); + if (SC_OCL_SPOT_NAN && isnan(part1)) { + debugPrintfEXT("part1 is nan.\n"); + return NAN; + } + + const float part2 = S_theta * S_ratio * theta * theta; + if (SC_OCL_SPOT_NAN && isnan(part2)) { + debugPrintfEXT("part2 is nan.\n"); + return NAN; + } + + return part1 + part2; +} + +float color_diff_RGB_XYZ(vec3 RGB1, vec3 RGB2) { + return norm2(RGB1 - RGB2); +} + +float color_diff_HSV(vec3 hsv1_vec3, vec3 hsv2_vec3) { + const float h1 = hsv1_vec3[0]; + const float s1 = hsv1_vec3[1]; + const float v1 = hsv1_vec3[2]; + + const float h2 = hsv2_vec3[0]; + const float s2 = hsv2_vec3[1]; + const float v2 = hsv2_vec3[2]; + + const float sv_1 = s1 * v1; + const float sv_2 = s2 * v2; + + const float dX = 50.0f * (cos(h1) * sv_1 - cos(h2) * sv_2); + const float dY = 50.0f * (sin(h1) * sv_1 - sin(h2) * sv_2); + const float dZ = 50.0f * (v1 - v2); + + return dX * dX + dY * dY + dZ * dZ; +} + +float color_diff_Lab94(vec3 lab1_vec3, vec3 lab2_vec3) { + const float L1 = lab1_vec3[0]; + const float a1 = lab1_vec3[1]; + const float b1 = lab1_vec3[2]; + + const float L2 = lab2_vec3[0]; + const float a2 = lab2_vec3[1]; + const float b2 = lab2_vec3[2]; + + const float deltaL_2 = square(L1 - L2); + const float C1_2 = a1 * a1 + b1 * b1; + const float C2_2 = a2 * a2 + b2 * b2; + + const float deltaCab_2 = square(sqrt(C1_2) - sqrt(C2_2)); + const float deltaHab_2 = square(a2 - a1) + square(b2 - b1) - deltaCab_2; + + const float SC_2 = square(sqrt(C1_2) * 0.045f + 1.0f); + const float SH_2 = square(sqrt(C2_2) * 0.015f + 1.0f); + + const float result = deltaL_2 + deltaCab_2 / SC_2 + deltaHab_2 / SH_2; + return result; +} + +float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3) { + const float kL = 1.0f; + const float kC = 1.0f; + const float kH = 1.0f; + const float L1 = lab1_vec3[0]; + const float a1 = lab1_vec3[1]; + const float b1 = lab1_vec3[2]; + + const float L2 = lab2_vec3[0]; + const float a2 = lab2_vec3[1]; + const float b2 = lab2_vec3[2]; + + float C1sab = sqrt(a1 * a1 + b1 * b1); + float C2sab = sqrt(a2 * a2 + b2 * b2); + float mCsab = (C1sab + C2sab) / 2; + float pow_mCsab_7 = pow(mCsab, 7); + float G = 0.5 * (1 - sqrt(pow_mCsab_7 / (pow_mCsab_7 + pow(25.0f, 7.0f)))); + float a1p = (1 + G) * a1; + float a2p = (1 + G) * a2; + float C1p = sqrt(a1p * a1p + b1 * b1); + float C2p = sqrt(a2p * a2p + b2 * b2); + float h1p, h2p; + if (b1 == 0 && a1p == 0) + h1p = 0; + else + h1p = atan(b1, a1p); + + if (h1p < 0) h1p += 2 * pi_fp32; + + if (b2 == 0 && a2p == 0) + h2p = 0; + else + h2p = atan(b2, a2p); + + if (h2p < 0) h2p += 2 * pi_fp32; + + float dLp = L2 - L1; + float dCp = C2p - C1p; + float dhp; + if (C1p * C2p == 0) { + dhp = 0; + } else { + if (abs(h2p - h1p) <= radians(180.0f)) { + dhp = h2p - h1p; + } else if (h2p - h1p > radians(180.0f)) { + dhp = h2p - h1p - radians(360.0f); + } else { + dhp = h2p - h1p + radians(360.0f); + } + } + + float dHp = 2 * sqrt(C1p * C2p) * sin(dhp / 2.0); + + float mLp = (L1 + L2) / 2; + float mCp = (C1p + C2p) / 2; + float mhp; + if (C1p * C2p == 0) { + mhp = (h1p + h2p); + } else if (abs(h2p - h1p) <= radians(180.0f)) { + mhp = (h1p + h2p) / 2; + } else if (h1p + h2p < radians(360.0f)) { + mhp = (h1p + h2p + radians(360.0f)) / 2; + } else { + mhp = (h1p + h2p - radians(360.0f)) / 2; + } + + float T = 1 - 0.17f * cos(mhp - radians(30.0f)) + 0.24f * cos(2 * mhp) + + 0.32f * cos(3 * mhp + radians(6.0f)) - + 0.20f * cos(4 * mhp - radians(63.0f)); + + float dTheta = + radians(30.0f) * exp(-square((mhp - radians(275.0f)) / radians(25.0f))); + + float RC = 2 * sqrt(pow(mCp, 7) / (pow(25.0f, 7.0f) + pow(mCp, 7.0f))); + float square_mLp_minus_50 = square(mLp - 50); + float SL = 1 + 0.015f * square_mLp_minus_50 / sqrt(20 + square_mLp_minus_50); + + float SC = 1 + 0.045f * mCp; + + float SH = 1 + 0.015f * mCp * T; + + float RT = -RC * sin(2 * dTheta); + + float Diffsquare = square(dLp / SL / kL) + square(dCp / SC / kC) + + square(dHp / SH / kH) + + RT * (dCp / SC / kC) * (dHp / SH / kH); + + return Diffsquare; +} From 3a0806785ecd29473692f9264231a4882ac5bf67 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 5 Nov 2023 14:03:40 +0800 Subject: [PATCH 0583/1123] implement gpu boosting (draft) with vulkan Signed-off-by: ToKiNoBug --- cmake/configure_kompute.cmake | 2 +- cmake/select_vectorize_flag.cmake | 2 +- utilities/GPUWrapper/Vulkan/CMakeLists.txt | 32 +- utilities/GPUWrapper/Vulkan/GPU_interface.cpp | 321 ++++++++++++++++++ utilities/GPUWrapper/Vulkan/compute.glsl | 55 +-- 5 files changed, 379 insertions(+), 33 deletions(-) create mode 100644 utilities/GPUWrapper/Vulkan/GPU_interface.cpp diff --git a/cmake/configure_kompute.cmake b/cmake/configure_kompute.cmake index 33cd72d0..714ffb04 100644 --- a/cmake/configure_kompute.cmake +++ b/cmake/configure_kompute.cmake @@ -7,7 +7,7 @@ set(KOMPUTE_OPT_USE_BUILT_IN_GOOGLE_TEST OFF) set(KOMPUTE_OPT_USE_BUILT_IN_VULKAN_HEADER OFF) FetchContent_Declare(kompute GIT_REPOSITORY https://github.com/SlopeCraft/kompute - GIT_TAG 72459d97a9ddbe3651d8449b2f8476151a7cb25d + GIT_TAG customize OVERRIDE_FIND_PACKAGE) message(STATUS "Downaloding SlopeCraft/kompute......") diff --git a/cmake/select_vectorize_flag.cmake b/cmake/select_vectorize_flag.cmake index fdf90ced..67d7e99d 100644 --- a/cmake/select_vectorize_flag.cmake +++ b/cmake/select_vectorize_flag.cmake @@ -4,7 +4,7 @@ include(CheckCXXCompilerFlag) message(STATUS "System processor arch = ${CMAKE_SYSTEM_PROCESSOR}") -if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") +if ((${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") OR (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")) if (${MSVC}) set(SlopeCraft_vectorize_flags "/arch:AVX2") else () diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index 5b1772fe..31d5c4ab 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -1,6 +1,11 @@ +include(${CMAKE_SOURCE_DIR}/cmake/find_ResourceCreator.cmake) +include(${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/ResourceCreator.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) + find_package(Vulkan COMPONENTS glslc REQUIRED) +find_package(Eigen3 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_kompute.cmake) find_package(kompute REQUIRED) @@ -8,17 +13,32 @@ find_package(kompute REQUIRED) target_sources(GPUInterface PRIVATE GPU_interface.cpp) target_link_libraries(GPUInterface PUBLIC Vulkan::Vulkan - kompute::kompute) + kompute::kompute + Eigen3::Eigen) target_compile_features(GPUInterface PRIVATE cxx_std_20) get_target_property(glslc_exe Vulkan::glslc LOCATION) message(STATUS "glslc found at ${glslc_exe}") set(shader_filename "${CMAKE_CURRENT_BINARY_DIR}/compute.spv") -add_custom_target(GPUInterface_shader ALL - COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${shader_filename} + +message(STATUS "Building compute shader to spirv...") +execute_process(COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${shader_filename} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + + COMMAND_ERROR_IS_FATAL ANY) + +add_resource_config_time(VkComputeShaderSPIRV_rc ${shader_filename}) +target_link_libraries(GPUInterface PRIVATE VkComputeShaderSPIRV_rc) + +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) +endif () + +set(shader_test_filename "${CMAKE_CURRENT_BINARY_DIR}/compute_test.spv") +add_custom_target(GPUInterface_shader_test ALL + COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${shader_test_filename} SOURCES compute.glsl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - BYPRODUCTS ${shader_filename} - COMMENT "Building compute shader ${shader_filename}") -add_dependencies(GPUInterface GPUInterface_shader) \ No newline at end of file + BYPRODUCTS ${shader_test_filename} + COMMENT "Building compute shader ${shader_test_filename}") \ No newline at end of file diff --git a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp new file mode 100644 index 00000000..18696498 --- /dev/null +++ b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp @@ -0,0 +1,321 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GPUWrapper/GPU_interface.h" + +extern "C" { +extern const unsigned char VkComputeShaderSPIRV_rc[]; +extern const unsigned int VkComputeShaderSPIRV_rc_length; +} + +namespace gpu_wrapper { + +constexpr uint32_t ceil_up_to(uint32_t num, uint32_t align) noexcept { + if (num % align == 0) { + return num; + } + + return (num / align + 1) * align; +} + +std::vector get_spirv() noexcept { + assert(VkComputeShaderSPIRV_rc_length % 4 == 0); + auto data = reinterpret_cast(VkComputeShaderSPIRV_rc); + + return std::vector{ + data, data + size_t(VkComputeShaderSPIRV_rc_length / 4)}; +} + +enum class vkerr : int { create_device_failure, create_instance_failure }; + +std::shared_ptr get_vk_instance() noexcept { + static std::mutex lock; + static std::shared_ptr instance{nullptr}; + + std::unique_lock lkgd{lock}; + if (instance == nullptr) { + vk::ApplicationInfo app_info{"VisualCraftL", VK_MAKE_VERSION(5, 0, 0), + "NoEngine", VK_MAKE_VERSION(1, 0, 0), + VK_API_VERSION_1_3}; + auto instance_r = vk::createInstance(vk::InstanceCreateInfo{{}, &app_info}); + instance = std::make_shared(instance_r); + assert(instance != nullptr); + } + return instance; +} + +const char* api_name() noexcept { return "Vulkan"; } + +size_t platform_num() noexcept { return 1; } + +class platform_impl : public platform_wrapper { + public: + platform_impl() : instance{get_vk_instance()} {} + std::shared_ptr instance; + + const char* name_v() const noexcept final { return "Vulkan"; } + size_t num_devices_v() const noexcept final { + return this->instance->enumeratePhysicalDevices().size(); + } +}; + +platform_wrapper* platform_wrapper::create(size_t idx, + int* errorcode) noexcept { + return new platform_impl; +} + +void platform_wrapper::destroy(gpu_wrapper::platform_wrapper* p) noexcept { + delete p; +} + +class device_impl : public device_wrapper { + public: + uint32_t device_index; + // std::shared_ptr phy_device; + vk::PhysicalDeviceProperties properties; + // std::shared_ptr device; + uint32_t selected_queue_family_index{}; + const char* name_v() const noexcept final { + return this->properties.deviceName; + } +}; + +std::optional select_queue_family( + std::span queue_family_props) noexcept { + std::vector indices; + indices.reserve(queue_family_props.size()); + + // for (auto [idx, family] : stdrange::enumerate_view{queue_family_props}) + for (size_t idx = 0; idx < queue_family_props.size(); idx++) { + auto& family = queue_family_props[idx]; + auto flags = family.queueFlags; + if (flags & vk::QueueFlagBits::eCompute) { + indices.emplace_back(idx); + } + } + if (indices.empty()) return std::nullopt; + + std::sort(indices.begin(), indices.end(), + [queue_family_props](uint32_t i, uint32_t j) -> bool { + const auto& a = queue_family_props[i]; + const auto& b = queue_family_props[j]; + if (a.queueFlags == b.queueFlags) { + return a.queueCount > b.queueCount; + } + const auto compute_required_flags = + vk::QueueFlagBits::eCompute | vk::QueueFlagBits::eTransfer; + const int a_compute = bool(a.queueFlags & compute_required_flags); + const int b_compute = bool(b.queueFlags & compute_required_flags); + + if (a_compute != b_compute) { + if (a_compute) + return true; + else + return false; + } + + assert(a_compute + b_compute == 2); + + const int a_graphics = + bool(a.queueFlags & vk::QueueFlagBits::eGraphics); + const int b_graphics = + bool(b.queueFlags & vk::QueueFlagBits::eGraphics); + + if (a_graphics != b_graphics) { + if (a_graphics) + return false; + else + return true; + } + + return a.queueCount > b.queueCount; + }); + + return indices.front(); +} + +device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, + size_t idx, int* errorcode) noexcept { + auto& plat = dynamic_cast(*pw); + auto deivces = plat.instance->enumeratePhysicalDevices(); + + auto result = new device_impl; + result->device_index = idx; + auto phy_device = deivces[idx]; + result->properties = phy_device.getProperties(); + { + auto qf_props = phy_device.getQueueFamilyProperties(); + + auto sqfi_opt = select_queue_family(qf_props); + if (!sqfi_opt) { + return nullptr; + } + result->selected_queue_family_index = sqfi_opt.value(); + } + + return result; +} + +void device_wrapper::destroy(gpu_wrapper::device_wrapper* dw) noexcept { + delete dw; +} + +struct task_option { + uint32_t task_num; + uint32_t color_count; + uint8_t algo; +}; + +class gpu_impl : public gpu_interface { + private: + kp::Manager manager; + + // Its size won't be changed + std::shared_ptr> compute_option; + // Their sizes may be changed + std::shared_ptr> colorset; + // std::vector colorset_host; + std::shared_ptr> tasks; + // std::vector tasks_host; + std::shared_ptr> result_idx; + // std::vector result_idx_host; + std::shared_ptr> result_diff; + // std::vector result_diff_host; + + std::shared_ptr algorithm; + + size_t task_count{UINT64_MAX}; + uint16_t color_count{UINT16_MAX}; + + template + void resize_tensor_size(std::shared_ptr> tensor, + size_t required_size) noexcept { + const size_t cur_size = tensor->size(); + if (cur_size >= required_size) { + return; + } + + tensor->rebuild(nullptr, required_size, sizeof(T)); + } + + public: + gpu_impl(uint32_t phy_device_idx, uint32_t selected_queue_index) + : manager{phy_device_idx, + {}, + {VK_KHR_8BIT_STORAGE_EXTENSION_NAME, + VK_KHR_16BIT_STORAGE_EXTENSION_NAME}} { + this->compute_option = this->manager.tensorT({task_option{}}); + + this->colorset = + this->manager.tensorT({0}, kp::Tensor::TensorTypes::eDevice); + this->tasks = + this->manager.tensorT({0}, kp::Tensor::TensorTypes::eDevice); + this->result_diff = + this->manager.tensorT({0}, kp::Tensor::TensorTypes::eDevice); + this->result_idx = + this->manager.tensorT({0}, kp::Tensor::TensorTypes::eDevice); + + this->algorithm = this->manager.algorithm( + {this->compute_option, this->colorset, this->tasks, this->result_diff, + this->result_idx}, + get_spirv(), {64, 1, 1}); + } + + const char* api_v() const noexcept final { return "Vulkan"; } + + void set_colorset_v( + size_t color_num, + const std::array& color_ptrs) noexcept final { + this->color_count = color_num; + this->resize_tensor_size(this->colorset, 3 * color_num); + // this->colorset_host.resize(3 * color_num); + + Eigen::Map< + Eigen::Array> + trans{this->colorset->data(), static_cast(color_num), 3}; + + for (size_t c = 0; c < 3; c++) { + for (size_t r = 0; r < color_num; r++) { + trans(r, c) = color_ptrs[c][r]; + } + } + } + + void set_task_v(size_t task_num, + const std::array* data) noexcept final { + this->task_count = task_num; + this->resize_tensor_size(this->tasks, task_num * 3); + this->resize_tensor_size(this->result_idx, task_num); + this->resize_tensor_size(this->result_diff, task_num); + + memcpy(this->tasks->data(), data, task_num * sizeof(float[3])); + } + + void wait_v() noexcept final { this->manager.sequence()->eval(); } + + void execute_v(::SCL_convertAlgo algo, bool wait) noexcept final { + task_option option{uint32_t(this->task_count), this->color_count, + uint8_t(algo)}; + this->compute_option->setData({option}); + + this->manager.sequence()->record( + {this->compute_option, this->colorset, this->tasks}); + + const uint32_t local_wg_size = this->local_work_group_size_v(); + + const uint32_t work_group_num = + ceil_up_to(this->task_count, local_wg_size) / local_wg_size; + this->algorithm->setWorkgroup({work_group_num, 1, 1}); + this->manager.sequence() + ->record(this->algorithm) + ->record({this->result_diff, this->result_idx}); + + if (wait) { + this->manager.sequence()->eval(); + } + } + + size_t task_count_v() const noexcept final { return this->task_count; } + std::string device_vendor_v() const noexcept final { + return this->manager.getDeviceProperties().deviceName; + } + const uint16_t* result_idx_v() const noexcept final { + return this->result_idx->data(); + } + const float* result_diff_v() const noexcept final { + return this->result_diff->data(); + } + size_t local_work_group_size_v() const noexcept { return 64; } + + // error handling + int error_code_v() const noexcept final { return 0; } + bool ok_v() const noexcept final { return true; } + std::string error_detail_v() const noexcept final { return {}; } +}; + +// gpu_interface* gpu_interface::create(gpu_wrapper::platform_wrapper* pw, +// gpu_wrapper::device_wrapper* dw) +// noexcept { +// +// } +gpu_interface* gpu_interface::create( + platform_wrapper*, device_wrapper* dw, + std::pair& err) noexcept { + auto d = dynamic_cast(dw); + err.first = 0; + // err.second.clear(); + return new gpu_impl{d->device_index, d->selected_queue_family_index}; +} + +void gpu_interface::destroy(gpu_wrapper::gpu_interface* gi) noexcept { + delete gi; +} +} // namespace gpu_wrapper \ No newline at end of file diff --git a/utilities/GPUWrapper/Vulkan/compute.glsl b/utilities/GPUWrapper/Vulkan/compute.glsl index 15bd6853..4831d380 100644 --- a/utilities/GPUWrapper/Vulkan/compute.glsl +++ b/utilities/GPUWrapper/Vulkan/compute.glsl @@ -22,7 +22,9 @@ const uint ALGO_XYZ = 88; const bool SC_OCL_SPOT_NAN = true; -layout (binding = 0) readonly buffer bufOpt { +layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout (std140, binding = 0) readonly buffer bufOpt { uint task_num; uint colorset_size; uint8_t algo; @@ -67,6 +69,9 @@ void compute(const uint global_idx); void main() { const uint global_idx = gl_GlobalInvocationID.x; + if (global_idx >= option.task_num) { + return; + } compute(global_idx); } @@ -86,37 +91,37 @@ void compute(const uint global_idx) { colorset_colors[idx * 3 + 2] }; if (true && have_nan(color_ava)) { debugPrintfEXT( - "Nan spotted at color_ava. color_ava = {%f,%f,%f}, get_global_id = %u.n", - color_ava[0], color_ava[1], color_ava[2], - uint(global_idx)); + "Nan spotted at color_ava. color_ava = {%f,%f,%f}, get_global_id = %u.n", + color_ava[0], color_ava[1], color_ava[2], + uint(global_idx)); return; } float diff_sq = 0; - /* + /* -float color_diff_RGB_XYZ(vec3 RGB1, vec3 RGB2); -float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2); -float color_diff_HSV(vec3 hsv1_vec3, vec3 hsv2_vec3); -float color_diff_Lab94(vec3 lab1_vec3, vec3 lab2_vec3); -float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3); -*/ + float color_diff_RGB_XYZ(vec3 RGB1, vec3 RGB2); + float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2); + float color_diff_HSV(vec3 hsv1_vec3, vec3 hsv2_vec3); + float color_diff_Lab94(vec3 lab1_vec3, vec3 lab2_vec3); + float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3); + */ switch (uint(option.algo)) { case ALGO_RGB_BETTER: - diff_sq = color_diff_RGB_Better(color_ava, unconverted); - break; + diff_sq = color_diff_RGB_Better(color_ava, unconverted); + break; case ALGO_HSV: - diff_sq = color_diff_HSV(color_ava, unconverted); - break; + diff_sq = color_diff_HSV(color_ava, unconverted); + break; case ALGO_LAB94: - diff_sq = color_diff_Lab94(color_ava, unconverted); - break; + diff_sq = color_diff_Lab94(color_ava, unconverted); + break; case ALGO_LAB00: - diff_sq = color_diff_Lab00(color_ava, unconverted); - break; - default: - diff_sq = color_diff_RGB_XYZ(color_ava, unconverted); + diff_sq = color_diff_Lab00(color_ava, unconverted); + break; + default : + diff_sq = color_diff_RGB_XYZ(color_ava, unconverted); } if (true && isnan(diff_sq)) { @@ -124,7 +129,7 @@ float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3); return; } if (result_diff > diff_sq) { - /* this branch may be optimized */ + /* this branch may be optimized */ result_idx = idx; result_diff = diff_sq; } @@ -156,11 +161,11 @@ float color_diff_RGB_Better(vec3 rgb1, vec3 rgb2) { const float sumRGBSquare = dot(rgb1, rgb2); const float theta = 2.0f / pi_fp32 * - acos((sumRGBSquare / sqrt(SqrModSquare + thre)) / 1.01f); + acos((sumRGBSquare * inversesqrt(SqrModSquare + thre)) / 1.01f); if (SC_OCL_SPOT_NAN && isnan(theta)) { debugPrintfEXT("theta is nan. sumRGBSquare = %f, SqrModSquare = %f.\n", - sumRGBSquare, SqrModSquare); + sumRGBSquare, SqrModSquare); return NAN; } @@ -321,7 +326,7 @@ float color_diff_Lab00(vec3 lab1_vec3, vec3 lab2_vec3) { float RC = 2 * sqrt(pow(mCp, 7) / (pow(25.0f, 7.0f) + pow(mCp, 7.0f))); float square_mLp_minus_50 = square(mLp - 50); - float SL = 1 + 0.015f * square_mLp_minus_50 / sqrt(20 + square_mLp_minus_50); + float SL = 1 + 0.015f * square_mLp_minus_50 * inversesqrt(20 + square_mLp_minus_50); float SC = 1 + 0.045f * mCp; From de470bf6bc8a0d55d1e2dc51140cd0f201e7aa4e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 5 Nov 2023 14:05:56 +0800 Subject: [PATCH 0584/1123] fix build with fmtlib v10.1.1 Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index ef035f96..aa1d2fcb 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -258,7 +258,7 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { if (!ok) { std::string msg = fmt::format( "Failed to parse {}, : invalid value for block state {} : {}", - filename, pair.key(), pair.value()); + filename, pair.key(), to_string(pair.value())); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } From 248d8051aeb24768ca78bb2d031c0c0dbf82257e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 5 Nov 2023 19:19:41 +0800 Subject: [PATCH 0585/1123] remove dependency of uint8_t Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/compute.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utilities/GPUWrapper/Vulkan/compute.glsl b/utilities/GPUWrapper/Vulkan/compute.glsl index 4831d380..b515e0a9 100644 --- a/utilities/GPUWrapper/Vulkan/compute.glsl +++ b/utilities/GPUWrapper/Vulkan/compute.glsl @@ -1,5 +1,5 @@ #version 450 -#extension GL_EXT_shader_8bit_storage: enable +//#extension GL_EXT_shader_8bit_storage: enable #extension GL_EXT_shader_16bit_storage: enable #extension GL_EXT_debug_printf: enable @@ -27,7 +27,7 @@ layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout (std140, binding = 0) readonly buffer bufOpt { uint task_num; uint colorset_size; - uint8_t algo; + uint algo; } option; layout (binding = 1) readonly buffer bufCC { float colorset_colors[]; From f17f61353a67de486ba9ea328fe349b2caf52be0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 5 Nov 2023 19:19:59 +0800 Subject: [PATCH 0586/1123] Enable features for uint16_t on GPU Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/GPU_interface.cpp | 131 +++++++++++++----- 1 file changed, 100 insertions(+), 31 deletions(-) diff --git a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp index 18696498..23cd522a 100644 --- a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp +++ b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp @@ -37,19 +37,35 @@ std::vector get_spirv() noexcept { enum class vkerr : int { create_device_failure, create_instance_failure }; std::shared_ptr get_vk_instance() noexcept { - static std::mutex lock; - static std::shared_ptr instance{nullptr}; - - std::unique_lock lkgd{lock}; - if (instance == nullptr) { - vk::ApplicationInfo app_info{"VisualCraftL", VK_MAKE_VERSION(5, 0, 0), - "NoEngine", VK_MAKE_VERSION(1, 0, 0), - VK_API_VERSION_1_3}; - auto instance_r = vk::createInstance(vk::InstanceCreateInfo{{}, &app_info}); - instance = std::make_shared(instance_r); + vk::ApplicationInfo app_info{"VisualCraftL", VK_MAKE_VERSION(5, 0, 0), + "NoEngine", VK_MAKE_VERSION(1, 0, 0), + VK_API_VERSION_1_3}; + vk::InstanceCreateInfo ici; + ici.pApplicationInfo = &app_info; + std::array extension_names{ + VK_EXT_DEBUG_REPORT_EXTENSION_NAME, + }; + ici.enabledExtensionCount = extension_names.size(); + ici.ppEnabledExtensionNames = extension_names.data(); + + std::array layer_names{ + //"VK_LAYER_LUNARG_assistant_layer", + //"VK_LAYER_LUNARG_standard_validation", + "VK_LAYER_KHRONOS_validation", + }; + ici.enabledLayerCount = layer_names.size(); + ici.ppEnabledLayerNames = layer_names.data(); + + try { + auto instance_r = vk::createInstance(ici); + auto instance = std::make_shared(instance_r); assert(instance != nullptr); + return instance; + + } catch (const std::exception& e) { + auto msg = e.what(); + return nullptr; } - return instance; } const char* api_name() noexcept { return "Vulkan"; } @@ -79,9 +95,9 @@ void platform_wrapper::destroy(gpu_wrapper::platform_wrapper* p) noexcept { class device_impl : public device_wrapper { public: uint32_t device_index; - // std::shared_ptr phy_device; + std::shared_ptr phy_device; vk::PhysicalDeviceProperties properties; - // std::shared_ptr device; + std::shared_ptr device; uint32_t selected_queue_family_index{}; const char* name_v() const noexcept final { return this->properties.deviceName; @@ -145,11 +161,12 @@ std::optional select_queue_family( device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, size_t idx, int* errorcode) noexcept { auto& plat = dynamic_cast(*pw); - auto deivces = plat.instance->enumeratePhysicalDevices(); + auto devices = plat.instance->enumeratePhysicalDevices(); auto result = new device_impl; result->device_index = idx; - auto phy_device = deivces[idx]; + result->phy_device = std::make_shared(devices[idx]); + auto& phy_device = *result->phy_device; result->properties = phy_device.getProperties(); { auto qf_props = phy_device.getQueueFamilyProperties(); @@ -160,6 +177,44 @@ device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, } result->selected_queue_family_index = sqfi_opt.value(); } + { + vk::DeviceCreateInfo dci{}; + std::array extensions{ + VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, + VK_KHR_16BIT_STORAGE_EXTENSION_NAME, + }; + + dci.enabledExtensionCount = extensions.size(); + dci.ppEnabledExtensionNames = extensions.data(); + + // check if 16 bit support is fully ok + vk::PhysicalDeviceFeatures2 pdf2; + vk::PhysicalDeviceVulkan11Features pdfv11; + pdf2.pNext = &pdfv11; + phy_device.getFeatures2(&pdf2); + assert(pdf2.features.shaderInt16); + assert(pdfv11.uniformAndStorageBuffer16BitAccess); + assert(pdfv11.storageBuffer16BitAccess); + dci.pEnabledFeatures = nullptr; + dci.pNext = &pdf2; + + // queue info + vk::DeviceQueueCreateInfo dqci; + dqci.queueCount = 1; + constexpr float prior = 1.0f; + dqci.pQueuePriorities = &prior; + dqci.queueFamilyIndex = result->selected_queue_family_index; + + dci.pQueueCreateInfos = &dqci; + dci.queueCreateInfoCount = 1; + + try { + result->device = + std::make_shared(phy_device.createDevice(dci)); + } catch (const std::exception& e) { + return nullptr; + } + } return result; } @@ -171,7 +226,7 @@ void device_wrapper::destroy(gpu_wrapper::device_wrapper* dw) noexcept { struct task_option { uint32_t task_num; uint32_t color_count; - uint8_t algo; + uint32_t algo; }; class gpu_impl : public gpu_interface { @@ -207,11 +262,14 @@ class gpu_impl : public gpu_interface { } public: - gpu_impl(uint32_t phy_device_idx, uint32_t selected_queue_index) - : manager{phy_device_idx, - {}, - {VK_KHR_8BIT_STORAGE_EXTENSION_NAME, - VK_KHR_16BIT_STORAGE_EXTENSION_NAME}} { + gpu_impl(platform_impl& pi, device_impl& di) + : manager{pi.instance, di.phy_device, di.device} { + // setup compute queues that ought to be setup by manager constructor + this->manager.computeQueueFamilyIndices() = { + di.selected_queue_family_index}; + this->manager.computeQueues() = {std::make_shared( + di.device->getQueue(di.selected_queue_family_index, 0))}; + this->compute_option = this->manager.tensorT({task_option{}}); this->colorset = @@ -259,11 +317,19 @@ class gpu_impl : public gpu_interface { memcpy(this->tasks->data(), data, task_num * sizeof(float[3])); } - void wait_v() noexcept final { this->manager.sequence()->eval(); } + void wait_v() noexcept final { + this->manager.sequence()->eval(); + fmt::println("Computation result: ["); + for (uint32_t i = 0; i < this->task_count; i++) { + fmt::println("\t[idx = {}, diff = {}]", this->result_idx->data()[i], + this->result_diff->data()[i]); + } + fmt::println("]"); + } void execute_v(::SCL_convertAlgo algo, bool wait) noexcept final { task_option option{uint32_t(this->task_count), this->color_count, - uint8_t(algo)}; + uint32_t(algo)}; this->compute_option->setData({option}); this->manager.sequence()->record( @@ -274,12 +340,13 @@ class gpu_impl : public gpu_interface { const uint32_t work_group_num = ceil_up_to(this->task_count, local_wg_size) / local_wg_size; this->algorithm->setWorkgroup({work_group_num, 1, 1}); + this->manager.sequence() ->record(this->algorithm) ->record({this->result_diff, this->result_idx}); if (wait) { - this->manager.sequence()->eval(); + this->wait_v(); } } @@ -301,18 +368,20 @@ class gpu_impl : public gpu_interface { std::string error_detail_v() const noexcept final { return {}; } }; -// gpu_interface* gpu_interface::create(gpu_wrapper::platform_wrapper* pw, -// gpu_wrapper::device_wrapper* dw) -// noexcept { -// -// } +gpu_interface* gpu_interface::create(gpu_wrapper::platform_wrapper* pw, + gpu_wrapper::device_wrapper* dw) noexcept { + std::pair temp; + return create(pw, dw, temp); +} gpu_interface* gpu_interface::create( - platform_wrapper*, device_wrapper* dw, + platform_wrapper* pw, device_wrapper* dw, std::pair& err) noexcept { + auto p = dynamic_cast(pw); auto d = dynamic_cast(dw); err.first = 0; // err.second.clear(); - return new gpu_impl{d->device_index, d->selected_queue_family_index}; + return new gpu_impl{*p, *d}; + // return new gpu_impl{d->device_index, d->selected_queue_family_index}; } void gpu_interface::destroy(gpu_wrapper::gpu_interface* gi) noexcept { From 483d87bfacdf807f7ed1cfd03637d243e4ae8ae1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 5 Nov 2023 20:22:48 +0800 Subject: [PATCH 0587/1123] Finished vulkan computation draft Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/GPU_interface.cpp | 33 +++++++++++-------- utilities/GPUWrapper/Vulkan/compute.glsl | 9 ++--- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp index 23cd522a..685a4277 100644 --- a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp +++ b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp @@ -183,7 +183,6 @@ device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, VK_KHR_16BIT_STORAGE_EXTENSION_NAME, }; - dci.enabledExtensionCount = extensions.size(); dci.ppEnabledExtensionNames = extensions.data(); @@ -247,6 +246,8 @@ class gpu_impl : public gpu_interface { std::shared_ptr algorithm; + std::shared_ptr sequence; + size_t task_count{UINT64_MAX}; uint16_t color_count{UINT16_MAX}; @@ -284,7 +285,9 @@ class gpu_impl : public gpu_interface { this->algorithm = this->manager.algorithm( {this->compute_option, this->colorset, this->tasks, this->result_diff, this->result_idx}, - get_spirv(), {64, 1, 1}); + get_spirv()); + + this->sequence = this->manager.sequence(); } const char* api_v() const noexcept final { return "Vulkan"; } @@ -318,13 +321,14 @@ class gpu_impl : public gpu_interface { } void wait_v() noexcept final { - this->manager.sequence()->eval(); - fmt::println("Computation result: ["); - for (uint32_t i = 0; i < this->task_count; i++) { - fmt::println("\t[idx = {}, diff = {}]", this->result_idx->data()[i], - this->result_diff->data()[i]); - } - fmt::println("]"); + this->sequence->eval(); + // fmt::println("Computation result: ["); + // for (uint32_t i = 0; i < this->task_count; i++) { + // fmt::println("\t[task {}, result idx = {}, result diff = {}]", i, + // this->result_idx->data()[i], + // this->result_diff->data()[i]); + // } + // fmt::println("]"); } void execute_v(::SCL_convertAlgo algo, bool wait) noexcept final { @@ -332,17 +336,18 @@ class gpu_impl : public gpu_interface { uint32_t(algo)}; this->compute_option->setData({option}); - this->manager.sequence()->record( + this->sequence->record( {this->compute_option, this->colorset, this->tasks}); const uint32_t local_wg_size = this->local_work_group_size_v(); const uint32_t work_group_num = ceil_up_to(this->task_count, local_wg_size) / local_wg_size; - this->algorithm->setWorkgroup({work_group_num, 1, 1}); - - this->manager.sequence() - ->record(this->algorithm) + this->algorithm->rebuild({this->compute_option, this->colorset, this->tasks, + this->result_diff, this->result_idx}, + get_spirv(), {work_group_num, 1, 1}); + + this->sequence->record(this->algorithm) ->record({this->result_diff, this->result_idx}); if (wait) { diff --git a/utilities/GPUWrapper/Vulkan/compute.glsl b/utilities/GPUWrapper/Vulkan/compute.glsl index b515e0a9..23646469 100644 --- a/utilities/GPUWrapper/Vulkan/compute.glsl +++ b/utilities/GPUWrapper/Vulkan/compute.glsl @@ -35,12 +35,12 @@ layout (binding = 1) readonly buffer bufCC { layout (binding = 2) readonly buffer bufUC { float unconverted_colors[]; }; -layout (binding = 3) writeonly buffer bufRID { - uint16_t result_idx_dst[]; -}; -layout (binding = 4) writeonly buffer bufRDD { +layout (binding = 3) writeonly buffer bufRDD { float result_diff_dst[]; }; +layout (binding = 4) writeonly buffer bufRID { + uint16_t result_idx_dst[]; +}; bool have_nan(vec3 v) { @@ -72,6 +72,7 @@ void main() { if (global_idx >= option.task_num) { return; } + //debugPrintfEXT("global_idx = %u, task_num = %u, colorset_size = %u, algo = %u", global_idx, option.colorset_size, option.algo); compute(global_idx); } From 9fbd735d13d3918e8081c935b30c0b6d0441e3dd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 6 Nov 2023 13:02:46 +0800 Subject: [PATCH 0588/1123] Fix crashing of lab00 with more than 16383 colors Signed-off-by: ToKiNoBug --- utilities/ColorManip/newTokiColor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 80d51903..ed38e14d 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -430,7 +430,7 @@ class newTokiColor // const ColorList &allow = Allowed->Lab; TempVectorXf_t Diff(Allowed->color_count(), 1); - for (short i = 0; i < Allowed->color_count(); i++) { + for (int i = 0; i < Allowed->color_count(); i++) { Diff(i) = Lab00_diff(L1s, a1s, b1s, Allowed->Lab(i, 0), Allowed->Lab(i, 1), Allowed->Lab(i, 2)); } From c8b1f12b1a16bef9f93dbc64914fb7ac142f0262 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 6 Nov 2023 13:51:39 +0800 Subject: [PATCH 0589/1123] implement error reporting for vulkan backend Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/GPU_interface.cpp | 293 ++++++++++++------ 1 file changed, 196 insertions(+), 97 deletions(-) diff --git a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp index 685a4277..ffafbdfc 100644 --- a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp +++ b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "GPUWrapper/GPU_interface.h" extern "C" { @@ -18,6 +19,31 @@ extern const unsigned int VkComputeShaderSPIRV_rc_length; namespace gpu_wrapper { +enum class error_code : int { + ok = 0, + create_instance_failure = 2000000000, + create_instance_failure_invalid_platform_index = 2000000001, + create_physical_device_failure = 2000001000, + create_logical_device_failure = 2000002000, + create_logical_device_failure_no_suitable_queue_family = 2000002001, + create_kompute_manager_failure = 2000003000, + manager_set_colorset_failure = 2000004000, + manager_set_tasks_failure = 2000005000, + manager_execute_failure = 2000006000, + manager_wait_failure = 2000007000, +}; + +struct error_pair { + error_code code; + std::string message; +}; + +void set_error_code(int* dst_nullable, error_code code) noexcept { + if (dst_nullable) { + *dst_nullable = int(code); + } +} + constexpr uint32_t ceil_up_to(uint32_t num, uint32_t align) noexcept { if (num % align == 0) { return num; @@ -34,9 +60,8 @@ std::vector get_spirv() noexcept { data, data + size_t(VkComputeShaderSPIRV_rc_length / 4)}; } -enum class vkerr : int { create_device_failure, create_instance_failure }; - -std::shared_ptr get_vk_instance() noexcept { +tl::expected, error_pair> +create_vk_instance() noexcept { vk::ApplicationInfo app_info{"VisualCraftL", VK_MAKE_VERSION(5, 0, 0), "NoEngine", VK_MAKE_VERSION(1, 0, 0), VK_API_VERSION_1_3}; @@ -63,7 +88,8 @@ std::shared_ptr get_vk_instance() noexcept { return instance; } catch (const std::exception& e) { - auto msg = e.what(); + fmt::print("Failed to create vulkan instance, exception details: {}", + e.what()); return nullptr; } } @@ -74,7 +100,7 @@ size_t platform_num() noexcept { return 1; } class platform_impl : public platform_wrapper { public: - platform_impl() : instance{get_vk_instance()} {} + platform_impl(std::shared_ptr i) : instance{i} {} std::shared_ptr instance; const char* name_v() const noexcept final { return "Vulkan"; } @@ -85,7 +111,18 @@ class platform_impl : public platform_wrapper { platform_wrapper* platform_wrapper::create(size_t idx, int* errorcode) noexcept { - return new platform_impl; + if (idx != 0) { + set_error_code(errorcode, + error_code::create_instance_failure_invalid_platform_index); + return nullptr; + } + auto i_exp = create_vk_instance(); + if (i_exp) { + set_error_code(errorcode, error_code::ok); + return new platform_impl{i_exp.value()}; + } + set_error_code(errorcode, i_exp.error().code); + return nullptr; } void platform_wrapper::destroy(gpu_wrapper::platform_wrapper* p) noexcept { @@ -159,63 +196,87 @@ std::optional select_queue_family( } device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, - size_t idx, int* errorcode) noexcept { + size_t idx, int* ec) noexcept { auto& plat = dynamic_cast(*pw); - auto devices = plat.instance->enumeratePhysicalDevices(); - - auto result = new device_impl; - result->device_index = idx; - result->phy_device = std::make_shared(devices[idx]); - auto& phy_device = *result->phy_device; - result->properties = phy_device.getProperties(); - { - auto qf_props = phy_device.getQueueFamilyProperties(); - - auto sqfi_opt = select_queue_family(qf_props); - if (!sqfi_opt) { - return nullptr; - } - result->selected_queue_family_index = sqfi_opt.value(); + std::vector devices; + try { + devices = plat.instance->enumeratePhysicalDevices(); + } catch (const std::exception& e) { + fmt::println("Failed to enumerate physical devices, detail: {}", e.what()); + set_error_code(ec, error_code::create_physical_device_failure); + return nullptr; } - { - vk::DeviceCreateInfo dci{}; - std::array extensions{ - VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, - VK_KHR_16BIT_STORAGE_EXTENSION_NAME, - }; - dci.enabledExtensionCount = extensions.size(); - dci.ppEnabledExtensionNames = extensions.data(); - - // check if 16 bit support is fully ok - vk::PhysicalDeviceFeatures2 pdf2; - vk::PhysicalDeviceVulkan11Features pdfv11; - pdf2.pNext = &pdfv11; - phy_device.getFeatures2(&pdf2); - assert(pdf2.features.shaderInt16); - assert(pdfv11.uniformAndStorageBuffer16BitAccess); - assert(pdfv11.storageBuffer16BitAccess); - dci.pEnabledFeatures = nullptr; - dci.pNext = &pdf2; - - // queue info - vk::DeviceQueueCreateInfo dqci; - dqci.queueCount = 1; - constexpr float prior = 1.0f; - dqci.pQueuePriorities = &prior; - dqci.queueFamilyIndex = result->selected_queue_family_index; - - dci.pQueueCreateInfos = &dqci; - dci.queueCreateInfoCount = 1; - - try { - result->device = - std::make_shared(phy_device.createDevice(dci)); - } catch (const std::exception& e) { - return nullptr; + try { + auto result = new device_impl; + result->device_index = idx; + result->phy_device = std::make_shared(devices[idx]); + auto& phy_device = *result->phy_device; + result->properties = phy_device.getProperties(); + { + auto qf_props = phy_device.getQueueFamilyProperties(); + + auto sqfi_opt = select_queue_family(qf_props); + if (!sqfi_opt) { + set_error_code( + ec, + error_code::create_logical_device_failure_no_suitable_queue_family); + delete result; + return nullptr; + } + result->selected_queue_family_index = sqfi_opt.value(); + } + { + vk::DeviceCreateInfo dci{}; + std::array extensions{ + VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, + VK_KHR_16BIT_STORAGE_EXTENSION_NAME, + }; + dci.enabledExtensionCount = extensions.size(); + dci.ppEnabledExtensionNames = extensions.data(); + + // check if 16 bit support is fully ok + vk::PhysicalDeviceFeatures2 pdf2; + vk::PhysicalDeviceVulkan11Features pdfv11; + pdf2.pNext = &pdfv11; + phy_device.getFeatures2(&pdf2); + assert(pdf2.features.shaderInt16); + assert(pdfv11.uniformAndStorageBuffer16BitAccess); + assert(pdfv11.storageBuffer16BitAccess); + dci.pEnabledFeatures = nullptr; + dci.pNext = &pdf2; + + // queue info + vk::DeviceQueueCreateInfo dqci; + dqci.queueCount = 1; + constexpr float prior = 1.0f; + dqci.pQueuePriorities = &prior; + dqci.queueFamilyIndex = result->selected_queue_family_index; + + dci.pQueueCreateInfos = &dqci; + dci.queueCreateInfoCount = 1; + + try { + result->device = + std::make_shared(phy_device.createDevice(dci)); + } catch (const std::exception& e) { + fmt::println("Failed to create logical device, details: {}", e.what()); + set_error_code(ec, error_code::create_logical_device_failure); + delete result; + return nullptr; + } } - } - return result; + set_error_code(ec, error_code::ok); + return result; + } catch (const std::exception& e) { + fmt::println("Failed to create logical device because {}", e.what()); + set_error_code(ec, error_code::create_logical_device_failure); + return nullptr; + } catch (...) { + fmt::println("Failed to create logical device because unknown exception."); + set_error_code(ec, error_code::create_logical_device_failure); + return nullptr; + } } void device_wrapper::destroy(gpu_wrapper::device_wrapper* dw) noexcept { @@ -251,9 +312,11 @@ class gpu_impl : public gpu_interface { size_t task_count{UINT64_MAX}; uint16_t color_count{UINT16_MAX}; + error_pair error{error_code::ok, ""}; + template void resize_tensor_size(std::shared_ptr> tensor, - size_t required_size) noexcept { + size_t required_size) { const size_t cur_size = tensor->size(); if (cur_size >= required_size) { return; @@ -295,33 +358,51 @@ class gpu_impl : public gpu_interface { void set_colorset_v( size_t color_num, const std::array& color_ptrs) noexcept final { - this->color_count = color_num; - this->resize_tensor_size(this->colorset, 3 * color_num); - // this->colorset_host.resize(3 * color_num); - - Eigen::Map< - Eigen::Array> - trans{this->colorset->data(), static_cast(color_num), 3}; - - for (size_t c = 0; c < 3; c++) { - for (size_t r = 0; r < color_num; r++) { - trans(r, c) = color_ptrs[c][r]; + try { + this->color_count = color_num; + this->resize_tensor_size(this->colorset, 3 * color_num); + // this->colorset_host.resize(3 * color_num); + + Eigen::Map< + Eigen::Array> + trans{this->colorset->data(), static_cast(color_num), 3}; + + for (size_t c = 0; c < 3; c++) { + for (size_t r = 0; r < color_num; r++) { + trans(r, c) = color_ptrs[c][r]; + } } + } catch (const std::exception& e) { + this->error.code = error_code::manager_set_colorset_failure; + this->error.message = + fmt::format("Failed to set colorset, detail: {}", e.what()); } } void set_task_v(size_t task_num, const std::array* data) noexcept final { - this->task_count = task_num; - this->resize_tensor_size(this->tasks, task_num * 3); - this->resize_tensor_size(this->result_idx, task_num); - this->resize_tensor_size(this->result_diff, task_num); + try { + this->task_count = task_num; + this->resize_tensor_size(this->tasks, task_num * 3); + this->resize_tensor_size(this->result_idx, task_num); + this->resize_tensor_size(this->result_diff, task_num); - memcpy(this->tasks->data(), data, task_num * sizeof(float[3])); + memcpy(this->tasks->data(), data, task_num * sizeof(float[3])); + } catch (const std::exception& e) { + this->error.code = error_code::manager_set_tasks_failure; + this->error.message = + fmt::format("Failed to set tasks, detail: {}", e.what()); + } } void wait_v() noexcept final { - this->sequence->eval(); + try { + this->sequence->eval(); + } catch (const std::exception& e) { + this->error.code = error_code::manager_wait_failure; + this->error.message = + fmt::format("Failed to wait for results, detail: {}", e.what()); + } // fmt::println("Computation result: ["); // for (uint32_t i = 0; i < this->task_count; i++) { // fmt::println("\t[task {}, result idx = {}, result diff = {}]", i, @@ -332,26 +413,34 @@ class gpu_impl : public gpu_interface { } void execute_v(::SCL_convertAlgo algo, bool wait) noexcept final { - task_option option{uint32_t(this->task_count), this->color_count, - uint32_t(algo)}; - this->compute_option->setData({option}); + try { + task_option option{uint32_t(this->task_count), this->color_count, + uint32_t(algo)}; + this->compute_option->setData({option}); - this->sequence->record( - {this->compute_option, this->colorset, this->tasks}); + this->sequence->record( + {this->compute_option, this->colorset, this->tasks}); - const uint32_t local_wg_size = this->local_work_group_size_v(); + const uint32_t local_wg_size = this->local_work_group_size_v(); - const uint32_t work_group_num = - ceil_up_to(this->task_count, local_wg_size) / local_wg_size; - this->algorithm->rebuild({this->compute_option, this->colorset, this->tasks, - this->result_diff, this->result_idx}, - get_spirv(), {work_group_num, 1, 1}); + const uint32_t work_group_num = + ceil_up_to(this->task_count, local_wg_size) / local_wg_size; + this->algorithm->rebuild( + {this->compute_option, this->colorset, this->tasks, this->result_diff, + this->result_idx}, + get_spirv(), {work_group_num, 1, 1}); - this->sequence->record(this->algorithm) - ->record({this->result_diff, this->result_idx}); + this->sequence->record(this->algorithm) + ->record( + {this->result_diff, this->result_idx}); - if (wait) { - this->wait_v(); + if (wait) { + this->wait_v(); + } + } catch (const std::exception& e) { + this->error.code = error_code::manager_execute_failure; + this->error.message = + fmt::format("Failed to execute computation, detail: {}", e.what()); } } @@ -368,9 +457,13 @@ class gpu_impl : public gpu_interface { size_t local_work_group_size_v() const noexcept { return 64; } // error handling - int error_code_v() const noexcept final { return 0; } - bool ok_v() const noexcept final { return true; } - std::string error_detail_v() const noexcept final { return {}; } + int error_code_v() const noexcept final { return int(this->error.code); } + bool ok_v() const noexcept final { + return (this->error.code == error_code::ok); + } + std::string error_detail_v() const noexcept final { + return this->error.message; + } }; gpu_interface* gpu_interface::create(gpu_wrapper::platform_wrapper* pw, @@ -385,8 +478,14 @@ gpu_interface* gpu_interface::create( auto d = dynamic_cast(dw); err.first = 0; // err.second.clear(); - return new gpu_impl{*p, *d}; - // return new gpu_impl{d->device_index, d->selected_queue_family_index}; + auto result = new gpu_impl{*p, *d}; + err.first = result->error_code_v(); + err.second = result->error_detail_v(); + if (err.first != 0) { + delete result; + return nullptr; + } + return result; } void gpu_interface::destroy(gpu_wrapper::gpu_interface* gi) noexcept { From 100b7200a5b1d908a093eeb413e78a4db79c12f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Thu, 9 Nov 2023 20:39:16 -0500 Subject: [PATCH 0590/1123] chore: Update Translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Qian Qian "Cubik"‎ --- SlopeCraft/others/SlopeCraft_en_US.ts | 78 +++++++++---------- VisualCraft/others/VisualCraft_en_US.ts | 16 ++-- .../others/BlockListManager_en_US.ts | 12 +-- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index f72dc4ed..824ac019 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -507,13 +507,13 @@ - + 大小: Size: - + 方块数量: Block count: @@ -648,12 +648,12 @@ Filenames of each image can be seen in the table below. FAQ - + 加载默认预设失败 Failed to load default presets - + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -662,113 +662,113 @@ Detail information: %1 - + 设置方块列表失败 Failed to setup blocklist - + 您设置的方块列表可能存在错误 There may be errors in your blocklist - + 可用颜色数量:%1 Avaliable colors: %1 - + 应用预设失败 Failed to apply preset - + 转化图像失败 Failed to convert image - - + + 缓存失败 Failed to save cache - - + + 未能创建缓存文件,错误信息: %1 Failed to create cache directory, error info: %1 - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - + 保存图像失败 Failed to save image - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - + 构建三维结构失败 Failed to build 3d structure - + 构建三维结构时,出现错误。可能是因为尝试跳步。 An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - + 方块数量:%1 Block count: %1 - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - + SlopeCraft 出现错误 An error occurred to SlopeCraft - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -1005,62 +1005,62 @@ Click Ignore to skip, Retry to retry and Cancel to cancel Copyright © 2021-2023 SlopeCraft deveploers - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 33094a94..15efb5bb 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -843,22 +843,22 @@ If you select a block in "Avaliable blocks" page, the other page will The great amount of colors makes GPU accleration necessary. Now OpenCL is supported, and %1 is what currently being used. - + 可用的计算设备(CPU + %1可用的显卡) Avaliable compute devices (CPU + %1-avaliable-GPUs) - + 无法获取 platform 信息。请检查驱动。OpenCL 错误码:%1. Failed to retrieve platform infomation, please check your deiver. OpenCL error code: %1 - + 无法获取 device 信息。请检查驱动。OpenCL 错误码:%1 Failed to retrieve device infomation, please check your deiver. OpenCL error code: %1 - + %1 这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft @@ -867,24 +867,24 @@ If you select a block in "Avaliable blocks" page, the other page will This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - + 创建 GPU 平台失败,平台序号为%1,设备序号为%2 Failed to create GPU platform, Platform index = %1, device index = %2 - + 创建 GPU 设备失败,平台序号为%1,设备序号为%2 Failed to create GPU device, Platform index = %1, device index = %2 - + 设置 GPU 设备失败。平台序号为%1,设备序号为%2,详细错误信息: %3 Failed to set GPU device. Platform index = %1, device index = %2, detailed information: %3 - + 设置计算设备失败 Failed to set compute device diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index 2f72ecc8..365bfc54 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -12,25 +12,25 @@ BlockListManager - - + + 解析方块列表失败 Failed to parse block list - - + + 加载预设错误 Failed to load preset - + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors - + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id From 3dccb28d7c2642ae1a0ccdb681f2e688c534bad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Thu, 9 Nov 2023 21:03:16 -0500 Subject: [PATCH 0591/1123] =?UTF-8?q?refactor:=20Window=20title=20don?= =?UTF-8?q?=E2=80=99t=20need=20copyright=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Qian Qian "Cubik"‎ --- SlopeCraft/SCWind.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index fcc55c0a..4d13cd91 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -977,22 +977,7 @@ void SCWind::set_lang(::SCL_language lang) noexcept { } QString impl_default_title() noexcept { - QString newtitle = - QStringLiteral("SlopeCraft %1").arg(SlopeCraft::SCL_getSCLVersion()); - -#ifdef WIN32 - newtitle += - " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Mifan-T"; // windowsf -#elif defined(_MAC) || defined(__APPLE__) - newtitle += - " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Cubik65536, Mifan-T"; // macOs -#else - newtitle += - " Copyright © 2021-2023 TokiNoBug, AbrasiveBoar, Mifan-T"; // unknown - // platform -#endif - - return newtitle; + return QStringLiteral("SlopeCraft %1").arg(SlopeCraft::SCL_getSCLVersion()); } const QString &SCWind::default_wind_title() noexcept { From bb1f3b010efa0ef590a0f74c51dfa0683e1043bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Thu, 9 Nov 2023 21:51:21 -0500 Subject: [PATCH 0592/1123] refactor: New About Message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Qian Qian Cubik‎ on-behalf-of: @iXORTech cubik65536@cubik65536.top --- SlopeCraft/SCWind_slots.cpp | 21 ++++---- SlopeCraft/others/SlopeCraft_en_US.ts | 75 +++++++++++++++++---------- 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 37cdf62e..ef8db526 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -866,20 +866,19 @@ void SCWind::connect_slots() noexcept { void SCWind::on_ac_about_triggered() noexcept { QString info; - info += - tr("感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft " - "是由我开发的一款立体地图画生成器,主要用于在 minecraft " - "中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地" - "图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 " - "SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen " - "等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 " - "minecraft 而设计的。AbrasiveBoar902 " - "为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS " - "的适配做出了贡献。"); + info += QStringLiteral("SlopeCraft %1").arg(SlopeCraft::SCL_getSCLVersion()); + info += "\n\n"; + info += tr("SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于" + "在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。"); + info += tr("本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供"); + info += "\n\n"; + info += tr("感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量"); + info += tr("感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献"); + info += tr("SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。"); info += "\n\n"; info += tr("本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。"); info += "\n\n"; - info += tr("版权所有 © 2021-2023 SlopeCraft 开发者"); + info += tr("Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有"); QMessageBox::information(this, tr("关于 SlopeCraft"), info); } diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 824ac019..fe653e32 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -608,7 +608,7 @@ Filenames of each image can be seen in the table below. - + 关于 SlopeCraft About SlopeCraft @@ -990,113 +990,132 @@ Click Yes to replace them, or No to cancel. Click Ignore to skip, Retry to retry and Cancel to cancel - - 感谢你使用 SlopeCraft,我是开发者 TokiNoBug。SlopeCraft 是由我开发的一款立体地图画生成器,主要用于在 minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。立体地图画的优势在于拥有更高的“画质”,此处不再详述。你正在使用的是 SlopeCraft 的第 5 代版本,在开发时使用了 Qt,zlib 和 eigen 等开源软件,对上述库的开发者表示感谢。也感谢 Mojang,整个软件就是为 minecraft 而设计的。AbrasiveBoar902 为本软件的设计和优化贡献了不少力量;Cubik65536 为本软件在 MacOS 的适配做出了贡献。 - Thank you for using SlopeCraft, I'm TokiNoBug, the developer. SlopeCraft is a minecraft map generator, supporting many kinds of maps.You are currently using the 5th generation of SlopeCraft, based on Qt, Eigen, zlib and many open source softwares. I'm grateful to developers of thest libs. Also thanks Mojang, the whole software is developed for minecraft. AbrasiveBoar902(PopChrono) made great effort to the designing and optimization. Besides, Cubik65536 made contribution to the adaption on MacOS. + + SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。 + SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). + + + + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 + The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) + + + + Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software + + + + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 + Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 + Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. + + + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - - 版权所有 © 2021-2023 SlopeCraft 开发者 - Copyright © 2021-2023 SlopeCraft deveploers + + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 + Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: From 6d42d07b75c33f5acb472a45dd3f3a5b4c489638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qian=20Qian=20=22Cubik=22=E2=80=8E?= Date: Thu, 9 Nov 2023 21:56:06 -0500 Subject: [PATCH 0593/1123] fix: Fix About Page style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Qian Qian "Cubik"‎ --- SlopeCraft/SCWind_slots.cpp | 3 +++ SlopeCraft/others/SlopeCraft_en_US.ts | 31 ++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index ef8db526..ef08b362 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -870,10 +870,13 @@ void SCWind::on_ac_about_triggered() noexcept { info += "\n\n"; info += tr("SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于" "在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。"); + info += "\n"; info += tr("本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供"); info += "\n\n"; info += tr("感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量"); + info += "\n"; info += tr("感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献"); + info += "\n"; info += tr("SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。"); info += "\n\n"; info += tr("本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。"); diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index fe653e32..5b40abe8 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -608,7 +608,7 @@ Filenames of each image can be seen in the table below. - + 关于 SlopeCraft About SlopeCraft @@ -995,31 +995,32 @@ Click Ignore to skip, Retry to retry and Cancel to cancel SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). - + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) - + + 感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量 Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software - + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. @@ -1084,38 +1085,38 @@ Click Ignore to skip, Retry to retry and Cancel to cancel Writing meta data - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: From a78604365ad5cf534aa793239c531f88804c51cd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 11 Nov 2023 16:03:08 +0800 Subject: [PATCH 0594/1123] create run_codesign script --- cmake/run_codesign.cmake | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 cmake/run_codesign.cmake diff --git a/cmake/run_codesign.cmake b/cmake/run_codesign.cmake new file mode 100644 index 00000000..96219490 --- /dev/null +++ b/cmake/run_codesign.cmake @@ -0,0 +1,62 @@ +if (DEFINED CMAKE_GENERATOR) + message(STATUS "Running at configuration time") + option(RCS_configure_time "Whether this script is running at configuration time" ON) +else () + # Otherwise we guess that it's running at build or installation time. + message(STATUS "Running at build/install time") + option(RCS_configure_time "Whether this script is running at configuration time" OFF) +endif () + +option(RCS_run_directly "" OFF) +if(RCS_configure_time) + set(RCS_source_file ${CMAKE_CURRENT_LIST_FILE}) +else() + set(RCS_this_file @rcs_this_file@) + set(RCS_bundle_name @rcs_bundle_name@) + set(RCS_bundle_version @rcs_bundle_version@) + + set(RCS_working_dir . CACHE FILEPATH "") +endif() + + +function(RCS_add_codesign target) + set(rcs_this_file "${CMAKE_CURRENT_BINARY_DIR}/run_codesign_install.cmake") + set(rcs_bundle_name ${target}) + get_target_property(rcs_bundle_version ${target} VERSION) + + configure_file(${RCS_source_file} + ${rcs_this_file} + @ONLY) + + install(SCRIPT ${rcs_this_file} + DESTINATION .) +endfunction() + +if(NOT RCS_configure_time) + if(NOT RCS_run_directly) + + message(STATUS "RCS_working_dir = \"${RCS_working_dir}\"") + + execute_process(COMMAND ${CMAKE_COMMAND} -DRCS_run_directly:BOOL=ON -DRCS_working_dir=${CMAKE_INSTALL_PREFIX} -P ${RCS_this_file} + WORKING_DIRECTORY ${RCS_working_dir} + COMMAND_ERROR_IS_FATAL ANY) + return() + endif() + + set(bundle_prefix "${RCS_working_dir}/${RCS_bundle_name}.app/Contents/MacOS") + + if(IS_SYMLINK "${bundle_prefix}/${RCS_bundle_name}") + message(STATUS "Found symlink file ${bundle_prefix}/${RCS_bundle_name}") + + file(REMOVE "${bundle_prefix}/${RCS_bundle_name}") + file(RENAME "${bundle_prefix}/${RCS_bundle_name}-${RCS_bundle_version}" "${bundle_prefix}/${RCS_bundle_name}") + endif () + + if(IS_SYMLINK "${bundle_prefix}/${RCS_bundle_name}") + message(WARNING "\"${bundle_prefix}/${RCS_bundle_name}\" is a symlink, but it should be regular file.") + endif () + + execute_process(COMMAND codesign --force --deep --sign=- ${RCS_bundle_name}.app + WORKING_DIRECTORY ${RCS_working_dir} + COMMAND_ERROR_IS_FATAL ANY) +endif() \ No newline at end of file From 5130d95981a5eb2c097f7800cdaab7af216db99d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 11 Nov 2023 16:34:02 +0800 Subject: [PATCH 0595/1123] Fix "invalid code signature" on mac-arm --- MapViewer/install.cmake | 7 +++++-- SlopeCraft/install.cmake | 7 +++++-- VisualCraft/install.cmake | 8 ++++++-- imageCutter/install.cmake | 7 +++++-- vccl/deploy_qt_for_vccl_macos.cmake.in | 12 ++++++------ vccl/install.cmake | 1 + 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 7f1f5f78..9d30a428 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -45,8 +45,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${MapViewer_Icon} DESTINATION MapViewer.app/Contents/Resources) - # QD_add_deployqt(MapViewer - # INSTALL_MODE INSTALL_DESTINATION .) + QD_add_deployqt(MapViewer + INSTALL_MODE INSTALL_DESTINATION .) + + include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) + RCS_add_codesign(MapViewer) return() endif () diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index d2692095..0d9a5279 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -56,8 +56,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) - # QD_add_deployqt(SlopeCraft - # INSTALL_MODE INSTALL_DESTINATION .) + QD_add_deployqt(SlopeCraft + INSTALL_MODE INSTALL_DESTINATION .) + + include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) + RCS_add_codesign(SlopeCraft) return() endif () diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 8662d95a..2e4f5559 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -57,8 +57,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${VCL_app_files} DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL ) - # QD_add_deployqt(VisualCraft - # INSTALL_MODE INSTALL_DESTINATION .) + + QD_add_deployqt(VisualCraft + INSTALL_MODE INSTALL_DESTINATION .) + + include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) + RCS_add_codesign(VisualCraft) return() endif () \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 78babad9..272d2b2b 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -56,8 +56,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${imageCutter_Icon} DESTINATION imageCutter.app/Contents/Resources) - # QD_add_deployqt(imageCutter - # INSTALL_MODE INSTALL_DESTINATION .) + QD_add_deployqt(imageCutter + INSTALL_MODE INSTALL_DESTINATION .) + + include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) + RCS_add_codesign(imageCutter) return() endif () diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index 602aaad7..c634d779 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -11,12 +11,12 @@ if (install_mode) return() endif () -#message(STATUS "Running macdeployqt for @AppName@ ...") -#execute_process( -# COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" -# WORKING_DIRECTORY "@vccl_prefix@" -# OUTPUT_QUIET -# COMMAND_ERROR_IS_FATAL ANY) +message(STATUS "Running macdeployqt for @AppName@ ...") +execute_process( + COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" + WORKING_DIRECTORY "@vccl_prefix@" + OUTPUT_QUIET + COMMAND_ERROR_IS_FATAL ANY) # message(WARNING "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") diff --git a/vccl/install.cmake b/vccl/install.cmake index be207e1e..873fc245 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -71,5 +71,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Do not run deploy_qt.cmake, but a specialied one install(SCRIPT ${deployqt_vccl_script} DESTINATION .) + return() endif () \ No newline at end of file From b0b1cb64cc11844ba016258e56ea9f737d2c6dd2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 11 Nov 2023 20:56:24 +0800 Subject: [PATCH 0596/1123] Change maximum map seq number in SC to 65536 Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index c48aa531..d8795cad 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1369,6 +1369,9 @@ 地图画起始序号: + + 65536 + From 5fedda5af01c8797ef738125659e166499825c8e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 11 Nov 2023 21:01:07 +0800 Subject: [PATCH 0597/1123] update version number to 5.2.1 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcaf14dc..25eb0550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.0) +set(SlopeCraft_version 5.2.1) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 56b2942fb74c6de783ea9da5a79d813c2fee8fec Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:30:03 +0800 Subject: [PATCH 0598/1123] [CI] use static qt in gh actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 27d16cdb..40dd4f25 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH=/Users/slopecraft/Documents/cpp/qt/qt6.6.0-static -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 07bd9f4a..263db3dd 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -30,16 +30,19 @@ jobs: - name: Install dependencies run: | brew install libpng - brew install qt@6 brew install xsimd + - name: Checkout repository + uses: actions/checkout@v4 + - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + run: | + curl -JL -o 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"3rdParty/Qt6.6.0-appleclang-static-x86_64" 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build @@ -89,16 +92,21 @@ jobs: - name: Install dependencies run: | brew install libpng - brew install qt@6 brew install xsimd + + - name: Checkout repository + uses: actions/checkout@v4 + - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + run: | + curl -JL -o 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"3rdParty/Qt6.6.0-appleclang-static-x86_64" 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z + - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - - name: Checkout repository - uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build From 999c979d3569cef1e50603fee0acfb031dbdfbe8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:33:48 +0800 Subject: [PATCH 0599/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 263db3dd..554b3202 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -35,8 +35,8 @@ jobs: uses: actions/checkout@v4 - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract run: | - curl -JL -o 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"3rdParty/Qt6.6.0-appleclang-static-x86_64" 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z + curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH @@ -98,8 +98,8 @@ jobs: uses: actions/checkout@v4 - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract run: | - curl -JL -o 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"3rdParty/Qt6.6.0-appleclang-static-x86_64" 3rdParty/Qt6.6.0-appleclang-static-x86_64.7z + curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From 34278ff116dbefa57baec9733d7fda633109c97f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:40:48 +0800 Subject: [PATCH 0600/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 123 +++++++++++++------------- 1 file changed, 61 insertions(+), 62 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 554b3202..085a1e57 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -7,63 +7,63 @@ on: - dev jobs: - gcc: - runs-on: macos-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - # - name: brew upgrade & update - # run: | - # brew update - # brew upgrade - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: | - brew install libpng - brew install xsimd - - name: Checkout repository - uses: actions/checkout@v4 - - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract - run: | - curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - - name: Build - run: | - cd build - cmake --build . --parallel - - name: CPack - run: | - cd build - cpack -G ZIP - - name: Test installation - run: | - cd build - cmake --install . - # chmod +x vccl.app/Contents/MacOS/vccl - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - path: build/SlopeCraft*.zip + # gcc: + # runs-on: macos-latest + # strategy: + # matrix: + # build_type: [ Debug, Release ] + # gpu_api: [ None ] + # env: + # BUILD_TYPE: ${{ matrix.build_type }} + # GPU_API: ${{ matrix.gpu_api }} + # steps: + # # - name: brew upgrade & update + # # run: | + # # brew update + # # brew upgrade + # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + # run: | + # echo $BUILD_TYPE + # echo $GPU_API + # - name: Install Ninja build system + # run: brew install ninja + # - name: Install dependencies + # run: | + # brew install libpng + # brew install xsimd + # - name: Checkout repository + # uses: actions/checkout@v4 + # - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + # run: | + # curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + # 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z + # - name: Add /usr/local/lib to PATH + # run: echo "/usr/local/lib" >> $GITHUB_PATH + # - name: Check PATH + # run: echo $PATH + # - name: Configure CMake + # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + # - name: Build + # run: | + # cd build + # cmake --build . --parallel + # - name: CPack + # run: | + # cd build + # cpack -G ZIP + # - name: Test installation + # run: | + # cd build + # cmake --install . + # # chmod +x vccl.app/Contents/MacOS/vccl + # + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # - name: Upload Artifacts + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc + # path: build/SlopeCraft*.zip clang: runs-on: macos-latest @@ -91,22 +91,21 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng - brew install xsimd + brew install libpng xsimd p7zip libzip - name: Checkout repository uses: actions/checkout@v4 - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract run: | - curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z + curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"~/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="~/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build From 932e1487d852f38b52d0ee766b544b3a67c0d67b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:45:43 +0800 Subject: [PATCH 0601/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 085a1e57..38db5688 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -105,7 +105,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="~/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - name: Build run: | cd build From a19f65bcf5df852a79d7abe39a6f56fc2027a07c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:49:06 +0800 Subject: [PATCH 0602/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 38db5688..39d254d6 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -99,6 +99,7 @@ jobs: run: | curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"~/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + ls ~/Downloads/Qt6.6.0-appleclang-static-x86_64 - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From d20af10407588de5dc4fdbfc143288ae45c461da Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 14:55:10 +0800 Subject: [PATCH 0603/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 39d254d6..861acca2 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -99,6 +99,7 @@ jobs: run: | curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"~/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + ls ~/Downloads ls ~/Downloads/Qt6.6.0-appleclang-static-x86_64 - name: Add /usr/local/lib to PATH From a524eeaa9daea7b05e911b693d9c9dd3f084725b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:09:31 +0800 Subject: [PATCH 0604/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 861acca2..8337ec7b 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -98,7 +98,7 @@ jobs: - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract run: | curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"~/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z ls ~/Downloads ls ~/Downloads/Qt6.6.0-appleclang-static-x86_64 From 2a8a38ba68d04992a06c049ab7396e5534b171f3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:15:03 +0800 Subject: [PATCH 0605/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 8337ec7b..ea98d02d 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -99,8 +99,7 @@ jobs: run: | curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z - ls ~/Downloads - ls ~/Downloads/Qt6.6.0-appleclang-static-x86_64 + chmox +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From 1be10db29e3a5f12de92b3009b21f04b2f22be8b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:20:10 +0800 Subject: [PATCH 0606/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index ea98d02d..5338bdc5 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -99,7 +99,7 @@ jobs: run: | curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z - chmox +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* + chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From 07f97299c8b96743d4910e418860c878d5dd58c3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:24:30 +0800 Subject: [PATCH 0607/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 5338bdc5..569660fc 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -100,6 +100,7 @@ jobs: curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* + chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* - name: Add /usr/local/lib to PATH run: echo "/usr/local/lib" >> $GITHUB_PATH From f51478d33e167ba1e9bb1e9bb8335c7f200a8beb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:55:27 +0800 Subject: [PATCH 0608/1123] allow passing flags to macdeployqt Signed-off-by: ToKiNoBug --- CMakeLists.txt | 4 ++++ MapViewer/install.cmake | 3 ++- SlopeCraft/install.cmake | 3 ++- VisualCraft/install.cmake | 3 ++- imageCutter/install.cmake | 3 ++- vccl/deploy_qt_for_vccl_macos.cmake.in | 3 ++- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25eb0550..200bf49e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,10 @@ if (${WIN32}) set(SlopeCraft_windeployqt_flags_build "${SlopeCraft_windeployqt_flags_install};--force" CACHE STRING "Flags to run windeployqt in build dir") endif () +if (${APPLE}) + set(SlopeCraft_macdeployqt_flags_install "" CACHE STRING "Flags to run macdeployqt during installation") + # set(SlopeCraft_macdeployqt_flags_build "${SlopeCraft_windeployqt_flags_install};--force" CACHE STRING "Flags to run macdeployqt in build dir") +endif () # manage the install prefix -------------------------------------------------- if (NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 9d30a428..b2904c2a 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -46,7 +46,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION MapViewer.app/Contents/Resources) QD_add_deployqt(MapViewer - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_macdeployqt_flags_install}) include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) RCS_add_codesign(MapViewer) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 0d9a5279..f36bc7cb 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -57,7 +57,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) QD_add_deployqt(SlopeCraft - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_macdeployqt_flags_install}) include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) RCS_add_codesign(SlopeCraft) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 2e4f5559..1ff89a2e 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -59,7 +59,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") ) QD_add_deployqt(VisualCraft - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_macdeployqt_flags_install}) include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) RCS_add_codesign(VisualCraft) diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 272d2b2b..a37c11a8 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -57,7 +57,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION imageCutter.app/Contents/Resources) QD_add_deployqt(imageCutter - INSTALL_MODE INSTALL_DESTINATION .) + INSTALL_MODE INSTALL_DESTINATION . + FLAGS ${SlopeCraft_macdeployqt_flags_install}) include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) RCS_add_codesign(imageCutter) diff --git a/vccl/deploy_qt_for_vccl_macos.cmake.in b/vccl/deploy_qt_for_vccl_macos.cmake.in index c634d779..e5a7a2e8 100644 --- a/vccl/deploy_qt_for_vccl_macos.cmake.in +++ b/vccl/deploy_qt_for_vccl_macos.cmake.in @@ -1,6 +1,7 @@ # This script should run during installation set(this_script_file @deployqt_vccl_script@) +set(macdeployqt_flags @SlopeCraft_macdeployqt_flags_install@) option(install_mode "" ON) if (install_mode) @@ -13,7 +14,7 @@ endif () message(STATUS "Running macdeployqt for @AppName@ ...") execute_process( - COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" + COMMAND "@SlopeCraft_Qt_macdeployqt_executable@" "@AppName@.app" "${macdeployqt_flags}" WORKING_DIRECTORY "@vccl_prefix@" OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY) From 78a3693161de7997ae152aa2ed9175f9fa69e39f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 15:59:08 +0800 Subject: [PATCH 0609/1123] [CI] try to fix mac-x64 gh action Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 569660fc..7f709b88 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -107,7 +107,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | cd build From f3442bec8cf0c784baa7521e902f34252d99aa5f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 16:39:53 +0800 Subject: [PATCH 0610/1123] [CI] restore macos-x64-gcc build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 119 +++++++++++++------------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 7f709b88..5842528c 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -7,63 +7,66 @@ on: - dev jobs: - # gcc: - # runs-on: macos-latest - # strategy: - # matrix: - # build_type: [ Debug, Release ] - # gpu_api: [ None ] - # env: - # BUILD_TYPE: ${{ matrix.build_type }} - # GPU_API: ${{ matrix.gpu_api }} - # steps: - # # - name: brew upgrade & update - # # run: | - # # brew update - # # brew upgrade - # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - # run: | - # echo $BUILD_TYPE - # echo $GPU_API - # - name: Install Ninja build system - # run: brew install ninja - # - name: Install dependencies - # run: | - # brew install libpng - # brew install xsimd - # - name: Checkout repository - # uses: actions/checkout@v4 - # - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract - # run: | - # curl -JL -o ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - # 7z x -o"./3rdParty/Qt6.6.0-appleclang-static-x86_64" ./3rdParty/Qt6.6.0-appleclang-static-x86_64.7z - # - name: Add /usr/local/lib to PATH - # run: echo "/usr/local/lib" >> $GITHUB_PATH - # - name: Check PATH - # run: echo $PATH - # - name: Configure CMake - # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_PREFIX_PATH=3rdParty/Qt6.6.0-appleclang-static-x86_64 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 - # - name: Build - # run: | - # cd build - # cmake --build . --parallel - # - name: CPack - # run: | - # cd build - # cpack -G ZIP - # - name: Test installation - # run: | - # cd build - # cmake --install . - # # chmod +x vccl.app/Contents/MacOS/vccl - # - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - name: Upload Artifacts - # uses: actions/upload-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-gcc - # path: build/SlopeCraft*.zip + gcc: + runs-on: macos-latest + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: + # - name: brew upgrade & update + # run: | + # brew update + # brew upgrade + - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + run: | + echo $BUILD_TYPE + echo $GPU_API + - name: Install Ninja build system + run: brew install ninja + - name: Install dependencies + run: | + brew install libpng xsimd libzip p7zip + + - name: Checkout repository + uses: actions/checkout@v4 + - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + run: | + curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* + chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* + + - name: Add /usr/local/lib to PATH + run: echo "/usr/local/lib" >> $GITHUB_PATH + - name: Check PATH + run: echo $PATH + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + - name: Build + run: | + cd build + cmake --build . --parallel + - name: CPack + run: | + cd build + cpack -G ZIP + - name: Test installation + run: | + cd build + cmake --install . + # chmod +x vccl.app/Contents/MacOS/vccl + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-gcc + path: build/SlopeCraft*.zip clang: runs-on: macos-latest @@ -128,5 +131,5 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-intel-clang + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-clang path: build/SlopeCraft*.zip From 6804772b9411a54085642d9541e8493d35dd911d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 17:50:12 +0800 Subject: [PATCH 0611/1123] [CI] fix macos-x64-gcc build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 5842528c..199bd744 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -45,7 +45,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | cd build From be62513f9f192d8c43c5b7b18d400e08cd4c8ada Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 12 Nov 2023 17:54:06 +0800 Subject: [PATCH 0612/1123] [CI] remove macos-x64-gcc build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 122 +++++++++++++------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 199bd744..a0e09e5e 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -7,67 +7,6 @@ on: - dev jobs: - gcc: - runs-on: macos-latest - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - steps: - # - name: brew upgrade & update - # run: | - # brew update - # brew upgrade - - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - run: | - echo $BUILD_TYPE - echo $GPU_API - - name: Install Ninja build system - run: brew install ninja - - name: Install dependencies - run: | - brew install libpng xsimd libzip p7zip - - - name: Checkout repository - uses: actions/checkout@v4 - - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract - run: | - curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z - chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* - chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* - - - name: Add /usr/local/lib to PATH - run: echo "/usr/local/lib" >> $GITHUB_PATH - - name: Check PATH - run: echo $PATH - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - - name: Build - run: | - cd build - cmake --build . --parallel - - name: CPack - run: | - cd build - cpack -G ZIP - - name: Test installation - run: | - cd build - cmake --install . - # chmod +x vccl.app/Contents/MacOS/vccl - - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-gcc - path: build/SlopeCraft*.zip - clang: runs-on: macos-latest strategy: @@ -133,3 +72,64 @@ jobs: with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-clang path: build/SlopeCraft*.zip + + # gcc: + # runs-on: macos-latest + # strategy: + # matrix: + # build_type: [ Debug, Release ] + # gpu_api: [ None ] + # env: + # BUILD_TYPE: ${{ matrix.build_type }} + # GPU_API: ${{ matrix.gpu_api }} + # steps: + # # - name: brew upgrade & update + # # run: | + # # brew update + # # brew upgrade + # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) + # run: | + # echo $BUILD_TYPE + # echo $GPU_API + # - name: Install Ninja build system + # run: brew install ninja + # - name: Install dependencies + # run: | + # brew install libpng xsimd libzip p7zip + # + # - name: Checkout repository + # uses: actions/checkout@v4 + # - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + # run: | + # curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + # 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + # chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* + # chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* + # + # - name: Add /usr/local/lib to PATH + # run: echo "/usr/local/lib" >> $GITHUB_PATH + # - name: Check PATH + # run: echo $PATH + # - name: Configure CMake + # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + # - name: Build + # run: | + # cd build + # cmake --build . --parallel + # - name: CPack + # run: | + # cd build + # cpack -G ZIP + # - name: Test installation + # run: | + # cd build + # cmake --install . + # # chmod +x vccl.app/Contents/MacOS/vccl + # + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # - name: Upload Artifacts + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-gcc + # path: build/SlopeCraft*.zip \ No newline at end of file From 601e6c9e9c21b8fd4a7282ad7506edbb5b3d9a81 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 12:56:01 +0800 Subject: [PATCH 0613/1123] [CI] try to fix mac arm actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 40dd4f25..8d72d42c 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,7 +24,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH=/Users/slopecraft/Documents/cpp/qt/qt6.6.0-static -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build From 305b4bc58b91dac5248f6402444fa2080e148121 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 13:01:09 +0800 Subject: [PATCH 0614/1123] [CI] try to fix mac arm actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 8d72d42c..2e7ff603 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -24,7 +24,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: | + ls $HOME/Documents/cpp/qt/qt6.6.0-static -l + cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build From e80c9cfd5d65b84183a5f935e92d490edceef9aa Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 13:05:00 +0800 Subject: [PATCH 0615/1123] [CI] try to fix mac arm actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 2e7ff603..63359c93 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -23,10 +23,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Configure CMake + - name: Check env run: | + whoami + pwd ls $HOME/Documents/cpp/qt/qt6.6.0-static -l - cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build From 51404cc5c8d6861602b9d46cfaac26e439c43277 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 13:09:33 +0800 Subject: [PATCH 0616/1123] [CI] try to fix mac arm actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 63359c93..5bfdac99 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -27,6 +27,7 @@ jobs: run: | whoami pwd + ls $HOME ls $HOME/Documents/cpp/qt/qt6.6.0-static -l - name: Configure CMake From 9992013572eea366c30ce939312cd7e99e8424fc Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 13:27:12 +0800 Subject: [PATCH 0617/1123] [CI] try to fix mac arm actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 5bfdac99..36df6264 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -23,12 +23,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Check env - run: | - whoami - pwd - ls $HOME - ls $HOME/Documents/cpp/qt/qt6.6.0-static -l + # - name: Check env + # run: | + # whoami + # pwd + # ls $HOME + # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 From 7c0b4822397af19e3fd2a2818a6a8fd856ff73ba Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 13 Nov 2023 22:39:49 +0800 Subject: [PATCH 0618/1123] [CI] fix VisualCraft.app in gh actions Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 24 +++++++++++++++++++---- .github/workflows/macos-build-x64.yml | 26 ++++++++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 36df6264..cccd990d 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -36,14 +36,30 @@ jobs: run: | cd build cmake --build . --parallel - - name: CPack + # - name: CPack + # run: | + # cd build + # cpack -G ZIP + - name: Install run: | cd build - cpack -G ZIP - - name: Test installation + cmake --install . + + - name: Fix VisualCraft.app + run: | + cd build/install + cd VisualCraft.app/Contents/Frameworks + cp /opt/homebrew/lib/libzstd.1.dylib . + cp /opt/homebrew/lib/liblzma.5.dylib . + install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + cd ../../.. + codesign --force --deep --sign=- VisualCraft.app + + - name: Compress as zip run: | cd build - cmake --install . + 7z a SlopeCraft-5.2.1-macOS-arm64.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index a0e09e5e..b3d6e8dc 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -54,17 +54,33 @@ jobs: run: | cd build cmake --build . --parallel - - name: CPack - run: | - cd build - cpack -G ZIP + # - name: CPack + # run: | + # cd build + # cpack -G ZIP - - name: Test installation + - name: Install run: | cd build cmake --install . + + - name: Fix VisualCraft.app + run: | + cd build/install + cd VisualCraft.app/Contents/Frameworks + cp /opt/homebrew/lib/libzstd.1.dylib . + cp /opt/homebrew/lib/liblzma.5.dylib . + install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + cd ../../.. + codesign --force --deep --sign=- VisualCraft.app # chmod +x vccl.app/Contents/MacOS/vccl + - name: Compress as zip + run: | + cd build + 7z a SlopeCraft-5.2.1-macOS-intel.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts From ad6a795ae553ea4bed5cf0a58b450d3eba053296 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 16:37:50 +0800 Subject: [PATCH 0619/1123] [CI] migrate Qt binaries to dedicated repo Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- .github/workflows/windows-build.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index b3d6e8dc..77db570a 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@v4 - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract run: | - curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z + curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/Qt6.6.0-appleclang-static-x86_64.7z 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 951a928f..329d1e8b 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -59,7 +59,7 @@ jobs: - name: Download Qt6.5.0-msvc-shared and extract run: | cmd - curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-msvc-shared.7z" + curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-mingw-windows/Qt6.5.0-gcc11-shared-offical.7z" 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z exit tree /f bin/Qt6.5.0-msvc-shared @@ -195,7 +195,7 @@ jobs: - name: Download Qt6.5.0-gcc11-shared-offical and extract run: | cmd - curl -JL -o bin/Qt6.5.0-gcc11-shared-offical.7z "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/win-binaries/Qt6.5.0-gcc11-shared-offical.7z" + curl -JL -o bin/Qt6.5.0-gcc11-shared-offical.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-mingw-windows/Qt6.5.0-gcc11-shared-offical.7z" 7z x -o"bin/Qt6.5.0-gcc11-shared-offical" bin/Qt6.5.0-gcc11-shared-offical.7z exit tree /f bin/Qt6.5.0-gcc11-shared-offical From 5011d37ac0f41afe435508e4170825db31f65aec Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 16:40:55 +0800 Subject: [PATCH 0620/1123] [CI] Find location of liblzma and libzstd dylib Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 77db570a..4ad1717b 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -35,6 +35,12 @@ jobs: run: | brew install libpng xsimd p7zip libzip + - name: Find liblzma and libzstd dylibs + run: | + find /opt/homebrew -name liblzma.5.dylib + find /opt/homebrew -name libzstd.1.dylib + + - name: Checkout repository uses: actions/checkout@v4 - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract @@ -68,6 +74,7 @@ jobs: run: | cd build/install cd VisualCraft.app/Contents/Frameworks + otool -L libzip.5.dylib cp /opt/homebrew/lib/libzstd.1.dylib . cp /opt/homebrew/lib/liblzma.5.dylib . install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib From 260af5677709dd6e7fd14c0a10d6a09b6e4d0331 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 16:43:44 +0800 Subject: [PATCH 0621/1123] [CI] Find location of liblzma and libzstd dylib Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 4ad1717b..45d2091f 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -37,8 +37,8 @@ jobs: - name: Find liblzma and libzstd dylibs run: | - find /opt/homebrew -name liblzma.5.dylib - find /opt/homebrew -name libzstd.1.dylib + find / -name liblzma.5.dylib 2>/dev/null + find / -name libzstd.1.dylib 2>/dev/null - name: Checkout repository From f77e53cb1a0a735dcd140d22dd43c483590483c5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 16:53:20 +0800 Subject: [PATCH 0622/1123] [CI] Fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 329d1e8b..fec68739 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -59,7 +59,7 @@ jobs: - name: Download Qt6.5.0-msvc-shared and extract run: | cmd - curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-mingw-windows/Qt6.5.0-gcc11-shared-offical.7z" + curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-msvc-windows/Qt6.5.0-msvc-shared.7z" 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z exit tree /f bin/Qt6.5.0-msvc-shared From d23af346d8c597fe22a328082ca1204f7378b799 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 18:13:50 +0800 Subject: [PATCH 0623/1123] [CI] find location of xz and zstd Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 45d2091f..a92a48cb 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -33,13 +33,14 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip + brew install libpng xsimd p7zip libzip zstd xz - name: Find liblzma and libzstd dylibs run: | - find / -name liblzma.5.dylib 2>/dev/null - find / -name libzstd.1.dylib 2>/dev/null - + find /usr/local/Cellar -name liblzma.5.dylib 2>/dev/null + find /usr/local/Cellar -name libzstd.1.dylib 2>/dev/null + + find - name: Checkout repository uses: actions/checkout@v4 From 45c27439c73ea58af9dc1bb6d30399bd7d8b4a2f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 15 Nov 2023 18:17:14 +0800 Subject: [PATCH 0624/1123] [CI] Fix macos-x64 build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index a92a48cb..7c615ef9 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -35,12 +35,10 @@ jobs: run: | brew install libpng xsimd p7zip libzip zstd xz - - name: Find liblzma and libzstd dylibs - run: | - find /usr/local/Cellar -name liblzma.5.dylib 2>/dev/null - find /usr/local/Cellar -name libzstd.1.dylib 2>/dev/null - - find + # - name: Find liblzma and libzstd dylibs + # run: | + # find /usr/local/Cellar -name liblzma.5.dylib 2>/dev/null + # find /usr/local/Cellar -name libzstd.1.dylib 2>/dev/null - name: Checkout repository uses: actions/checkout@v4 @@ -76,8 +74,8 @@ jobs: cd build/install cd VisualCraft.app/Contents/Frameworks otool -L libzip.5.dylib - cp /opt/homebrew/lib/libzstd.1.dylib . - cp /opt/homebrew/lib/liblzma.5.dylib . + cp /usr/local/Cellar/zstd/1.5.5/lib/libzstd.1.dylib . + cp /usr/local/Cellar/xz/5.4.4/lib/liblzma.5.dylib . install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib cd ../../.. From 01a32677675a91adf3b7c2b22017b2120b861b48 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 15:13:06 +0800 Subject: [PATCH 0625/1123] introduce DylibDeployer and Codesigner Signed-off-by: ToKiNoBug --- CMakeLists.txt | 1 + MapViewer/install.cmake | 7 +++- SlopeCraft/install.cmake | 7 +++- VisualCraft/install.cmake | 7 +++- cmake/configure_DylibDeployer.cmake | 16 ++++++++ cmake/run_codesign.cmake | 62 ----------------------------- imageCutter/install.cmake | 8 +++- 7 files changed, 38 insertions(+), 70 deletions(-) create mode 100644 cmake/configure_DylibDeployer.cmake delete mode 100644 cmake/run_codesign.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 200bf49e..27cd57cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ include(cmake/find_HeuristicFlow.cmake) include(cmake/find_qt6.cmake) include(cmake/configure_DLLDeployer.cmake) +include(cmake/configure_DylibDeployer.cmake) # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index b2904c2a..909a0d04 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -49,8 +49,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) - include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) - RCS_add_codesign(MapViewer) + DylibD_add_deploy(MapViewer + INSTALL_DESTINATION . + RPATH_POLICY REPLACE) + RCS_add_codesign(MapViewer + INSTALL_DESTINATION .) return() endif () diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index f36bc7cb..5a8d3223 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -60,8 +60,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) - include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) - RCS_add_codesign(SlopeCraft) + DylibD_add_deploy(SlopeCraft + INSTALL_DESTINATION . + RPATH_POLICY REPLACE) + RCS_add_codesign(SlopeCraft + INSTALL_DESTINATION .) return() endif () diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 1ff89a2e..a8873694 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -62,8 +62,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) - include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) - RCS_add_codesign(VisualCraft) + DylibD_add_deploy(VisualCraft + INSTALL_DESTINATION . + RPATH_POLICY REPLACE) + RCS_add_codesign(VisualCraft + INSTALL_DESTINATION .) return() endif () \ No newline at end of file diff --git a/cmake/configure_DylibDeployer.cmake b/cmake/configure_DylibDeployer.cmake new file mode 100644 index 00000000..f6c86e35 --- /dev/null +++ b/cmake/configure_DylibDeployer.cmake @@ -0,0 +1,16 @@ +if (NOT APPLE) + return() +endif () + +include(${CMAKE_CURRENT_LIST_DIR}/configure_DLLDeployer.cmake) + +set(DylibD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DylibDeployer.cmake) +set(DylibD_file ${DylibD_download_dir}/DylibDeployer.cmake) +SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.0/DylibDeployer.cmake + ${DylibD_file}) +include(${DylibD_file}) + +set(Codesigner_file ${DylibD_download_dir}/Codesigner.cmake) +SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.0/Codesigner.cmake + ${Codesigner_file}) +include(${Codesigner_file}) \ No newline at end of file diff --git a/cmake/run_codesign.cmake b/cmake/run_codesign.cmake deleted file mode 100644 index 96219490..00000000 --- a/cmake/run_codesign.cmake +++ /dev/null @@ -1,62 +0,0 @@ -if (DEFINED CMAKE_GENERATOR) - message(STATUS "Running at configuration time") - option(RCS_configure_time "Whether this script is running at configuration time" ON) -else () - # Otherwise we guess that it's running at build or installation time. - message(STATUS "Running at build/install time") - option(RCS_configure_time "Whether this script is running at configuration time" OFF) -endif () - -option(RCS_run_directly "" OFF) -if(RCS_configure_time) - set(RCS_source_file ${CMAKE_CURRENT_LIST_FILE}) -else() - set(RCS_this_file @rcs_this_file@) - set(RCS_bundle_name @rcs_bundle_name@) - set(RCS_bundle_version @rcs_bundle_version@) - - set(RCS_working_dir . CACHE FILEPATH "") -endif() - - -function(RCS_add_codesign target) - set(rcs_this_file "${CMAKE_CURRENT_BINARY_DIR}/run_codesign_install.cmake") - set(rcs_bundle_name ${target}) - get_target_property(rcs_bundle_version ${target} VERSION) - - configure_file(${RCS_source_file} - ${rcs_this_file} - @ONLY) - - install(SCRIPT ${rcs_this_file} - DESTINATION .) -endfunction() - -if(NOT RCS_configure_time) - if(NOT RCS_run_directly) - - message(STATUS "RCS_working_dir = \"${RCS_working_dir}\"") - - execute_process(COMMAND ${CMAKE_COMMAND} -DRCS_run_directly:BOOL=ON -DRCS_working_dir=${CMAKE_INSTALL_PREFIX} -P ${RCS_this_file} - WORKING_DIRECTORY ${RCS_working_dir} - COMMAND_ERROR_IS_FATAL ANY) - return() - endif() - - set(bundle_prefix "${RCS_working_dir}/${RCS_bundle_name}.app/Contents/MacOS") - - if(IS_SYMLINK "${bundle_prefix}/${RCS_bundle_name}") - message(STATUS "Found symlink file ${bundle_prefix}/${RCS_bundle_name}") - - file(REMOVE "${bundle_prefix}/${RCS_bundle_name}") - file(RENAME "${bundle_prefix}/${RCS_bundle_name}-${RCS_bundle_version}" "${bundle_prefix}/${RCS_bundle_name}") - endif () - - if(IS_SYMLINK "${bundle_prefix}/${RCS_bundle_name}") - message(WARNING "\"${bundle_prefix}/${RCS_bundle_name}\" is a symlink, but it should be regular file.") - endif () - - execute_process(COMMAND codesign --force --deep --sign=- ${RCS_bundle_name}.app - WORKING_DIRECTORY ${RCS_working_dir} - COMMAND_ERROR_IS_FATAL ANY) -endif() \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index a37c11a8..15c23978 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -60,8 +60,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) - include(${CMAKE_SOURCE_DIR}/cmake/run_codesign.cmake) - RCS_add_codesign(imageCutter) + DylibD_add_deploy(imageCutter + INSTALL_DESTINATION . + RPATH_POLICY REPLACE) + + RCS_add_codesign(imageCutter + INSTALL_DESTINATION .) return() endif () From fcaa9b9805d04087938e35dff71f9ce1223cabb3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 15:23:44 +0800 Subject: [PATCH 0626/1123] install SCL and VCL into bundle Signed-off-by: ToKiNoBug --- SlopeCraft/install.cmake | 4 ++++ SlopeCraftL/install.cmake | 26 +++++++++++++------------- VisualCraft/install.cmake | 4 ++++ VisualCraftL/install.cmake | 16 ++++++++-------- vccl/install.cmake | 9 +++++++++ 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 5a8d3223..f03a517b 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -56,6 +56,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") file(COPY ${SlopeCraft_install_presets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) + install(TARGETS SlopeCraftL + RUNTIME DESTINATION SlopeCraft.app/Contents/Frameworks + LIBRARY DESTINATION SlopeCraft.app/Contents/Frameworks) + QD_add_deployqt(SlopeCraft INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index e85b7177..b0880d5e 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -12,7 +12,7 @@ set(SlopeCraft_SCL_Cpp_include_files ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h SlopeCraftL.h SlopeCraftL_global.h - ) +) if (CMAKE_SYSTEM_NAME MATCHES "Windows") # install for applications @@ -26,7 +26,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib # LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib - ) + ) # install(TARGETS SlopeCraftL_C # RUNTIME DESTINATION ./../install_SlopeCraftL/C/bin @@ -63,17 +63,17 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # install for applications - install(TARGETS SlopeCraftL - RUNTIME DESTINATION . - LIBRARY DESTINATION .) + # install(TARGETS SlopeCraftL + # RUNTIME DESTINATION . + # LIBRARY DESTINATION .) # install to lib dirs - install(TARGETS SlopeCraftL - RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - - # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - ) + # install(TARGETS SlopeCraftL + # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib + # + # # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib + # ) # install(TARGETS SlopeCraftL_C # RUNTIME DESTINATION ../install_SlopeCraftL/C/bin @@ -81,8 +81,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # # LIBRARY DESTINATION ../install_SlopeCraftL/C/lib # ) - install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION ../install_SlopeCraftL/Cpp/include) + # install(FILES ${SlopeCraft_SCL_Cpp_include_files} + # DESTINATION ../install_SlopeCraftL/Cpp/include) # install(FILES ${SlopeCraft_SCL_C_include_files} # DESTINATION ../install_SlopeCraftL/C/include) diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index a8873694..2370590d 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -58,6 +58,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION VisualCraft.app/Contents/MacOS/Blocks_VCL ) + install(TARGETS VisualCraftL + RUNTIME DESTINATION VisualCraft.app/Contents/Frameworks + LIBRARY DESTINATION VisualCraft.app/Contents/Frameworks) + QD_add_deployqt(VisualCraft INSTALL_MODE INSTALL_DESTINATION . FLAGS ${SlopeCraft_macdeployqt_flags_install}) diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index 9b685572..45a3fbbf 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -10,7 +10,7 @@ if (${WIN32}) RUNTIME DESTINATION . # LIBRARY DESTINATION . - ) + ) install(FILES ${VCL_app_files} DESTINATION Blocks_VCL) @@ -18,7 +18,7 @@ if (${WIN32}) install(TARGETS VisualCraftL RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) - + DLLD_add_deploy(VisualCraftL INSTALL_MODE INSTALL_DESTINATION .) @@ -55,17 +55,17 @@ if (${LINUX}) endif () if (${APPLE}) - install(TARGETS VisualCraftL - RUNTIME DESTINATION . - LIBRARY DESTINATION .) + # install(TARGETS VisualCraftL + # RUNTIME DESTINATION . + # LIBRARY DESTINATION .) # zips and blocklist jsons are installed inside each macos bundle # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip # install(FILES ${VCL_app_files} # DESTINATION Blocks_VCL) - install(TARGETS VisualCraftL - RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) + # install(TARGETS VisualCraftL + # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin + # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) return() endif () diff --git a/vccl/install.cmake b/vccl/install.cmake index 873fc245..316b1782 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -68,9 +68,18 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(FILES ${VCL_app_files} DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) + install(TARGETS VisualCraftL + RUNTIME DESTINATION VisualCraft.app/Contents/Frameworks + LIBRARY DESTINATION VisualCraft.app/Contents/Frameworks) + # Do not run deploy_qt.cmake, but a specialied one install(SCRIPT ${deployqt_vccl_script} DESTINATION .) + DylibD_add_deploy(vccl + INSTALL_DESTINATION ${vccl_prefix}) + RCS_add_codesign(vccl + INSTALL_DESTINATION ${vccl_prefix}) + return() endif () \ No newline at end of file From ff9aa5429d375426db1699f48042fcb6648b8bef Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 15:30:01 +0800 Subject: [PATCH 0627/1123] Change the name or macOS package Signed-off-by: ToKiNoBug --- cpack/make-packs.cmake | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cpack/make-packs.cmake b/cpack/make-packs.cmake index 583aec0d..e5637104 100644 --- a/cpack/make-packs.cmake +++ b/cpack/make-packs.cmake @@ -16,7 +16,13 @@ if (${APPLE}) if (${cpu_arch} STREQUAL "AMD64") set(cpu_arch "x86_64") endif () - set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${cpu_arch}") + + if (${cpu_arch} STREQUAL "x86_64") + set(CPACK_SYSTEM_NAME "macOS-Intel") + endif () + if (${cpu_arch} STREQUAL "arm64") + set(CPACK_SYSTEM_NAME "macOS-Silicon") + endif () endif () include(${CMAKE_SOURCE_DIR}/cpack/deb.cmake) From 2f9517792c4759eaed383c793d080111946c8ad3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 15:30:56 +0800 Subject: [PATCH 0628/1123] [CI] Change the name or macOS package Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 22 +++++++++++----------- .github/workflows/macos-build-x64.yml | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index cccd990d..585f899c 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -45,21 +45,21 @@ jobs: cd build cmake --install . - - name: Fix VisualCraft.app - run: | - cd build/install - cd VisualCraft.app/Contents/Frameworks - cp /opt/homebrew/lib/libzstd.1.dylib . - cp /opt/homebrew/lib/liblzma.5.dylib . - install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib - install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib - cd ../../.. - codesign --force --deep --sign=- VisualCraft.app + # - name: Fix VisualCraft.app + # run: | + # cd build/install + # cd VisualCraft.app/Contents/Frameworks + # cp /opt/homebrew/lib/libzstd.1.dylib . + # cp /opt/homebrew/lib/liblzma.5.dylib . + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + # cd ../../.. + # codesign --force --deep --sign=- VisualCraft.app - name: Compress as zip run: | cd build - 7z a SlopeCraft-5.2.1-macOS-arm64.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 7c615ef9..3b40c5a7 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -69,23 +69,23 @@ jobs: cd build cmake --install . - - name: Fix VisualCraft.app - run: | - cd build/install - cd VisualCraft.app/Contents/Frameworks - otool -L libzip.5.dylib - cp /usr/local/Cellar/zstd/1.5.5/lib/libzstd.1.dylib . - cp /usr/local/Cellar/xz/5.4.4/lib/liblzma.5.dylib . - install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib - install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib - cd ../../.. - codesign --force --deep --sign=- VisualCraft.app + # - name: Fix VisualCraft.app + # run: | + # cd build/install + # cd VisualCraft.app/Contents/Frameworks + # otool -L libzip.5.dylib + # cp /usr/local/Cellar/zstd/1.5.5/lib/libzstd.1.dylib . + # cp /usr/local/Cellar/xz/5.4.4/lib/liblzma.5.dylib . + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + # cd ../../.. + # codesign --force --deep --sign=- VisualCraft.app # chmod +x vccl.app/Contents/MacOS/vccl - name: Compress as zip run: | cd build - 7z a SlopeCraft-5.2.1-macOS-intel.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + 7z a SlopeCraft-5.2.1-macOS-Intel.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV From 1da00c3c30b551a841fe90f2f4851c4e7a8d8037 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 15:50:50 +0800 Subject: [PATCH 0629/1123] [CI] Fix download link of macOS x64 build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 3b40c5a7..e77f43ad 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -42,10 +42,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + - name: Download qt6.6.0-static-x86_64-apple-darwin.tar.xz and extract run: | - curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/Qt6.6.0-appleclang-static-x86_64.7z - 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + curl -JL -o ~/Downloads/qt6.6.0-static-x86_64-apple-darwin.tar.xz https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz + cd ~/Downloads + tar xzf qt6.6.0-static-x86_64-apple-darwin.tar.xz + mv qt6.6.0-static-x86_64-apple-darwin Qt6.6.0-appleclang-static-x86_64 chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* @@ -121,10 +123,10 @@ jobs: # # - name: Checkout repository # uses: actions/checkout@v4 - # - name: Download Qt6.6.0-appleclang-static-x86_64.7z and extract + # - name: Download qt6.6.0-static-x86_64-apple-darwin.tar.xz and extract # run: | - # curl -JL -o ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/Qt6.6.0-appleclang-static-x86_64.7z - # 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/Qt6.6.0-appleclang-static-x86_64.7z + # curl -JL -o ~/Downloads/qt6.6.0-static-x86_64-apple-darwin.tar.xz https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/mac-binaries/qt6.6.0-static-x86_64-apple-darwin.tar.xz + # 7z x -o"$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64" ~/Downloads/qt6.6.0-static-x86_64-apple-darwin.tar.xz # chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/bin/* # chmod +x ~/Downloads/Qt6.6.0-appleclang-static-x86_64/libexec/* # From 8b8ee6e6cb9eb2fb2ebc48cd0eb43a683f558800 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 16:38:09 +0800 Subject: [PATCH 0630/1123] [CI] Change CMAKE_OSX_DEPLOYMENT_TARGET for x64 to 10.15 ('aligned_alloc' is only available on macOS 10.15 or newer Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index e77f43ad..d21d87d9 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -33,7 +33,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip zstd xz + brew install libpng xsimd p7zip libzip zstd xz eigen # - name: Find liblzma and libzstd dylibs # run: | @@ -55,8 +55,8 @@ jobs: run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + - name: Configure CMake # + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | cd build From f77d79da097ccfca289cf28a7283d0248aa9d706 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 20 Nov 2023 19:27:11 +0800 Subject: [PATCH 0631/1123] Use DylibDeployer and Codesigner of v1.0.2 Signed-off-by: ToKiNoBug --- cmake/configure_DylibDeployer.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/configure_DylibDeployer.cmake b/cmake/configure_DylibDeployer.cmake index f6c86e35..9c48969e 100644 --- a/cmake/configure_DylibDeployer.cmake +++ b/cmake/configure_DylibDeployer.cmake @@ -6,11 +6,11 @@ include(${CMAKE_CURRENT_LIST_DIR}/configure_DLLDeployer.cmake) set(DylibD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DylibDeployer.cmake) set(DylibD_file ${DylibD_download_dir}/DylibDeployer.cmake) -SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.0/DylibDeployer.cmake +SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/DylibDeployer.cmake ${DylibD_file}) include(${DylibD_file}) set(Codesigner_file ${DylibD_download_dir}/Codesigner.cmake) -SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.0/Codesigner.cmake +SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/Codesigner.cmake ${Codesigner_file}) include(${Codesigner_file}) \ No newline at end of file From c8d5d161842b5eeeff72e676408b0062049c7c6a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 27 Nov 2023 00:38:19 +0800 Subject: [PATCH 0632/1123] [macOS] Fix install dest of VCL for vccl Signed-off-by: ToKiNoBug --- vccl/install.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vccl/install.cmake b/vccl/install.cmake index 316b1782..6ee224a8 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -69,8 +69,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) install(TARGETS VisualCraftL - RUNTIME DESTINATION VisualCraft.app/Contents/Frameworks - LIBRARY DESTINATION VisualCraft.app/Contents/Frameworks) + RUNTIME DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks + LIBRARY DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks) # Do not run deploy_qt.cmake, but a specialied one install(SCRIPT ${deployqt_vccl_script} From 60907d71c76680aa053cf27784ba3e71226b2c1f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 30 Nov 2023 23:33:16 +0800 Subject: [PATCH 0633/1123] recognise amd64 better Signed-off-by: ToKiNoBug --- cmake/select_vectorize_flag.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/select_vectorize_flag.cmake b/cmake/select_vectorize_flag.cmake index fdf90ced..4c308cad 100644 --- a/cmake/select_vectorize_flag.cmake +++ b/cmake/select_vectorize_flag.cmake @@ -4,7 +4,8 @@ include(CheckCXXCompilerFlag) message(STATUS "System processor arch = ${CMAKE_SYSTEM_PROCESSOR}") -if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") +set(amd64_arch_names AMD64 x86_64) +if (${CMAKE_SYSTEM_PROCESSOR} IN_LIST amd64_arch_names) if (${MSVC}) set(SlopeCraft_vectorize_flags "/arch:AVX2") else () @@ -16,7 +17,7 @@ elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64") # set(SlopeCraft_vectorize_flags -mcpu=apple-m1 -mfpu=neon) # endif () else () - message(WARNING "Unknown cpu arch, using -march=native") + message(WARNING "Unknown cpu arch \"${CMAKE_SYSTEM_PROCESSOR}\", using -march=native") endif () From 52dd926999747ce071d5dea0a85aca7d050714ec Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 30 Nov 2023 23:55:28 +0800 Subject: [PATCH 0634/1123] Fix build with fmt v10 Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 2 +- cmake/configure_fmtlib.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index ef035f96..73f2d5ff 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -258,7 +258,7 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { if (!ok) { std::string msg = fmt::format( "Failed to parse {}, : invalid value for block state {} : {}", - filename, pair.key(), pair.value()); + filename, pair.key().c_str(), to_string(pair.value())); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } diff --git a/cmake/configure_fmtlib.cmake b/cmake/configure_fmtlib.cmake index f989424c..62359fe7 100644 --- a/cmake/configure_fmtlib.cmake +++ b/cmake/configure_fmtlib.cmake @@ -4,7 +4,7 @@ set(SC_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) -find_package(fmt QUIET) +find_package(fmt 9.1.0 QUIET) if (NOT ${fmt_FOUND}) include(FetchContent) From e6ba59377f7bcd5f29f227facf7643134cb23865 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 1 Dec 2023 00:20:57 +0800 Subject: [PATCH 0635/1123] add icons and application list for gnome Signed-off-by: ToKiNoBug --- MapViewer/install.cmake | 6 ++++++ MapViewer/others/MapViewer.desktop | 7 +++++++ SlopeCraft/install.cmake | 8 +++++--- SlopeCraft/others/SlopeCraft.desktop | 7 +++++++ VisualCraft/install.cmake | 6 ++++++ VisualCraft/others/VisualCraft.desktop | 7 +++++++ imageCutter/install.cmake | 6 ++++++ imageCutter/others/imageCutter.desktop | 7 +++++++ 8 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 MapViewer/others/MapViewer.desktop create mode 100644 SlopeCraft/others/SlopeCraft.desktop create mode 100644 VisualCraft/others/VisualCraft.desktop create mode 100644 imageCutter/others/imageCutter.desktop diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 909a0d04..87740af7 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -28,6 +28,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") BUNDLE DESTINATION lib ) + install(FILES others/MapViewer_64.png + DESTINATION share/pixmaps + RENAME com.github.SlopeCraft.MapViewer.png) + install(FILES others/MapViewer.desktop + DESTINATION share/applications) + # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() diff --git a/MapViewer/others/MapViewer.desktop b/MapViewer/others/MapViewer.desktop new file mode 100644 index 00000000..45bc8c27 --- /dev/null +++ b/MapViewer/others/MapViewer.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=MapViewer +Comment=Minecraft map browser +Exec=MapViewer +Icon=com.github.SlopeCraft.MapViewer.png +Type=Application +Keywords=SlopeCraft; \ No newline at end of file diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index f03a517b..e2b38f60 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -154,10 +154,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") file(COPY ${SlopeCraft_install_png_customblocks} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) - file(GLOB SlopeCraft_Icon ${CMAKE_SOURCE_DIR}/SlopeCraftMain/others/SlopeCraftIconNew.png) - install(FILES ${SlopeCraft_Icon} - DESTINATION bin/icons) + install(FILES others/SlopeCraftIconNew.png + DESTINATION share/pixmaps + RENAME com.github.SlopeCraft.SlopeCraft.png) + install(FILES others/SlopeCraft.desktop + DESTINATION share/applications) # Install presets install(FILES ${SlopeCraft_install_presets} diff --git a/SlopeCraft/others/SlopeCraft.desktop b/SlopeCraft/others/SlopeCraft.desktop new file mode 100644 index 00000000..937add58 --- /dev/null +++ b/SlopeCraft/others/SlopeCraft.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=SlopeCraft +Comment=Map Pixel Art Generator for Minecraft +Exec=SlopeCraft +Icon=com.github.SlopeCraft.SlopeCraft.png +Type=Application +Keywords=SlopeCraft; \ No newline at end of file diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 2370590d..15dff4f1 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -31,6 +31,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(FILES vc-config.json DESTINATION bin) + install(FILES others/Vc_256.png + DESTINATION share/pixmaps + RENAME com.github.SlopeCraft.VisualCraft.png) + install(FILES others/VisualCraft.desktop + DESTINATION share/applications) + # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) diff --git a/VisualCraft/others/VisualCraft.desktop b/VisualCraft/others/VisualCraft.desktop new file mode 100644 index 00000000..9abde249 --- /dev/null +++ b/VisualCraft/others/VisualCraft.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=VisualCraft +Comment=Visual Pixel Art Generator for Minecraft +Exec=VisualCraft +Icon=com.github.SlopeCraft.VisualCraft.png +Type=Application +Keywords=SlopeCraft; \ No newline at end of file diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index 15c23978..e45cc226 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -39,6 +39,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") BUNDLE DESTINATION lib ) + install(FILES others/imageCutterIconNew.png + DESTINATION share/pixmaps + RENAME com.github.SlopeCraft.imageCutter.png) + install(FILES others/imageCutter.desktop + DESTINATION share/applications) + # Install platforms and imageformats plugins include(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) return() diff --git a/imageCutter/others/imageCutter.desktop b/imageCutter/others/imageCutter.desktop new file mode 100644 index 00000000..bc4ce1c1 --- /dev/null +++ b/imageCutter/others/imageCutter.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=imageCutter +Comment=Image preprocessor for SlopeCraft +Exec=imageCutter +Icon=com.github.SlopeCraft.imageCutter.png +Type=Application +Keywords=SlopeCraft; \ No newline at end of file From e35bf1847ab9e08dcd5b60532eb2390428cdd134 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 1 Dec 2023 18:32:20 +0800 Subject: [PATCH 0636/1123] [Linux] install headers to include/SlopeCraft Signed-off-by: ToKiNoBug --- SlopeCraftL/install.cmake | 2 +- VisualCraftL/install.cmake | 2 +- cmake/configure_cereal.cmake | 2 +- utilities/install.cmake | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index b0880d5e..d8a24035 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -57,7 +57,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") LIBRARY DESTINATION lib) install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION include) + DESTINATION include/SlopeCraft) return() endif () diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index 45a3fbbf..0bac5117 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -46,7 +46,7 @@ if (${LINUX}) install(FILES ${VCL_app_files} DESTINATION bin/Blocks_VCL) install(FILES ${VCL_include_headers} - DESTINATION include) + DESTINATION include/SlopeCraft) # install(TARGETS libzip::zip # RUNTIME DESTINATION bin diff --git a/cmake/configure_cereal.cmake b/cmake/configure_cereal.cmake index a904fc39..cce92666 100644 --- a/cmake/configure_cereal.cmake +++ b/cmake/configure_cereal.cmake @@ -3,7 +3,7 @@ set(BUILD_SANDBOX OFF) set(BUILD_DOC OFF) set(CEREAL_INSTALL OFF) -find_package(cereal QUIET) +find_package(cereal 1.3.2 QUIET) if (${cereal_FOUND}) return() diff --git a/utilities/install.cmake b/utilities/install.cmake index 630f2b7e..60d3a6b5 100644 --- a/utilities/install.cmake +++ b/utilities/install.cmake @@ -1,19 +1,19 @@ -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(FILES ${CMAKE_BINARY_DIR}/utilities/SC_version_buildtime.h - DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include) + DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include/SlopeCraft) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(FILES ${CMAKE_BINARY_DIR}/utilities/SC_version_buildtime.h - DESTINATION include) + DESTINATION include/SlopeCraft) return() -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") return() -endif() \ No newline at end of file +endif () \ No newline at end of file From d5585afc900eb93f11d844dde7d1def37cabec2e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 1 Dec 2023 18:35:26 +0800 Subject: [PATCH 0637/1123] Update version number to 5.2.2 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27cd57cc..7857a840 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.1) +set(SlopeCraft_version 5.2.2) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 18a801d0782e6c8256f71095081091452c0bc489 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 3 Dec 2023 22:00:44 +0800 Subject: [PATCH 0638/1123] try to find magic_enum first Signed-off-by: ToKiNoBug --- cmake/configure_magic_enum.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/configure_magic_enum.cmake b/cmake/configure_magic_enum.cmake index a6c71ea4..43d2fab3 100644 --- a/cmake/configure_magic_enum.cmake +++ b/cmake/configure_magic_enum.cmake @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.14) +find_package(magic_enum 0.8.2 QUIET) + +if (${magic_enum_FOUND}) + return() +endif () + include(FetchContent) FetchContent_Declare(magic_enum From d8616830df30139693abb518a51612c9786cf361 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 7 Dec 2023 20:31:52 +0800 Subject: [PATCH 0639/1123] update Heu to 1.6.4.1 to fix some warnings in Linux Signed-off-by: ToKiNoBug --- cmake/find_HeuristicFlow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/find_HeuristicFlow.cmake b/cmake/find_HeuristicFlow.cmake index cc968b0a..d71fabe3 100644 --- a/cmake/find_HeuristicFlow.cmake +++ b/cmake/find_HeuristicFlow.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare(Heu GIT_REPOSITORY https://github.com/SlopeCraft/HeuristicFlow.git - GIT_TAG v1.6.4 + GIT_TAG v1.6.4.1 OVERRIDE_FIND_PACKAGE) FetchContent_MakeAvailable(Heu) From 52b434e61898e255dc284e6b6da290182b3cb15e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 7 Dec 2023 20:37:36 +0800 Subject: [PATCH 0640/1123] Fix most build warnings in Linux Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 20 ++++++++++++++------ SlopeCraftL/SlopeCraftL_global.h | 15 +++++++++++---- SlopeCraftL/TokiSlopeCraft_cache.cpp | 3 ++- VisualCraft/ColorBrowser.cpp | 6 +----- VisualCraftL/VisualCraftL_global.h | 7 ++++++- utilities/ColorManip/ColorDiff.cpp | 2 +- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 4 ++-- 7 files changed, 37 insertions(+), 20 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index ef08b362..b421e05c 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -413,7 +413,7 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { cvt_task &task = *taskopt.value(); const ptrdiff_t index = &task - this->tasks.data(); - assert(index >= 0 && index < this->tasks.size()); + assert(index >= 0 && index < ptrdiff_t(this->tasks.size())); if (!task.is_converted) [[unlikely]] { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); @@ -868,20 +868,28 @@ void SCWind::on_ac_about_triggered() noexcept { QString info; info += QStringLiteral("SlopeCraft %1").arg(SlopeCraft::SCL_getSCLVersion()); info += "\n\n"; - info += tr("SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于" - "在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。"); + info += + tr("SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于" + "在 Minecraft " + "中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。"); info += "\n"; - info += tr("本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供"); + info += + tr("本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 " + "以及贡献者) 提供"); info += "\n\n"; info += tr("感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量"); info += "\n"; info += tr("感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献"); info += "\n"; - info += tr("SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。"); + info += + tr("SlopeCraft 在开发时使用了 Qt,zlib 和 eigen " + "等开源库,对上述库的开发者表示感谢。"); info += "\n\n"; info += tr("本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。"); info += "\n\n"; - info += tr("Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有"); + info += + tr("Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, " + "iXOR Technology, Mifan-T, 以及贡献者). 版权所有"); QMessageBox::information(this, tr("关于 SlopeCraft"), info); } diff --git a/SlopeCraftL/SlopeCraftL_global.h b/SlopeCraftL/SlopeCraftL_global.h index 182f12a8..5645ec94 100644 --- a/SlopeCraftL/SlopeCraftL_global.h +++ b/SlopeCraftL/SlopeCraftL_global.h @@ -23,8 +23,15 @@ This file is part of SlopeCraft. #ifndef SLOPECRAFTL_GLOBAL_H #define SLOPECRAFTL_GLOBAL_H -#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ - defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ +#ifdef Q_DECL_EXPORT +#undef Q_DECL_EXPORT +#endif +#ifdef Q_DECL_IMPORT +#undef Q_DECL_IMPORT +#endif + +#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ + defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ defined(__WIN32__) || defined(__NT__) #define Q_DECL_EXPORT __declspec(dllexport) #define Q_DECL_IMPORT __declspec(dllimport) @@ -53,6 +60,6 @@ This file is part of SlopeCraft. #include #else #include "SC_version_buildtime.h" -#endif // SLOPECRAFTL_NOT_INSTALLED +#endif // SLOPECRAFTL_NOT_INSTALLED -#endif // SLOPECRAFTL_GLOBAL_H +#endif // SLOPECRAFTL_GLOBAL_H diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 560ef5f9..d9b52e23 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -326,7 +326,8 @@ void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { } bool TokiSlopeCraft::examine_build_cache( - const build_options &opt, std::span expected_sha3_512, + [[maybe_unused]] const build_options &opt, + std::span expected_sha3_512, build_cache_ir *ir) const noexcept { assert(this->kernelStep >= SCL_step::converted); diff --git a/VisualCraft/ColorBrowser.cpp b/VisualCraft/ColorBrowser.cpp index 5ac454ba..6eab7738 100644 --- a/VisualCraft/ColorBrowser.cpp +++ b/VisualCraft/ColorBrowser.cpp @@ -62,7 +62,7 @@ void compose_blocks(QImage &dst, const QImage &src, int idx, const int rows = src.height(); const int col_begin = idx * (rows + margin); - const int col_end = col_begin + rows; + [[maybe_unused]] const int col_end = col_begin + rows; assert(dst.width() >= col_end); @@ -131,7 +131,6 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, color_id_list[idx], pair.first.data(), &pair.second); if (num <= 0) { - const auto ret = QMessageBox::warning( this, ColorBrowser::tr("获取颜色表失败"), ColorBrowser::tr( @@ -149,7 +148,6 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, abort(); return; } else { - // ignore the error pair.first.resize(0); continue; @@ -171,7 +169,6 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, VCL_model *const model = VCL_get_block_model(pair.first, VCL_get_resource_pack()); if (model == nullptr) { - const auto ret = QMessageBox::warning( this, ColorBrowser::tr("计算投影图像失败"), ColorBrowser::tr("在尝试获取方块 \"%1\" 的方块模型时出现错误。") @@ -194,7 +191,6 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, reinterpret_cast(proj.scanLine(0)), proj.sizeInBytes()); if (!ok) { - const auto ret = QMessageBox::warning( this, ColorBrowser::tr("计算投影图像失败"), ColorBrowser::tr( diff --git a/VisualCraftL/VisualCraftL_global.h b/VisualCraftL/VisualCraftL_global.h index 205d4936..8896b51d 100644 --- a/VisualCraftL/VisualCraftL_global.h +++ b/VisualCraftL/VisualCraftL_global.h @@ -23,7 +23,12 @@ This file is part of SlopeCraft. #ifndef SLOPECRAFT_VISUALCRAFT_VISUALCRAFTL_GLOBAL_H #define SLOPECRAFT_VISUALCRAFT_VISUALCRAFTL_GLOBAL_H -// #ifdef VISUALCRAFTL_BUILD +#ifdef Q_DECL_EXPORT +#undef Q_DECL_EXPORT +#endif +#ifdef Q_DECL_IMPORT +#undef Q_DECL_IMPORT +#endif #if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 36f20ee7..3dc3f8d4 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -129,7 +129,7 @@ void colordiff_RGB_batch(std::span r1p, std::span g1p, } } -inline void assert_if_nan(batch_t val) noexcept { +inline void assert_if_nan([[maybe_unused]] batch_t val) noexcept { for (size_t i = 0; i < batch_size; i++) { assert(!std::isnan(val.get(i))); } diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 6ab968dc..ec673b88 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -111,8 +111,8 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { return; } - this->queue = - cl::CommandQueue(this->context, this->device, NULL, &this->error); + this->queue = cl::CommandQueue(this->context, this->device, + cl::QueueProperties::None, &this->error); if (!this->ok()) { this->err_msg = "Failed to create command queue."; From 418f59daecfeaa585136646efef0a476f621421d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 20:09:54 +0800 Subject: [PATCH 0641/1123] Add an output when fetching 3rdParty libs Signed-off-by: ToKiNoBug --- cmake/find_HeuristicFlow.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/find_HeuristicFlow.cmake b/cmake/find_HeuristicFlow.cmake index d71fabe3..9d23e117 100644 --- a/cmake/find_HeuristicFlow.cmake +++ b/cmake/find_HeuristicFlow.cmake @@ -6,6 +6,7 @@ FetchContent_Declare(Heu GIT_TAG v1.6.4.1 OVERRIDE_FIND_PACKAGE) +message(STATUS "Downloading HeuristicFlow") FetchContent_MakeAvailable(Heu) find_package(Heu 1.6.4 REQUIRED) \ No newline at end of file From c7df15aa0b1b8f4701a18c7fa33a4d22a3b6bf8b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 20:19:13 +0800 Subject: [PATCH 0642/1123] [CI] Update windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 39 ++++++++++------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index fec68739..4b1bb0b8 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -12,11 +12,13 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL ] + gpu_api: [ None, OpenCL, Vulkan ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL vectorize: false + - gpu_api: Vulkan + vectorize: false env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -34,12 +36,16 @@ jobs: - name: Install deps with vcpkg shell: cmd - run: vcpkg install --triplet=x64-windows zlib libpng libzip eigen3 xsimd + run: vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' run: vcpkg install opencl --triplet=x64-windows + - name: Install Vulkan with vcpkg + if: matrix.gpu_api == 'Vulkan' + run: vcpkg install vulkan vulkan-headers --triplet=x64-windows + - name: Checkout repository uses: actions/checkout@v4 @@ -141,7 +147,7 @@ jobs: echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - name: Filter perl-related pathes from env:path, and append directory of gcc12 to path + - name: Filter perl-related pathes from env:path, and append directory of gcc13 to path run: | $basedir=(pwd).path.replace("\\","/") $exclude_key_words="perl","Strawberry" @@ -166,8 +172,8 @@ jobs: - name: Download mingw64 and extract run: | cmd - curl -JL -o bin/gcc12.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/12.2.0-rt_v10-rev0/x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" - 7z x -obin bin/gcc12.7z + curl -JL -o bin/gcc13.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/13.2.0-rt_v11-rev1/x86_64-13.2.0-release-posix-seh-ucrt-rt_v11-rev1.7z" + 7z x -obin bin/gcc13.7z exit # gcc installation dir: bin/mingw64 # gcc.exe: bin/mingw64/bin/gcc.exe @@ -179,7 +185,7 @@ jobs: $GPU_API=$env:GPU_API $env:path=$env:NEW_PATH echo "env:path = $env:path" - vcpkg install --triplet=x64-mingw-dynamic zlib libpng libzip eigen3 xsimd + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams - name: Install OpenCL with vcpkg @@ -237,8 +243,8 @@ jobs: $basedir=(pwd).path.replace("\\","/") $env:path=$env:NEW_PATH cd ./build - cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" + #cpack -G ZIP -B "$basedir/pack" #- name: Upload zip pack # uses: actions/upload-artifact@v3 @@ -253,22 +259,3 @@ jobs: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-gcc-7z path: pack/SlopeCraft*.7z if-no-files-found: error - - - #- name: Tree /f - # run: tree /f D:/ > bin/all_files_on_D.txt - #- name: Upload all_files_on_D.txt - # uses: actions/upload-artifact@v3 - # with: - # name: all_files_on_D.txt - # path: bin/all_files_on_D.txt - # if-no-files-found: error - - - - #- name: Upload gcc - # uses: actions/upload-artifact@v3 - # with: - # name: gcc12-with-zlib,libzip,libpng - # path: bin/mingw64 - # if-no-files-found: error From ca7b923be6679756b0a530185f161e406dfdbeaa Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 21:20:14 +0800 Subject: [PATCH 0643/1123] [SC] Replace zstr with Boost::iostreams and zstd Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 24 ++++++++++++--------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 32 ++++++++++++++++++++++------ cmake/configure_boost.cmake | 7 ++++++ cmake/configure_zstd.cmake | 14 ++++++++++++ cmake/configure_zstr.cmake | 10 --------- 5 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 cmake/configure_boost.cmake create mode 100644 cmake/configure_zstd.cmake delete mode 100644 cmake/configure_zstr.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 5d88994a..92f3c2ba 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -3,23 +3,26 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_zstr.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_zstd.cmake) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) -find_package(zstr REQUIRED) +#find_package(zstr REQUIRED) find_package(Heu REQUIRED) +find_package(Boost COMPONENTS iostreams REQUIRED) +find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") message(STATUS "Configuring on Windows. Adding rc file to " ${PROJECT_NAME}) configure_file(others/SlopeCraftL.rc.in others/SlopeCraftL.rc) set(SlopeCraft_SCL_windows_rc_files ${CMAKE_CURRENT_BINARY_DIR}/others/SlopeCraftL.rc) -endif() +endif () set(SlopeCraft_SCL_sources ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h @@ -87,17 +90,18 @@ set(SlopeCraft_SCL_link_libs OpenMP::OpenMP_CXX fmt::fmt Eigen3::Eigen - zstr::zstr - Heu::Genetic) + Heu::Genetic + Boost::iostreams + ${SC_zstd_target_name}) # link to dependents target_link_libraries(SlopeCraftL PUBLIC ${SlopeCraft_SCL_link_libs}) target_compile_options(SlopeCraftL PRIVATE ${SlopeCraft_vectorize_flags}) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") target_compile_options(SlopeCraftL PRIVATE "-fvisibility=hidden" "-fPIC") -endif() +endif () # set shared-lib properties set_target_properties(SlopeCraftL PROPERTIES @@ -108,9 +112,9 @@ set_target_properties(SlopeCraftL PROPERTIES MACOSX_BUNDLE TRUE ) -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") set_target_properties(SlopeCraftL PROPERTIES PREFIX "") -endif() +endif () include(install.cmake) \ No newline at end of file diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index d9b52e23..b8af99d1 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -8,7 +8,10 @@ #include #include -#include +#include +#include +#include +#include namespace stdfs = std::filesystem; // common utilities ------------------------------------ @@ -276,7 +279,7 @@ std::string TokiSlopeCraft::current_build_dir() const noexcept { std::string TokiSlopeCraft::build_cache_filename_of( std::string_view build_dir) noexcept { - return fmt::format("{}/build.gz", build_dir); + return fmt::format("{}/build.zst", build_dir); } std::string TokiSlopeCraft::current_build_cache_filename() const noexcept { @@ -305,7 +308,16 @@ void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { const std::string filename = build_cache_filename_of(build_dir); { // std::ofstream ofs{build_cache_file, std::ios::binary}; - zstr::ofstream ofs{filename, std::ios::binary, Z_DEFAULT_COMPRESSION}; + boost::iostreams::filtering_ostream ofs{}; + ofs.set_auto_close(true); + { + boost::iostreams::zstd_params params; + params.level = uint32_t(ZSTD_defaultCLevel()); + ofs.push(boost::iostreams::zstd_compressor{params}); + ofs.push(boost::iostreams::file_sink{filename, std::ios::binary}); + } + + // zstr::ofstream ofs{filename, std::ios::binary, Z_DEFAULT_COMPRESSION}; if (!ofs) { err = fmt::format("ofstream failed to open cache file {}", filename); return; @@ -317,7 +329,7 @@ void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { boa(this->build_opt); boa(this->schem); } - ofs.close(); + // ofs.close(); } auto sha3_512 = this->current_build_task_hash(); @@ -344,7 +356,15 @@ bool TokiSlopeCraft::examine_build_cache( build_cache_ir temp; try { auto filename = this->build_cache_filename_of(build_dir); - zstr::ifstream ifs{filename, std::ios::binary}; + // zstr::ifstream ifs{filename, std::ios::binary}; + boost::iostreams::filtering_istream ifs; + ifs.set_auto_close(true); + { + boost::iostreams::zstd_params params; + params.level = uint32_t(ZSTD_defaultCLevel()); + ifs.push(boost::iostreams::zstd_decompressor{}); + ifs.push(boost::iostreams::file_source{filename, std::ios::binary}); + } if (!ifs) { return false; } @@ -355,7 +375,7 @@ bool TokiSlopeCraft::examine_build_cache( bia(temp.build_option); bia(temp.schem); } - ifs.close(); + // ifs.close(); } catch (...) { return false; } diff --git a/cmake/configure_boost.cmake b/cmake/configure_boost.cmake new file mode 100644 index 00000000..33c965b2 --- /dev/null +++ b/cmake/configure_boost.cmake @@ -0,0 +1,7 @@ +find_package(Boost + COMPONENTS iostreams + REQUIRED) + +if (NOT TARGET Boost::iostreams) + message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") +endif () \ No newline at end of file diff --git a/cmake/configure_zstd.cmake b/cmake/configure_zstd.cmake new file mode 100644 index 00000000..33362b41 --- /dev/null +++ b/cmake/configure_zstd.cmake @@ -0,0 +1,14 @@ +find_package(zstd + REQUIRED) + +set(SC_zstd_target_name "") +if (TARGET zstd::libzstd_shared) + set(SC_zstd_target_name "zstd::libzstd_shared") +elseif (TARGET zstd::zstd) + set(SC_zstd_target_name "zstd::zstd") +elseif (TARGET zstd::libzstd_static) + set(SC_zstd_target_name "zstd::libzstd_static") +elseif () + message(FATAL_ERROR "No zstd library target imported.") +endif () +message(STATUS "Found zstd: ${SC_zstd_target_name}") \ No newline at end of file diff --git a/cmake/configure_zstr.cmake b/cmake/configure_zstr.cmake deleted file mode 100644 index 2eae3697..00000000 --- a/cmake/configure_zstr.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# https://github.com/mateidavid/zstr - -include(FetchContent) - -FetchContent_Declare(zstr - GIT_REPOSITORY - https://github.com/mateidavid/zstr.git GIT_TAG v1.0.7 - OVERRIDE_FIND_PACKAGE) - -FetchContent_MakeAvailable(zstr) \ No newline at end of file From c385724fb6b4e6cfa84d60977b17d67b48508308 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 21:54:24 +0800 Subject: [PATCH 0644/1123] [SC] Replace zstr and Chocobo1 hash with Boost and zstd Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 -- SlopeCraftL/TokiSlopeCraft_cache.cpp | 31 +++++++++++++++++++--------- cmake/configure_hash.cmake | 17 --------------- utilities/ColorManip/CMakeLists.txt | 5 ++++- utilities/ColorManip/hash.cpp | 20 ++++++++++++------ utilities/ColorManip/newColorSet.hpp | 11 +++++----- 6 files changed, 45 insertions(+), 41 deletions(-) delete mode 100644 cmake/configure_hash.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 92f3c2ba..cace6497 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -2,7 +2,6 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_zstd.cmake) @@ -10,7 +9,6 @@ find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) -#find_package(zstr REQUIRED) find_package(Heu REQUIRED) find_package(Boost COMPONENTS iostreams REQUIRED) find_package(zstd REQUIRED) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index b8af99d1..402bd516 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include @@ -13,6 +11,9 @@ #include #include +#include +#include + namespace stdfs = std::filesystem; // common utilities ------------------------------------ std::string write_hash(std::string_view filename, @@ -89,7 +90,7 @@ const char *TokiSlopeCraft::cacheDir() const noexcept { const std::string_view hash_suffix{".sha3_512"}; -#define SC_HASH_ADD_DATA(hasher, obj) hasher.addData(&obj, sizeof(obj)); +#define SC_HASH_ADD_DATA(hasher, obj) hasher.process_bytes(&obj, sizeof(obj)); uint64_t to_short_hash(std::span full_hash) noexcept { assert(full_hash.size() >= 8); @@ -106,14 +107,19 @@ uint64_t to_short_hash(std::span full_hash) noexcept { } // type hash and dir ------------------------------------ std::vector TokiSlopeCraft::type_hash() noexcept { - Chocobo1::SHA3_512 hash; + // Chocobo1::SHA3_512 hash; + boost::uuids::detail::sha1 hash; SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mapType); SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mcVer); TokiSlopeCraft::Allowed.hash_add_data(hash); - hash.finalize(); - return hash.toVector(); + boost::uuids::detail::sha1::digest_type digest; + hash.get_digest(digest); + std::span dig{reinterpret_cast(digest), + sizeof(digest)}; + + return {dig.begin(), dig.end()}; } std::string TokiSlopeCraft::type_dir_of(std::string_view cache_dir) noexcept { @@ -235,17 +241,18 @@ void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { std::vector TokiSlopeCraft::build_task_hash_of( const Eigen::ArrayXXi &mapPic, std::span blkids, const build_options &opt) noexcept { - Chocobo1::SHA3_512 hash; + boost::uuids::detail::sha1 hash; + // Chocobo1::SHA3_512 hash; { const int64_t rows{mapPic.rows()}; const int64_t cols{mapPic.cols()}; SC_HASH_ADD_DATA(hash, rows); SC_HASH_ADD_DATA(hash, cols); - hash.addData(mapPic.data(), mapPic.size() * sizeof(uint32_t)); + hash.process_bytes(mapPic.data(), mapPic.size() * sizeof(uint32_t)); } for (auto blkid : blkids) { - hash.addData(blkid.data(), blkid.size()); + hash.process_bytes(blkid.data(), blkid.size()); } { SC_HASH_ADD_DATA(hash, opt.maxAllowedHeight); @@ -256,8 +263,12 @@ std::vector TokiSlopeCraft::build_task_hash_of( SC_HASH_ADD_DATA(hash, opt.enderman_proof); SC_HASH_ADD_DATA(hash, opt.connect_mushrooms); } + boost::uuids::detail::sha1::digest_type digest; + hash.get_digest(digest); + std::span dig{reinterpret_cast(digest), + sizeof(digest)}; - return hash.finalize().toVector(); + return {dig.begin(), dig.end()}; } std::vector TokiSlopeCraft::current_build_task_hash() const noexcept { diff --git a/cmake/configure_hash.cmake b/cmake/configure_hash.cmake deleted file mode 100644 index a24d0dbe..00000000 --- a/cmake/configure_hash.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# https://github.com/Chocobo1/Hash - -set(SlopeCraft_Chocobo1_Hash_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/Hash/src) - -if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/Hash/.git) - return() -endif() - -file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/3rdParty/Hash) - -message(STATUS "cloning https://github.com/Chocobo1/Hash.git") - -execute_process(COMMAND git clone https://github.com/Chocobo1/Hash.git - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty - COMMAND_ERROR_IS_FATAL ANY) - -# execute_process(git checkout ) \ No newline at end of file diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 24c83c40..a3771190 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -8,11 +8,12 @@ find_package(OpenMP REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_hash.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_xsimd.cmake) find_package(cereal REQUIRED) find_package(xsimd REQUIRED) +find_package(Boost REQUIRED) add_library(ColorManip @@ -37,6 +38,8 @@ target_compile_features(ColorManip PUBLIC cxx_std_20) target_include_directories(ColorManip PUBLIC ${CMAKE_SOURCE_DIR}/utilities ${SlopeCraft_Chocobo1_Hash_include_dir}) +target_include_directories(ColorManip PRIVATE + ${Boost_INCLUDE_DIRS}) target_link_libraries(ColorManip PRIVATE Heu::Genetic) diff --git a/utilities/ColorManip/hash.cpp b/utilities/ColorManip/hash.cpp index fff57061..9d3d0fd0 100644 --- a/utilities/ColorManip/hash.cpp +++ b/utilities/ColorManip/hash.cpp @@ -1,7 +1,10 @@ #include "newColorSet.hpp" #include "imageConvert.hpp" +#include +#include + +namespace buuid = boost::uuids::detail; -#include /* std::vector internal::hash_of_colorset( const hash_temp &temp) noexcept { @@ -25,15 +28,20 @@ std::vector internal::hash_of_colorset( std::vector libImageCvt::hash_of_image( Eigen::Map> img) noexcept { - Chocobo1::SHA3_512 stream; + buuid::sha1 hash; { const auto rows{img.rows()}; const auto cols{img.cols()}; - stream.addData(&rows, sizeof(rows)); - stream.addData(&cols, sizeof(cols)); + hash.process_bytes(&rows, sizeof(rows)); + hash.process_bytes(&cols, sizeof(cols)); } - stream.addData(img.data(), sizeof(uint32_t) * img.size()); + hash.process_bytes(img.data(), sizeof(uint32_t) * img.size()); + buuid::sha1::digest_type dig; + hash.get_digest(dig); - return stream.finalize().toVector(); + std::span temp{reinterpret_cast(dig), + sizeof(dig)}; + + return {temp.begin(), temp.end()}; } \ No newline at end of file diff --git a/utilities/ColorManip/newColorSet.hpp b/utilities/ColorManip/newColorSet.hpp index 2893f612..e70d1177 100644 --- a/utilities/ColorManip/newColorSet.hpp +++ b/utilities/ColorManip/newColorSet.hpp @@ -131,14 +131,15 @@ class colorset_new : public std::conditional_t< for (const auto &cptrs : temp.color_ptrs) { for (const float *fptr : cptrs) { - stream.addData(fptr, temp.color_count * sizeof(float)); + stream.process_bytes(fptr, temp.color_count * sizeof(float)); } } - stream.addData(temp.color_id_ptr, - temp.color_count * - (temp.is_maptical ? sizeof(uint8_t) : sizeof(uint16_t))); - stream.addData(&temp.color_count, sizeof(temp.color_count)); + stream.process_bytes( + temp.color_id_ptr, + temp.color_count * + (temp.is_maptical ? sizeof(uint8_t) : sizeof(uint16_t))); + stream.process_bytes(&temp.color_count, sizeof(temp.color_count)); } }; From a5580f59afa8efe48a2a5c64e83b498e15e53809 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 22:04:57 +0800 Subject: [PATCH 0645/1123] [CI] install boost in CI Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- .github/workflows/macos-build-arm64.yml | 4 ++++ .github/workflows/macos-build-x64.yml | 2 +- .github/workflows/windows-build.yml | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index bf178e5d..a6d9192b 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -34,7 +34,7 @@ jobs: run: sudo apt install cmake ninja-build - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev + run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev - name: Install xsimd run: | diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 585f899c..ba35af12 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -30,6 +30,10 @@ jobs: # ls $HOME # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l + - name: Install dependencies + run: | + brew install boost + - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index d21d87d9..dda1c4a4 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -33,7 +33,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip zstd xz eigen + brew install libpng xsimd p7zip libzip zstd xz eigen boost # - name: Find liblzma and libzstd dylibs # run: | diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 4b1bb0b8..06bb713d 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -36,7 +36,7 @@ jobs: - name: Install deps with vcpkg shell: cmd - run: vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams + run: vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' From a718987e8e914377185cf3751acccf10d7ce8248 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 22:13:41 +0800 Subject: [PATCH 0646/1123] [CI] add vulkan for linux Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index a6d9192b..ec6d35a6 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL ] + gpu_api: [ None, OpenCL, Vulkan ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} @@ -53,10 +53,14 @@ jobs: - name: Install additional qt-related packages run: sudo apt install x11-utils libxcb-xinerama0 libxv1 libgl-dev # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - - name: Install OpenCL sdk + - name: Install OpenCL SDK if: matrix.gpu_api == 'OpenCL' run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + - name: Install Vulkan SDK + if: matrix.gpu_api == 'Vulkan' + run: sudo apt install vulkan-tools vulkan-utils libvulkan1 + - name: See clinfo if: matrix.gpu_api == 'OpenCL' run: clinfo From 2f730e35d49e60fe22fe3eb41d630c5bf8641d8d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 8 Dec 2023 22:26:23 +0800 Subject: [PATCH 0647/1123] [CI] try to fix vulkan-build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- .github/workflows/windows-build.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index ec6d35a6..ab93f8e1 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -59,7 +59,7 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' - run: sudo apt install vulkan-tools vulkan-utils libvulkan1 + run: sudo apt install vulkan-tools slibvulkan1 - name: See clinfo if: matrix.gpu_api == 'OpenCL' diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 06bb713d..bb0e028a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -42,9 +42,9 @@ jobs: if: matrix.gpu_api == 'OpenCL' run: vcpkg install opencl --triplet=x64-windows - - name: Install Vulkan with vcpkg - if: matrix.gpu_api == 'Vulkan' - run: vcpkg install vulkan vulkan-headers --triplet=x64-windows + # - name: Install Vulkan with vcpkg + # if: matrix.gpu_api == 'Vulkan' + # run: vcpkg install vulkan vulkan-headers --triplet=x64-windows - name: Checkout repository uses: actions/checkout@v4 From b45e5405ff470644b11520c47e0cdc4e9900996d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:17:12 +0800 Subject: [PATCH 0648/1123] [CI] try to install vulkan sdk on windows Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index bb0e028a..3d48c3d8 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -42,9 +42,14 @@ jobs: if: matrix.gpu_api == 'OpenCL' run: vcpkg install opencl --triplet=x64-windows - # - name: Install Vulkan with vcpkg - # if: matrix.gpu_api == 'Vulkan' - # run: vcpkg install vulkan vulkan-headers --triplet=x64-windows + - name: Install Vulkan with vcpkg + if: matrix.gpu_api == 'Vulkan' + run: | + cmd + curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" + 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z + exit + tree /f C:\Program Files\VulkanSDK - name: Checkout repository uses: actions/checkout@v4 @@ -76,7 +81,7 @@ jobs: run: | mkdir build mkdir install - set PATH=C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps + set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build @@ -185,7 +190,7 @@ jobs: $GPU_API=$env:GPU_API $env:path=$env:NEW_PATH echo "env:path = $env:path" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid - name: Install OpenCL with vcpkg From 6b8672f5a7b744510a1a6d5740ca6dc815c0af23 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:18:43 +0800 Subject: [PATCH 0649/1123] [CI] fix Linux build with vulkan Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index ab93f8e1..3b672dda 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -59,7 +59,7 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' - run: sudo apt install vulkan-tools slibvulkan1 + run: sudo apt install vulkan-tools libvulkan1 - name: See clinfo if: matrix.gpu_api == 'OpenCL' From 7a52ea91a919d7818dcc91451db45f8bb726d1e8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:27:34 +0800 Subject: [PATCH 0650/1123] [CI] fix windows build with vulkan Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 3d48c3d8..6c500f2d 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -42,15 +42,6 @@ jobs: if: matrix.gpu_api == 'OpenCL' run: vcpkg install opencl --triplet=x64-windows - - name: Install Vulkan with vcpkg - if: matrix.gpu_api == 'Vulkan' - run: | - cmd - curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" - 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z - exit - tree /f C:\Program Files\VulkanSDK - - name: Checkout repository uses: actions/checkout@v4 @@ -67,6 +58,15 @@ jobs: mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty + - name: Install Vulkan with vcpkg + if: matrix.gpu_api == 'Vulkan' + run: | + cmd + curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" + 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z + exit + tree /f C:\Program Files\VulkanSDK + - name: Download Qt6.5.0-msvc-shared and extract run: | cmd From e6b343ba109611fdb7652aa1cc057d6ae0971c19 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:30:10 +0800 Subject: [PATCH 0651/1123] [CI] fix linux build with zstd Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 3b672dda..52e0c17a 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -33,8 +33,8 @@ jobs: - name: Install cmake, ninja run: sudo apt install cmake ninja-build - - name: Install libzip, libpng, Eigen3 - run: sudo apt install libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev + - name: Install dependencies + run: sudo apt install zstd xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev - name: Install xsimd run: | From 177ef3e9950ed23cf81820fc8ee6b431dbda4bc1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:34:00 +0800 Subject: [PATCH 0652/1123] [CI] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 52e0c17a..723cddcd 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -55,7 +55,10 @@ jobs: # Without these libs, cmake cannot find Qt6::Gui. But if you install nvidia-cuda-toolkit, they will be installed automatically - name: Install OpenCL SDK if: matrix.gpu_api == 'OpenCL' - run: sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + run: | + sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo + whereis glslc + glslc --version - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' From 2f55167431436fe6a68b1c72f90c297c92bb0c7e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 11:35:51 +0800 Subject: [PATCH 0653/1123] [CI] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 723cddcd..b2f98db5 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -57,19 +57,14 @@ jobs: if: matrix.gpu_api == 'OpenCL' run: | sudo apt install ocl-icd-libopencl1 ocl-icd-opencl-dev ocl-icd-dev opencl-c-headers opencl-clhpp-headers clinfo - whereis glslc - glslc --version + clinfo - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' - run: sudo apt install vulkan-tools libvulkan1 - - - name: See clinfo - if: matrix.gpu_api == 'OpenCL' - run: clinfo - - - name: Install xz (Release as tar.xz) - run: sudo apt install xz-utils + run: | + sudo apt install vulkan-tools libvulkan1 + whereis glslc + glslc --version - name: Checkout repository uses: actions/checkout@v4 From f72f232038353480a2aae49aebf6aa3d90ffc4ee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 12:29:01 +0800 Subject: [PATCH 0654/1123] [CI] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index b2f98db5..f6a96fef 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -62,7 +62,7 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-tools libvulkan1 + sudo apt install vulkan-tools libvulkan1 glslang-tools whereis glslc glslc --version From eb4b239478272020964b83a6263953cd72d8ae86 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 12:33:40 +0800 Subject: [PATCH 0655/1123] [CI] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 6c500f2d..01782461 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -65,7 +65,7 @@ jobs: curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z exit - tree /f C:\Program Files\VulkanSDK + tree /f "C:\Program Files\VulkanSDK" - name: Download Qt6.5.0-msvc-shared and extract run: | @@ -82,7 +82,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH=D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - name: CMake build shell: cmd From d67c853aa072c5b24b113964eff39eaefdeaf215 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 9 Dec 2023 12:43:59 +0800 Subject: [PATCH 0656/1123] [CI] hide windows-vulkan build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 01782461..7e614ef6 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL, Vulkan ] + gpu_api: [ None, OpenCL ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL From 2a7576dca9a2e85d932dbc2a2e43d678a28e5f80 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Jan 2024 11:23:41 +0800 Subject: [PATCH 0657/1123] Add new project logo Signed-off-by: ToKiNoBug --- README-en.md | 3 ++- README.md | 2 +- docs/SlopeCraft_ba-style@nulla.top.png | Bin 0 -> 13847 bytes 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 docs/SlopeCraft_ba-style@nulla.top.png diff --git a/README-en.md b/README-en.md index 842f0868..0c725371 100644 --- a/README-en.md +++ b/README-en.md @@ -1,6 +1,7 @@ [中文](README.md) | **English** -

SlopeCraft

+![SlopeCraft logo](docs/SlopeCraft_ba-style@nulla.top.png) +

Get your Minecraft pixel painting in multiple kinds of forms! diff --git a/README.md b/README.md index 78290601..29b1c871 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ **中文** | [English](README-en.md) -

SlopeCraft

+![SlopeCraft logo](docs/SlopeCraft_ba-style@nulla.top.png)

生成多种样式的 Minecraft 地图画! diff --git a/docs/SlopeCraft_ba-style@nulla.top.png b/docs/SlopeCraft_ba-style@nulla.top.png new file mode 100644 index 0000000000000000000000000000000000000000..8f824d3ac044dc22e557ed180917ab7d0c465d88 GIT binary patch literal 13847 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 literal 0 HcmV?d00001 From c75c08cd21a7a74c656c47ba448c8972aadd4166 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 11:59:42 +0800 Subject: [PATCH 0658/1123] Fix mistakes about reproducible in VCL Signed-off-by: ToKiNoBug --- VisualCraftL/VCL_blocks_fixed.json | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 2c8e0890..5a75b08b 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -25,8 +25,7 @@ "endermanPickable": true, "nameEN": "Clay block", "nameZH": "黏土块", - "version": "all", - "reproducible": false + "version": "all" }, "minecraft:black_concrete": { "background": true, @@ -893,8 +892,7 @@ "class": "nether", "nameEN": "Nether brick", "nameZH": "地狱砖块", - "version": 13, - "reproducible": false + "version": 13 }, "minecraft:nether_wart_block": { "class": "nether", @@ -913,8 +911,7 @@ "class": "nether", "nameEN": "Soul sand", "nameZH": "灵魂沙", - "version": "all", - "reproducible": false + "version": "all" }, "minecraft:soul_soil": { "class": "nether", @@ -1653,8 +1650,7 @@ ], "nameEN": "Nether brick slab", "nameZH": "地狱砖块上半砖", - "version": 13, - "reproducible": false + "version": 13 }, "minecraft:oak_slab[half=top]": { "burnable": true, @@ -1997,15 +1993,19 @@ "class": "stone", "nameEN": "Polished diorite", "nameZH": "磨制闪长岩", - "version": 13, - "reproducible": false + "version": 13 }, "minecraft:polished_granite": { "class": "stone", "nameEN": "Polished granite", "nameZH": "磨制花岗岩", - "version": 13, - "reproducible": false + "version": 13 + }, + "minecraft:polished_andesite": { + "class": "stone", + "nameEN": "Polished andesite", + "nameZH": "磨制安山岩", + "version": 13 }, "minecraft:quartz_block": { "class": "ore", @@ -2523,15 +2523,13 @@ "class": "the_end", "nameEN": "End stone", "nameZH": "末地石", - "version": "all", - "reproducible": false + "version": "all" }, "minecraft:end_stone_bricks": { "class": "the_end", "nameEN": "Endstone bricks", "nameZH": "末地石砖", - "version": 13, - "reproducible": false + "version": 13 }, "minecraft:purpur_block": { "class": "the_end", From f8fac9745a7f6e681a22ff1c4facea20cd6d7342 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 12:08:42 +0800 Subject: [PATCH 0659/1123] Fix large litematica export Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.h | 17 +++++++++++++++++ utilities/Schem/bit_shrink.cpp | 19 ++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 8ea7909e..302c29a4 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -35,6 +35,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "SC_GlobalEnums.h" @@ -268,6 +269,22 @@ class Schem { } }; +/** + * Find minimum value >= a that can is multiple of b + * @tparam int_t + * @param a + * @param b + * @return + */ +template + requires std::integral && std::integral +constexpr int_t ceil_up_to(int_t a, uint_t b) { + if (a % b == 0) { + return a; + } + return ((a / b) + 1) * b; +} + } // namespace libSchem #endif // SCHEM_SCHEM_H \ No newline at end of file diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index 5ab29c41..396ff3c9 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -21,15 +21,12 @@ This file is part of SlopeCraft. */ #include "bit_shrink.h" - +#include "Schem.h" #include -#include #include #include #include -#include - #include // no flip now @@ -111,17 +108,17 @@ void shrink_bits(const uint16_t *const src, const size_t src_count, const int bits_per_element = std::ceil(std::log2(block_types)); //::std::cout << "bits_per_element = " << bits_per_element << ::std::endl; - - if (bits_per_element > 16) { - exit(1); - return; - } + assert(bits_per_element <= 16); + // if (bits_per_element > 16) { + // exit(1); + // return; + // } const size_t total_bits = bits_per_element * src_count; - const size_t bytes_required = std::ceil(total_bits / 8.0); + const size_t bytes_required = libSchem::ceil_up_to(total_bits, 8); const size_t uint64_t_required = - std::ceil(bytes_required / float(sizeof(uint64_t))); + libSchem::ceil_up_to(bytes_required, sizeof(uint64_t)); dest->resize(uint64_t_required); memset(dest->data(), 0, bytes_required); From f6f9b4996e8a0f5452246ac5df005531791844c4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 13:03:13 +0800 Subject: [PATCH 0660/1123] install cmake exports Signed-off-by: ToKiNoBug --- MapViewer/install.cmake | 3 +++ SlopeCraft/install.cmake | 4 ++++ SlopeCraftL/CMakeLists.txt | 7 +++--- SlopeCraftL/install.cmake | 16 ++++--------- VisualCraft/CMakeLists.txt | 10 ++++---- VisualCraft/install.cmake | 4 ++++ VisualCraftL/CMakeLists.txt | 47 +++++++++++++++++-------------------- VisualCraftL/install.cmake | 43 +++++++-------------------------- cmake/install.cmake | 16 ++++++++++++- imageCutter/install.cmake | 3 +++ utilities/install.cmake | 22 +++-------------- vccl/install.cmake | 4 ++++ 12 files changed, 80 insertions(+), 99 deletions(-) diff --git a/MapViewer/install.cmake b/MapViewer/install.cmake index 87740af7..91f56371 100644 --- a/MapViewer/install.cmake +++ b/MapViewer/install.cmake @@ -5,6 +5,7 @@ set(AppName MapViewer) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS MapViewer + EXPORT SlopeCraftTargets RUNTIME DESTINATION . ) @@ -24,6 +25,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Linux") # set_target_properties(MapViewer PROPERTIES INSTALL_RPATH "../lib") install(TARGETS MapViewer + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin BUNDLE DESTINATION lib ) @@ -41,6 +43,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS MapViewer + EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION . ) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index e2b38f60..86c61e67 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -21,6 +21,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS # Install app install(TARGETS SlopeCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION . ) @@ -57,6 +58,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) install(TARGETS SlopeCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION SlopeCraft.app/Contents/Frameworks LIBRARY DESTINATION SlopeCraft.app/Contents/Frameworks) @@ -76,6 +78,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Windows") # Install app install(TARGETS SlopeCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION . ) @@ -133,6 +136,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") # Install for Linux # Install app install(TARGETS SlopeCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin ) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index cace6497..52c7f1b0 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -68,11 +68,12 @@ add_library(SlopeCraftL SHARED ${SlopeCraft_SCL_sources}) # add_library(SlopeCraftL_C SHARED ${SlopeCraft_SCL_sources}) target_compile_features(SlopeCraftL PRIVATE cxx_std_20) -target_include_directories(SlopeCraftL INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(SlopeCraftL INTERFACE + $ + $) target_include_directories(SlopeCraftL PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} ${SlopeCraft_Chocobo1_Hash_include_dir} - ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/utilities) @@ -93,7 +94,7 @@ set(SlopeCraft_SCL_link_libs ${SC_zstd_target_name}) # link to dependents -target_link_libraries(SlopeCraftL PUBLIC ${SlopeCraft_SCL_link_libs}) +target_link_libraries(SlopeCraftL PUBLIC $) target_compile_options(SlopeCraftL PRIVATE ${SlopeCraft_vectorize_flags}) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index d8a24035..ab8f4f92 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -13,29 +13,22 @@ set(SlopeCraft_SCL_Cpp_include_files SlopeCraftL.h SlopeCraftL_global.h ) +install(FILES ${SlopeCraft_SCL_Cpp_include_files} + DESTINATION include/SlopeCraft) if (CMAKE_SYSTEM_NAME MATCHES "Windows") # install for applications install(TARGETS SlopeCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION . LIBRARY DESTINATION .) - # install to lib dirs - install(TARGETS SlopeCraftL - RUNTIME DESTINATION ./../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib - - # LIBRARY DESTINATION ./../install_SlopeCraftL/Cpp/lib - ) - # install(TARGETS SlopeCraftL_C # RUNTIME DESTINATION ./../install_SlopeCraftL/C/bin # LIBRARY DESTINATION ./../install_SlopeCraftL/C/lib # LIBRARY DESTINATION ./../install_SlopeCraftL/C/lib # ) - install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION ./../install_SlopeCraftL/Cpp/include) DLLD_add_deploy(SlopeCraftL INSTALL_MODE INSTALL_DESTINATION .) @@ -53,11 +46,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") # install for applications install(TARGETS SlopeCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - install(FILES ${SlopeCraft_SCL_Cpp_include_files} - DESTINATION include/SlopeCraft) return() endif () diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index daa8dc8b..f4f1e539 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -13,12 +13,12 @@ find_package(magic_enum REQUIRED) find_package(OpenMP REQUIRED) -if(${WIN32}) +if (${WIN32}) configure_file(others/VisualCraft.rc.in others/VisualCraft.rc) set(VisualCraft_win_files ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraft.rc) -else() +else () set(VisualCraft_win_files) -endif() +endif () set(VisualCraft_header_files VCWind.h @@ -126,13 +126,13 @@ include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) configure_file(vc-config-to-bin-dir.json.in vc-config.json) -if(${WIN32}) +if (${WIN32}) add_custom_target(SC_create_symlink_VC COMMAND mklink VisualCraftL.dll "..\\VisualCraftL\\VisualCraftL.dll" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS VisualCraftL COMMENT "Create symlink to VisualCraftL.dll for VisualCraft.exe") add_dependencies(SC_create_all_symlinks SC_create_symlink_VC) -endif() +endif () include(install.cmake) \ No newline at end of file diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index 15dff4f1..efba413a 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -3,6 +3,7 @@ set(AppName VisualCraft) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS VisualCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION . ) @@ -25,6 +26,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS VisualCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin ) @@ -46,6 +48,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS VisualCraft + EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION .) @@ -65,6 +68,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") ) install(TARGETS VisualCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION VisualCraft.app/Contents/Frameworks LIBRARY DESTINATION VisualCraft.app/Contents/Frameworks) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index b822ac0e..ef2ff9ae 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -7,23 +7,23 @@ set(VCL_enable_internal_test OFF) include(config_versions.cmake) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") file(STRINGS others/VisualCraftL.def.in VCL_def_funs) set(VCL_counter 0) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.def "") - foreach(VCL_fun_name ${VCL_def_funs}) + foreach (VCL_fun_name ${VCL_def_funs}) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.def ${VCL_fun_name}) - if(VCL_counter GREATER 0) + if (VCL_counter GREATER 0) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.def " @" ${VCL_counter} "\n") - else() + else () file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.def "\n") - endif() + endif () math(EXPR VCL_counter "${VCL_counter} +1") - endforeach(VCL_fun_name ${VCL_def_funs}) + endforeach (VCL_fun_name ${VCL_def_funs}) unset(VCL_def_funs) unset(VCL_counter) @@ -32,9 +32,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.def ${CMAKE_CURRENT_BINARY_DIR}/others/VisualCraftL.rc) -else() +else () set(VCL_win_sources) -endif() +endif () # find_package(OpenCL) set(VCL_source_files @@ -89,14 +89,11 @@ target_include_directories(VisualCraftL PRIVATE ${VCL_include_dirs}) target_include_directories(VisualCraftL_static PUBLIC ${VCL_include_dirs}) target_include_directories(VisualCraftL PUBLIC - ${CMAKE_SOURCE_DIR}/utilities) -target_include_directories(VisualCraftL_static PUBLIC - ${CMAKE_SOURCE_DIR}/utilities) - -target_include_directories(VisualCraftL PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_BINARY_DIR}/utilities) + $ + $ + $) target_include_directories(VisualCraftL_static PUBLIC + ${CMAKE_SOURCE_DIR}/utilities ${CMAKE_CURRENT_SOURCE_DIR}) set(VCL_link_libs @@ -110,7 +107,7 @@ set(VCL_link_libs fmt::fmt ProcessBlockId) -target_link_libraries(VisualCraftL PRIVATE ${VCL_link_libs}) +target_link_libraries(VisualCraftL PRIVATE $) target_link_libraries(VisualCraftL_static PUBLIC ${VCL_link_libs}) # message(STATUS "ret = " ${ret}) @@ -124,35 +121,35 @@ target_compile_options(VisualCraftL PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_options(VisualCraftL_static PRIVATE ${SlopeCraft_vectorize_flags}) # target_compile_options(VisualCraftL PRIVATE "-std=c++20") -if(NOT ${MSVC}) +if (NOT ${MSVC}) target_compile_options(VisualCraftL PUBLIC "-flto") # target_compile_options(VisualCraftL PUBLIC "-Wall") -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Windows") # if the system is windows, remove the "lib" prefix. set_target_properties(VisualCraftL PROPERTIES PREFIX "") -endif() +endif () -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") target_compile_options(VisualCraftL PUBLIC "-fvisibility=hidden" ) get_target_property(VCL_libzip_type libzip::zip TYPE) get_target_property(VCL_libzip_location libzip::zip LOCATION) - if(VCL_libzip_type STREQUAL "SHARED_LIBRARY") + if (VCL_libzip_type STREQUAL "SHARED_LIBRARY") get_filename_component(VCL_libzip_dir ${VCL_libzip_location} DIRECTORY) message(STATUS "VCL_libzip_dir = " ${VCL_libzip_dir}) # target_link_directories(VisualCraftL PUBLIC ${VCL_libzip_dir}) - target_link_libraries(VisualCraftL PUBLIC libzip::zip) + target_link_libraries(VisualCraftL PUBLIC $) target_link_libraries(VisualCraftL_static PUBLIC libzip::zip) - endif() + endif () # target_link_options(VisualCraftL PRIVATE -rpath=${VCL_libzip_dir}) -endif() +endif () set_target_properties(VisualCraftL PROPERTIES VERSION ${PROJECT_VERSION} diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index 0bac5117..d6d90f8f 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -3,10 +3,13 @@ include(setup_zip_names.cmake) set(VCL_include_headers VisualCraftL.h VisualCraftL_global.h) +install(FILES ${VCL_include_headers} + DESTINATION include/SlopeCraft) if (${WIN32}) # install for app install(TARGETS VisualCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION . # LIBRARY DESTINATION . @@ -14,58 +17,30 @@ if (${WIN32}) install(FILES ${VCL_app_files} DESTINATION Blocks_VCL) - # install for lib - install(TARGETS VisualCraftL - RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) - DLLD_add_deploy(VisualCraftL INSTALL_MODE INSTALL_DESTINATION .) - # install(TARGETS VisualCraftL_static - # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) - install(FILES ${VCL_include_headers} - DESTINATION ../install_SlopeCraftL/Cpp/include) - # SlopeCraft_install_if_is_shared(ZLIB::ZLIB .) - # SlopeCraft_install_if_is_shared(libzip::zip .) - # SlopeCraft_install_if_is_shared(PNG::PNG .) - return() endif () if (${LINUX}) install(TARGETS VisualCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - install(TARGETS VisualCraftL_static - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib) + # install(TARGETS VisualCraftL_static + # EXPORT SlopeCraftTargets + # RUNTIME DESTINATION bin + # LIBRARY DESTINATION lib) install(FILES ${VCL_app_files} DESTINATION bin/Blocks_VCL) - install(FILES ${VCL_include_headers} - DESTINATION include/SlopeCraft) - - # install(TARGETS libzip::zip - # RUNTIME DESTINATION bin - # LIBRARY DESTINATION lib) return() endif () if (${APPLE}) - # install(TARGETS VisualCraftL - # RUNTIME DESTINATION . - # LIBRARY DESTINATION .) - - # zips and blocklist jsons are installed inside each macos bundle - # Install zips. In vccl-config.json or vc-config.json, they are refered like ./Blocks_VCL/Vanilla_1_19_3.zip - # install(FILES ${VCL_app_files} - # DESTINATION Blocks_VCL) - # install(TARGETS VisualCraftL - # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib) + # VCL is installed into vccl or VC return() endif () diff --git a/cmake/install.cmake b/cmake/install.cmake index fc48e0be..ae41c6c3 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -4,10 +4,24 @@ set(SlopeCraft_readme_and_license_files README.md README-en.md license-translations/LICENSE-zh.md - ) +) include(${CMAKE_SOURCE_DIR}/cmake/add_compiler_path_to_prefix.cmake) +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${CMAKE_BINARY_DIR}/SlopeCraftConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) +install(FILES ${CMAKE_BINARY_DIR}/SlopeCraftConfigVersion.cmake + DESTINATION lib/cmake/SlopeCraft) + +install(EXPORT SlopeCraftTargets + FILE SlopeCraftTargets.cmake + NAMESPACE SlopeCraft:: + DESTINATION lib/cmake/SlopeCraft) + if (${WIN32}) #include(${CMAKE_SOURCE_DIR}/cmake/scan_deps_for_lib.cmake) install(FILES ${SlopeCraft_readme_and_license_files} diff --git a/imageCutter/install.cmake b/imageCutter/install.cmake index e45cc226..34902f0a 100644 --- a/imageCutter/install.cmake +++ b/imageCutter/install.cmake @@ -5,6 +5,7 @@ set(AppName imageCutter) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS imageCutter + EXPORT SlopeCraftTargets RUNTIME DESTINATION . ) @@ -35,6 +36,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Linux") # et_target_properties(imageCutter PROPERTIES INSTALL_RPATH "../lib") install(TARGETS imageCutter + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin BUNDLE DESTINATION lib ) @@ -52,6 +54,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") install(TARGETS imageCutter + EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION . ) diff --git a/utilities/install.cmake b/utilities/install.cmake index 60d3a6b5..ebe845af 100644 --- a/utilities/install.cmake +++ b/utilities/install.cmake @@ -1,19 +1,3 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Windows") - install(FILES - ${CMAKE_BINARY_DIR}/utilities/SC_version_buildtime.h - DESTINATION ${CMAKE_INSTALL_PREFIX}/../install_SlopeCraftL/Cpp/include/SlopeCraft) - - return() -endif () - -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - install(FILES - ${CMAKE_BINARY_DIR}/utilities/SC_version_buildtime.h - DESTINATION include/SlopeCraft) - - return() -endif () - -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - return() -endif () \ No newline at end of file +install(FILES + ${CMAKE_BINARY_DIR}/utilities/SC_version_buildtime.h + DESTINATION include/SlopeCraft) \ No newline at end of file diff --git a/vccl/install.cmake b/vccl/install.cmake index 6ee224a8..4b69bba7 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -6,6 +6,7 @@ set(AppName vccl) if (CMAKE_SYSTEM_NAME MATCHES "Windows") install(TARGETS vccl + EXPORT SlopeCraftTargets RUNTIME DESTINATION .) install(FILES vccl-config.json DESTINATION .) @@ -36,6 +37,7 @@ endif () if (CMAKE_SYSTEM_NAME MATCHES "Linux") install(TARGETS vccl + EXPORT SlopeCraftTargets RUNTIME DESTINATION bin LIBRARY DESTINATION lib) install(FILES vccl-config.json @@ -57,6 +59,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include(${CMAKE_SOURCE_DIR}/VisualCraftL/setup_zip_names.cmake) install(TARGETS vccl + EXPORT SlopeCraftTargets RUNTIME DESTINATION ${vccl_prefix} BUNDLE DESTINATION ${vccl_prefix}) @@ -69,6 +72,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) install(TARGETS VisualCraftL + EXPORT SlopeCraftTargets RUNTIME DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks LIBRARY DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks) From 09fd7d518071a2589943c0eee83ed6c075221143 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 19:09:33 +0800 Subject: [PATCH 0661/1123] install shaderc manually in linux-build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index f6a96fef..bfa9bc88 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -63,6 +63,10 @@ jobs: if: matrix.gpu_api == 'Vulkan' run: | sudo apt install vulkan-tools libvulkan1 glslang-tools + cd .. + wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz + tar xvf install.tgz + sudo mv -r install/* /usr whereis glslc glslc --version From de94e97901b174b04844c12494f18a751b77baee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 19:13:45 +0800 Subject: [PATCH 0662/1123] try to fix mac build Signed-off-by: ToKiNoBug --- SlopeCraft/install.cmake | 2 +- SlopeCraftL/install.cmake | 28 ++++------------------------ VisualCraft/install.cmake | 2 +- VisualCraftL/install.cmake | 5 ++++- vccl/install.cmake | 2 +- 5 files changed, 11 insertions(+), 28 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 86c61e67..dd840fa8 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -21,7 +21,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS # Install app install(TARGETS SlopeCraft - EXPORT SlopeCraftTargets + #EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION . ) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index ab8f4f92..0f2151ad 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -54,30 +54,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") endif () if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - # install for applications - # install(TARGETS SlopeCraftL - # RUNTIME DESTINATION . - # LIBRARY DESTINATION .) - - # install to lib dirs - # install(TARGETS SlopeCraftL - # RUNTIME DESTINATION ../install_SlopeCraftL/Cpp/bin - # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - # - # # LIBRARY DESTINATION ../install_SlopeCraftL/Cpp/lib - # ) - - # install(TARGETS SlopeCraftL_C - # RUNTIME DESTINATION ../install_SlopeCraftL/C/bin - # LIBRARY DESTINATION ../install_SlopeCraftL/C/lib - # - # LIBRARY DESTINATION ../install_SlopeCraftL/C/lib - # ) - # install(FILES ${SlopeCraft_SCL_Cpp_include_files} - # DESTINATION ../install_SlopeCraftL/Cpp/include) - - # install(FILES ${SlopeCraft_SCL_C_include_files} - # DESTINATION ../install_SlopeCraftL/C/include) + install(TARGETS SlopeCraftL + EXPORT SlopeCraftTargets + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib) return() endif () diff --git a/VisualCraft/install.cmake b/VisualCraft/install.cmake index efba413a..96f5a60f 100644 --- a/VisualCraft/install.cmake +++ b/VisualCraft/install.cmake @@ -68,7 +68,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") ) install(TARGETS VisualCraftL - EXPORT SlopeCraftTargets + # EXPORT SlopeCraftTargets RUNTIME DESTINATION VisualCraft.app/Contents/Frameworks LIBRARY DESTINATION VisualCraft.app/Contents/Frameworks) diff --git a/VisualCraftL/install.cmake b/VisualCraftL/install.cmake index d6d90f8f..52a2faa3 100644 --- a/VisualCraftL/install.cmake +++ b/VisualCraftL/install.cmake @@ -40,7 +40,10 @@ if (${LINUX}) endif () if (${APPLE}) - # VCL is installed into vccl or VC + install(TARGETS VisualCraftL + EXPORT SlopeCraftTargets + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib) return() endif () diff --git a/vccl/install.cmake b/vccl/install.cmake index 4b69bba7..9bb4e0f4 100644 --- a/vccl/install.cmake +++ b/vccl/install.cmake @@ -72,7 +72,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${vccl_prefix}/vccl.app/Contents/MacOS/Blocks_VCL) install(TARGETS VisualCraftL - EXPORT SlopeCraftTargets + #EXPORT SlopeCraftTargets RUNTIME DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks LIBRARY DESTINATION ${vccl_prefix}/vccl.app/Contents/Frameworks) From 6f2db80501552de24a2a2e14af19f059f80232b6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 19:17:29 +0800 Subject: [PATCH 0663/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index bfa9bc88..9daacbc5 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -66,7 +66,7 @@ jobs: cd .. wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz tar xvf install.tgz - sudo mv -r install/* /usr + sudo mv install/* /usr whereis glslc glslc --version From a8a9860382bb26dd108d623d0f600810bd62e19e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 19:19:01 +0800 Subject: [PATCH 0664/1123] try to fix mac build Signed-off-by: ToKiNoBug --- SlopeCraft/install.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index dd840fa8..373b5c34 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -21,7 +21,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install for macOS # Install app install(TARGETS SlopeCraft - #EXPORT SlopeCraftTargets + EXPORT SlopeCraftTargets RUNTIME DESTINATION . BUNDLE DESTINATION . ) @@ -58,7 +58,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/Presets) install(TARGETS SlopeCraftL - EXPORT SlopeCraftTargets + #EXPORT SlopeCraftTargets RUNTIME DESTINATION SlopeCraft.app/Contents/Frameworks LIBRARY DESTINATION SlopeCraft.app/Contents/Frameworks) From 6cedd85b5156c9060f8f7fc66de658993481ccad Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 19:30:31 +0800 Subject: [PATCH 0665/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9daacbc5..76fe128c 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -34,7 +34,7 @@ jobs: run: sudo apt install cmake ninja-build - name: Install dependencies - run: sudo apt install zstd xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev + run: sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev - name: Install xsimd run: | From d6d8926cef6598fbf3721c3688349e900cc59d09 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 20:08:42 +0800 Subject: [PATCH 0666/1123] try to fix linux build Signed-off-by: ToKiNoBug --- cmake/configure_zstd.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/configure_zstd.cmake b/cmake/configure_zstd.cmake index 33362b41..f0e29fd8 100644 --- a/cmake/configure_zstd.cmake +++ b/cmake/configure_zstd.cmake @@ -1,4 +1,5 @@ -find_package(zstd +find_package(ZSTD + CONFIG REQUIRED) set(SC_zstd_target_name "") From 38c0a58c3fad50fc1bb9911b77a4f09092fc4115 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 20:37:45 +0800 Subject: [PATCH 0667/1123] try to fix linux build Signed-off-by: ToKiNoBug --- cmake/configure_zstd.cmake | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/cmake/configure_zstd.cmake b/cmake/configure_zstd.cmake index f0e29fd8..04095ca1 100644 --- a/cmake/configure_zstd.cmake +++ b/cmake/configure_zstd.cmake @@ -1,6 +1,33 @@ -find_package(ZSTD - CONFIG - REQUIRED) + + +find_package(ZSTD QUIET) +if (NOT ZSTD_FOUND) + message(STATUS "Failed to find zstd with \"find_package\", try importing manually...") + find_library(zstd_lib_loc NAMES zstd REQUIRED) + message(STATUS "Found zstd manually at ${zstd_lib_loc}") + + cmake_path(GET zstd_lib_loc EXTENSION zstd_lib_ext) + message(STATUS "zstd_lib_ext: ${zstd_lib_ext}") + set(zstd_is_shared OFF) + set(shared_lib_extension ".dll;.so;.dylib") + foreach (shared_lib_ext ${shared_lib_extension}) + if (${zstd_lib_ext} MATCHES ${shared_lib_ext}) + set(zstd_is_shared ON) + break() + endif () + endforeach () + if (${zstd_is_shared}) + add_library(zstd_manually_imported SHARED IMPORTED) + else () + add_library(zstd_manually_imported STATIC IMPORTED) + endif () + set_target_properties(zstd_manually_imported PROPERTIES + IMPORTED_LOCATION ${zstd_lib_loc}) + + cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) + cmake_path(GET zstd_install_dir PARENT_PATH zstd_install_dir) + target_include_directories(zstd_manually_imported INTERFACE "${zstd_install_dir}/include") +endif () set(SC_zstd_target_name "") if (TARGET zstd::libzstd_shared) @@ -9,6 +36,8 @@ elseif (TARGET zstd::zstd) set(SC_zstd_target_name "zstd::zstd") elseif (TARGET zstd::libzstd_static) set(SC_zstd_target_name "zstd::libzstd_static") +elseif (TARGET zstd_manually_imported) + set(SC_zstd_target_name "zstd_manually_imported") elseif () message(FATAL_ERROR "No zstd library target imported.") endif () From a0dedc41aff26563b01af4e8d3220cfacdb7ab1b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 20:40:42 +0800 Subject: [PATCH 0668/1123] try to fix linux build Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 52c7f1b0..d598d7b8 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -11,7 +11,7 @@ find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) find_package(Boost COMPONENTS iostreams REQUIRED) -find_package(zstd REQUIRED) +#find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) From e0996742f254dbc5adc0cf8120380cc3199232c0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 21:04:35 +0800 Subject: [PATCH 0669/1123] try to fix linux build Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft_cache.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 402bd516..8c361770 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -323,7 +323,12 @@ void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { ofs.set_auto_close(true); { boost::iostreams::zstd_params params; + // ZSTD_defaultCLevel() doesn't exist below zstd 1.5 +#if ZSTD_VERSION_MINOR >= 5 params.level = uint32_t(ZSTD_defaultCLevel()); +#else + params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); +#endif ofs.push(boost::iostreams::zstd_compressor{params}); ofs.push(boost::iostreams::file_sink{filename, std::ios::binary}); } From d546534cecd09d4cabac1a045485e3a7f4958473 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 21:36:28 +0800 Subject: [PATCH 0670/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 76fe128c..6a782c13 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -65,8 +65,8 @@ jobs: sudo apt install vulkan-tools libvulkan1 glslang-tools cd .. wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz - tar xvf install.tgz - sudo mv install/* /usr + tar xf install.tgz + sudo cp -r install/* /usr whereis glslc glslc --version From 0a69ea68d81c1eda816f237abc04bb9a63534255 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jan 2024 22:01:17 +0800 Subject: [PATCH 0671/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 6a782c13..279c7cd3 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -62,14 +62,16 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-tools libvulkan1 glslang-tools - cd .. - wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz - tar xf install.tgz - sudo cp -r install/* /usr + sudo apt install vulkan-sdk whereis glslc glslc --version + # vulkan-tools libvulkan1 glslang-tools + # cd .. + # wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz + # tar xf install.tgz + # sudo cp -r install/* /usr + - name: Checkout repository uses: actions/checkout@v4 From c74a3f04a58e2feda365372f0988e3e724fd9e33 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 16:19:29 +0800 Subject: [PATCH 0672/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 279c7cd3..c95033df 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -62,15 +62,17 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-sdk + sudo apt install vulkan-tools libvulkan1 glslang-tools + cd .. + wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz + tar xf install.tgz + sudo cp -r install/* /usr whereis glslc glslc --version - # vulkan-tools libvulkan1 glslang-tools - # cd .. - # wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz - # tar xf install.tgz - # sudo cp -r install/* /usr + # + #vulkan-sdk + # - name: Checkout repository uses: actions/checkout@v4 From a7a09617aec44176fe86005495d3af7074000ce1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 16:24:13 +0800 Subject: [PATCH 0673/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index c95033df..1f504202 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -62,7 +62,7 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-tools libvulkan1 glslang-tools + sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools cd .. wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz tar xf install.tgz From 00263da647d1d15f156ac02a880f9f22489454a2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 16:48:22 +0800 Subject: [PATCH 0674/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 1f504202..3ff70455 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -63,12 +63,14 @@ jobs: if: matrix.gpu_api == 'Vulkan' run: | sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools - cd .. - wget https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/446/20240123-122115/install.tgz - tar xf install.tgz - sudo cp -r install/* /usr + cd ~/Downloads + wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz + tar xf vulkansdk-linux-x86_64-1.3.275.0 + sudo cp -r ./vulkansdk-linux-x86_64-1.3.275.0/1.3.275.0/x86_64 /usr whereis glslc glslc --version + whereis vulkaninfo + vulkaninfo --version # #vulkan-sdk From 6f81d7fb1a8f6b1e83d209eeed15c93dae64293a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 17:11:39 +0800 Subject: [PATCH 0675/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 3ff70455..2810beb7 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -80,7 +80,7 @@ jobs: uses: actions/checkout@v4 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: CMake build run: cmake --build ./build --parallel From 25397639837880e79ca1b281208098f9d8cc9adb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 17:16:12 +0800 Subject: [PATCH 0676/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 2810beb7..dc10d238 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -62,7 +62,8 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools + sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools + mkdir -p ~/Downloads cd ~/Downloads wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0 From ab6761021c1162cc4707e1480cb7ef18480f0ab5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 17:26:04 +0800 Subject: [PATCH 0677/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index dc10d238..dac4b3af 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -63,8 +63,7 @@ jobs: if: matrix.gpu_api == 'Vulkan' run: | sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools - mkdir -p ~/Downloads - cd ~/Downloads + cd .. wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0 sudo cp -r ./vulkansdk-linux-x86_64-1.3.275.0/1.3.275.0/x86_64 /usr From 788db71188aad59869a05808e1557bbb902aff37 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 17:38:18 +0800 Subject: [PATCH 0678/1123] try to fix linux build Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft_cache.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 8c361770..de4dcdc7 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -377,7 +377,11 @@ bool TokiSlopeCraft::examine_build_cache( ifs.set_auto_close(true); { boost::iostreams::zstd_params params; +#if ZSTD_VERSION_MINOR >= 5 params.level = uint32_t(ZSTD_defaultCLevel()); +#else + params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); +#endif ifs.push(boost::iostreams::zstd_decompressor{}); ifs.push(boost::iostreams::file_source{filename, std::ios::binary}); } From 3d3abf7e1e7c65f1e01e0986cee582247f7633e0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 18:13:34 +0800 Subject: [PATCH 0679/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index dac4b3af..23047aa3 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -65,7 +65,7 @@ jobs: sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools cd .. wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz - tar xf vulkansdk-linux-x86_64-1.3.275.0 + tar xf vulkansdk-linux-x86_64-1.3.275.0.tar.xz sudo cp -r ./vulkansdk-linux-x86_64-1.3.275.0/1.3.275.0/x86_64 /usr whereis glslc glslc --version From 58a0e3cbed9cf526d9d34203bb992a32da968564 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 19:06:16 +0800 Subject: [PATCH 0680/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 23047aa3..151fbb8e 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -66,6 +66,7 @@ jobs: cd .. wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0.tar.xz + ls -l sudo cp -r ./vulkansdk-linux-x86_64-1.3.275.0/1.3.275.0/x86_64 /usr whereis glslc glslc --version From 70fd184f7be9fa158c72dc5782e2b000d08fa562 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 19:12:54 +0800 Subject: [PATCH 0681/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 151fbb8e..45eb4e39 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -67,7 +67,7 @@ jobs: wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0.tar.xz ls -l - sudo cp -r ./vulkansdk-linux-x86_64-1.3.275.0/1.3.275.0/x86_64 /usr + sudo cp -r ./1.3.275.0/x86_64 /usr whereis glslc glslc --version whereis vulkaninfo From 1b4600564529c3332580e84e3df706d36a2b9bca Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 19:15:03 +0800 Subject: [PATCH 0682/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 45eb4e39..09f11286 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -67,7 +67,7 @@ jobs: wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0.tar.xz ls -l - sudo cp -r ./1.3.275.0/x86_64 /usr + sudo cp -r ./1.3.275.0/x86_64/* /usr whereis glslc glslc --version whereis vulkaninfo From 0ca2aaf89c726c4ea9069d4495ce98ed6b353f8c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 19:24:50 +0800 Subject: [PATCH 0683/1123] try to fix linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 09f11286..96689e53 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -71,7 +71,6 @@ jobs: whereis glslc glslc --version whereis vulkaninfo - vulkaninfo --version # #vulkan-sdk From d54d9011c0c47f8f809c51d5644eda22e6361de6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 21:23:42 +0800 Subject: [PATCH 0684/1123] fix gcc-12 build Signed-off-by: ToKiNoBug --- cmake/configure_kompute.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/configure_kompute.cmake b/cmake/configure_kompute.cmake index 714ffb04..bd2466fe 100644 --- a/cmake/configure_kompute.cmake +++ b/cmake/configure_kompute.cmake @@ -7,7 +7,7 @@ set(KOMPUTE_OPT_USE_BUILT_IN_GOOGLE_TEST OFF) set(KOMPUTE_OPT_USE_BUILT_IN_VULKAN_HEADER OFF) FetchContent_Declare(kompute GIT_REPOSITORY https://github.com/SlopeCraft/kompute - GIT_TAG customize + GIT_TAG 37afc4f814eb941adb5c0c9a76fc0d8c4ebc6e53 OVERRIDE_FIND_PACKAGE) message(STATUS "Downaloding SlopeCraft/kompute......") From 56370901ae4b0bac186605086b3d75f3a4e515c0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 21:41:30 +0800 Subject: [PATCH 0685/1123] import tl-expected Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- cmake/configure_tl_expected.cmake | 11 +++++++++++ utilities/GPUWrapper/Vulkan/CMakeLists.txt | 6 +++++- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 cmake/configure_tl_expected.cmake diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 96689e53..43c76528 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -34,7 +34,7 @@ jobs: run: sudo apt install cmake ninja-build - name: Install dependencies - run: sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev + run: sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev tl-expected - name: Install xsimd run: | diff --git a/cmake/configure_tl_expected.cmake b/cmake/configure_tl_expected.cmake new file mode 100644 index 00000000..ab7d0925 --- /dev/null +++ b/cmake/configure_tl_expected.cmake @@ -0,0 +1,11 @@ + find_package(tl-expected QUIET) + if (NOT tl-expected_FOUND) + include(FetchContent) + message(STATUS "Downloading tl-expected...") + FetchContent_Declare(tl-expected + GIT_REPOSITORY https://github.com/TartanLlama/expected.git + GIT_TAG v1.1 + OVERRIDE_FIND_PACKAGE) + FetchContent_MakeAvailable(tl-expected) + find_package(tl-expected CONFIG REQUIRED) + endif () \ No newline at end of file diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index 31d5c4ab..26f59c1f 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -10,11 +10,15 @@ find_package(Eigen3 REQUIRED) include(${CMAKE_SOURCE_DIR}/cmake/configure_kompute.cmake) find_package(kompute REQUIRED) +include(${CMAKE_SOURCE_DIR}/cmake/configure_tl_expected.cmake) +find_package(tl-expected REQUIRED) + target_sources(GPUInterface PRIVATE GPU_interface.cpp) target_link_libraries(GPUInterface PUBLIC Vulkan::Vulkan kompute::kompute - Eigen3::Eigen) + Eigen3::Eigen + tl::expected) target_compile_features(GPUInterface PRIVATE cxx_std_20) get_target_property(glslc_exe Vulkan::glslc LOCATION) From 5f30277adffb9fc203dc663be3f24625996c6b32 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 31 Jan 2024 21:43:51 +0800 Subject: [PATCH 0686/1123] import tl-expected Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 43c76528..a4a8d6ab 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -34,7 +34,8 @@ jobs: run: sudo apt install cmake ninja-build - name: Install dependencies - run: sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev tl-expected + run: + sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libexpected-dev - name: Install xsimd run: | From bc3054a870827f0e833d904e902b45e1de4078d6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 14:55:12 +0800 Subject: [PATCH 0687/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 141 +++++++++++------- .../x86_64-mac-to-arm64-mac.cmake | 77 ++++++++++ 2 files changed, 162 insertions(+), 56 deletions(-) create mode 100644 cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index ba35af12..37644b2d 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -7,71 +7,100 @@ on: - dev jobs: - clang: - runs-on: self-hosted - strategy: - matrix: - build_type: [ Debug, Release ] - gpu_api: [ None ] - env: - BUILD_TYPE: ${{ matrix.build_type }} - GPU_API: ${{ matrix.gpu_api }} - + clang-x86_64-to-arm64: + runs-on: macos-latest steps: - - name: pwd - run: pwd + - name: Install dependents + run: | + brew install cmake xz p7zip llvm ninja qt@6 + vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost + whereis qmake - name: Checkout repository uses: actions/checkout@v4 - # - name: Check env - # run: | - # whoami - # pwd - # ls $HOME - # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l - - - name: Install dependencies - run: | - brew install boost - - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - - name: Build - run: | - cd build - cmake --build . --parallel - # - name: CPack - # run: | - # cd build - # cpack -G ZIP - - name: Install + - name: Cross compile qtbase 6.6.0 run: | + cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME + mkdir $HOME/qt6.6.0-x86_64-mac-to-arm64-mac + wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qtbase-everywhere-src-6.6.0.tar.xz + tar xf qtbase-everywhere-src-6.6.0.tar.xz + mv qtbase-everywhere-src-6.6.0 qtbase-6.6.0 + cd qtbase-6.6.0 + mkdir build cd build - cmake --install . + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -device macx-clang - # - name: Fix VisualCraft.app - # run: | - # cd build/install - # cd VisualCraft.app/Contents/Frameworks - # cp /opt/homebrew/lib/libzstd.1.dylib . - # cp /opt/homebrew/lib/liblzma.5.dylib . - # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib - # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib - # cd ../../.. - # codesign --force --deep --sign=- VisualCraft.app - - - name: Compress as zip + - name: Cross compile qttools 6.6.0 run: | - cd build - 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qttools-everywhere-src-6.6.0.tar.xz + tar xf qttools-everywhere-src-6.6.0.tar.xz - - name: Get short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang - path: build/SlopeCraft*.zip + # clang: + # runs-on: self-hosted + # strategy: + # matrix: + # build_type: [ Debug, Release ] + # gpu_api: [ None ] + # env: + # BUILD_TYPE: ${{ matrix.build_type }} + # GPU_API: ${{ matrix.gpu_api }} + # + # steps: + # - name: pwd + # run: pwd + # + # - name: Checkout repository + # uses: actions/checkout@v4 + # # - name: Check env + # # run: | + # # whoami + # # pwd + # # ls $HOME + # # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l + # + # - name: Install dependencies + # run: | + # brew install boost + # + # - name: Configure CMake + # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + # - name: Build + # run: | + # cd build + # cmake --build . --parallel + # # - name: CPack + # # run: | + # # cd build + # # cpack -G ZIP + # - name: Install + # run: | + # cd build + # cmake --install . + # + # # - name: Fix VisualCraft.app + # # run: | + # # cd build/install + # # cd VisualCraft.app/Contents/Frameworks + # # cp /opt/homebrew/lib/libzstd.1.dylib . + # # cp /opt/homebrew/lib/liblzma.5.dylib . + # # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + # # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + # # cd ../../.. + # # codesign --force --deep --sign=- VisualCraft.app + # + # - name: Compress as zip + # run: | + # cd build + # 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + # + # - name: Get short SHA + # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + # - name: Upload Artifacts + # uses: actions/upload-artifact@v3 + # with: + # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang + # path: build/SlopeCraft*.zip @@ -128,4 +157,4 @@ jobs: # uses: actions/upload-artifact@v3 # with: # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang - # path: build/install/SlopeCraft*.zip +# path: build/install/SlopeCraft*.zip diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake new file mode 100644 index 00000000..b7371664 --- /dev/null +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.18) +include_guard(GLOBAL) + +set(CMAKE_SYSTEM_NAME Darwin) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(TARGET_SYSROOT "") +set(CMAKE_SYSROOT ${TARGET_SYSROOT}) + +#set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:/usr/lib/aarch64-linux-gnu/pkgconfig) +#set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/pkgconfig/:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${TARGET_SYSROOT}/usr/lib/pkgconfig) +#set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) + +# if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables +set(CMAKE_C_COMPILER /usr/local/opt/llvm/bin/clang) +set(CMAKE_CXX_COMPILER /usr/local/opt/llvm/bin/clang++) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") + +set(QT_COMPILER_FLAGS "-march=armv8-a") +set(QT_COMPILER_FLAGS_RELEASE "-O3 -pipe") +set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_BUILD_RPATH ${TARGET_SYSROOT}) + + +include(CMakeInitializeConfigs) + +function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING) + if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS") + set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}") + + foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) + if (DEFINED QT_COMPILER_FLAGS_${config}) + set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}") + endif () + endforeach () + endif () + + + if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS") + foreach (config SHARED MODULE EXE) + set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}") + endforeach () + endif () + + _cmake_initialize_per_config_variable(${ARGV}) +endfunction() + +#set(XCB_PATH_VARIABLE ${TARGET_SYSROOT}) +# +#set(GL_INC_DIR ${TARGET_SYSROOT}/usr/include) +#set(GL_LIB_DIR ${TARGET_SYSROOT}:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/:${TARGET_SYSROOT}/usr:${TARGET_SYSROOT}/usr/lib) +# +#set(EGL_INCLUDE_DIR ${GL_INC_DIR}) +#set(EGL_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libEGL.so) +# +#set(OPENGL_INCLUDE_DIR ${GL_INC_DIR}) +#set(OPENGL_opengl_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libOpenGL.so) +# +#set(GLESv2_INCLUDE_DIR ${GL_INC_DIR}) +#set(GLESv2_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libGLESv2.so) +# +#set(gbm_INCLUDE_DIR ${GL_INC_DIR}) +#set(gbm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libgbm.so) +# +#set(Libdrm_INCLUDE_DIR ${GL_INC_DIR}) +#set(Libdrm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libdrm.so) +# +#set(XCB_XCB_INCLUDE_DIR ${GL_INC_DIR}) +#set(XCB_XCB_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libxcb.so) \ No newline at end of file From 79ee33de47a60ab8dd2e907b4e5218ed694ce420 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 15:26:29 +0800 Subject: [PATCH 0688/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 37644b2d..356be4ba 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -13,8 +13,10 @@ jobs: - name: Install dependents run: | brew install cmake xz p7zip llvm ninja qt@6 - vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost whereis qmake + + + #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost - name: Checkout repository uses: actions/checkout@v4 From 92a38a3105c18c3c3dec5b3a1ba80163307162ea Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 15:43:26 +0800 Subject: [PATCH 0689/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 356be4ba..e6e782fa 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -14,7 +14,7 @@ jobs: run: | brew install cmake xz p7zip llvm ninja qt@6 whereis qmake - + #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost @@ -31,7 +31,9 @@ jobs: cd qtbase-6.6.0 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -device macx-clang + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -device macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake + cmake --build . --parallel + cmake --install . - name: Cross compile qttools 6.6.0 run: | From 8569e9cb06e073515c8b3c2f047bcd1128209391 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 16:09:16 +0800 Subject: [PATCH 0690/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index e6e782fa..35040b7a 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -31,7 +31,7 @@ jobs: cd qtbase-6.6.0 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -device macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path /usr/local/bin -device macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake cmake --build . --parallel cmake --install . diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index b7371664..0a26b7f2 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -20,7 +20,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=armv8-a") set(QT_COMPILER_FLAGS_RELEASE "-O3 -pipe") -set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed") +set(QT_LINKER_FLAGS "-Wl,-O -Wl,--hash-style=gnu -Wl,--as-needed") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) From 3d7ef6dfb6c8d828f996a15cbbba6e3086bf2aab Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 16:25:26 +0800 Subject: [PATCH 0691/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 13 ++++++------- .../tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 4 +++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 35040b7a..3a022bd1 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -25,20 +25,19 @@ jobs: run: | cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME mkdir $HOME/qt6.6.0-x86_64-mac-to-arm64-mac - wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qtbase-everywhere-src-6.6.0.tar.xz - tar xf qtbase-everywhere-src-6.6.0.tar.xz - mv qtbase-everywhere-src-6.6.0 qtbase-6.6.0 + git clone https://github.com/qt/qtbase.git qtbase-6.6.0 --recursive cd qtbase-6.6.0 + git checkout v6.6.0 mkdir build cd build ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path /usr/local/bin -device macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake cmake --build . --parallel cmake --install . - - name: Cross compile qttools 6.6.0 - run: | - wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qttools-everywhere-src-6.6.0.tar.xz - tar xf qttools-everywhere-src-6.6.0.tar.xz + # - name: Cross compile qttools 6.6.0 + # run: | + # wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qttools-everywhere-src-6.6.0.tar.xz + # tar xf qttools-everywhere-src-6.6.0.tar.xz # clang: # runs-on: self-hosted diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 0a26b7f2..5501c08a 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -3,6 +3,8 @@ include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Darwin) set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(CMAKE_C_COMPILER_TARGET "aarch64-apple-darwin") +set(CMAKE_CXX_COMPILER_TARGET "aarch64-apple-darwin") set(TARGET_SYSROOT "") set(CMAKE_SYSROOT ${TARGET_SYSROOT}) @@ -20,7 +22,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=armv8-a") set(QT_COMPILER_FLAGS_RELEASE "-O3 -pipe") -set(QT_LINKER_FLAGS "-Wl,-O -Wl,--hash-style=gnu -Wl,--as-needed") +#set(QT_LINKER_FLAGS "-Wl,-O -Wl,--hash-style=gnu -Wl,--as-needed") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) From e89c8286f5cbb68dc6dabc3b42ab27ec6b5dc566 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 16:32:37 +0800 Subject: [PATCH 0692/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 3a022bd1..5b23be8e 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -30,7 +30,7 @@ jobs: git checkout v6.6.0 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path /usr/local/bin -device macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path /usr/local/bin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake cmake --build . --parallel cmake --install . From 4c0fa164a20cddb858c5f45ed92a4109fe55f1ce Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 16:47:36 +0800 Subject: [PATCH 0693/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 5b23be8e..50c2b041 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -12,8 +12,10 @@ jobs: steps: - name: Install dependents run: | - brew install cmake xz p7zip llvm ninja qt@6 - whereis qmake + brew install cmake xz p7zip llvm ninja + wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz + tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz + mv qt6.6.0-static-x86_64-apple-darwin $HOME #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost @@ -30,7 +32,7 @@ jobs: git checkout v6.6.0 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path /usr/local/bin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake cmake --build . --parallel cmake --install . From f2bf33ac49495f72c38de70656b79f72a013907e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 17:04:35 +0800 Subject: [PATCH 0694/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 31 +++++++++++++++---- .../x86_64-mac-to-arm64-mac.cmake | 8 ++--- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 50c2b041..a3a6b9a2 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -27,19 +27,38 @@ jobs: run: | cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME mkdir $HOME/qt6.6.0-x86_64-mac-to-arm64-mac - git clone https://github.com/qt/qtbase.git qtbase-6.6.0 --recursive - cd qtbase-6.6.0 + git clone https://github.com/qt/qtbase.git qtbase --recursive + cd qtbase git checkout v6.6.0 mkdir build cd build ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake cmake --build . --parallel cmake --install . + rm -rf ./* - # - name: Cross compile qttools 6.6.0 - # run: | - # wget https://download.qt.io/official_releases/qt/6.6/6.6.0/submodules/qttools-everywhere-src-6.6.0.tar.xz - # tar xf qttools-everywhere-src-6.6.0.tar.xz + - name: Cross compile qttools 6.6.0 + run: | + git clone https://github.com/qt/qttools.git qttools --recursive + cd qttools + git checkout v6.6.0 + mkdir build + cd build + $HOME/qt6.6.0-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. + cmake --build . --parallel + cmake --install . + rm -rf ./* + + - name: Compress installed Qt binaries + run: | + tar cvf qt6.6.0-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.0-x86_64-mac-to-arm64-mac/* + xz -9 qt6.6.0-x86_64-mac-to-arm64-mac.tar -T0 + + - name: Upload Qt6.6.0-host-x86_64-mac-target-arm64-mac + uses: actions/upload-artifact@v3 + with: + name: Qt6.6.0-host-x86_64-mac-target-arm64-mac + path: qt6.6.0-x86_64-mac-to-arm64-mac.tar.xz # clang: # runs-on: self-hosted diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 5501c08a..67c42a00 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Darwin) -set(CMAKE_SYSTEM_PROCESSOR aarch64) -set(CMAKE_C_COMPILER_TARGET "aarch64-apple-darwin") -set(CMAKE_CXX_COMPILER_TARGET "aarch64-apple-darwin") +set(CMAKE_SYSTEM_PROCESSOR arm64) +set(CMAKE_C_COMPILER_TARGET "arm64-apple-darwin") +set(CMAKE_CXX_COMPILER_TARGET "arm64-apple-darwin") set(TARGET_SYSROOT "") set(CMAKE_SYSROOT ${TARGET_SYSROOT}) @@ -20,7 +20,7 @@ set(CMAKE_CXX_COMPILER /usr/local/opt/llvm/bin/clang++) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") -set(QT_COMPILER_FLAGS "-march=armv8-a") +set(QT_COMPILER_FLAGS "-march=arm64") set(QT_COMPILER_FLAGS_RELEASE "-O3 -pipe") #set(QT_LINKER_FLAGS "-Wl,-O -Wl,--hash-style=gnu -Wl,--as-needed") From 20cc590591d3cfe47cf89898a1a15b379d635b5d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 17:19:50 +0800 Subject: [PATCH 0695/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 3 ++- cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index a3a6b9a2..908c4119 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -13,6 +13,7 @@ jobs: - name: Install dependents run: | brew install cmake xz p7zip llvm ninja + vcpkg install --triplet=arm64-osx zlib zstd wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz mv qt6.6.0-static-x86_64-apple-darwin $HOME @@ -32,7 +33,7 @@ jobs: git checkout v6.6.0 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx cmake --build . --parallel cmake --install . rm -rf ./* diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 67c42a00..134a685f 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -5,6 +5,7 @@ set(CMAKE_SYSTEM_NAME Darwin) set(CMAKE_SYSTEM_PROCESSOR arm64) set(CMAKE_C_COMPILER_TARGET "arm64-apple-darwin") set(CMAKE_CXX_COMPILER_TARGET "arm64-apple-darwin") +set(CMAKE_OSX_ARCHITECTURES "arm64") set(TARGET_SYSROOT "") set(CMAKE_SYSROOT ${TARGET_SYSROOT}) From f01e09824153004584528aea4c0f79f3a55801e6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 17:57:40 +0800 Subject: [PATCH 0696/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 1 + cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 908c4119..a0e0fa90 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -12,6 +12,7 @@ jobs: steps: - name: Install dependents run: | + brew remove zlib brew install cmake xz p7zip llvm ninja vcpkg install --triplet=arm64-osx zlib zstd wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 134a685f..074c9f98 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) +set(CMAKE_CROSSCOMPILING ON) set(CMAKE_SYSTEM_NAME Darwin) set(CMAKE_SYSTEM_PROCESSOR arm64) set(CMAKE_C_COMPILER_TARGET "arm64-apple-darwin") @@ -17,6 +18,8 @@ set(CMAKE_SYSROOT ${TARGET_SYSROOT}) # if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables set(CMAKE_C_COMPILER /usr/local/opt/llvm/bin/clang) set(CMAKE_CXX_COMPILER /usr/local/opt/llvm/bin/clang++) +set(CMAKE_C_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) +set(CMAKE_CXX_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") From 01fb5f14222ade084480dbfeb0835a6d3da9a10c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 18:06:30 +0800 Subject: [PATCH 0697/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 074c9f98..9f586f51 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -21,7 +21,7 @@ set(CMAKE_CXX_COMPILER /usr/local/opt/llvm/bin/clang++) set(CMAKE_C_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) set(CMAKE_CXX_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include -fuse-ld=lld") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=arm64") From 28e63cf4a671e20d4d6acc6ed2957951992e639d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 18:17:51 +0800 Subject: [PATCH 0698/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake index 9f586f51..4609e0f9 100644 --- a/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake +++ b/cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_CROSSCOMPILING ON) -set(CMAKE_SYSTEM_NAME Darwin) -set(CMAKE_SYSTEM_PROCESSOR arm64) +set(CMAKE_SYSTEM_NAME "Darwin") +set(CMAKE_SYSTEM_PROCESSOR "arm64") set(CMAKE_C_COMPILER_TARGET "arm64-apple-darwin") set(CMAKE_CXX_COMPILER_TARGET "arm64-apple-darwin") set(CMAKE_OSX_ARCHITECTURES "arm64") +set(CMAKE_OSX_DEPLOYMENT_TARGET 12) set(TARGET_SYSROOT "") set(CMAKE_SYSROOT ${TARGET_SYSROOT}) @@ -18,10 +19,8 @@ set(CMAKE_SYSROOT ${TARGET_SYSROOT}) # if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables set(CMAKE_C_COMPILER /usr/local/opt/llvm/bin/clang) set(CMAKE_CXX_COMPILER /usr/local/opt/llvm/bin/clang++) -set(CMAKE_C_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) -set(CMAKE_CXX_LINK_EXECUTABLE /usr/local/opt/llvm/bin/lld) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include -fuse-ld=lld") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=arm64") From 7cae895061ae16bf3d238c230118e9a25229b09a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 18:54:37 +0800 Subject: [PATCH 0699/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index a0e0fa90..e4c3a0dd 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -25,42 +25,42 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Cross compile qtbase 6.6.0 + - name: Cross compile qtbase 6.6.2 run: | cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME - mkdir $HOME/qt6.6.0-x86_64-mac-to-arm64-mac + mkdir $HOME/qt6.6.2-x86_64-mac-to-arm64-mac git clone https://github.com/qt/qtbase.git qtbase --recursive cd qtbase - git checkout v6.6.0 + git checkout v6.6.2 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.0-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.2-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx cmake --build . --parallel cmake --install . rm -rf ./* - - name: Cross compile qttools 6.6.0 + - name: Cross compile qttools 6.6.2 run: | git clone https://github.com/qt/qttools.git qttools --recursive cd qttools - git checkout v6.6.0 + git checkout v6.6.2 mkdir build cd build - $HOME/qt6.6.0-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. + $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. cmake --build . --parallel cmake --install . rm -rf ./* - name: Compress installed Qt binaries run: | - tar cvf qt6.6.0-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.0-x86_64-mac-to-arm64-mac/* - xz -9 qt6.6.0-x86_64-mac-to-arm64-mac.tar -T0 + tar cvf qt6.6.2-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/* + xz -9 qt6.6.2-x86_64-mac-to-arm64-mac.tar -T0 - - name: Upload Qt6.6.0-host-x86_64-mac-target-arm64-mac + - name: Upload Qt6.6.2-host-x86_64-mac-target-arm64-mac uses: actions/upload-artifact@v3 with: - name: Qt6.6.0-host-x86_64-mac-target-arm64-mac - path: qt6.6.0-x86_64-mac-to-arm64-mac.tar.xz + name: Qt6.6.2-host-x86_64-mac-target-arm64-mac + path: qt6.6.2-x86_64-mac-to-arm64-mac.tar.xz # clang: # runs-on: self-hosted From f8c4aec1de28f5b07de9127474533006ea897de9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 18:59:40 +0800 Subject: [PATCH 0700/1123] [CI] try to cross compile qt6.6.0 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index e4c3a0dd..a8ce2782 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -34,7 +34,7 @@ jobs: git checkout v6.6.2 mkdir build cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.2-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx + ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx cmake --build . --parallel cmake --install . rm -rf ./* From 37d2f86e14b9f4fda185e9b519cc2b18a5c71305 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 19:15:58 +0800 Subject: [PATCH 0701/1123] [CI] build x86_64 mac binaries with and without vectorize Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 344 ++++++++++++------------ .github/workflows/macos-build-x64.yml | 7 +- cmake/select_vectorize_flag.cmake | 1 + 3 files changed, 181 insertions(+), 171 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index a8ce2782..68e9e7b1 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -7,180 +7,186 @@ on: - dev jobs: - clang-x86_64-to-arm64: + nothing: runs-on: macos-latest steps: - - name: Install dependents - run: | - brew remove zlib - brew install cmake xz p7zip llvm ninja - vcpkg install --triplet=arm64-osx zlib zstd - wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz - tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz - mv qt6.6.0-static-x86_64-apple-darwin $HOME - - - #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost + - name: checkout + run: echo "rua" - - name: Checkout repository - uses: actions/checkout@v4 +# clang-x86_64-to-arm64: +# runs-on: macos-latest +# steps: +# - name: Install dependents +# run: | +# brew remove zlib +# brew install cmake xz p7zip llvm ninja +# vcpkg install --triplet=arm64-osx zlib zstd +# wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz +# tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz +# mv qt6.6.0-static-x86_64-apple-darwin $HOME +# +# +# #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost +# +# - name: Checkout repository +# uses: actions/checkout@v4 +# +# - name: Cross compile qtbase 6.6.2 +# run: | +# cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME +# mkdir $HOME/qt6.6.2-x86_64-mac-to-arm64-mac +# git clone https://github.com/qt/qtbase.git qtbase --recursive +# cd qtbase +# git checkout v6.6.2 +# mkdir build +# cd build +# ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx +# cmake --build . --parallel +# cmake --install . +# rm -rf ./* +# +# - name: Cross compile qttools 6.6.2 +# run: | +# git clone https://github.com/qt/qttools.git qttools --recursive +# cd qttools +# git checkout v6.6.2 +# mkdir build +# cd build +# $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. +# cmake --build . --parallel +# cmake --install . +# rm -rf ./* +# +# - name: Compress installed Qt binaries +# run: | +# tar cvf qt6.6.2-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/* +# xz -9 qt6.6.2-x86_64-mac-to-arm64-mac.tar -T0 +# +# - name: Upload Qt6.6.2-host-x86_64-mac-target-arm64-mac +# uses: actions/upload-artifact@v3 +# with: +# name: Qt6.6.2-host-x86_64-mac-target-arm64-mac +# path: qt6.6.2-x86_64-mac-to-arm64-mac.tar.xz - - name: Cross compile qtbase 6.6.2 - run: | - cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME - mkdir $HOME/qt6.6.2-x86_64-mac-to-arm64-mac - git clone https://github.com/qt/qtbase.git qtbase --recursive - cd qtbase - git checkout v6.6.2 - mkdir build - cd build - ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx - cmake --build . --parallel - cmake --install . - rm -rf ./* +# clang: +# runs-on: self-hosted +# strategy: +# matrix: +# build_type: [ Debug, Release ] +# gpu_api: [ None ] +# env: +# BUILD_TYPE: ${{ matrix.build_type }} +# GPU_API: ${{ matrix.gpu_api }} +# +# steps: +# - name: pwd +# run: pwd +# +# - name: Checkout repository +# uses: actions/checkout@v4 +# # - name: Check env +# # run: | +# # whoami +# # pwd +# # ls $HOME +# # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l +# +# - name: Install dependencies +# run: | +# brew install boost +# +# - name: Configure CMake +# run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 +# - name: Build +# run: | +# cd build +# cmake --build . --parallel +# # - name: CPack +# # run: | +# # cd build +# # cpack -G ZIP +# - name: Install +# run: | +# cd build +# cmake --install . +# +# # - name: Fix VisualCraft.app +# # run: | +# # cd build/install +# # cd VisualCraft.app/Contents/Frameworks +# # cp /opt/homebrew/lib/libzstd.1.dylib . +# # cp /opt/homebrew/lib/liblzma.5.dylib . +# # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib +# # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib +# # cd ../../.. +# # codesign --force --deep --sign=- VisualCraft.app +# +# - name: Compress as zip +# run: | +# cd build +# 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* +# +# - name: Get short SHA +# run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV +# - name: Upload Artifacts +# uses: actions/upload-artifact@v3 +# with: +# name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang +# path: build/SlopeCraft*.zip - - name: Cross compile qttools 6.6.2 - run: | - git clone https://github.com/qt/qttools.git qttools --recursive - cd qttools - git checkout v6.6.2 - mkdir build - cd build - $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. - cmake --build . --parallel - cmake --install . - rm -rf ./* - - name: Compress installed Qt binaries - run: | - tar cvf qt6.6.2-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/* - xz -9 qt6.6.2-x86_64-mac-to-arm64-mac.tar -T0 - - name: Upload Qt6.6.2-host-x86_64-mac-target-arm64-mac - uses: actions/upload-artifact@v3 - with: - name: Qt6.6.2-host-x86_64-mac-target-arm64-mac - path: qt6.6.2-x86_64-mac-to-arm64-mac.tar.xz - - # clang: - # runs-on: self-hosted - # strategy: - # matrix: - # build_type: [ Debug, Release ] - # gpu_api: [ None ] - # env: - # BUILD_TYPE: ${{ matrix.build_type }} - # GPU_API: ${{ matrix.gpu_api }} - # - # steps: - # - name: pwd - # run: pwd - # - # - name: Checkout repository - # uses: actions/checkout@v4 - # # - name: Check env - # # run: | - # # whoami - # # pwd - # # ls $HOME - # # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l - # - # - name: Install dependencies - # run: | - # brew install boost - # - # - name: Configure CMake - # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - # - name: Build - # run: | - # cd build - # cmake --build . --parallel - # # - name: CPack - # # run: | - # # cd build - # # cpack -G ZIP - # - name: Install - # run: | - # cd build - # cmake --install . - # - # # - name: Fix VisualCraft.app - # # run: | - # # cd build/install - # # cd VisualCraft.app/Contents/Frameworks - # # cp /opt/homebrew/lib/libzstd.1.dylib . - # # cp /opt/homebrew/lib/liblzma.5.dylib . - # # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib - # # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib - # # cd ../../.. - # # codesign --force --deep --sign=- VisualCraft.app - # - # - name: Compress as zip - # run: | - # cd build - # 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* - # - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - name: Upload Artifacts - # uses: actions/upload-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang - # path: build/SlopeCraft*.zip - - - - # macos-build: - # runs-on: macos-latest - # strategy: - # matrix: - # build_type: [ Debug, Release ] - # gpu_api: [ None ] - # env: - # BUILD_TYPE: ${{ matrix.build_type }} - # GPU_API: ${{ matrix.gpu_api }} - # steps: - # - name: brew update - # run: brew update - # - name: echo matrix variables (build_type = ${{ matrix.build_type }}) - # run: | - # echo $BUILD_TYPE - # echo $GPU_API - # - name: Install build system - # run: brew install ninja cmake - # - name: Install dependencies - # run: | - # brew install libpng qt@6 eigen - # brew reinstall libomp - # - name: Add /usr/local/lib to PATH - # run: echo "/usr/local/lib" >> $GITHUB_PATH - # - name: Check PATH - # run: echo $PATH - # - name: Checkout repository - # uses: actions/checkout@v4 - # - name: Configure CMake - # run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar - # - name: Build and Install - # run: | - # cd build - # cmake --build . --parallel - # cmake --install . - # cd install - # chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft - # chmod +x MapViewer.app/Contents/MacOS/MapViewer - # chmod +x imageCutter.app/Contents/MacOS/imageCutter - # chmod +x VisualCraft.app/Contents/MacOS/VisualCraft - # chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl - # # chmod +x vccl.app/Contents/MacOS/vccl - # - name: Compress as zip - # run: | - # cd ./build/install - # zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* - # - # - name: Get short SHA - # run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - # - name: Upload Artifacts - # uses: actions/upload-artifact@v3 - # with: - # name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang +# macos-build: +# runs-on: macos-latest +# strategy: +# matrix: +# build_type: [ Debug, Release ] +# gpu_api: [ None ] +# env: +# BUILD_TYPE: ${{ matrix.build_type }} +# GPU_API: ${{ matrix.gpu_api }} +# steps: +# - name: brew update +# run: brew update +# - name: echo matrix variables (build_type = ${{ matrix.build_type }}) +# run: | +# echo $BUILD_TYPE +# echo $GPU_API +# - name: Install build system +# run: brew install ninja cmake +# - name: Install dependencies +# run: | +# brew install libpng qt@6 eigen +# brew reinstall libomp +# - name: Add /usr/local/lib to PATH +# run: echo "/usr/local/lib" >> $GITHUB_PATH +# - name: Check PATH +# run: echo $PATH +# - name: Checkout repository +# uses: actions/checkout@v4 +# - name: Configure CMake +# run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=/System/Volumes/Data/usr/local/Cellar +# - name: Build and Install +# run: | +# cd build +# cmake --build . --parallel +# cmake --install . +# cd install +# chmod +x SlopeCraft.app/Contents/MacOS/SlopeCraft +# chmod +x MapViewer.app/Contents/MacOS/MapViewer +# chmod +x imageCutter.app/Contents/MacOS/imageCutter +# chmod +x VisualCraft.app/Contents/MacOS/VisualCraft +# chmod +x vccl-contents/vccl.app/Contents/MacOS/vccl +# # chmod +x vccl.app/Contents/MacOS/vccl +# - name: Compress as zip +# run: | +# cd ./build/install +# zip -9 -r -y SlopeCraft-5.2.0-macos.zip ./* +# +# - name: Get short SHA +# run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV +# - name: Upload Artifacts +# uses: actions/upload-artifact@v3 +# with: +# name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-clang # path: build/install/SlopeCraft*.zip diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index dda1c4a4..2a63c2b9 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -13,9 +13,11 @@ jobs: matrix: build_type: [ Debug, Release ] gpu_api: [ None ] + vectorize: [ ON, OFF ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} + VECTORIZE: ${{ matrix.vectorize }} steps: # - name: brew upgrade & update # run: | @@ -29,6 +31,7 @@ jobs: run: | echo $BUILD_TYPE echo $GPU_API + echo $VECTORIZE - name: Install Ninja build system run: brew install ninja - name: Install dependencies @@ -56,7 +59,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake # - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -D$SlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | cd build @@ -94,7 +97,7 @@ jobs: - name: Upload Artifacts uses: actions/upload-artifact@v3 with: - name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-x64-clang + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vectorize-${{ matrix.vectorize }}-macos-x64-clang path: build/SlopeCraft*.zip # gcc: diff --git a/cmake/select_vectorize_flag.cmake b/cmake/select_vectorize_flag.cmake index 4c308cad..35f1c668 100644 --- a/cmake/select_vectorize_flag.cmake +++ b/cmake/select_vectorize_flag.cmake @@ -5,6 +5,7 @@ include(CheckCXXCompilerFlag) message(STATUS "System processor arch = ${CMAKE_SYSTEM_PROCESSOR}") set(amd64_arch_names AMD64 x86_64) + if (${CMAKE_SYSTEM_PROCESSOR} IN_LIST amd64_arch_names) if (${MSVC}) set(SlopeCraft_vectorize_flags "/arch:AVX2") From 194509d41b04354675a3f6a1da314ccfca8cb361 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 19:19:08 +0800 Subject: [PATCH 0702/1123] [CI] fix macos ci Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 2a63c2b9..63ef5001 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -59,7 +59,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake # - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -D$SlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | cd build From 1ccd5725636ddbb7bb63c83b516724fd4b64c265 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 20:35:40 +0800 Subject: [PATCH 0703/1123] update to 1.20.4 Signed-off-by: ToKiNoBug --- VisualCraft/vc-config.json | 2 +- cmake/configure_vanilla_zips.cmake | 22 +++++++++++----------- vccl/vccl-config.json | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/VisualCraft/vc-config.json b/VisualCraft/vc-config.json index 5246e465..d85e9927 100644 --- a/VisualCraft/vc-config.json +++ b/VisualCraft/vc-config.json @@ -34,7 +34,7 @@ ], [ 20, - "./Blocks_VCL/Vanilla_1_20_1.zip" + "./Blocks_VCL/Vanilla_1_20_4.zip" ] ], "default_block_state_list": [ diff --git a/cmake/configure_vanilla_zips.cmake b/cmake/configure_vanilla_zips.cmake index c877287d..c7df60b9 100644 --- a/cmake/configure_vanilla_zips.cmake +++ b/cmake/configure_vanilla_zips.cmake @@ -1,13 +1,13 @@ set(VCL_zip_names - "Vanilla_1_12_2.zip" - "Vanilla_1_13_2.zip" - "Vanilla_1_14_4.zip" - "Vanilla_1_15_2.zip" - "Vanilla_1_16_5.zip" - "Vanilla_1_17_1.zip" - "Vanilla_1_18_2.zip" - "Vanilla_1_19_3.zip" - "Vanilla_1_20_1.zip") + "Vanilla_1_12_2.zip" + "Vanilla_1_13_2.zip" + "Vanilla_1_14_4.zip" + "Vanilla_1_15_2.zip" + "Vanilla_1_16_5.zip" + "Vanilla_1_17_1.zip" + "Vanilla_1_18_2.zip" + "Vanilla_1_19_3.zip" + "Vanilla_1_20_4.zip") #https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/Vanilla_1_20_1.zip set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") @@ -28,8 +28,8 @@ foreach (mcver RANGE 12 20) string(CONCAT VCL_current_download_url ${VCL_url_prefix} ${VCL_current_zip_name}) file(DOWNLOAD - ${VCL_current_download_url} - ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) + ${VCL_current_download_url} + ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) if (EXISTS ${CMAKE_SOURCE_DIR}/binaries/${VCL_current_zip_name}) message(STATUS "Downloaded resoruce pack for MC${mcver}.") diff --git a/vccl/vccl-config.json b/vccl/vccl-config.json index 5246e465..d85e9927 100644 --- a/vccl/vccl-config.json +++ b/vccl/vccl-config.json @@ -34,7 +34,7 @@ ], [ 20, - "./Blocks_VCL/Vanilla_1_20_1.zip" + "./Blocks_VCL/Vanilla_1_20_4.zip" ] ], "default_block_state_list": [ From fd38551b01d00e385ea6e3bf03be7a3781279111 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 20:36:46 +0800 Subject: [PATCH 0704/1123] update version number Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7857a840..441ead76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.2) +set(SlopeCraft_version 5.2.3) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From f44e669256ec478ce01d46e262c54e7a198cfb68 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 21:10:13 +0800 Subject: [PATCH 0705/1123] remove static reference to colorsets in utilities Signed-off-by: ToKiNoBug --- SlopeCraftL/Colors.cpp | 10 ++-- SlopeCraftL/TokiSlopeCraft.cpp | 17 +++--- SlopeCraftL/TokiSlopeCraft_cache.cpp | 2 +- VisualCraftL/TokiVC.cpp | 48 ++++++++-------- utilities/ColorManip/imageConvert.hpp | 50 ++++++++-------- utilities/ColorManip/newTokiColor.hpp | 69 ++++++++++++++--------- utilities/MapImageCvter/MapImageCvter.cpp | 11 ++-- utilities/MapImageCvter/MapImageCvter.h | 3 +- 8 files changed, 118 insertions(+), 92 deletions(-) diff --git a/SlopeCraftL/Colors.cpp b/SlopeCraftL/Colors.cpp index 38d04d83..9e3d8e55 100644 --- a/SlopeCraftL/Colors.cpp +++ b/SlopeCraftL/Colors.cpp @@ -25,10 +25,10 @@ This file is part of SlopeCraft. #include -template <> -const colorset_allowed_t *const TokiColor::Allowed = &TokiSlopeCraft::Allowed; -template <> -const colorset_basic_t *const TokiColor::Basic = &TokiSlopeCraft::Basic; +// template <> +// const colorset_allowed_t *const TokiColor::Allowed = +// &TokiSlopeCraft::Allowed; template <> const colorset_basic_t *const +// TokiColor::Basic = &TokiSlopeCraft::Basic; namespace SlopeCraft { int colorCount4External() { return TokiSlopeCraft::Allowed.color_count(); } @@ -50,7 +50,7 @@ AllowedMapList4External() { TokiSlopeCraft::Allowed.map_data(), colorCount4External()); } -} // end namespace SlopeCraft +} // end namespace SlopeCraft void SCL_testHSV() { const float rgb[][3] = {{0, 0, 0}, {1, 1, 1}, {0.99, 0, 0}, {0, 1, 0}, diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 2abcff22..bc374be5 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -21,7 +21,6 @@ This file is part of SlopeCraft. */ #include "TokiSlopeCraft.h" -#include #ifdef RGB #undef RGB @@ -44,15 +43,15 @@ std::unordered_set TokiSlopeCraft::kernel_hash_set; std::mutex SCL_internal_lock; -template <> -const colorset_basic_t &libImageCvt::ImageCvter::basic_colorset = - TokiSlopeCraft::Basic; +// template <> +// const colorset_basic_t &libImageCvt::ImageCvter::basic_colorset = +// TokiSlopeCraft::Basic; +// +// template <> +// const colorset_allowed_t &libImageCvt::ImageCvter::allowed_colorset = +// TokiSlopeCraft::Allowed; -template <> -const colorset_allowed_t &libImageCvt::ImageCvter::allowed_colorset = - TokiSlopeCraft::Allowed; - -TokiSlopeCraft::TokiSlopeCraft() { +TokiSlopeCraft::TokiSlopeCraft() : image_cvter{Basic, Allowed} { kernelStep = step::nothing; this->image_cvter.clear_images(); this->image_cvter.clear_color_hash(); diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index de4dcdc7..6eb52ab0 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -209,7 +209,7 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, return false; } - libMapImageCvt::MapImageCvter temp; + libMapImageCvt::MapImageCvter temp{Basic, Allowed}; const uint64_t expected_hash = this->image_cvter.task_hash(algo, dither); const std::string filename = this->convert_cache_filename_of( convert_dir(this->current_type_dir(), expected_hash)); diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 12ba8618..d79e669d 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -36,29 +36,29 @@ libImageCvt::template ImageCvter::allowed_colorset_t TokiVC::colorset_allowed; // bind static members for template classes -template <> -const libImageCvt::template ImageCvter::basic_colorset_t - &libImageCvt::template ImageCvter::basic_colorset = - TokiVC::colorset_basic; - -template <> -const libImageCvt::template ImageCvter::allowed_colorset_t - &libImageCvt::template ImageCvter::allowed_colorset = - TokiVC::colorset_allowed; - -template <> -const libImageCvt::template ImageCvter::basic_colorset_t - *const newTokiColor< - false, libImageCvt::template ImageCvter::basic_colorset_t, - libImageCvt::template ImageCvter::allowed_colorset_t>::Basic = - &TokiVC::colorset_basic; - -template <> -const libImageCvt::template ImageCvter::allowed_colorset_t - *const newTokiColor< - false, libImageCvt::template ImageCvter::basic_colorset_t, - libImageCvt::template ImageCvter::allowed_colorset_t>::Allowed = - &TokiVC::colorset_allowed; +// template <> +// const libImageCvt::template ImageCvter::basic_colorset_t +// &libImageCvt::template ImageCvter::basic_colorset = +// TokiVC::colorset_basic; +// +// template <> +// const libImageCvt::template ImageCvter::allowed_colorset_t +// &libImageCvt::template ImageCvter::allowed_colorset = +// TokiVC::colorset_allowed; +// +// template <> +// const libImageCvt::template ImageCvter::basic_colorset_t +// *const newTokiColor< +// false, libImageCvt::template ImageCvter::basic_colorset_t, +// libImageCvt::template ImageCvter::allowed_colorset_t>::Basic = +// &TokiVC::colorset_basic; +// +// template <> +// const libImageCvt::template ImageCvter::allowed_colorset_t +// *const newTokiColor< +// false, libImageCvt::template ImageCvter::basic_colorset_t, +// libImageCvt::template ImageCvter::allowed_colorset_t>::Allowed +// = &TokiVC::colorset_allowed; // global variables that VCL uses VCL_resource_pack TokiVC::pack; @@ -82,7 +82,7 @@ bool is_allowed_color_set_ready = false; std::set TokiVC_register; } // namespace TokiVC_internal -TokiVC::TokiVC() { +TokiVC::TokiVC() : img_cvter{colorset_basic, colorset_allowed} { TokiVC_internal::global_lock.lock(); if (TokiVC_internal::is_basic_color_set_ready) { this->_step = VCL_Kernel_step::VCL_wait_for_image; diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 88658040..cb2e7e34 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -92,10 +92,15 @@ class ImageCvter : public GPU_wrapper_wrapper { using coloridx_t = colorid_t; // These static member must be implemented by caller - static const basic_colorset_t &basic_colorset; - static const allowed_colorset_t &allowed_colorset; + // static const basic_colorset_t &basic_colorset; + // static const allowed_colorset_t &allowed_colorset; + + ImageCvter(const basic_colorset_t &basic, const allowed_colorset_t &allowed) + : basic_colorset{basic}, allowed_colorset{allowed} {} protected: + const basic_colorset_t &basic_colorset; + const allowed_colorset_t &allowed_colorset; Eigen::ArrayXX _raw_image; ::SCL_convertAlgo algo; bool dither{false}; @@ -362,7 +367,8 @@ class ImageCvter : public GPU_wrapper_wrapper { #pragma omp parallel for schedule(dynamic) for (int taskIdx = 0; taskIdx < (int)taskCount; taskIdx++) { - tasks[taskIdx]->second.compute(tasks[taskIdx]->first); + tasks[taskIdx]->second.compute(tasks[taskIdx]->first, + this->allowed_colorset); } // #warning we should parallelize here /* @@ -415,7 +421,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (auto &pair : this->_color_hash) { if (!pair.second.is_result_computed()) { if ((pair.first._ARGB & 0xFF'00'00'00) == 0) { - pair.second.compute(pair.first); + pair.second.compute(pair.first, this->allowed_colorset); } else { tasks.emplace_back(&pair); } @@ -460,25 +466,25 @@ class ImageCvter : public GPU_wrapper_wrapper { switch (algo) { case SCL_convertAlgo::RGB: case SCL_convertAlgo::RGB_Better: - colorset_ptrs = {TokiColor_t::Allowed->rgb_data(0), - TokiColor_t::Allowed->rgb_data(1), - TokiColor_t::Allowed->rgb_data(2)}; + colorset_ptrs = {this->allowed_colorset.rgb_data(0), + this->allowed_colorset.rgb_data(1), + this->allowed_colorset.rgb_data(2)}; break; case SCL_convertAlgo::HSV: - colorset_ptrs = {TokiColor_t::Allowed->hsv_data(0), - TokiColor_t::Allowed->hsv_data(1), - TokiColor_t::Allowed->hsv_data(2)}; + colorset_ptrs = {this->allowed_colorset.hsv_data(0), + this->allowed_colorset.hsv_data(1), + this->allowed_colorset.hsv_data(2)}; break; case SCL_convertAlgo::Lab94: case SCL_convertAlgo::Lab00: - colorset_ptrs = {TokiColor_t::Allowed->lab_data(0), - TokiColor_t::Allowed->lab_data(1), - TokiColor_t::Allowed->lab_data(2)}; + colorset_ptrs = {this->allowed_colorset.lab_data(0), + this->allowed_colorset.lab_data(1), + this->allowed_colorset.lab_data(2)}; break; case SCL_convertAlgo::XYZ: - colorset_ptrs = {TokiColor_t::Allowed->xyz_data(0), - TokiColor_t::Allowed->xyz_data(1), - TokiColor_t::Allowed->xyz_data(2)}; + colorset_ptrs = {this->allowed_colorset.xyz_data(0), + this->allowed_colorset.xyz_data(1), + this->allowed_colorset.xyz_data(2)}; break; default: abort(); @@ -486,7 +492,7 @@ class ImageCvter : public GPU_wrapper_wrapper { if (gpu_task_count > 0) { // set colorset for ocl - this->gpu->set_colorset_v(TokiColor_t::Allowed->color_count(), + this->gpu->set_colorset_v(this->allowed_colorset.color_count(), colorset_ptrs); if (!this->gpu->ok_v()) { return false; @@ -500,7 +506,7 @@ class ImageCvter : public GPU_wrapper_wrapper { // compute rest tasks on cpu for (uint64_t ctid = 0; ctid < cpu_task_count; ctid++) { const uint64_t tid = gpu_task_count + ctid; - tasks[tid]->second.compute(tasks[tid]->first); + tasks[tid]->second.compute(tasks[tid]->first, this->allowed_colorset); } if (gpu_task_count > 0) { @@ -515,11 +521,11 @@ class ImageCvter : public GPU_wrapper_wrapper { TokiColor_t &tc = tasks[tid]->second; const uint16_t tempidx = this->gpu->result_idx_v()[tid]; - if (tempidx >= TokiColor_t::Allowed->color_count()) { + if (tempidx >= this->allowed_colorset.color_count()) { abort(); } - tc.set_gpu_result(TokiColor_t::Allowed->color_id(tempidx), + tc.set_gpu_result(this->allowed_colorset.color_id(tempidx), this->gpu->result_diff_v()[tid]); } @@ -592,7 +598,7 @@ class ImageCvter : public GPU_wrapper_wrapper { convert_unit cu(current_argb, this->algo); auto ret = this->_color_hash.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; - it_to_old_color->second.compute(cu); + it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; } @@ -631,7 +637,7 @@ class ImageCvter : public GPU_wrapper_wrapper { if (it_to_old_color == this->_color_hash.end()) { auto ret = this->_color_hash.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; - it_to_old_color->second.compute(cu); + it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; } diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index ed38e14d..71116c5e 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -114,8 +114,8 @@ class newTokiColor float ResultDiff; // color diff for the result // These two members must be defined by caller - static const basic_t *const Basic; - static const allowed_t *const Allowed; + // static const basic_t *const Basic; + // static const allowed_t *const Allowed; public: explicit newTokiColor() { @@ -136,7 +136,7 @@ class newTokiColor this->result_color_id = __result_color_id; } - auto compute(convert_unit cu) noexcept { + auto compute(convert_unit cu, const allowed_t &allowed) noexcept { if (getA(cu._ARGB) == 0) { if constexpr (is_not_optical) { this->Result = 0; @@ -160,17 +160,17 @@ class newTokiColor switch (cu.algo) { case ::SCL_convertAlgo::RGB: - return applyRGB(c3); + return applyRGB(c3, allowed); case ::SCL_convertAlgo::RGB_Better: - return applyRGB_plus(c3); + return applyRGB_plus(c3, allowed); case ::SCL_convertAlgo::HSV: - return applyHSV(c3); + return applyHSV(c3, allowed); case ::SCL_convertAlgo::Lab94: - return applyLab94(c3); + return applyLab94(c3, allowed); case ::SCL_convertAlgo::Lab00: - return applyLab00(c3); + return applyLab00(c3, allowed); case ::SCL_convertAlgo::XYZ: - return applyXYZ(c3); + return applyXYZ(c3, allowed); default: abort(); @@ -187,7 +187,9 @@ class newTokiColor } private: - auto find_result(const TempVectorXf_t &diff) noexcept { + auto find_result(const TempVectorXf_t &diff, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; if (diff.isNaN().any()) { for (int idx = 0; idx < diff.size(); idx++) { assert(!std::isnan(diff[idx])); @@ -199,7 +201,7 @@ class newTokiColor if constexpr (is_not_optical) { this->Result = Allowed->Map(tempidx); - if (Base_t::needFindSide) this->doSide(diff); + if (Base_t::needFindSide) this->doSide(diff, allowed_colorset); return this->Result; } else { @@ -209,7 +211,9 @@ class newTokiColor } } - auto find_result(const std::vector &diff) noexcept { + auto find_result(const std::vector &diff, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; int minidx = 0; float min = diff[0]; @@ -233,7 +237,8 @@ class newTokiColor } template - void doSide(const TempVectorXf_t &Diff) { + void doSide(const TempVectorXf_t &Diff, const allowed_t &allowed_colorset) { + const allowed_t *Allowed = &allowed_colorset; static_assert(is_not_optical); int tempIndex = 0; @@ -299,7 +304,9 @@ class newTokiColor return; } - auto applyRGB(const Eigen::Array3f &c3) noexcept { + auto applyRGB(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; TempVectorXf_t Diff(Allowed->color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; @@ -307,11 +314,13 @@ class newTokiColor Allowed->rgb_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; - const auto ret = find_result(Diff); + const auto ret = find_result(Diff, allowed_colorset); return ret; } - auto applyRGB_plus(const Eigen::Array3f &c3) noexcept { + auto applyRGB_plus(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; // const ColorList &allowedColors = Allowed->_RGB; TempVectorXf_t Diff(Allowed->color_count(), 1); @@ -322,7 +331,7 @@ class newTokiColor Allowed->rgb_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; - const auto ret = find_result(Diff); + const auto ret = find_result(Diff, allowed_colorset); return ret; #if false @@ -384,11 +393,13 @@ class newTokiColor S_theta * S_ratio * theta.square(); } //+S_theta*S_ratio*theta.square() + return find_result(Diff, allowed_colorset); #endif - return find_result(Diff); } - auto applyHSV(const Eigen::Array3f &c3) noexcept { + auto applyHSV(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; // const ColorList &allowedColors = Allowed->HSV; TempVectorXf_t Diff(Allowed->color_count(), 1); @@ -398,10 +409,12 @@ class newTokiColor colordiff_HSV_batch(Allowed->hsv_data_span(0), Allowed->hsv_data_span(1), Allowed->hsv_data_span(2), c3span, diff_span); - return find_result(Diff); + return find_result(Diff, allowed_colorset); } - auto applyXYZ(const Eigen::Array3f &c3) noexcept { + auto applyXYZ(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; TempVectorXf_t Diff(Allowed->color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; @@ -409,20 +422,24 @@ class newTokiColor Allowed->xyz_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; - const auto ret = find_result(Diff); + const auto ret = find_result(Diff, allowed_colorset); return ret; } - auto applyLab94(const Eigen::Array3f &c3) noexcept { + auto applyLab94(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; TempVectorXf_t Diff(Allowed->color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; colordiff_Lab94_batch(Allowed->lab_data_span(0), Allowed->lab_data_span(1), Allowed->lab_data_span(2), c3span, diff_span); - return find_result(Diff); + return find_result(Diff, allowed_colorset); } - auto applyLab00(const Eigen::Array3f &c3) noexcept { + auto applyLab00(const Eigen::Array3f &c3, + const allowed_t &allowed_colorset) noexcept { + const allowed_t *Allowed = &allowed_colorset; // int tempIndex = 0; const float L1s = c3[0]; const float a1s = c3[1]; @@ -435,7 +452,7 @@ class newTokiColor Allowed->Lab(i, 1), Allowed->Lab(i, 2)); } - return find_result(Diff); + return find_result(Diff, allowed_colorset); } public: diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index a5c338e7..8caa63f7 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -30,8 +30,11 @@ This file is part of SlopeCraft. using namespace libImageCvt; -libMapImageCvt::MapImageCvter::MapImageCvter() - : gacvter(new GACvter::GAConverter) {} +libMapImageCvt::MapImageCvter::MapImageCvter( + const Base_t::basic_colorset_t &basic, + const Base_t::allowed_colorset_t &allowed) + : libImageCvt::ImageCvter{basic, allowed}, + gacvter(new GACvter::GAConverter) {} void libMapImageCvt::MapImageCvter::convert_image( const ::SCL_convertAlgo algo, bool dither, @@ -97,7 +100,7 @@ bool libMapImageCvt::MapImageCvter::examine_cache( if (!ifs) { // cache file not exist return false; } - MapImageCvter im; + MapImageCvter im{this->basic_colorset, this->allowed_colorset}; try { cereal::BinaryInputArchive bia{ifs}; @@ -119,7 +122,7 @@ bool libMapImageCvt::MapImageCvter::examine_cache( bool libMapImageCvt::MapImageCvter::load_cache( const char *filename, uint64_t expected_task_hash) noexcept { - MapImageCvter temp; + MapImageCvter temp{this->basic_colorset, this->allowed_colorset}; if (!this->examine_cache(filename, expected_task_hash, &temp)) { return false; } diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 19dbdcb3..0a48e043 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -52,7 +52,8 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { static constexpr int size_of_tokicolor = sizeof(TokiColor_t); - explicit MapImageCvter(); + MapImageCvter(const Base_t::basic_colorset_t &basic, + const Base_t::allowed_colorset_t &allowed); ~MapImageCvter() = default; From cd862fb82e2dbbc055bd581c210215b8a4cd3a41 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 21:25:47 +0800 Subject: [PATCH 0706/1123] remove mutable static member of newTokiColor Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft.cpp | 2 +- SlopeCraftL/TokiSlopeCraft_convert.cpp | 2 +- utilities/ColorManip/CMakeLists.txt | 1 - utilities/ColorManip/StaticMembers.cpp | 37 ----- utilities/ColorManip/colorset_maptical.hpp | 18 ++- utilities/ColorManip/newTokiColor.hpp | 171 +++++++++++---------- 6 files changed, 103 insertions(+), 128 deletions(-) delete mode 100644 utilities/ColorManip/StaticMembers.cpp diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index bc374be5..5f4667ee 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -203,7 +203,7 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, TokiSlopeCraft::mapType = type; TokiSlopeCraft::mcVer = ver; - TokiColor::needFindSide = (TokiSlopeCraft::mapType == mapTypes::Slope); + Allowed.need_find_side = (TokiSlopeCraft::mapType == mapTypes::Slope); TokiSlopeCraft::blockPalette.resize(64); diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp index 81d66734..5573270b 100644 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ b/SlopeCraftL/TokiSlopeCraft_convert.cpp @@ -252,9 +252,9 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, MapFile.writeByteArrayHead("colors", 16384); { - uchar ColorCur = 0; for (short rr = 0; rr < 128; rr++) { for (short cc = 0; cc < 128; cc++) { + uint8_t ColorCur; if (rr + offset[0] < mapPic.rows() && cc + offset[1] < mapPic.cols()) ColorCur = mapPic(rr + offset[0], cc + offset[1]); diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index a3771190..afbb2ca8 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -24,7 +24,6 @@ add_library(ColorManip newColorSet.hpp newTokiColor.hpp - StaticMembers.cpp hash.cpp colorset_maptical.hpp diff --git a/utilities/ColorManip/StaticMembers.cpp b/utilities/ColorManip/StaticMembers.cpp deleted file mode 100644 index 1e8fd3e2..00000000 --- a/utilities/ColorManip/StaticMembers.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "newTokiColor.hpp" - -#include "colorset_maptical.hpp" -/* -std::array newTokiColorBase::DepthCount = {64, 64, 64, 64}; -bool newTokiColorBase::needFindSide = false; -*/ - -std::array newtokicolor_base_maptical::DepthCount = {64, 64, 64, - 64}; -bool newtokicolor_base_maptical::needFindSide = false; -/* -SCL_convertAlgo newTokiColorBase::convertAlgo = - SCL_convertAlgo::RGB_Better; - */ diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 6ccd974a..503a54f8 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -51,9 +51,9 @@ class newtokicolor_base_maptical { uint8_t Result{0}; // 最终调色结果 public: - static bool needFindSide; - static std::array DepthCount; - // static ::SCL_convertAlgo convertAlgo; + // static bool needFindSide; + // static std::array DepthCount; + // static ::SCL_convertAlgo convertAlgo; public: inline bool is_result_computed() const noexcept { return (Result != 0); } @@ -130,7 +130,14 @@ class alignas(32) colorset_maptical_allowed { // std::array __map; int _color_count; + std::array depth_counter; + public: + bool need_find_side{false}; + [[nodiscard]] const std::array &depth_count() const noexcept { + return this->depth_counter; + } + inline int color_count() const noexcept { return _color_count; } inline float RGB(int r, int c) const noexcept { @@ -230,14 +237,13 @@ class alignas(32) colorset_maptical_allowed { writeidx++; } } - - newtokicolor_base_maptical::DepthCount.fill(0); + this->depth_counter.fill(0); for (int idx = 0; idx < this->color_count(); idx++) { const uint8_t mapcolor = this->Map(idx); const uint8_t base = mapcolor >> 2; if (base != 0) { const uint8_t depth = mapcolor & 0b11; - newtokicolor_base_maptical::DepthCount[depth]++; + this->depth_counter[depth]++; } } diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 71116c5e..a787952c 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -34,6 +34,7 @@ This file is part of SlopeCraft. #include #include #include +#include // using Eigen::Dynamic; namespace { @@ -189,7 +190,6 @@ class newTokiColor private: auto find_result(const TempVectorXf_t &diff, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; if (diff.isNaN().any()) { for (int idx = 0; idx < diff.size(); idx++) { assert(!std::isnan(diff[idx])); @@ -200,20 +200,19 @@ class newTokiColor this->ResultDiff = diff.minCoeff(&tempidx); if constexpr (is_not_optical) { - this->Result = Allowed->Map(tempidx); - if (Base_t::needFindSide) this->doSide(diff, allowed_colorset); + this->Result = allowed_colorset.Map(tempidx); + if (allowed_colorset.need_find_side) this->doSide(diff, allowed_colorset); return this->Result; } else { - this->result_color_id = Allowed->color_id(tempidx); + this->result_color_id = allowed_colorset.color_id(tempidx); // std::cout << tempidx << '\t' << this->result_color_id << '\n'; return this->color_id(); } } - auto find_result(const std::vector &diff, + auto find_result(std::span &diff, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; int minidx = 0; float min = diff[0]; @@ -226,19 +225,18 @@ class newTokiColor } } if constexpr (is_not_optical) { - this->Result = Allowed->Map(minidx); - if (Base_t::needFindSide) this->doSide(diff); + this->Result = allowed_colorset.Map(minidx); + if (allowed_colorset.need_find_side) this->doSide(diff); return this->Result; } else { - this->result_color_id = Allowed->color_id(minidx); + this->result_color_id = allowed_colorset.color_id(minidx); return this->color_id(); } } template void doSide(const TempVectorXf_t &Diff, const allowed_t &allowed_colorset) { - const allowed_t *Allowed = &allowed_colorset; static_assert(is_not_optical); int tempIndex = 0; @@ -248,53 +246,63 @@ class newTokiColor this->sideSelectivity[1] = 1e35f; this->sideResult[1] = 0; - if (!Base_t::needFindSide) return; + if (!allowed_colorset.need_find_side) return; switch (this->Result % 4) { case 3: return; case 0: // 1,2 - if (Base_t::DepthCount[1]) { + if (allowed_colorset.depth_count()[1]) { this->sideSelectivity[0] = - Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) + Diff.segment(allowed_colorset.depth_count()[0], + allowed_colorset.depth_count()[1]) .minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); + this->sideResult[0] = allowed_colorset.Map( + allowed_colorset.depth_count()[0] + tempIndex); } - if (Base_t::DepthCount[2]) { + if (allowed_colorset.depth_count()[2]) { this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], - Base_t::DepthCount[2]) + Diff.segment(allowed_colorset.depth_count()[0] + + allowed_colorset.depth_count()[1], + allowed_colorset.depth_count()[2]) .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + - Base_t::DepthCount[1] + tempIndex); + this->sideResult[1] = allowed_colorset.Map( + allowed_colorset.depth_count()[0] + + allowed_colorset.depth_count()[1] + tempIndex); } break; case 1: // 0,2 - if (Base_t::DepthCount[0]) { + if (allowed_colorset.depth_count()[0]) { this->sideSelectivity[0] = - Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(0 + tempIndex); + Diff.segment(0, allowed_colorset.depth_count()[0]) + .minCoeff(&tempIndex); + this->sideResult[0] = allowed_colorset.Map(0 + tempIndex); } - if (Base_t::DepthCount[2]) { + if (allowed_colorset.depth_count()[2]) { this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0] + Base_t::DepthCount[1], - Base_t::DepthCount[2]) + Diff.segment(allowed_colorset.depth_count()[0] + + allowed_colorset.depth_count()[1], + allowed_colorset.depth_count()[2]) .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + - Base_t::DepthCount[1] + tempIndex); + this->sideResult[1] = allowed_colorset.Map( + allowed_colorset.depth_count()[0] + + allowed_colorset.depth_count()[1] + tempIndex); } break; case 2: // 0,1 - if (Base_t::DepthCount[0]) { + if (allowed_colorset.depth_count()[0]) { this->sideSelectivity[0] = - Diff.segment(0, Base_t::DepthCount[0]).minCoeff(&tempIndex); - this->sideResult[0] = Allowed->Map(0 + tempIndex); + Diff.segment(0, allowed_colorset.depth_count()[0]) + .minCoeff(&tempIndex); + this->sideResult[0] = allowed_colorset.Map(0 + tempIndex); } - if (Base_t::DepthCount[1]) { + if (allowed_colorset.depth_count()[1]) { this->sideSelectivity[1] = - Diff.segment(Base_t::DepthCount[0], Base_t::DepthCount[1]) + Diff.segment(allowed_colorset.depth_count()[0], + allowed_colorset.depth_count()[1]) .minCoeff(&tempIndex); - this->sideResult[1] = Allowed->Map(Base_t::DepthCount[0] + tempIndex); + this->sideResult[1] = allowed_colorset.Map( + allowed_colorset.depth_count()[0] + tempIndex); } break; } @@ -306,12 +314,12 @@ class newTokiColor auto applyRGB(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; - TempVectorXf_t Diff(Allowed->color_count(), 1); + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; - colordiff_RGB_batch(Allowed->rgb_data_span(0), Allowed->rgb_data_span(1), - Allowed->rgb_data_span(2), c3span, diff_span); + colordiff_RGB_batch(allowed_colorset.rgb_data_span(0), + allowed_colorset.rgb_data_span(1), + allowed_colorset.rgb_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; const auto ret = find_result(Diff, allowed_colorset); @@ -320,15 +328,14 @@ class newTokiColor auto applyRGB_plus(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; - // const ColorList &allowedColors = Allowed->_RGB; + // const ColorList &allowedColors = allowed_colorset._RGB; - TempVectorXf_t Diff(Allowed->color_count(), 1); + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; - colordiff_RGBplus_batch(Allowed->rgb_data_span(0), - Allowed->rgb_data_span(1), - Allowed->rgb_data_span(2), c3span, diff_span); + colordiff_RGBplus_batch( + allowed_colorset.rgb_data_span(0), allowed_colorset.rgb_data_span(1), + allowed_colorset.rgb_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; const auto ret = find_result(Diff, allowed_colorset); @@ -340,45 +347,45 @@ class newTokiColor float g = c3[1]; float b = c3[2]; auto SqrModSquare = ((R * R + g * g + b * b) * - (Allowed->rgb(0).square() + Allowed->rgb(1).square() + - Allowed->rgb(2).square())) + (allowed_colorset.rgb(0).square() + allowed_colorset.rgb(1).square() + + allowed_colorset.rgb(2).square())) .sqrt(); - auto deltaR = (R - Allowed->rgb(0)); - auto deltaG = (g - Allowed->rgb(1)); - auto deltaB = (b - Allowed->rgb(2)); + auto deltaR = (R - allowed_colorset.rgb(0)); + auto deltaG = (g - allowed_colorset.rgb(1)); + auto deltaB = (b - allowed_colorset.rgb(2)); auto SigmaRGB = - (R + g + b + Allowed->rgb(0) + Allowed->rgb(1) + Allowed->rgb(2)) / + (R + g + b + allowed_colorset.rgb(0) + allowed_colorset.rgb(1) + allowed_colorset.rgb(2)) / 3.0f; auto S_r = - ((Allowed->rgb(0) + R) < SigmaRGB) - .select((Allowed->rgb(0) + R) / (SigmaRGB + threshold), 1.0f); + ((allowed_colorset.rgb(0) + R) < SigmaRGB) + .select((allowed_colorset.rgb(0) + R) / (SigmaRGB + threshold), 1.0f); auto S_g = - ((Allowed->rgb(1) + g) < SigmaRGB) - .select((Allowed->rgb(1) + g) / (SigmaRGB + threshold), 1.0f); + ((allowed_colorset.rgb(1) + g) < SigmaRGB) + .select((allowed_colorset.rgb(1) + g) / (SigmaRGB + threshold), 1.0f); auto S_b = - ((Allowed->rgb(2) + b) < SigmaRGB) - .select((Allowed->rgb(2) + b) / (SigmaRGB + threshold), 1.0f); + ((allowed_colorset.rgb(2) + b) < SigmaRGB) + .select((allowed_colorset.rgb(2) + b) / (SigmaRGB + threshold), 1.0f); auto sumRGBsquare = - R * Allowed->rgb(0) + g * Allowed->rgb(1) + b * Allowed->rgb(2); + R * allowed_colorset.rgb(0) + g * allowed_colorset.rgb(1) + b * allowed_colorset.rgb(2); auto theta = 2.0 / M_PI * (sumRGBsquare / (SqrModSquare + threshold) / 1.01f).acos(); - auto OnedDeltaR = deltaR.abs() / (R + Allowed->rgb(0) + threshold); - auto OnedDeltaG = deltaG.abs() / (g + Allowed->rgb(1) + threshold); - auto OnedDeltaB = deltaB.abs() / (b + Allowed->rgb(2) + threshold); + auto OnedDeltaR = deltaR.abs() / (R + allowed_colorset.rgb(0) + threshold); + auto OnedDeltaG = deltaG.abs() / (g + allowed_colorset.rgb(1) + threshold); + auto OnedDeltaB = deltaB.abs() / (b + allowed_colorset.rgb(2) + threshold); auto sumOnedDelta = OnedDeltaR + OnedDeltaG + OnedDeltaB + threshold; auto S_tr = OnedDeltaR / sumOnedDelta * S_r.square(); auto S_tg = OnedDeltaG / sumOnedDelta * S_g.square(); auto S_tb = OnedDeltaB / sumOnedDelta * S_b.square(); auto S_theta = S_tr + S_tg + S_tb; - auto Rmax = Allowed->rgb(0) - .max(Allowed->rgb(1)) - .max(Allowed->rgb(2)) + auto Rmax = allowed_colorset.rgb(0) + .max(allowed_colorset.rgb(1)) + .max(allowed_colorset.rgb(2)) .max(threshold); // auto Rmax = allowedColors.rowwise().maxCoeff(); auto S_ratio = Rmax.max(std::max(R, std::max(g, b))); - TempVectorXf_t dist(Allowed->color_count(), 1); + TempVectorXf_t dist(allowed_colorset.color_count(), 1); if constexpr (is_not_optical) { dist = (S_r.square() * w_r * deltaR.square() + S_g.square() * w_g * deltaG.square() + @@ -399,27 +406,27 @@ class newTokiColor auto applyHSV(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; - // const ColorList &allowedColors = Allowed->HSV; + // const ColorList &allowedColors = allowed_colorset.HSV; - TempVectorXf_t Diff(Allowed->color_count(), 1); + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; - colordiff_HSV_batch(Allowed->hsv_data_span(0), Allowed->hsv_data_span(1), - Allowed->hsv_data_span(2), c3span, diff_span); + colordiff_HSV_batch(allowed_colorset.hsv_data_span(0), + allowed_colorset.hsv_data_span(1), + allowed_colorset.hsv_data_span(2), c3span, diff_span); return find_result(Diff, allowed_colorset); } auto applyXYZ(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; - TempVectorXf_t Diff(Allowed->color_count(), 1); + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; - colordiff_RGB_batch(Allowed->xyz_data_span(0), Allowed->xyz_data_span(1), - Allowed->xyz_data_span(2), c3span, diff_span); + colordiff_RGB_batch(allowed_colorset.xyz_data_span(0), + allowed_colorset.xyz_data_span(1), + allowed_colorset.xyz_data_span(2), c3span, diff_span); // Data.CurrentColor-=allowedColors; const auto ret = find_result(Diff, allowed_colorset); @@ -428,28 +435,28 @@ class newTokiColor auto applyLab94(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; - TempVectorXf_t Diff(Allowed->color_count(), 1); + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); std::span diff_span{Diff.data(), (size_t)Diff.size()}; std::span c3span{c3.data(), 3}; - colordiff_Lab94_batch(Allowed->lab_data_span(0), Allowed->lab_data_span(1), - Allowed->lab_data_span(2), c3span, diff_span); + colordiff_Lab94_batch(allowed_colorset.lab_data_span(0), + allowed_colorset.lab_data_span(1), + allowed_colorset.lab_data_span(2), c3span, diff_span); return find_result(Diff, allowed_colorset); } auto applyLab00(const Eigen::Array3f &c3, const allowed_t &allowed_colorset) noexcept { - const allowed_t *Allowed = &allowed_colorset; // int tempIndex = 0; const float L1s = c3[0]; const float a1s = c3[1]; const float b1s = c3[2]; - // const ColorList &allow = Allowed->Lab; - TempVectorXf_t Diff(Allowed->color_count(), 1); + // const ColorList &allow = allowed_colorset.Lab; + TempVectorXf_t Diff(allowed_colorset.color_count(), 1); - for (int i = 0; i < Allowed->color_count(); i++) { - Diff(i) = Lab00_diff(L1s, a1s, b1s, Allowed->Lab(i, 0), - Allowed->Lab(i, 1), Allowed->Lab(i, 2)); + for (int i = 0; i < allowed_colorset.color_count(); i++) { + Diff(i) = + Lab00_diff(L1s, a1s, b1s, allowed_colorset.Lab(i, 0), + allowed_colorset.Lab(i, 1), allowed_colorset.Lab(i, 2)); } return find_result(Diff, allowed_colorset); From 63bfbda69dc0ff2dcb2fd7a64b57a1cbaaaf3e08 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 22:20:00 +0800 Subject: [PATCH 0707/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 6 ++- VisualCraftL/TokiVC.cpp | 70 +++++++++------------------ 2 files changed, 28 insertions(+), 48 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 63ef5001..69f6baf3 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None ] + gpu_api: [ None, Vulkan ] vectorize: [ ON, OFF ] env: BUILD_TYPE: ${{ matrix.build_type }} @@ -43,6 +43,10 @@ jobs: # find /usr/local/Cellar -name liblzma.5.dylib 2>/dev/null # find /usr/local/Cellar -name libzstd.1.dylib 2>/dev/null + - name: Install Vulkan sdk + if: matrix.gpu_api == 'Vulkan' + run: brew install molten-vk + - name: Checkout repository uses: actions/checkout@v4 - name: Download qt6.6.0-static-x86_64-apple-darwin.tar.xz and extract diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index d79e669d..2a87d52a 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -26,7 +26,6 @@ This file is part of SlopeCraft. #include #include #include -#include #include #include @@ -35,31 +34,6 @@ libImageCvt::template ImageCvter::basic_colorset_t libImageCvt::template ImageCvter::allowed_colorset_t TokiVC::colorset_allowed; -// bind static members for template classes -// template <> -// const libImageCvt::template ImageCvter::basic_colorset_t -// &libImageCvt::template ImageCvter::basic_colorset = -// TokiVC::colorset_basic; -// -// template <> -// const libImageCvt::template ImageCvter::allowed_colorset_t -// &libImageCvt::template ImageCvter::allowed_colorset = -// TokiVC::colorset_allowed; -// -// template <> -// const libImageCvt::template ImageCvter::basic_colorset_t -// *const newTokiColor< -// false, libImageCvt::template ImageCvter::basic_colorset_t, -// libImageCvt::template ImageCvter::allowed_colorset_t>::Basic = -// &TokiVC::colorset_basic; -// -// template <> -// const libImageCvt::template ImageCvter::allowed_colorset_t -// *const newTokiColor< -// false, libImageCvt::template ImageCvter::basic_colorset_t, -// libImageCvt::template ImageCvter::allowed_colorset_t>::Allowed -// = &TokiVC::colorset_allowed; - // global variables that VCL uses VCL_resource_pack TokiVC::pack; VCL_block_state_list TokiVC::bsl; @@ -136,12 +110,12 @@ bool add_projection_image_for_bsl(const std::vector &bs_list, return false; } - if constexpr (false) { - std::string msg = - fmt::format("Computing projection image for full id \"{}\"\n", - blkp->full_id_ptr()->c_str()); - VCL_report(VCL_report_type_t::information, msg.c_str()); - } + // { + // std::string msg = + // fmt::format("Computing projection image for full id \"{}\"\n", + // blkp->full_id_ptr()->c_str()); + // VCL_report(VCL_report_type_t::information, msg.c_str()); + // } block_model::EImgRowMajor_t *img = &blkp->project_image_on_exposed_face; @@ -478,11 +452,11 @@ bool TokiVC::set_resource_no_lock() noexcept { return false; } - if constexpr (false) { - std::string msg = fmt::format("Size of map_color_blocks = {}\n", - map_color_blocks.size()); - VCL_report(VCL_report_type_t::information, msg.c_str()); - } + // { + // std::string msg = fmt::format("Size of map_color_blocks = {}\n", + // map_color_blocks.size()); + // VCL_report(VCL_report_type_t::information, msg.c_str()); + // } for (int layers = 2; layers <= max_block_layers; layers++) { if (!add_color_trans_to_trans_start_recurse( @@ -493,11 +467,11 @@ bool TokiVC::set_resource_no_lock() noexcept { } } - if constexpr (false) { - std::string msg = fmt::format("Size of map_color_blocks = {}\n", - map_color_blocks.size()); - VCL_report(VCL_report_type_t::information, msg.c_str()); - } + // { + // std::string msg = fmt::format("Size of map_color_blocks = {}\n", + // map_color_blocks.size()); + // VCL_report(VCL_report_type_t::information, msg.c_str()); + // } std::vector> colors_temp; TokiVC::LUT_basic_color_idx_to_blocks.clear(); @@ -616,11 +590,13 @@ bool TokiVC::set_allowed_no_lock( allowed_list.resize(TokiVC::LUT_basic_color_idx_to_blocks.size()); std::fill(allowed_list.begin(), allowed_list.end(), 0); - if constexpr (false) { - std::string msg = fmt::format("TokiVC::colorset_basic.color_count() = {}.", - TokiVC::colorset_basic.color_count()); - VCL_report(VCL_report_type_t::information, msg.c_str()); - } + // { + // std::string msg = fmt::format("TokiVC::colorset_basic.color_count() = + // {} + // .", + // TokiVC::colorset_basic.color_count()); + // VCL_report(VCL_report_type_t::information, msg.c_str()); + // } for (size_t idx = 0; idx < TokiVC::LUT_basic_color_idx_to_blocks.size(); idx++) { From 1f06ace06861667e7c6595a9817efcae6076021b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 22:39:59 +0800 Subject: [PATCH 0708/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 69f6baf3..3df7fe44 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -45,7 +45,9 @@ jobs: - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' - run: brew install molten-vk + run: | + brew install molten-vk glslang vulkan-header vulkan-loader vulkan-tools vulkan-profiles + whereis glslc - name: Checkout repository uses: actions/checkout@v4 @@ -62,7 +64,7 @@ jobs: run: echo "/usr/local/lib" >> $GITHUB_PATH - name: Check PATH run: echo $PATH - - name: Configure CMake # + - name: Configure CMake run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" - name: Build run: | From a354208f0852fbec630902c092479ea6b6af2fa0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 22:42:29 +0800 Subject: [PATCH 0709/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 3df7fe44..170e3713 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -46,7 +46,7 @@ jobs: - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' run: | - brew install molten-vk glslang vulkan-header vulkan-loader vulkan-tools vulkan-profiles + brew install molten-vk glslang vulkan-headers vulkan-loader vulkan-tools vulkan-profiles whereis glslc - name: Checkout repository From 5d43d3d01d441fb66666839fdb8de9f9e03676da Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 22:56:34 +0800 Subject: [PATCH 0710/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 170e3713..aed22a29 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -24,7 +24,9 @@ jobs: # brew update # brew upgrade - name: Install LLVM clang - run: brew install llvm + run: | + brew update + brew install llvm - name: Check clang run: /usr/local/opt/llvm/bin/clang --version - name: echo matrix variables (build_type = ${{ matrix.build_type }}) From 7f41cd1c2fd12f6b33a91726159f211c5dae367e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 23:10:11 +0800 Subject: [PATCH 0711/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index aed22a29..b5e5db0a 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -48,8 +48,9 @@ jobs: - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' run: | - brew install molten-vk glslang vulkan-headers vulkan-loader vulkan-tools vulkan-profiles + brew install molten-vk vulkan-headers vulkan-loader vulkan-tools vulkan-profiles glslang shaderc whereis glslc + glslc --version - name: Checkout repository uses: actions/checkout@v4 From 821a69f599207988987a02c88bdeeac46dc30787 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 23:20:34 +0800 Subject: [PATCH 0712/1123] enable vulkan for macos Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index b5e5db0a..d64b9a69 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -68,7 +68,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build From e35d61b9d25a818d87d5a6fa6eb65011022ca7f0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 27 Feb 2024 23:29:56 +0800 Subject: [PATCH 0713/1123] fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index d64b9a69..0733e618 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -38,7 +38,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip zstd xz eigen boost + brew install libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum # - name: Find liblzma and libzstd dylibs # run: | From 126b9de0e1435595922f0882bb5e703359faad34 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 11:18:53 +0800 Subject: [PATCH 0714/1123] change version number back to 5.2.2 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 441ead76..7857a840 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.3) +set(SlopeCraft_version 5.2.2) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 91f9ba1a6f46b8b67255908a8b6e1261bc0fb1ef Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 14:43:32 +0800 Subject: [PATCH 0715/1123] try to fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 0733e618..0307d29e 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -19,13 +19,12 @@ jobs: GPU_API: ${{ matrix.gpu_api }} VECTORIZE: ${{ matrix.vectorize }} steps: - # - name: brew upgrade & update - # run: | - # brew update - # brew upgrade - - name: Install LLVM clang + - name: brew upgrade & update run: | brew update + brew upgrade + - name: Install LLVM clang + run: | brew install llvm - name: Check clang run: /usr/local/opt/llvm/bin/clang --version From 39ddeb376887f7fcff9379c18cbe9ca3c14083ef Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 19:25:20 +0800 Subject: [PATCH 0716/1123] try to fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 0307d29e..141ec74d 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -22,6 +22,7 @@ jobs: - name: brew upgrade & update run: | brew update + brew remove python brew upgrade - name: Install LLVM clang run: | From 2e8eeca1629a0d7619ca341fade30b189034bd51 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 19:27:58 +0800 Subject: [PATCH 0717/1123] try to fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 141ec74d..d5c24c61 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -22,7 +22,7 @@ jobs: - name: brew upgrade & update run: | brew update - brew remove python + brew remove python aws-sam-cli pipx brew upgrade - name: Install LLVM clang run: | From 6e65496bc3c3359c1671121c6a29a61d347fe51d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 19:48:51 +0800 Subject: [PATCH 0718/1123] try to fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index d5c24c61..31f073d2 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -22,7 +22,8 @@ jobs: - name: brew upgrade & update run: | brew update - brew remove python aws-sam-cli pipx + brew remove aws-sam-cli pipx cfn-lint + brew remove python brew upgrade - name: Install LLVM clang run: | From 056d0e6f3ae592e0e01a32a330757d8a939e1934 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 20:25:28 +0800 Subject: [PATCH 0719/1123] try to fix macos build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 31f073d2..ba224803 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -19,12 +19,12 @@ jobs: GPU_API: ${{ matrix.gpu_api }} VECTORIZE: ${{ matrix.vectorize }} steps: - - name: brew upgrade & update - run: | - brew update - brew remove aws-sam-cli pipx cfn-lint - brew remove python - brew upgrade + # - name: brew upgrade & update + # run: | + # brew update + # brew remove aws-sam-cli pipx cfn-lint + # brew remove python + # brew upgrade - name: Install LLVM clang run: | brew install llvm @@ -49,7 +49,7 @@ jobs: - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' run: | - brew install molten-vk vulkan-headers vulkan-loader vulkan-tools vulkan-profiles glslang shaderc + brew install molten-vk vulkan-headers vulkan-loader vulkan-tools glslang shaderc whereis glslc glslc --version From c058ee666bc69119712ac136c446f250ec304b0e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 28 Feb 2024 21:21:33 +0800 Subject: [PATCH 0720/1123] remove fmt binaries from macos release Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index ba224803..6fdc243d 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -39,7 +39,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum + brew install libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt # - name: Find liblzma and libzstd dylibs # run: | From f8cd5fcbe80c7025f77a2ba1c2d120c2bfb99949 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 25 Mar 2024 21:37:25 +0800 Subject: [PATCH 0721/1123] replace use of std::cout with println Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 16 +--------- vccl/vccl.cpp | 10 +++---- vccl/vccl_parse_default.cpp | 58 +++++++++++++++---------------------- 3 files changed, 30 insertions(+), 54 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 4d13cd91..1fb8bb05 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -514,7 +514,6 @@ QProgressBar *SCWind::current_bar() noexcept { return this->ui->pbar_cvt; case 2: return this->ui->pbar_export; - break; default: return nullptr; } @@ -754,7 +753,6 @@ void SCWind::refresh_current_build_display( } int x{-1}, y{-1}, z{-1}; - int64_t block_count{-1}; { if (is_image_built_in_kernel) { // the caller garentee that the image is built in kernel @@ -777,7 +775,7 @@ void SCWind::refresh_current_build_display( } } this->kernel->get3DSize(&x, &y, &z); - block_count = this->kernel->getBlockCounts(); + const int64_t block_count = this->kernel->getBlockCounts(); this->ui->lb_show_3dsize->setText( tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); @@ -991,40 +989,28 @@ QString SCWind::workStatus_to_string(::SCL_workStatues status) noexcept { break; case SlopeCraft::workStatues::buidingHeighMap: return tr("正在构建高度矩阵"); - break; case SlopeCraft::workStatues::building3D: return tr("正在构建三维结构"); - break; case SlopeCraft::workStatues::collectingColors: return tr("正在收集整张图片的颜色"); - break; case SlopeCraft::workStatues::compressing: return tr("正在压缩立体地图画"); - break; case SlopeCraft::workStatues::constructingBridges: return tr("正在为立体地图画搭桥"); - break; case SlopeCraft::workStatues::converting: return tr("正在匹配颜色"); - break; case SlopeCraft::workStatues::dithering: return tr("正在使用抖动仿色"); - break; case SlopeCraft::workStatues::flippingToWall: return tr("正在将平板地图画变为墙面地图画"); - break; case SlopeCraft::workStatues::writing3D: return tr("正在写入三维结构"); - break; case SlopeCraft::workStatues::writingBlockPalette: return tr("正在写入方块列表"); - break; case SlopeCraft::workStatues::writingMapDataFiles: return tr("正在写入地图数据文件"); - break; case SlopeCraft::workStatues::writingMetaInfo: return tr("正在写入基础信息"); - break; } return {}; diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 6d3cab98..9c67526f 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -181,11 +181,11 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); if (show_config) { - cout << fmt::format("Version : {}\n", SC_VERSION_STR); - cout << fmt::format("Build type : {}\n", CMAKE_BUILD_TYPE); - cout << fmt::format("GPU API : {}\n", SC_GPU_API); - cout << fmt::format("Vectorize : {}\n", SC_VECTORIZE); - cout << fmt::format("Gprof : {}\n", SC_GPROF); + fmt::println("Version : {}", SC_VERSION_STR); + fmt::println("Build type : {}", CMAKE_BUILD_TYPE); + fmt::println("GPU API : {}", SC_GPU_API); + fmt::println("Vectorize : {}", SC_VECTORIZE); + fmt::println("Gprof : {}", SC_GPROF); return 0; } diff --git a/vccl/vccl_parse_default.cpp b/vccl/vccl_parse_default.cpp index fb3aa6bb..3783f95c 100644 --- a/vccl/vccl_parse_default.cpp +++ b/vccl/vccl_parse_default.cpp @@ -26,17 +26,16 @@ This file is part of SlopeCraft. #include #include #include -#include #include void cb_progress_range_set(void *, int, int, int) {} void cb_progress_add(void *, int) {} using std::cout, std::endl; -#define VCCL_PRIVATE_MACRO_MAKE_CASE(enum_val) \ - if (str == #enum_val) { \ - ok = true; \ - return SCL_convertAlgo::enum_val; \ +#define VCCL_PRIVATE_MACRO_MAKE_CASE(enum_val) \ + if (str == #enum_val) { \ + ok = true; \ + return SCL_convertAlgo::enum_val; \ } SCL_convertAlgo str_to_algo(std::string_view str, bool &ok) noexcept { @@ -57,7 +56,6 @@ int list_gpu() { const size_t plat_num = VCL_platform_num(); cout << plat_num << " platforms found on this computer : \n"; for (size_t pid = 0; pid < plat_num; pid++) { - VCL_GPU_Platform *plat = VCL_get_platform(pid); if (plat == nullptr) { cout << "Failed to get platform " << pid << '\n'; @@ -155,7 +153,6 @@ int set_allowed(VCL_block_state_list *bsl, const inputs &input) noexcept { return 0; } - void list_supported_formats() noexcept { auto fmts = QImageReader::supportedImageFormats(); cout << "Supported image formats : "; @@ -183,9 +180,8 @@ int run(const inputs &input) noexcept { kernel->set_prefer_gpu(input.prefer_gpu); if (input.prefer_gpu) { - bool ok = true; + bool ok; while (true) { - auto plat = VCL_get_platform(input.platform_idx); if (plat == nullptr) { ok = false; @@ -231,7 +227,7 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - cout << fmt::format( + fmt::print( "Parsing resource pack and block state list in {} miliseconds.\n", wt * 1000); } @@ -245,8 +241,7 @@ int run(const inputs &input) noexcept { } if (input.show_color_num) { - cout << fmt::format("{} colors avaliable.\n", - VCL_get_allowed_colors(nullptr, 0)); + fmt::println("{} colors avaliable.", VCL_get_allowed_colors(nullptr, 0)); } if (input.export_test_lite) { @@ -255,15 +250,14 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime(); if (!VCL_export_test_litematic(filename.c_str())) { - cout << fmt::format("Failed to export test litematic \"{}\"", filename) - << endl; + fmt::print("Failed to export test litematic \"{}\"\n", filename); return __LINE__; } wt = omp_get_wtime() - wt; if (input.benchmark) { - cout << fmt::format("Exported \"{}\" in {} seconds.\n", filename, wt); + fmt::print("Exported \"{}\" in {} seconds.\n", filename, wt); } } @@ -280,7 +274,7 @@ int run(const inputs &input) noexcept { QImage img(QString::fromLocal8Bit(img_filename.c_str())); if (img.isNull()) { - cout << fmt::format("Failed to open image {}", img_filename) << endl; + fmt::print("Failed to open image {}\n", img_filename); VCL_destroy_kernel(kernel); return __LINE__; } @@ -308,8 +302,8 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - cout << fmt::format("Converted {} pixels in {} seconds.\n", - img.height() * img.width(), wt); + fmt::print("Converted {} pixels in {} seconds.\n", + img.height() * img.width(), wt); } if (input.make_converted_image) { @@ -324,7 +318,7 @@ int run(const inputs &input) noexcept { const bool ok = img.save(QString::fromLocal8Bit(dst_name_str.c_str())); if (!ok) { - cout << fmt::format("Failed to save image {}\n", dst_name_str); + fmt::print("Failed to save image {}\n", dst_name_str); return __LINE__; } // cout << dst_path << endl; @@ -333,7 +327,6 @@ int run(const inputs &input) noexcept { if (input.make_flat_diagram) { double wtime[3]; for (uint8_t layer = 0; layer < input.layers; layer++) { - std::string dst_name_str(input.prefix); dst_name_str += pure_filename_no_extension; dst_name_str += "_flagdiagram_layer="; @@ -347,16 +340,14 @@ int run(const inputs &input) noexcept { option.split_line_col_margin = input.flat_diagram_splitline_margin_col; wtime[layer] = omp_get_wtime(); if (!kernel->export_flag_diagram(dst_name_str.c_str(), option, layer)) { - cout << fmt::format("Failed to export flat diagram {}\n", - dst_name_str); + fmt::print("Failed to export flat diagram {}\n", dst_name_str); return __LINE__; } wtime[layer] = omp_get_wtime() - wtime[layer]; } if (input.benchmark) { - cout << fmt::format("Export flatdiagram containing {} images in ", - input.layers); + fmt::print("Export flatdiagram containing {} images in ", input.layers); for (int i = 0; i < input.layers; i++) { cout << wtime[i] << ", "; } @@ -376,8 +367,7 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - cout << fmt::format("Built {} blocks in {} seconds.\n", - kernel->xyz_size(), wt); + fmt::print("Built {} blocks in {} seconds.\n", kernel->xyz_size(), wt); } if (input.make_litematic) { @@ -390,13 +380,13 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - cout << fmt::format("Failed to export {}.", filename) << endl; + fmt::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - cout << fmt::format("Export litematic with {} blocks in {} seconds.\n", - kernel->xyz_size(), wt); + fmt::println("Export litematic with {} blocks in {} seconds.", + kernel->xyz_size(), wt); } } @@ -410,13 +400,13 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - cout << fmt::format("Failed to export {}.", filename) << endl; + fmt::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - cout << fmt::format("Export WE schem with {} blocks in {} seconds.\n", - kernel->xyz_size(), wt); + fmt::print("Export WE schem with {} blocks in {} seconds.\n", + kernel->xyz_size(), wt); } } @@ -430,12 +420,12 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - cout << fmt::format("Failed to export {}.", filename) << endl; + fmt::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - cout << fmt::format( + fmt::print( "Export vanilla structure file with {} blocks in {} seconds.\n", kernel->xyz_size(), wt); } From 74c1ec0a5c6901a51c23115455522b9b97a26575 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 25 Mar 2024 21:37:48 +0800 Subject: [PATCH 0722/1123] update to nlohmann json 3.11.3 Signed-off-by: ToKiNoBug --- cmake/find_nlohmann_json.cmake | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/cmake/find_nlohmann_json.cmake b/cmake/find_nlohmann_json.cmake index 3f2feccd..52f61f76 100644 --- a/cmake/find_nlohmann_json.cmake +++ b/cmake/find_nlohmann_json.cmake @@ -1,31 +1,32 @@ set(SlopeCraft_download_njson OFF) -if(NOT DEFINED SlopeCraft_Nlohmann_json_include_dir) - if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann/json.hpp) +if (NOT DEFINED SlopeCraft_Nlohmann_json_include_dir) + if (EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann/json.hpp) set(SlopeCraft_Nlohmann_json_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann) - else() + else () set(SlopeCraft_download_njson ON) - endif() -else() + endif () +else () # check if cmake can find the json file - if(EXISTS ${SlopeCraft_Nlohmann_json_include_dir}/json.hpp) - # nothing to do - else() - message(WARNING - "The original value of SlopeCraft_Nlohmann_json_include_dir is invalid: failed to find " + if (EXISTS ${SlopeCraft_Nlohmann_json_include_dir}/json.hpp) + # nothing to do + else () + message(WARNING + "The original value of SlopeCraft_Nlohmann_json_include_dir is invalid: failed to find " ${SlopeCraft_Nlohmann_json_include_dir}/json.hpp) set(SlopeCraft_download_njson ON) - endif() -endif() + endif () +endif () -if(${SlopeCraft_download_njson}) +if (${SlopeCraft_download_njson}) message(STATUS "Downloading nlohmann json...") - file(DOWNLOAD - "https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp" + file(DOWNLOAD + "https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp" ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann/json.hpp + HASH 9bea4c8066ef4a1c206b2be5a36302f8926f7fdc6087af5d20b417d0cf103ea6 SHOW_PROGRESS) message(STATUS "nlohmann json downloaded") set(SlopeCraft_download_njson OFF) set(SlopeCraft_Nlohmann_json_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann) -endif() \ No newline at end of file +endif () \ No newline at end of file From ff79bbb1d320ff50d649371c35e06dad7e6e20e5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 11:43:43 +0800 Subject: [PATCH 0723/1123] slightly improve LossyCompressor Signed-off-by: ToKiNoBug --- SlopeCraftL/lossyCompressor.cpp | 35 +++++++++++++++++---------------- SlopeCraftL/lossyCompressor.h | 9 +++++---- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/SlopeCraftL/lossyCompressor.cpp b/SlopeCraftL/lossyCompressor.cpp index dce6feda..e91ebd3e 100644 --- a/SlopeCraftL/lossyCompressor.cpp +++ b/SlopeCraftL/lossyCompressor.cpp @@ -29,12 +29,12 @@ This file is part of SlopeCraft. const double initializeNonZeroRatio = 0.05; -const uint16_t popSize = 50; +constexpr uint16_t popSize = 50; uint16_t maxFailTimes = 30; uint16_t LossyCompressor::maxGeneration = 600; -const double crossoverProb = 0.9; -const double mutateProb = 0.01; -const uint32_t reportRate = 50; +constexpr double crossoverProb = 0.9; +constexpr double mutateProb = 0.01; +constexpr uint32_t reportRate = 50; using Var_t = Eigen::ArrayX; @@ -83,7 +83,7 @@ class solver_t heu::RecordOption::DONT_RECORD_FITNESS, heu::SelectMethod::Tournament, args_t, iFun, fFun, heu::GADefaults::cFunSwapXs, heu::GADefaults::mFun> { -public: + public: void customOptAfterEachGeneration() { if (this->generation() % reportRate == 0) { std::clock_t &prevClock = this->_args.prevClock; @@ -98,12 +98,11 @@ class solver_t } }; -LossyCompressor::LossyCompressor() { - solver = new solver_t; +LossyCompressor::LossyCompressor() : solver{new solver_t{}} { solver->setTournamentSize(3); } -LossyCompressor::~LossyCompressor() { delete solver; } +LossyCompressor::~LossyCompressor() {} void LossyCompressor::setSource(const Eigen::ArrayXi &_base, const TokiColor **src) { @@ -121,12 +120,15 @@ void LossyCompressor::setSource(const Eigen::ArrayXi &_base, void LossyCompressor::runGenetic(uint16_t maxHeight, bool allowNaturalCompress) { { - static heu::GAOption opt; + heu::GAOption opt; opt.crossoverProb = crossoverProb; opt.maxFailTimes = maxFailTimes; opt.maxGenerations = maxGeneration; opt.mutateProb = mutateProb; opt.populationSize = popSize; + solver->setOption(opt); + } + { solver_t::ArgsType args; args.setDimensions(source.size()); args.src = source.data(); @@ -134,17 +136,14 @@ void LossyCompressor::runGenetic(uint16_t maxHeight, args.maxHeight = maxHeight; args.ptr = this; args.prevClock = std::clock(); - - solver->setOption(opt); solver->setArgs(args); - solver->initializePop(); } + solver->initializePop(); solver->run(); } bool LossyCompressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { - (*progressRangeSetPtr)(*windPtr, 0, maxGeneration, 0); // std::cerr<<"Genetic algorithm started\n"; @@ -152,8 +151,8 @@ bool LossyCompressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { maxFailTimes = 30; maxGeneration = 200; while (tryTimes < 3) { - runGenetic(maxHeight, allowNaturalCompress); - if (resultFitness() <= 0) { + this->runGenetic(maxHeight, allowNaturalCompress); + if (this->resultFitness() <= 0) { tryTimes++; maxFailTimes = -1; maxGeneration *= 2; @@ -164,7 +163,9 @@ bool LossyCompressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { } const Eigen::ArrayX &LossyCompressor::getResult() const { - return solver->result(); + return this->solver->result(); } -double LossyCompressor::resultFitness() const { return solver->bestFitness(); } +double LossyCompressor::resultFitness() const { + return this->solver->bestFitness(); +} diff --git a/SlopeCraftL/lossyCompressor.h b/SlopeCraftL/lossyCompressor.h index d7c43144..d18be7f5 100644 --- a/SlopeCraftL/lossyCompressor.h +++ b/SlopeCraftL/lossyCompressor.h @@ -30,6 +30,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "Colors.h" #include "HeightLine.h" @@ -40,7 +41,7 @@ This file is part of SlopeCraft. class solver_t; class LossyCompressor { -public: + public: LossyCompressor(); ~LossyCompressor(); void setSource(const Eigen::ArrayXi &, const TokiColor *[]); @@ -53,9 +54,9 @@ class LossyCompressor { void (**progressAddPtr)(void *, int); void (**keepAwakePtr)(void *); -private: + private: friend class solver_t; - solver_t *solver; + std::unique_ptr solver; std::vector source; static uint16_t maxGeneration; @@ -64,4 +65,4 @@ class LossyCompressor { }; double randD(); -#endif // LOSSYCOMPRESSOR_H +#endif // LOSSYCOMPRESSOR_H From 293713f1b161408b15c9d1272e3525ea3b71fa6b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 11:43:53 +0800 Subject: [PATCH 0724/1123] slightly improve WaterItem Signed-off-by: ToKiNoBug --- SlopeCraftL/WaterItem.cpp | 56 --------------------------------------- SlopeCraftL/WaterItem.h | 32 +++++++++++++--------- 2 files changed, 20 insertions(+), 68 deletions(-) delete mode 100644 SlopeCraftL/WaterItem.cpp diff --git a/SlopeCraftL/WaterItem.cpp b/SlopeCraftL/WaterItem.cpp deleted file mode 100644 index 78a62a68..00000000 --- a/SlopeCraftL/WaterItem.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "WaterItem.h" - -const TokiPos nullPos = TokiRC(-1, -1); -const waterItem nullWater = TokiRC(-32768, -32768); -const short WaterColumnSize[3] = {11, 6, 1}; -// waterItem (*TokiWater)(int,int)=TokiRC; -// short (*waterHigh)(waterItem)=TokiRow; -// short (*waterLow)(waterItem)=TokiCol; -TokiPos TokiRC(int row, int col) { - /*unsigned int u; - *((short*)&u)=row; - *(((short*)&u)+1)=col; - return u;*/ - return (row << 16) | (col & 0x0000FFFF); -} -short TokiRow(TokiPos pos) { return pos >> 16; } -short TokiCol(TokiPos pos) { return pos & 0x0000FFFF; } -/* -waterItem TokiWater(short high,short low) -{ - unsigned int u; - *((short*)&u)=high; - *(((short*)&u)+1)=low; - return u; -} -short waterHigh(waterItem item) -{ - return *((short*)&item); -} -short waterLow(waterItem item) -{ - return *(((short*)&item)+1); -} -*/ diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/WaterItem.h index 6ee945da..e1d7ce42 100644 --- a/SlopeCraftL/WaterItem.h +++ b/SlopeCraftL/WaterItem.h @@ -29,19 +29,27 @@ using TokiPos = uint32_t; // typedef unsigned int TokiPos; // typedef unsigned int waterItem; using waterItem = uint32_t; -extern const TokiPos nullPos; -extern const waterItem nullWater; -extern const short WaterColumnSize[3]; -TokiPos TokiRC(int row, int col); // 前16bit存储row,后16bit存储col -short TokiRow(TokiPos); -short TokiCol(TokiPos); +constexpr TokiPos TokiRC(int row, int col) { // 前16bit存储row,后16bit存储col + /*unsigned int u; + *((int16_t*)&u)=row; + *(((int16_t*)&u)+1)=col; + return u;*/ + return (row << 16) | (col & 0x0000FFFF); +} + +constexpr int16_t TokiRow(TokiPos pos) { return pos >> 16; } +constexpr int16_t TokiCol(TokiPos pos) { return pos & 0x0000FFFF; } + +constexpr TokiPos nullPos = TokiRC(-1, -1); +constexpr waterItem nullWater = TokiRC(-32768, -32768); +constexpr int16_t WaterColumnSize[3] = {11, 6, 1}; constexpr waterItem (*TokiWater)(int, int) = TokiRC; -constexpr short (*waterHigh)(waterItem) = TokiRow; -constexpr short (*waterLow)(waterItem) = TokiCol; +constexpr int16_t (*waterHigh)(waterItem) = TokiRow; +constexpr int16_t (*waterLow)(waterItem) = TokiCol; /* -waterItem TokiWater(short high,short low);//前两字节存储high,后两字节存储low -short waterHigh(waterItem); -short waterLow(waterItem);*/ +waterItem TokiWater(int16_t high,int16_t +low);//前两字节存储high,后两字节存储low int16_t waterHigh(waterItem); int16_t +waterLow(waterItem);*/ -#endif // WATERITEM_H +#endif // WATERITEM_H From c369d7d3a1391ebf5589e75df874d562f26da8d1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 13:22:03 +0800 Subject: [PATCH 0725/1123] load block list from zip Signed-off-by: ToKiNoBug --- Blocks/CustomBlocks.json | 528 ------- Blocks/CustomBlocks/BlockList.json | 526 +++++++ Blocks/FixedBlocks.json | 1716 ---------------------- Blocks/FixedBlocks/BlockList.json | 1714 +++++++++++++++++++++ SlopeCraftL/CMakeLists.txt | 45 +- SlopeCraftL/SlopeCraftL.cpp | 231 ++- SlopeCraftL/SlopeCraftL.h | 10 +- SlopeCraftL/TokiSlopeCraft.cpp | 2 +- SlopeCraftL/simpleBlock.cpp | 142 +- SlopeCraftL/simpleBlock.h | 15 +- SlopeCraftL/tests/load_scl_blocklist.cpp | 88 ++ 11 files changed, 2633 insertions(+), 2384 deletions(-) delete mode 100644 Blocks/CustomBlocks.json create mode 100644 Blocks/CustomBlocks/BlockList.json delete mode 100644 Blocks/FixedBlocks.json create mode 100644 Blocks/FixedBlocks/BlockList.json create mode 100644 SlopeCraftL/tests/load_scl_blocklist.cpp diff --git a/Blocks/CustomBlocks.json b/Blocks/CustomBlocks.json deleted file mode 100644 index ea2fb56e..00000000 --- a/Blocks/CustomBlocks.json +++ /dev/null @@ -1,528 +0,0 @@ -{ - "CustomBlocks": [ - // 这个文件列出了所有用户自定义的方块的信息", - // 你可以按照这样的格式自定义添加新的方块,包括 mod 方块", - // 但必须遵守 json 格式", - // 如果 json 格式出错,整个文件都会无法解析,SlopeCraft 会报错。 - { - // baseColor 是这种方块对应的基色,是必填项(非常非常重要!!!!!!!)", - "baseColor": 15, - // id 是这种方块的 id,也是必填项,最好附带完整的方块状态,必须加 minecraft:前缀", - "id": "minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]", - // nameZH 是方块中文名称,必填", - "nameZH": "涂蜡切制铜台阶", - // nameEN 是方块英文名称,必填", - "nameEN": "Waxed cut copper slab", - // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", - "icon": "waxed_cut_copper_slab.png", - // version 是方块最早出现的版本。0 代表早于 1.12,12 代表 1.12,13 代表 1.13,如此类推。255 代表尚未出现的版本", - "version": 17 - // idOld 是该方块在 1.12 的方块 id(如果有的话),必须加 minecraft:前缀,选填,默认为空字符串", - // needGlass 代表这个方块的下方需要依附其他方块,默认为否", - // isGlowing 代表这个方块是发光的,默认为否", - // endermanPickable 代表这个方块可以被末影人偷走,默认为否", - // burnable 代表这个方块会被火焰、岩浆或闪电点燃并燃烧,默认为否 - }, - // This json file includes information of all custom blocks. - // You can add your custom block in such format, including mod-blocks. - // But always remember to follow json format - // The whole file will failed to be parsed once an error occurred in json format, then SlopeCraft will complain. - { - // baseColor is the base color of this block on map, a compulsory item(EXTREMELY IMPORTANT!!!!) - "baseColor": 11, - // id is the block id with full blockstatus with minecraft: prefix. Compulsory item. - "id": "minecraft:stone_slab[type=top,waterlogged=false]", - // nameZH is the Chinese name. Compulsory item. - "nameZH": "石头台阶", - // nameEN is the English name. Compulsory item. - "nameEN": "Stone slab", - // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. - "icon": "stone_slab.png", - // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. - "version": 14 - // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string - - // needGlass means if this block must be setted on a solid block, default value is false - // isGlowing means if the block glows, default value is false. - // endermanPickable means if the block can be picked by enderman, default value is false - // burnable means if the block can be lit by fire, lava or lightning blot, default value is false - }, - { - "baseColor": 2, - "id": "minecraft:sandstone_slab[type=top,waterlogged=false]", - "nameZH": "砂岩台阶", - "nameEN": "Sandstone slab", - "icon": "smooth_sandstone_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=sandstone]" - }, - { - "baseColor": 11, - "id": "minecraft:cobblestone_slab[type=top,waterlogged=false]", - "nameZH": "圆石台阶", - "nameEN": "Cobblestone slab", - "icon": "cobblestone_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" - }, - { - "baseColor": 11, - "id": "minecraft:smooth_stone_slab[type=top,waterlogged=false]", - "nameZH": "平滑石台阶", - "nameEN": "Smooth stone slab", - "icon": "smooth_stone_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=smooth_stone]" - }, - { - "baseColor": 28, - "id": "minecraft:brick_slab[type=top,waterlogged=false]", - "nameZH": "红砖台阶", - "nameEN": "Brick slab", - "icon": "bricks_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=brick]" - }, - { - "baseColor": 11, - "id": "minecraft:stone_brick_slab[type=top,waterlogged=false]", - "nameZH": "石砖台阶", - "nameEN": "Stonebrick slab", - "icon": "stone_bricks_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=stone_brick]" - }, - { - "baseColor": 35, - "id": "minecraft:nether_brick_slab[type=top,waterlogged=false]", - "nameZH": "下界砖台阶", - "nameEN": "Nether brick slab", - "icon": "nether_bricks_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=nether_brick]" - }, - { - "baseColor": 14, - "id": "minecraft:quartz_slab[type=top,waterlogged=false]", - "nameZH": "石英台阶", - "nameEN": "Quartz slab", - "icon": "quartz_block_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab[half=top,variant=quartz]" - }, - { - "baseColor": 13, - "id": "minecraft:oak_slab[type=top,waterlogged=false]", - "nameZH": "橡木台阶", - "nameEN": "Oak slab", - "icon": "oak_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=oak]" - }, - { - "baseColor": 34, - "id": "minecraft:spruce_slab[type=top,waterlogged=false]", - "nameZH": "云杉木台阶", - "nameEN": "Spruce slab", - "icon": "spruce_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=spruce]", - "burnable": true - }, - { - "baseColor": 2, - "id": "minecraft:birch_slab[type=top,waterlogged=false]", - "nameZH": "白桦木台阶", - "nameEN": "Birch slab", - "icon": "birch_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=birch]", - "burnable": true - }, - { - "baseColor": 10, - "id": "minecraft:jungle_slab[type=top,waterlogged=false]", - "nameZH": "丛林木台阶", - "nameEN": "Jungle slab", - "icon": "jungle_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=jungle]", - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:acacia_slab[type=top,waterlogged=false]", - "nameZH": "金合欢木台阶", - "nameEN": "Acacia slab", - "icon": "acacia_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=acacia]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:dark_oak_slab[type=top,waterlogged=false]", - "nameZH": "深色橡木台阶", - "nameEN": "Dark oak slab", - "icon": "dark_oak_planks_slab.png", - "version": 0, - "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", - "burnable": true - }, - { - "baseColor": 53, - "id": "minecraft:crimson_slab[type=top,waterlogged=false]", - "nameZH": "绯红木台阶", - "nameEN": "Crimson slab", - "icon": "crimson_planks_slab.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 56, - "id": "minecraft:warped_slab[type=top,waterlogged=false]", - "nameZH": "诡异木台阶", - "nameEN": "Warped slab", - "icon": "warped_planks_slab.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 28, - "id": "minecraft:mangrove_slab[type=top,waterlogged=false]", - "nameZH": "红树木台阶", - "nameEN": "Mangrove slab", - "icon": "mangrove_planks_slab.png", - "version": 19, - "burnable": true - }, - { - "baseColor": 36, - "id": "minecraft:cherry_slab[type=top,waterlogged=false]", - "nameZH": "樱花木台阶", - "nameEN": "Cherry slab", - "icon": "cherry_slab_slab.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 18, - "id": "minecraft:bamboo_slab[type=top,waterlogged=false]", - "nameZH": "竹台阶", - "nameEN": "Bamboo slab", - "icon": "bamboo_planks_slab.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 18, - "id": "minecraft:bamboo_mosaic_slab[type=top,waterlogged=false]", - "nameZH": "竹马赛克台阶", - "nameEN": "Bamboo mosaic slab", - "icon": "bamboo_mosaic_slab.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", - "nameZH": "红砂岩台阶", - "nameEN": "Red sandstone slab", - "icon": "smooth_red_sandstone_slab.png", - "version": 0, - "idOld": "minecraft:stone_slab2[half=top,variant=red_sandstone]" - }, - { - "baseColor": 16, - "id": "minecraft:purpur_slab[type=top,waterlogged=false]", - "nameZH": "紫珀台阶", - "nameEN": "Purpur slab", - "icon": "purpur_block_slab.png", - "version": 0, - "idOld": "minecraft:purpur_slab[half=top,variant=default]" - }, - { - "baseColor": 23, - "id": "minecraft:prismarine_slab[type=top,waterlogged=false]", - "nameZH": "海晶石台阶", - "nameEN": "Prismarine slab", - "icon": "prismarine_slab.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=prismarine]" - }, - { - "baseColor": 31, - "id": "minecraft:prismarine_brick_slab[type=top,waterlogged=false]", - "nameZH": "海晶石砖台阶", - "nameEN": "Prismarine brick slab", - "icon": "prismarine_bricks_slab.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=prismarine_bricks]" - }, - { - "baseColor": 31, - "id": "minecraft:dark_prismarine_slab[type=top,waterlogged=false]", - "nameZH": "暗海晶石台阶", - "nameEN": "Dark prismarine slab", - "icon": "dark_prismarine_slab.png", - "version": 13, - "idOld": "minecraft:stone_slab[half=top,variant=dark_prismarine]" - }, - { - "baseColor": 2, - "id": "minecraft:end_stone_brick_slab[type=top,waterlogged=false]", - "nameZH": "末地石砖台阶", - "nameEN": "Endstone brick slab", - "icon": "end_stone_bricks_slab.png", - "version": 14 - }, - { - "baseColor": 2, - "id": "minecraft:sandstone", - "nameZH": "砂岩", - "nameEN": "Sand stone", - "icon": "sandstone.png", - "version": 0 - }, - { - "baseColor": 2, - "id": "minecraft:bone_block[axis=y]", - "nameZH": "骨块", - "nameEN": "Bone block", - "icon": "bone_block_top.png", - "version": 0 - }, - { - "baseColor": 10, - "id": "minecraft:granite", - "nameZH": "花岗岩", - "nameEN": "Granite", - "icon": "granite.png", - "version": 0, - "idOld": "minecraft:stone[variant=granite]" - }, - { - "baseColor": 10, - "id": "minecraft:granite_slab[type=top,waterlogged=false]", - "nameZH": "花岗岩台阶", - "nameEN": "Granite slab", - "icon": "granite_slab.png", - "version": 14 - }, - { - "baseColor": 10, - "id": "minecraft:polished_granite", - "nameZH": "磨制花岗岩", - "nameEN": "Polished granite", - "icon": "polished_granite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_granite]" - }, - { - "baseColor": 10, - "id": "minecraft:polished_granite_slab[type=top,waterlogged=false]", - "nameZH": "磨制花岗岩台阶", - "nameEN": "Polished granite slab", - "icon": "polished_granite_slab.png", - "version": 14 - }, - { - "baseColor": 11, - "id": "minecraft:andesite", - "nameZH": "安山岩", - "nameEN": "Andesite", - "icon": "andesite.png", - "version": 0, - "idOld": "minecraft:stone[variant=andesite]" - }, - { - "baseColor": 11, - "id": "minecraft:andesite_slab[type=top,waterlogged=false]", - "nameZH": "安山岩台阶", - "nameEN": "Andesite slab", - "icon": "andesite_slab.png", - "version": 14 - }, - { - "baseColor": 11, - "id": "minecraft:polished_andesite", - "nameZH": "磨制安山岩", - "nameEN": "Polished andesite", - "icon": "polished_andesite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_andesite]" - }, - { - "baseColor": 11, - "id": "minecraft:polished_andesite_slab[type=top,waterlogged=false]", - "nameZH": "磨制安山岩台阶", - "nameEN": "Polished andesite slab", - "icon": "polished_andesite_slab.png", - "version": 14 - }, - { - "baseColor": 14, - "id": "minecraft:diorite", - "nameZH": "闪长岩", - "nameEN": "Diorite", - "icon": "diorite.png", - "version": 0, - "idOld": "minecraft:stone[variant=diorite]" - }, - { - "baseColor": 14, - "id": "minecraft:diorite_slab[type=top,waterlogged=false]", - "nameZH": "闪长岩台阶", - "nameEN": "Diorite slab", - "icon": "diorite_slab.png", - "version": 14 - }, - { - "baseColor": 14, - "id": "minecraft:polished_diorite", - "nameZH": "磨制闪长岩", - "nameEN": "Polished diorite", - "icon": "polished_diorite.png", - "version": 0, - "idOld": "minecraft:stone[variant=smooth_diorite]" - }, - { - "baseColor": 14, - "id": "minecraft:polished_diorite_slab[type=top,waterlogged=false]", - "nameZH": "磨制闪长岩台阶", - "nameEN": "Polished diorite slab", - "icon": "polished_diorite_slab.png", - "version": 14 - }, - { - "baseColor": 15, - "id": "minecraft:red_sandstone", - "nameZH": "红砂岩", - "nameEN": "Red sandstone", - "icon": "red_sandstone.png", - "version": 0, - "idOld": "minecraft:red_sandstone[type=red_sandstone]" - }, - { - "baseColor": 19, - "id": "minecraft:melon", - "nameZH": "西瓜", - "nameEN": "Melon", - "icon": "melon_top.png", - "version": 0, - "idOld": "minecraft:melon_block" - }, - { - "baseColor": 24, - "id": "minecraft:mycelium[snowy=false]", - "nameZH": "菌丝体", - "nameEN": "Mycelium", - "icon": "mycelium_top.png", - "version": 0 - }, - { - "baseColor": 27, - "id": "minecraft:moss_block", - "nameZH": "苔藓块", - "nameEN": "Moss block", - "icon": "moss_block.png", - "version": 17 - }, - { - "baseColor": 29, - "id": "minecraft:basalt[axis=y]", - "nameZH": "玄武岩", - "nameEN": "Basalt", - "icon": "basalt_top.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:blackstone", - "nameZH": "黑石", - "nameEN": "Black stone", - "icon": "blackstone.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:blackstone_slab[type=top,waterlogged=false]", - "nameZH": "黑石台阶", - "nameEN": "Black stone slab", - "icon": "blackstone_slab.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:polished_blackstone_slab[type=top,waterlogged=false]", - "nameZH": "磨制黑石台阶", - "nameEN": "Polished black stone slab", - "icon": "polished_blackstone_slab.png", - "version": 16 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_brick_slab[type=top,waterlogged=false]", - "nameZH": "深板岩砖台阶", - "nameEN": "Deepslate bricks slab", - "icon": "deepslate_bricks_slab.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_tile_slab[type=top,waterlogged=false]", - "nameZH": "深板岩瓦台阶", - "nameEN": "Deepslate tiles slab", - "icon": "deepslate_tiles_slab.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:cobbled_deepslate_slab[type=top,waterlogged=false]", - "nameZH": "深板岩圆石台阶", - "nameEN": "Cobbled deepslate slab", - "icon": "cobbled_deepslate_slab.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:polished_deepslate_slab[type=top,waterlogged=false]", - "nameZH": "磨制深板岩台阶", - "nameEN": "Polished deepslate slab", - "icon": "polished_deepslate_slab.png", - "version": 17 - }, - { - "baseColor": 29, - "id": "minecraft:crying_obsidian", - "nameZH": "哭泣的黑曜石", - "nameEN": "Crying obsidian", - "icon": "crying_obsidian.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:netherite_block", - "nameZH": "下界合金块", - "nameEN": "Netherite block", - "icon": "netherite_block.png", - "version": 16 - }, - { - "baseColor": 43, - "id": "minecraft:tuff", - "nameZH": "凝灰岩", - "nameEN": "Tuff", - "icon": "tuff.png", - "version": 17 - }, - { - "baseColor": 44, - "id": "minecraft:mud_brick_slab[type=top,waterlogged=false]", - "nameZH": "泥砖台阶", - "nameEN": "Mud bricks slab", - "icon": "mud_bricks_slab.png", - "version": 19 - } - ] -} \ No newline at end of file diff --git a/Blocks/CustomBlocks/BlockList.json b/Blocks/CustomBlocks/BlockList.json new file mode 100644 index 00000000..af7d4add --- /dev/null +++ b/Blocks/CustomBlocks/BlockList.json @@ -0,0 +1,526 @@ +[ + // 这个文件列出了所有用户自定义的方块的信息", + // 你可以按照这样的格式自定义添加新的方块,包括 mod 方块", + // 但必须遵守 json 格式", + // 如果 json 格式出错,整个文件都会无法解析,SlopeCraft 会报错。 + { + // baseColor 是这种方块对应的基色,是必填项(非常非常重要!!!!!!!)", + "baseColor": 15, + // id 是这种方块的 id,也是必填项,最好附带完整的方块状态,必须加 minecraft:前缀", + "id": "minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]", + // nameZH 是方块中文名称,必填", + "nameZH": "涂蜡切制铜台阶", + // nameEN 是方块英文名称,必填", + "nameEN": "Waxed cut copper slab", + // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", + "icon": "waxed_cut_copper_slab.png", + // version 是方块最早出现的版本。0 代表早于 1.12,12 代表 1.12,13 代表 1.13,如此类推。255 代表尚未出现的版本", + "version": 17 + // idOld 是该方块在 1.12 的方块 id(如果有的话),必须加 minecraft:前缀,选填,默认为空字符串", + // needGlass 代表这个方块的下方需要依附其他方块,默认为否", + // isGlowing 代表这个方块是发光的,默认为否", + // endermanPickable 代表这个方块可以被末影人偷走,默认为否", + // burnable 代表这个方块会被火焰、岩浆或闪电点燃并燃烧,默认为否 + }, + // This json file includes information of all custom blocks. + // You can add your custom block in such format, including mod-blocks. + // But always remember to follow json format + // The whole file will failed to be parsed once an error occurred in json format, then SlopeCraft will complain. + { + // baseColor is the base color of this block on map, a compulsory item(EXTREMELY IMPORTANT!!!!) + "baseColor": 11, + // id is the block id with full blockstatus with minecraft: prefix. Compulsory item. + "id": "minecraft:stone_slab[type=top,waterlogged=false]", + // nameZH is the Chinese name. Compulsory item. + "nameZH": "石头台阶", + // nameEN is the English name. Compulsory item. + "nameEN": "Stone slab", + // icon is the image filename correspoing to this block, the image should be put under CustomBlocks directory. Compulsory item. + "icon": "stone_slab.png", + // version is the earliest version when the block is added to Minecraft. 0 means earlier than 1.12, 12 means 1.12, 13 means 1.13, and so on. 255 means future version. + "version": 14 + // idOld is the blockid in 1.12 (if there is) with minecraft: prefix. default value is an empty string + + // needGlass means if this block must be setted on a solid block, default value is false + // isGlowing means if the block glows, default value is false. + // endermanPickable means if the block can be picked by enderman, default value is false + // burnable means if the block can be lit by fire, lava or lightning blot, default value is false + }, + { + "baseColor": 2, + "id": "minecraft:sandstone_slab[type=top,waterlogged=false]", + "nameZH": "砂岩台阶", + "nameEN": "Sandstone slab", + "icon": "smooth_sandstone_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=sandstone]" + }, + { + "baseColor": 11, + "id": "minecraft:cobblestone_slab[type=top,waterlogged=false]", + "nameZH": "圆石台阶", + "nameEN": "Cobblestone slab", + "icon": "cobblestone_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=cobblestone]" + }, + { + "baseColor": 11, + "id": "minecraft:smooth_stone_slab[type=top,waterlogged=false]", + "nameZH": "平滑石台阶", + "nameEN": "Smooth stone slab", + "icon": "smooth_stone_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=smooth_stone]" + }, + { + "baseColor": 28, + "id": "minecraft:brick_slab[type=top,waterlogged=false]", + "nameZH": "红砖台阶", + "nameEN": "Brick slab", + "icon": "bricks_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=brick]" + }, + { + "baseColor": 11, + "id": "minecraft:stone_brick_slab[type=top,waterlogged=false]", + "nameZH": "石砖台阶", + "nameEN": "Stonebrick slab", + "icon": "stone_bricks_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=stone_brick]" + }, + { + "baseColor": 35, + "id": "minecraft:nether_brick_slab[type=top,waterlogged=false]", + "nameZH": "下界砖台阶", + "nameEN": "Nether brick slab", + "icon": "nether_bricks_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=nether_brick]" + }, + { + "baseColor": 14, + "id": "minecraft:quartz_slab[type=top,waterlogged=false]", + "nameZH": "石英台阶", + "nameEN": "Quartz slab", + "icon": "quartz_block_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab[half=top,variant=quartz]" + }, + { + "baseColor": 13, + "id": "minecraft:oak_slab[type=top,waterlogged=false]", + "nameZH": "橡木台阶", + "nameEN": "Oak slab", + "icon": "oak_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=oak]" + }, + { + "baseColor": 34, + "id": "minecraft:spruce_slab[type=top,waterlogged=false]", + "nameZH": "云杉木台阶", + "nameEN": "Spruce slab", + "icon": "spruce_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=spruce]", + "burnable": true + }, + { + "baseColor": 2, + "id": "minecraft:birch_slab[type=top,waterlogged=false]", + "nameZH": "白桦木台阶", + "nameEN": "Birch slab", + "icon": "birch_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=birch]", + "burnable": true + }, + { + "baseColor": 10, + "id": "minecraft:jungle_slab[type=top,waterlogged=false]", + "nameZH": "丛林木台阶", + "nameEN": "Jungle slab", + "icon": "jungle_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=jungle]", + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:acacia_slab[type=top,waterlogged=false]", + "nameZH": "金合欢木台阶", + "nameEN": "Acacia slab", + "icon": "acacia_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=acacia]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:dark_oak_slab[type=top,waterlogged=false]", + "nameZH": "深色橡木台阶", + "nameEN": "Dark oak slab", + "icon": "dark_oak_planks_slab.png", + "version": 0, + "idOld": "minecraft:wooden_slab[half=top,variant=dark_oak]", + "burnable": true + }, + { + "baseColor": 53, + "id": "minecraft:crimson_slab[type=top,waterlogged=false]", + "nameZH": "绯红木台阶", + "nameEN": "Crimson slab", + "icon": "crimson_planks_slab.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:warped_slab[type=top,waterlogged=false]", + "nameZH": "诡异木台阶", + "nameEN": "Warped slab", + "icon": "warped_planks_slab.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:mangrove_slab[type=top,waterlogged=false]", + "nameZH": "红树木台阶", + "nameEN": "Mangrove slab", + "icon": "mangrove_planks_slab.png", + "version": 19, + "burnable": true + }, + { + "baseColor": 36, + "id": "minecraft:cherry_slab[type=top,waterlogged=false]", + "nameZH": "樱花木台阶", + "nameEN": "Cherry slab", + "icon": "cherry_slab_slab.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_slab[type=top,waterlogged=false]", + "nameZH": "竹台阶", + "nameEN": "Bamboo slab", + "icon": "bamboo_planks_slab.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_mosaic_slab[type=top,waterlogged=false]", + "nameZH": "竹马赛克台阶", + "nameEN": "Bamboo mosaic slab", + "icon": "bamboo_mosaic_slab.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:red_sandstone_slab[type=top,waterlogged=false]", + "nameZH": "红砂岩台阶", + "nameEN": "Red sandstone slab", + "icon": "smooth_red_sandstone_slab.png", + "version": 0, + "idOld": "minecraft:stone_slab2[half=top,variant=red_sandstone]" + }, + { + "baseColor": 16, + "id": "minecraft:purpur_slab[type=top,waterlogged=false]", + "nameZH": "紫珀台阶", + "nameEN": "Purpur slab", + "icon": "purpur_block_slab.png", + "version": 0, + "idOld": "minecraft:purpur_slab[half=top,variant=default]" + }, + { + "baseColor": 23, + "id": "minecraft:prismarine_slab[type=top,waterlogged=false]", + "nameZH": "海晶石台阶", + "nameEN": "Prismarine slab", + "icon": "prismarine_slab.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=prismarine]" + }, + { + "baseColor": 31, + "id": "minecraft:prismarine_brick_slab[type=top,waterlogged=false]", + "nameZH": "海晶石砖台阶", + "nameEN": "Prismarine brick slab", + "icon": "prismarine_bricks_slab.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=prismarine_bricks]" + }, + { + "baseColor": 31, + "id": "minecraft:dark_prismarine_slab[type=top,waterlogged=false]", + "nameZH": "暗海晶石台阶", + "nameEN": "Dark prismarine slab", + "icon": "dark_prismarine_slab.png", + "version": 13, + "idOld": "minecraft:stone_slab[half=top,variant=dark_prismarine]" + }, + { + "baseColor": 2, + "id": "minecraft:end_stone_brick_slab[type=top,waterlogged=false]", + "nameZH": "末地石砖台阶", + "nameEN": "Endstone brick slab", + "icon": "end_stone_bricks_slab.png", + "version": 14 + }, + { + "baseColor": 2, + "id": "minecraft:sandstone", + "nameZH": "砂岩", + "nameEN": "Sand stone", + "icon": "sandstone.png", + "version": 0 + }, + { + "baseColor": 2, + "id": "minecraft:bone_block[axis=y]", + "nameZH": "骨块", + "nameEN": "Bone block", + "icon": "bone_block_top.png", + "version": 0 + }, + { + "baseColor": 10, + "id": "minecraft:granite", + "nameZH": "花岗岩", + "nameEN": "Granite", + "icon": "granite.png", + "version": 0, + "idOld": "minecraft:stone[variant=granite]" + }, + { + "baseColor": 10, + "id": "minecraft:granite_slab[type=top,waterlogged=false]", + "nameZH": "花岗岩台阶", + "nameEN": "Granite slab", + "icon": "granite_slab.png", + "version": 14 + }, + { + "baseColor": 10, + "id": "minecraft:polished_granite", + "nameZH": "磨制花岗岩", + "nameEN": "Polished granite", + "icon": "polished_granite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_granite]" + }, + { + "baseColor": 10, + "id": "minecraft:polished_granite_slab[type=top,waterlogged=false]", + "nameZH": "磨制花岗岩台阶", + "nameEN": "Polished granite slab", + "icon": "polished_granite_slab.png", + "version": 14 + }, + { + "baseColor": 11, + "id": "minecraft:andesite", + "nameZH": "安山岩", + "nameEN": "Andesite", + "icon": "andesite.png", + "version": 0, + "idOld": "minecraft:stone[variant=andesite]" + }, + { + "baseColor": 11, + "id": "minecraft:andesite_slab[type=top,waterlogged=false]", + "nameZH": "安山岩台阶", + "nameEN": "Andesite slab", + "icon": "andesite_slab.png", + "version": 14 + }, + { + "baseColor": 11, + "id": "minecraft:polished_andesite", + "nameZH": "磨制安山岩", + "nameEN": "Polished andesite", + "icon": "polished_andesite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_andesite]" + }, + { + "baseColor": 11, + "id": "minecraft:polished_andesite_slab[type=top,waterlogged=false]", + "nameZH": "磨制安山岩台阶", + "nameEN": "Polished andesite slab", + "icon": "polished_andesite_slab.png", + "version": 14 + }, + { + "baseColor": 14, + "id": "minecraft:diorite", + "nameZH": "闪长岩", + "nameEN": "Diorite", + "icon": "diorite.png", + "version": 0, + "idOld": "minecraft:stone[variant=diorite]" + }, + { + "baseColor": 14, + "id": "minecraft:diorite_slab[type=top,waterlogged=false]", + "nameZH": "闪长岩台阶", + "nameEN": "Diorite slab", + "icon": "diorite_slab.png", + "version": 14 + }, + { + "baseColor": 14, + "id": "minecraft:polished_diorite", + "nameZH": "磨制闪长岩", + "nameEN": "Polished diorite", + "icon": "polished_diorite.png", + "version": 0, + "idOld": "minecraft:stone[variant=smooth_diorite]" + }, + { + "baseColor": 14, + "id": "minecraft:polished_diorite_slab[type=top,waterlogged=false]", + "nameZH": "磨制闪长岩台阶", + "nameEN": "Polished diorite slab", + "icon": "polished_diorite_slab.png", + "version": 14 + }, + { + "baseColor": 15, + "id": "minecraft:red_sandstone", + "nameZH": "红砂岩", + "nameEN": "Red sandstone", + "icon": "red_sandstone.png", + "version": 0, + "idOld": "minecraft:red_sandstone[type=red_sandstone]" + }, + { + "baseColor": 19, + "id": "minecraft:melon", + "nameZH": "西瓜", + "nameEN": "Melon", + "icon": "melon_top.png", + "version": 0, + "idOld": "minecraft:melon_block" + }, + { + "baseColor": 24, + "id": "minecraft:mycelium[snowy=false]", + "nameZH": "菌丝体", + "nameEN": "Mycelium", + "icon": "mycelium_top.png", + "version": 0 + }, + { + "baseColor": 27, + "id": "minecraft:moss_block", + "nameZH": "苔藓块", + "nameEN": "Moss block", + "icon": "moss_block.png", + "version": 17 + }, + { + "baseColor": 29, + "id": "minecraft:basalt[axis=y]", + "nameZH": "玄武岩", + "nameEN": "Basalt", + "icon": "basalt_top.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:blackstone", + "nameZH": "黑石", + "nameEN": "Black stone", + "icon": "blackstone.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:blackstone_slab[type=top,waterlogged=false]", + "nameZH": "黑石台阶", + "nameEN": "Black stone slab", + "icon": "blackstone_slab.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:polished_blackstone_slab[type=top,waterlogged=false]", + "nameZH": "磨制黑石台阶", + "nameEN": "Polished black stone slab", + "icon": "polished_blackstone_slab.png", + "version": 16 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_brick_slab[type=top,waterlogged=false]", + "nameZH": "深板岩砖台阶", + "nameEN": "Deepslate bricks slab", + "icon": "deepslate_bricks_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_tile_slab[type=top,waterlogged=false]", + "nameZH": "深板岩瓦台阶", + "nameEN": "Deepslate tiles slab", + "icon": "deepslate_tiles_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:cobbled_deepslate_slab[type=top,waterlogged=false]", + "nameZH": "深板岩圆石台阶", + "nameEN": "Cobbled deepslate slab", + "icon": "cobbled_deepslate_slab.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:polished_deepslate_slab[type=top,waterlogged=false]", + "nameZH": "磨制深板岩台阶", + "nameEN": "Polished deepslate slab", + "icon": "polished_deepslate_slab.png", + "version": 17 + }, + { + "baseColor": 29, + "id": "minecraft:crying_obsidian", + "nameZH": "哭泣的黑曜石", + "nameEN": "Crying obsidian", + "icon": "crying_obsidian.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:netherite_block", + "nameZH": "下界合金块", + "nameEN": "Netherite block", + "icon": "netherite_block.png", + "version": 16 + }, + { + "baseColor": 43, + "id": "minecraft:tuff", + "nameZH": "凝灰岩", + "nameEN": "Tuff", + "icon": "tuff.png", + "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:mud_brick_slab[type=top,waterlogged=false]", + "nameZH": "泥砖台阶", + "nameEN": "Mud bricks slab", + "icon": "mud_bricks_slab.png", + "version": 19 + } +] \ No newline at end of file diff --git a/Blocks/FixedBlocks.json b/Blocks/FixedBlocks.json deleted file mode 100644 index 137c6acf..00000000 --- a/Blocks/FixedBlocks.json +++ /dev/null @@ -1,1716 +0,0 @@ -{ - "FixedBlocks": [ - { - "baseColor": 0, - "id": "minecraft:glass", - "nameZH": "玻璃", - "nameEN": "Glass", - "icon": "glass.png", - "version": 0 - }, - { - "baseColor": 1, - "id": "minecraft:grass_block[snowy=false]", - "nameZH": "草方块", - "nameEN": "Grass block", - "icon": "grass_block.png", - "version": 0, - "idOld": "minecraft:grass[snowy=false]", - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 1, - "id": "minecraft:slime_block", - "nameZH": "黏液块", - "nameEN": "Slime block", - "icon": "slime_block.png", - "version": 0, - "idOld": "minecraft:slime" - }, - { - "baseColor": 2, - "id": "minecraft:birch_planks", - "nameZH": "白桦木板", - "nameEN": "Birch plank", - "icon": "birch_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=birch]", - "burnable": true - }, - { - "baseColor": 2, - "id": "minecraft:smooth_sandstone", - "nameZH": "平滑砂岩", - "nameEN": "Smooth sandstone", - "icon": "smooth_sandstone.png", - "version": 0, - "idOld": "minecraft:sandstone[type=smooth_sandstone]" - }, - { - "baseColor": 2, - "id": "minecraft:glowstone", - "nameZH": "荧石", - "nameEN": "Glowstone", - "icon": "glowstone.png", - "version": 0, - "isGlowing": true - }, - { - "baseColor": 2, - "id": "minecraft:end_stone", - "nameZH": "末地石", - "nameEN": "End stone", - "icon": "end_stone.png", - "version": 0 - }, - { - "baseColor": 2, - "id": "minecraft:end_stone_bricks", - "nameZH": "末地石砖", - "nameEN": "Endstone bricks", - "icon": "end_stone_bricks.png", - "version": 0, - "idOld": "minecraft:end_bricks" - }, - { - "baseColor": 2, - "id": "minecraft:turtle_egg[eggs=4,hatch=0]", - "nameZH": "海龟蛋", - "nameEN": "Turtle egg", - "icon": "turtle_egg.png", - "version": 13, - "needGlass": true, - "wallUseable": false - }, - { - "baseColor": 2, - "id": "minecraft:ochre_froglight[axis=y]", - "nameZH": "赭黄蛙明灯", - "nameEN": "Ochre Froglight", - "icon": "ochre_froglight_top.png", - "version": 19, - "isGlowing": true - }, - { - "baseColor": 3, - "id": "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "蘑菇柄", - "nameEN": "Mushroom stem", - "icon": "mushroom_stem.png", - "version": 13, - "burnable": true - }, - { - "baseColor": 3, - "id": "minecraft:cobweb", - "nameZH": "蜘蛛网", - "nameEN": "Cobweb", - "icon": "cobweb.png", - "version": 0, - "idOld": "minecraft:web" - }, - { - "baseColor": 4, - "id": "minecraft:redstone_block", - "nameZH": "红石块", - "nameEN": "Redstone block", - "icon": "redstone_block.png", - "version": 0 - }, - { - "baseColor": 4, - "id": "minecraft:tnt[unstable=false]", - "nameZH": "TNT", - "nameEN": "TNT", - "icon": "tnt.png", - "version": 0, - "idOld": "minecraft:tnt[explode=false]", - "endermanPickable": true, - "burnable": true - }, - { - "baseColor": 5, - "id": "minecraft:ice", - "nameZH": "冰", - "nameEN": "Ice", - "icon": "ice.png", - "version": 0 - }, - { - "baseColor": 5, - "id": "minecraft:packed_ice", - "nameZH": "浮冰", - "nameEN": "Packed ice", - "icon": "packed_ice.png", - "version": 0 - }, - { - "baseColor": 5, - "id": "minecraft:blue_ice", - "nameZH": "蓝冰", - "nameEN": "Blue ice", - "icon": "blue_ice.png", - "version": 13 - }, - { - "baseColor": 6, - "id": "minecraft:iron_block", - "nameZH": "铁块", - "nameEN": "Iron block", - "icon": "iron_block.png", - "version": 0 - }, - { - "baseColor": 6, - "id": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", - "nameZH": "酿造台", - "nameEN": "brewing stand", - "icon": "brewing_stand.png", - "version": 0, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:heavy_weighted_pressure_plate[power=0]", - "nameZH": "重质测重压力板", - "nameEN": "Iron pressure plate", - "icon": "heavy_weighted_pressure_plate.png", - "version": 0, - "needGlass": true, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:iron_trapdoor[facing=north,half=top,open=false,powered=false,waterlogged=false]", - "nameZH": "铁活板门", - "nameEN": "Iron trapdoor", - "icon": "iron_trapdoor.png", - "version": 0, - "idOld": "minecraft:iron_trapdoor[facing=north,half=top,open=false]", - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:lantern[hanging=false]", - "nameZH": "灯笼", - "nameEN": "lantern", - "icon": "lantern.png", - "version": 14, - "wallUseable": false - }, - { - "baseColor": 6, - "id": "minecraft:grindstone[face=floor,facing=north]", - "nameZH": "砂轮", - "nameEN": "Grindstone", - "icon": "grindstone.png", - "version": 14, - "wallUseable": false - }, - { - "baseColor": 7, - "id": "minecraft:oak_leaves[distance=7,persistent=true]", - "nameZH": "橡树树叶", - "nameEN": "Oak leaves", - "icon": "oak_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:spruce_leaves[distance=7,persistent=true]", - "nameZH": "云杉树叶", - "nameEN": "Spurce leaves", - "icon": "spruce_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:birch_leaves[distance=7,persistent=true]", - "nameZH": "白桦树叶", - "nameEN": "Brich leaves", - "icon": "birch_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:jungle_leaves[distance=7,persistent=true]", - "nameZH": "丛林树叶", - "nameEN": "Jungle leaves", - "icon": "jungle_leaves.png", - "version": 0, - "idOld": "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:acacia_leaves[distance=7,persistent=true]", - "nameZH": "金合欢树叶", - "nameEN": "Acacia leaves", - "icon": "acacia_leaves.png", - "version": 0, - "idOld": "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" - }, - { - "baseColor": 7, - "id": "minecraft:dark_oak_leaves[distance=7,persistent=true]", - "nameZH": "深色橡树树叶", - "nameEN": "Dark oat leaves", - "icon": "dark_oak_leaves.png", - "version": 0, - "idOld": "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" - }, - { - "baseColor": 8, - "id": "minecraft:white_concrete", - "nameZH": "白色混凝土", - "nameEN": "White concrete", - "icon": "white_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:white_wool", - "nameZH": "白色羊毛", - "nameEN": "White wool", - "icon": "white_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:white_stained_glass", - "nameZH": "白色染色玻璃", - "nameEN": "White glass", - "icon": "white_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=white]" - }, - { - "baseColor": 8, - "id": "minecraft:snow_block", - "nameZH": "雪块", - "nameEN": "Snow", - "icon": "snow_block.png", - "version": 0, - "idOld": "minecraft:snow" - }, - { - "baseColor": 9, - "id": "minecraft:clay", - "nameZH": "黏土块", - "nameEN": "Clay block", - "icon": "clay.png", - "version": 0, - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:coarse_dirt", - "nameZH": "砂土", - "nameEN": "Coarse dirt", - "icon": "coarse_dirt.png", - "version": 13, - "idOld": "minecraft:dirt[variant=coarse_dirt,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:jungle_planks", - "nameZH": "丛林木板", - "nameEN": "Jungle plank", - "icon": "jungle_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=jungle]", - "burnable": true - }, - { - "baseColor": 10, - "id": "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "棕色蘑菇方块", - "nameEN": "Brown mushroom block", - "icon": "brown_mushroom_block.png", - "version": 0, - "idOld": "minecraft:brown_mushroom_block[variant=all_outside]" - }, - { - "baseColor": 10, - "id": "minecraft:dirt", - "nameZH": "泥土", - "nameEN": "Dirt", - "icon": "dirt.png", - "version": 0, - "idOld": "minecraft:dirt[variant=dirt,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 10, - "id": "minecraft:packed_mud", - "nameZH": "泥坯", - "nameEN": "Packed mud", - "icon": "packed_mud.png", - "version": 19 - }, - { - "baseColor": 11, - "id": "minecraft:cobblestone", - "nameZH": "圆石", - "nameEN": "Cobblestone", - "icon": "cobblestone.png", - "version": 0 - }, - { - "baseColor": 11, - "id": "minecraft:stone", - "nameZH": "石头", - "nameEN": "Stone", - "icon": "stone.png", - "version": 0, - "idOld": "minecraft:stone[variant=stone]" - }, - { - "baseColor": 11, - "id": "minecraft:smooth_stone", - "nameZH": "平滑石头", - "nameEN": "Smooth stone", - "icon": "smooth_stone.png", - "version": 13 - }, - { - "baseColor": 11, - "id": "minecraft:stone_bricks", - "nameZH": "石砖", - "nameEN": "Stone brick", - "icon": "stone_bricks.png", - "version": 0, - "idOld": "minecraft:stonebrick[variant=stonebrick]" - }, - { - "baseColor": 12, - "id": "minecraft:water[level=0]", - "nameZH": "水", - "nameEN": "Water", - "icon": "water.png", - "version": 0, - "wallUseable": false - }, - { - "baseColor": 13, - "id": "minecraft:oak_planks", - "nameZH": "橡木木板", - "nameEN": "Oak plank", - "icon": "oak_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=oak]", - "burnable": true - }, - { - "baseColor": 14, - "id": "minecraft:quartz_block", - "nameZH": "石英块", - "nameEN": "Quartz block", - "icon": "quartz_block.png", - "version": 0, - "idOld": "minecraft:quartz_block[variant=default]" - }, - { - "baseColor": 14, - "id": "minecraft:sea_lantern", - "nameZH": "海晶灯", - "nameEN": "Sea lantern", - "icon": "sea_lantern.png", - "version": 0 - }, - { - "baseColor": 14, - "id": "minecraft:target[power=0]", - "nameZH": "标靶", - "nameEN": "Target", - "icon": "target.png", - "version": 16 - }, - { - "baseColor": 15, - "id": "minecraft:orange_concrete", - "nameZH": "橙色混凝土", - "nameEN": "Orange concrete", - "icon": "orange_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:orange_wool", - "nameZH": "橙色羊毛", - "nameEN": "Orange wool", - "icon": "orange_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:orange_stained_glass", - "nameZH": "橙色染色玻璃", - "nameEN": "Orange glass", - "icon": "orange_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=orange]" - }, - { - "baseColor": 15, - "id": "minecraft:acacia_planks", - "nameZH": "金合欢木板", - "nameEN": "Acacia plank", - "icon": "acacia_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=acacia]", - "burnable": true - }, - { - "baseColor": 15, - "id": "minecraft:pumpkin", - "nameZH": "南瓜", - "nameEN": "Pumpkin", - "icon": "pumpkin.png", - "version": 0, - "idOld": "minecraft:pumpkin[variant=north]", - "endermanPickable": true - }, - { - "baseColor": 15, - "id": "minecraft:terracotta", - "nameZH": "陶瓦", - "nameEN": "Terracotta", - "icon": "terracotta.png", - "version": 0, - "idOld": "minecraft:hardened_clay" - }, - { - "baseColor": 15, - "id": "minecraft:smooth_red_sandstone", - "nameZH": "平滑红砂岩", - "nameEN": "Smooth red sandstone", - "icon": "smooth_red_sandstone.png", - "version": 0, - "idOld": "minecraft:red_sandstone[type=smooth_red_sandstone]" - }, - { - "baseColor": 15, - "id": "minecraft:honey_block", - "nameZH": "蜂蜜块", - "nameEN": "Honey block", - "icon": "honey_block.png", - "version": 15 - }, - { - "baseColor": 15, - "id": "minecraft:honeycomb_block", - "nameZH": "蜜脾块", - "nameEN": "Honey comb block", - "icon": "honeycomb_block.png", - "version": 15 - }, - { - "baseColor": 15, - "id": "minecraft:raw_copper_block", - "nameZH": "粗铜块", - "nameEN": "Raw copper block", - "icon": "raw_copper_block.png", - "version": 17 - }, - { - "baseColor": 15, - "id": "minecraft:waxed_copper_block", - "nameZH": "涂蜡铜块", - "nameEN": "Waxed copper", - "icon": "waxed_copper_block.png", - "version": 17 - }, - { - "baseColor": 15, - "id": "minecraft:waxed_cut_copper", - "nameZH": "涂蜡切制铜块", - "nameEN": "Waxed cut copper", - "icon": "waxed_cut_copper.png", - "version": 17 - }, - { - "baseColor": 16, - "id": "minecraft:magenta_concrete", - "nameZH": "品红色混凝土", - "nameEN": "Magenta concrete", - "icon": "magenta_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:magenta_wool", - "nameZH": "品红色羊毛", - "nameEN": "Magenta wool", - "icon": "magenta_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:magenta_stained_glass", - "nameZH": "品红色染色玻璃", - "nameEN": "Magenta glass", - "icon": "magenta_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=magenta]" - }, - { - "baseColor": 16, - "id": "minecraft:purpur_block", - "nameZH": "紫珀块", - "nameEN": "Purpur block", - "icon": "purpur_block.png", - "version": 0 - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_concrete", - "nameZH": "淡蓝色混凝土", - "nameEN": "Light blue concrete", - "icon": "light_blue_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=light_blue]" - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_wool", - "nameZH": "淡蓝色羊毛", - "nameEN": "light blue wool", - "icon": "light_blue_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=light_blue]" - }, - { - "baseColor": 17, - "id": "minecraft:light_blue_stained_glass", - "nameZH": "淡蓝色染色玻璃", - "nameEN": "Light blue glass", - "icon": "light_blue_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=light_blue]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_concrete", - "nameZH": "黄色混凝土", - "nameEN": "Yellow concrete", - "icon": "yellow_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_wool", - "nameZH": "黄色羊毛", - "nameEN": "Yellow wool", - "icon": "yellow_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:yellow_stained_glass", - "nameZH": "黄色染色玻璃", - "nameEN": "yellow glass", - "icon": "yellow_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=yellow]" - }, - { - "baseColor": 18, - "id": "minecraft:hay_block[axis=y]", - "nameZH": "干草捆", - "nameEN": "Hay block", - "icon": "hay_block.png", - "version": 0 - }, - { - "baseColor": 19, - "id": "minecraft:lime_concrete", - "nameZH": "黄绿色混凝土", - "nameEN": "Lime concrete", - "icon": "lime_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=lime]" - }, - { - "baseColor": 19, - "id": "minecraft:lime_wool", - "nameZH": "黄绿色羊毛", - "nameEN": "Lime wool", - "icon": "lime_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=lime]" - }, - { - "baseColor": 19, - "id": "minecraft:lime_stained_glass", - "nameZH": "黄绿色染色玻璃", - "nameEN": "Lime glass", - "icon": "lime_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=lime]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_concrete", - "nameZH": "粉红色混凝土", - "nameEN": "Pink concrete", - "icon": "pink_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_wool", - "nameZH": "粉红色羊毛", - "nameEN": "Pink wool", - "icon": "pink_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pink_stained_glass", - "nameZH": "粉红色染色玻璃", - "nameEN": "Pink glass", - "icon": "pink_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=pink]" - }, - { - "baseColor": 20, - "id": "minecraft:pearlescent_froglight[axis=y]", - "nameZH": "珠光蛙明灯", - "nameEN": "Verdant Froglight", - "icon": "pearlescent_froglight_top.png", - "version": 19, - "isGlowing": true - }, - { - "baseColor": 21, - "id": "minecraft:gray_concrete", - "nameZH": "灰色混凝土", - "nameEN": "Gray concrete", - "icon": "gray_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=gray]" - }, - { - "baseColor": 21, - "id": "minecraft:gray_wool", - "nameZH": "灰色羊毛", - "nameEN": "Gray wool", - "icon": "gray_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=gray]", - "burnable": true - }, - { - "baseColor": 21, - "id": "minecraft:gray_stained_glass", - "nameZH": "灰色染色玻璃", - "nameEN": "Gray glass", - "icon": "gray_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=gray]" - }, - { - "baseColor": 21, - "id": "minecraft:tinted_glass", - "nameZH": "遮光玻璃", - "nameEN": "Tinted glass", - "icon": "tinted_glass.png", - "version": 17 - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_concrete", - "nameZH": "淡灰色混凝土", - "nameEN": "Light gray concrete", - "icon": "light_gray_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=silver]" - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_wool", - "nameZH": "淡灰色羊毛", - "nameEN": "Light gray wool", - "icon": "light_gray_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=silver]", - "burnable": true - }, - { - "baseColor": 22, - "id": "minecraft:light_gray_stained_glass", - "nameZH": "淡灰色染色玻璃", - "nameEN": "Light gray glass", - "icon": "light_gray_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=silver]" - }, - { - "baseColor": 23, - "id": "minecraft:cyan_concrete", - "nameZH": "青色混凝土", - "nameEN": "Cyan concrete", - "icon": "cyan_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=cyan]" - }, - { - "baseColor": 23, - "id": "minecraft:cyan_wool", - "nameZH": "青色羊毛", - "nameEN": "Cyan wool", - "icon": "cyan_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=cyan]", - "burnable": true - }, - { - "baseColor": 23, - "id": "minecraft:cyan_stained_glass", - "nameZH": "青色染色玻璃", - "nameEN": "Cyan glass", - "icon": "cyan_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=cyan]" - }, - { - "baseColor": 23, - "id": "minecraft:prismarine", - "nameZH": "海晶石", - "nameEN": "Prismarine", - "icon": "prismarine.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=prismarine]" - }, - { - "baseColor": 23, - "id": "minecraft:sculk_sensor[power=0,sculk_sensor_phase=inactive,waterlogged=false]", - "nameZH": "幽匿感测体", - "nameEN": "Sculk sensor", - "icon": "sculk_sensor_side.png", - "version": 19 - }, - { - "baseColor": 24, - "id": "minecraft:purple_concrete", - "nameZH": "紫色混凝土", - "nameEN": "Purple concrete", - "icon": "purple_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=purple]" - }, - { - "baseColor": 24, - "id": "minecraft:purple_wool", - "nameZH": "紫色羊毛", - "nameEN": "Purple wool", - "icon": "purple_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=purple]", - "burnable": true - }, - { - "baseColor": 24, - "id": "minecraft:purple_stained_glass", - "nameZH": "紫色染色玻璃", - "nameEN": "Purple glass", - "icon": "purple_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=purple]" - }, - { - "baseColor": 24, - "id": "minecraft:amethyst_block", - "nameZH": "紫水晶块", - "nameEN": "Amethyst block", - "icon": "amethyst_block.png", - "version": 17 - }, - { - "baseColor": 25, - "id": "minecraft:blue_concrete", - "nameZH": "蓝色混凝土", - "nameEN": "Blue concrete", - "icon": "blue_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=blue]" - }, - { - "baseColor": 25, - "id": "minecraft:blue_wool", - "nameZH": "蓝色羊毛", - "nameEN": "Blue wool", - "icon": "blue_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=blue]", - "burnable": true - }, - { - "baseColor": 25, - "id": "minecraft:blue_stained_glass", - "nameZH": "蓝色染色玻璃", - "nameEN": "Blue glass", - "icon": "blue_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=blue]" - }, - { - "baseColor": 26, - "id": "minecraft:brown_concrete", - "nameZH": "棕色混凝土", - "nameEN": "Brown concrete", - "icon": "brown_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=brown]" - }, - { - "baseColor": 26, - "id": "minecraft:brown_wool", - "nameZH": "棕色羊毛", - "nameEN": "Brown wool", - "icon": "brown_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=brown]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:brown_stained_glass", - "nameZH": "棕色染色玻璃", - "nameEN": "Brown glass", - "icon": "brown_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=brown]" - }, - { - "baseColor": 26, - "id": "minecraft:dark_oak_planks", - "nameZH": "深色橡木木板", - "nameEN": "Dark oak plank", - "icon": "dark_oak_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=dark_oak]", - "burnable": true - }, - { - "baseColor": 26, - "id": "minecraft:soul_sand", - "nameZH": "灵魂沙", - "nameEN": "Soul sand", - "icon": "soul_sand.png", - "version": 0 - }, - { - "baseColor": 26, - "id": "minecraft:soul_soil", - "nameZH": "灵魂土", - "nameEN": "Soul soil", - "icon": "soul_soil.png", - "version": 16 - }, - { - "baseColor": 27, - "id": "minecraft:green_concrete", - "nameZH": "绿色混凝土", - "nameEN": "Green concrete", - "icon": "green_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=green]" - }, - { - "baseColor": 27, - "id": "minecraft:green_wool", - "nameZH": "绿色羊毛", - "nameEN": "Green wool", - "icon": "green_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=green]", - "burnable": true - }, - { - "baseColor": 27, - "id": "minecraft:green_stained_glass", - "nameZH": "绿色染色玻璃", - "nameEN": "Green glass", - "icon": "green_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=green]" - }, - { - "baseColor": 27, - "id": "minecraft:dried_kelp_block", - "nameZH": "海带块", - "nameEN": "Kelp block", - "icon": "dried_kelp_block.png", - "version": 13 - }, - { - "baseColor": 28, - "id": "minecraft:red_concrete", - "nameZH": "红色混凝土", - "nameEN": "Red concrete", - "icon": "red_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=red]" - }, - { - "baseColor": 28, - "id": "minecraft:red_wool", - "nameZH": "红色羊毛", - "nameEN": "Red wool", - "icon": "red_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=red]", - "burnable": true - }, - { - "baseColor": 28, - "id": "minecraft:red_stained_glass", - "nameZH": "红色染色玻璃", - "nameEN": "Red glass", - "icon": "red_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=red]" - }, - { - "baseColor": 28, - "id": "minecraft:bricks", - "nameZH": "红砖块", - "nameEN": "Bricks", - "icon": "bricks.png", - "version": 0, - "idOld": "minecraft:brick_block" - }, - { - "baseColor": 28, - "id": "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", - "nameZH": "红色蘑菇方块", - "nameEN": "Red mushroom block", - "icon": "red_mushroom_block.png", - "version": 0, - "idOld": "minecraft:red_mushroom_block[variant=all_outside]", - "burnable": true - }, - { - "baseColor": 28, - "id": "minecraft:nether_wart_block", - "nameZH": "下界疣块", - "nameEN": "Nether wart block", - "icon": "nether_wart_block.png", - "version": 0 - }, - { - "baseColor": 28, - "id": "minecraft:shroomlight", - "nameZH": "菌光体", - "nameEN": "Shroomlight", - "icon": "shroomlight.png", - "version": 16, - "isGlowing": true - }, - { - "baseColor": 28, - "id": "minecraft:mangrove_planks", - "nameZH": "红树木板", - "nameEN": "Mangrove planks", - "icon": "mangrove_planks.png", - "version": 19, - "burnable": true - }, - { - "baseColor": 29, - "id": "minecraft:black_concrete", - "nameZH": "黑色混凝土", - "nameEN": "Black concrete", - "icon": "black_concrete.png", - "version": 0, - "idOld": "minecraft:concrete[color=black]" - }, - { - "baseColor": 29, - "id": "minecraft:black_wool", - "nameZH": "黑色羊毛", - "nameEN": "Black wool", - "icon": "black_wool.png", - "version": 0, - "idOld": "minecraft:wool[color=black]", - "burnable": true - }, - { - "baseColor": 29, - "id": "minecraft:black_stained_glass", - "nameZH": "黑色染色玻璃", - "nameEN": "Blakc glass", - "icon": "black_stained_glass.png", - "version": 0, - "idOld": "minecraft:stained_glass[color=black]" - }, - { - "baseColor": 29, - "id": "minecraft:obsidian", - "nameZH": "黑曜石", - "nameEN": "Obsidian", - "icon": "obsidian.png", - "version": 0 - }, - { - "baseColor": 29, - "id": "minecraft:coal_block", - "nameZH": "煤炭块", - "nameEN": "Coal block", - "icon": "coal_block.png", - "version": 0 - }, - { - "baseColor": 29, - "id": "minecraft:polished_basalt[axis=y]", - "nameZH": "磨制玄武岩", - "nameEN": "Polished basalt", - "icon": "polished_basalt.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:polished_blackstone", - "nameZH": "磨制黑石", - "nameEN": "Polished blackstone", - "icon": "polished_blackstone.png", - "version": 16 - }, - { - "baseColor": 29, - "id": "minecraft:sculk", - "nameZH": "幽匿块", - "nameEN": "Sculk block", - "icon": "sculk.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_catalyst[bloom=false]", - "nameZH": "幽匿催发体", - "nameEN": "Sculk catalyst", - "icon": "sculk_catalyst_top.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_shrieker[shrieking=false,waterlogged=false]", - "nameZH": "幽匿尖啸体", - "nameEN": "Sculk shrieker", - "icon": "sculk_shrieker_side.png", - "version": 19 - }, - { - "baseColor": 29, - "id": "minecraft:sculk_vein[down=true,east=false,north=false,south=false,up=false,waterlogged=false,west=false]", - "nameZH": "幽匿脉络", - "nameEN": "Sculk vein", - "icon": "sculk_vein.png", - "version": 19, - "needGlass": true - }, - { - "baseColor": 30, - "id": "minecraft:gold_block", - "nameZH": "金块", - "nameEN": "Gold block", - "icon": "gold_block.png", - "version": 0 - }, - { - "baseColor": 30, - "id": "minecraft:light_weighted_pressure_plate[power=0]", - "nameZH": "轻质测重压力板", - "nameEN": "Gold pressure plate", - "icon": "light_weighted_pressure_plate.png", - "version": 0, - "needGlass": true - }, - { - "baseColor": 30, - "id": "minecraft:raw_gold_block", - "nameZH": "粗金块", - "nameEN": "Raw gold block", - "icon": "raw_gold_block.png", - "version": 17 - }, - { - "baseColor": 31, - "id": "minecraft:diamond_block", - "nameZH": "钻石块", - "nameEN": "Diamond block", - "icon": "diamond_block.png", - "version": 0 - }, - { - "baseColor": 31, - "id": "minecraft:prismarine_bricks", - "nameZH": "海晶石砖", - "nameEN": "Prismarine bricks", - "icon": "prismarine_bricks.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=prismarine_bricks]" - }, - { - "baseColor": 31, - "id": "minecraft:dark_prismarine", - "nameZH": "暗海晶石", - "nameEN": "Dark prismarine", - "icon": "dark_prismarine.png", - "version": 0, - "idOld": "minecraft:prismarine[variant=dark_prismarine]" - }, - { - "baseColor": 32, - "id": "minecraft:lapis_block", - "nameZH": "青金石块", - "nameEN": "Lapis block", - "icon": "lapis_block.png", - "version": 0 - }, - { - "baseColor": 33, - "id": "minecraft:emerald_block", - "nameZH": "绿宝石块", - "nameEN": "Emerald block", - "icon": "emerald_block.png", - "version": 0 - }, - { - "baseColor": 34, - "id": "minecraft:podzol[snowy=false]", - "nameZH": "灰化土", - "nameEN": "Podzol", - "icon": "podzol.png", - "version": 0, - "idOld": "minecraft:dirt[variant=podzol,snowy=false]", - "endermanPickable": true - }, - { - "baseColor": 34, - "id": "minecraft:spruce_planks", - "nameZH": "云杉木板", - "nameEN": "Spruce plank", - "icon": "spruce_planks.png", - "version": 0, - "idOld": "minecraft:planks[variant=spruce]", - "burnable": true - }, - { - "baseColor": 34, - "id": "minecraft:campfire[facing=north,lit=true,signal_fire=false,waterlogged=false]", - "nameZH": "营火", - "nameEN": "Campfire", - "icon": "campfire.png", - "version": 14, - "isGlowing": true, - "wallUseable": false - }, - { - "baseColor": 35, - "id": "minecraft:netherrack", - "nameZH": "下界岩", - "nameEN": "Netherrack", - "icon": "netherrack.png", - "version": 0 - }, - { - "baseColor": 35, - "id": "minecraft:nether_bricks", - "nameZH": "下界砖块", - "nameEN": "Nether brick", - "icon": "nether_bricks.png", - "version": 0, - "idOld": "minecraft:nether_brick" - }, - { - "baseColor": 35, - "id": "minecraft:magma_block", - "nameZH": "岩浆块", - "nameEN": "Magma block", - "icon": "magma_block.png", - "version": 0, - "idOld": "minecraft:magma" - }, - { - "baseColor": 36, - "id": "minecraft:white_terracotta", - "nameZH": "白色陶瓦", - "nameEN": "White terracotta", - "icon": "white_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=white]" - }, - { - "baseColor": 36, - "id": "minecraft:calcite", - "nameZH": "方解石", - "nameEN": "Calcite", - "icon": "calcite.png", - "version": 17 - }, - { - "baseColor": 37, - "id": "minecraft:orange_terracotta", - "nameZH": "橙色陶瓦", - "nameEN": "Orange terracotta", - "icon": "orange_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=orange]" - }, - { - "baseColor": 38, - "id": "minecraft:magenta_terracotta", - "nameZH": "品红色陶瓦", - "nameEN": "Magenta terracotta", - "icon": "magenta_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=magenta]" - }, - { - "baseColor": 39, - "id": "minecraft:light_blue_terracotta", - "nameZH": "淡蓝色陶瓦", - "nameEN": "Light blue terracotta", - "icon": "light_blue_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=light_blue]" - }, - { - "baseColor": 40, - "id": "minecraft:yellow_terracotta", - "nameZH": "黄色陶瓦", - "nameEN": "Yellow terracotta", - "icon": "yellow_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=yellow]" - }, - { - "baseColor": 41, - "id": "minecraft:lime_terracotta", - "nameZH": "黄绿色陶瓦", - "nameEN": "Lime terracotta", - "icon": "lime_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=lime]" - }, - { - "baseColor": 42, - "id": "minecraft:pink_terracotta", - "nameZH": "粉红色陶瓦", - "nameEN": "Pink terracotta", - "icon": "pink_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=pink]" - }, - { - "baseColor": 43, - "id": "minecraft:gray_terracotta", - "nameZH": "灰色陶瓦", - "nameEN": "Gray terracotta", - "icon": "gray_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=gray]" - }, - { - "baseColor": 44, - "id": "minecraft:light_gray_terracotta", - "nameZH": "淡灰色陶瓦", - "nameEN": "Light gray terracotta", - "icon": "light_gray_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=silver]" - }, - { - "baseColor": 44, - "id": "minecraft:waxed_exposed_copper", - "nameZH": "斑驳的涂蜡铜块", - "nameEN": "Waxed exposed copper", - "icon": "waxed_exposed_copper.png", - "version": 17 - }, - { - "baseColor": 44, - "id": "minecraft:waxed_exposed_cut_copper", - "nameZH": "斑驳的涂蜡切制铜块", - "nameEN": "Waxed exposed cut copper", - "icon": "waxed_exposed_cut_copper.png", - "version": 17 - }, - { - "baseColor": 44, - "id": "minecraft:mud_bricks", - "nameZH": "泥砖", - "nameEN": "Mud bricks", - "icon": "mud_bricks.png", - "version": 19 - }, - { - "baseColor": 45, - "id": "minecraft:cyan_terracotta", - "nameZH": "青色陶瓦", - "nameEN": "Cyan terracotta", - "icon": "cyan_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=cyan]" - }, - { - "baseColor": 45, - "id": "minecraft:mud", - "nameZH": "泥巴", - "nameEN": "Mud", - "icon": "mud.png", - "version": 19 - }, - { - "baseColor": 46, - "id": "minecraft:purple_terracotta", - "nameZH": "紫色陶瓦", - "nameEN": "Purple terracotta", - "icon": "purple_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=purple]" - }, - { - "baseColor": 47, - "id": "minecraft:blue_terracotta", - "nameZH": "蓝色陶瓦", - "nameEN": "Blue terracotta", - "icon": "blue_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=blue]" - }, - { - "baseColor": 48, - "id": "minecraft:brown_terracotta", - "nameZH": "棕色陶瓦", - "nameEN": "Brown terracotta", - "icon": "brown_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=brown]" - }, - { - "baseColor": 48, - "id": "minecraft:dripstone_block", - "nameZH": "滴水石块", - "nameEN": "DripStone Block", - "icon": "dripstone_block.png", - "version": 17 - }, - { - "baseColor": 49, - "id": "minecraft:green_terracotta", - "nameZH": "绿色陶瓦", - "nameEN": "Green terracotta", - "icon": "green_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=green]" - }, - { - "baseColor": 50, - "id": "minecraft:red_terracotta", - "nameZH": "红色陶瓦", - "nameEN": "Red terracotta", - "icon": "red_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=red]" - }, - { - "baseColor": 51, - "id": "minecraft:black_terracotta", - "nameZH": "黑色陶瓦", - "nameEN": "Black terracotta", - "icon": "black_terracotta.png", - "version": 0, - "idOld": "minecraft:stained_hardened_clay[color=black]" - }, - { - "baseColor": 52, - "id": "minecraft:crimson_nylium", - "nameZH": "绯红菌岩", - "nameEN": "Crimson nylium", - "icon": "crimson_nylium.png", - "version": 16, - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 53, - "id": "minecraft:crimson_planks", - "nameZH": "绯红木板", - "nameEN": "Crimson plank", - "icon": "crimson_planks.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 53, - "id": "minecraft:stripped_crimson_stem[axis=y]", - "nameZH": "去皮绯红菌柄", - "nameEN": "Stripped crimson log", - "icon": "stripped_crimson_stem.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 54, - "id": "minecraft:crimson_hyphae[axis=y]", - "nameZH": "绯红菌核", - "nameEN": "Crimson hyphae", - "icon": "crimson_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 54, - "id": "minecraft:stripped_crimson_hyphae[axis=y]", - "nameZH": "去皮绯红菌核", - "nameEN": "Stripped crimson hyphae", - "icon": "stripped_crimson_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 55, - "id": "minecraft:warped_nylium", - "nameZH": "诡异菌岩", - "nameEN": "Warped nylium", - "icon": "warped_nylium.png", - "version": 16, - "endermanPickable": true, - "wallUseable": false - }, - { - "baseColor": 55, - "id": "minecraft:waxed_oxidized_copper", - "nameZH": "氧化的涂蜡铜块", - "nameEN": "Waxed oxided copper", - "icon": "waxed_oxidized_copper.png", - "version": 17 - }, - { - "baseColor": 55, - "id": "minecraft:waxed_oxidized_cut_copper", - "nameZH": "氧化的涂蜡切制铜块", - "nameEN": "Waxed oxided cut copper", - "icon": "waxed_oxidized_cut_copper.png", - "version": 17 - }, - { - "baseColor": 56, - "id": "minecraft:warped_planks", - "nameZH": "诡异木板", - "nameEN": "Warped plank", - "icon": "warped_planks.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 56, - "id": "minecraft:stripped_warped_stem[axis=y]", - "nameZH": "去皮诡异菌柄", - "nameEN": "Stripped warped log", - "icon": "stripped_warped_stem.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 56, - "id": "minecraft:waxed_weathered_copper", - "nameZH": "锈蚀的涂蜡铜块", - "nameEN": "Waxed weathered copper", - "icon": "waxed_weathered_copper.png", - "version": 17 - }, - { - "baseColor": 56, - "id": "minecraft:waxed_weathered_cut_copper", - "nameZH": "锈蚀的涂蜡切制铜块", - "nameEN": "Waxed weathered cut copper", - "icon": "waxed_weathered_cut_copper.png", - "version": 17 - }, - { - "baseColor": 57, - "id": "minecraft:warped_hyphae[axis=y]", - "nameZH": "诡异菌核", - "nameEN": "Warped hyphae", - "icon": "warped_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 57, - "id": "minecraft:stripped_warped_hyphae[axis=y]", - "nameZH": "去皮诡异菌核", - "nameEN": "Stripped warped hyphae", - "icon": "stripped_warped_hyphae.png", - "version": 16, - "burnable": true - }, - { - "baseColor": 58, - "id": "minecraft:warped_wart_block", - "nameZH": "诡异疣块", - "nameEN": "Warped wart block", - "icon": "warped_wart_block.png", - "version": 16 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate", - "nameZH": "深板岩", - "nameEN": "Deepslate", - "icon": "deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:chiseled_deepslate", - "nameZH": "雕纹深板岩", - "nameEN": "Chiseled deepslate", - "icon": "chiseled_deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:polished_deepslate", - "nameZH": "磨制深板岩", - "nameEN": "Polished deepslate", - "icon": "polished_deepslate.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_bricks", - "nameZH": "深板岩砖", - "nameEN": "Deepslate bricks", - "icon": "deepslate_bricks.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:deepslate_tiles", - "nameZH": "深板岩瓦", - "nameEN": "Deepslate tiles", - "icon": "deepslate_tiles.png", - "version": 17 - }, - { - "baseColor": 59, - "id": "minecraft:cobbled_deepslate", - "nameZH": "深板岩圆石", - "nameEN": "Cobbled deepslate", - "icon": "cobbled_deepslate.png", - "version": 17 - }, - { - "baseColor": 60, - "id": "minecraft:raw_iron_block", - "nameZH": "粗铁块", - "nameEN": "Raw iron block", - "icon": "raw_iron_block.png", - "version": 17 - }, - { - "baseColor": 61, - "id": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", - "nameZH": "发光地衣", - "nameEN": "Glow lichen", - "icon": "glow_lichen.png", - "version": 17, - "needGlass": true, - "isGlowing": true, - "burnable": true, - "wallUseable": false - }, - { - "baseColor": 61, - "id": "minecraft:verdant_froglight[axis=y]", - "nameZH": "青翠蛙明灯", - "nameEN": "Verdant Froglight", - "icon": "verdant_froglight_top.png", - "version": 19, - "isGlowing": true - }, - { - "baseColor": 43, - "id": "minecraft:cherry_wood", - "nameZH": "樱花木头", - "nameEN": "Cherry wood", - "icon": "cherry_log.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 36, - "id": "minecraft:cherry_planks", - "nameZH": "樱花木板", - "nameEN": "Cherry planks", - "icon": "cherry_planks.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 42, - "id": "minecraft:stripped_cherry_wood[axis=y]", - "nameZH": "去皮樱花木头", - "nameEN": "Stripped cherry wood", - "icon": "stripped_cherry_log.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 18, - "id": "minecraft:bamboo_planks", - "nameZH": "竹板", - "nameEN": "Bamboo planks", - "icon": "bamboo_planks.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 18, - "id": "minecraft:bamboo_block[axis=x]", - "nameZH": "竹块(侧面)", - "nameEN": "Bamboo block(axis=x)", - "icon": "bamboo_block.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 20, - "id": "minecraft:cherry_leaves[persistent=true]", - "nameZH": "樱花树叶", - "nameEN": "Cherry leaves", - "icon": "cherry_leaves.png", - "version": 20, - "burnable": true - }, - { - "baseColor": 50, - "id": "minecraft:decorated_pot", - "nameZH": "陶罐", - "nameEN": "Decorated pot", - "icon": "burn_pottery_pattern.png", - "version": 20 - } - ] -} \ No newline at end of file diff --git a/Blocks/FixedBlocks/BlockList.json b/Blocks/FixedBlocks/BlockList.json new file mode 100644 index 00000000..f4816d9d --- /dev/null +++ b/Blocks/FixedBlocks/BlockList.json @@ -0,0 +1,1714 @@ +[ + { + "baseColor": 0, + "id": "minecraft:glass", + "nameZH": "玻璃", + "nameEN": "Glass", + "icon": "glass.png", + "version": 0 + }, + { + "baseColor": 1, + "id": "minecraft:grass_block[snowy=false]", + "nameZH": "草方块", + "nameEN": "Grass block", + "icon": "grass_block.png", + "version": 0, + "idOld": "minecraft:grass[snowy=false]", + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 1, + "id": "minecraft:slime_block", + "nameZH": "黏液块", + "nameEN": "Slime block", + "icon": "slime_block.png", + "version": 0, + "idOld": "minecraft:slime" + }, + { + "baseColor": 2, + "id": "minecraft:birch_planks", + "nameZH": "白桦木板", + "nameEN": "Birch plank", + "icon": "birch_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=birch]", + "burnable": true + }, + { + "baseColor": 2, + "id": "minecraft:smooth_sandstone", + "nameZH": "平滑砂岩", + "nameEN": "Smooth sandstone", + "icon": "smooth_sandstone.png", + "version": 0, + "idOld": "minecraft:sandstone[type=smooth_sandstone]" + }, + { + "baseColor": 2, + "id": "minecraft:glowstone", + "nameZH": "荧石", + "nameEN": "Glowstone", + "icon": "glowstone.png", + "version": 0, + "isGlowing": true + }, + { + "baseColor": 2, + "id": "minecraft:end_stone", + "nameZH": "末地石", + "nameEN": "End stone", + "icon": "end_stone.png", + "version": 0 + }, + { + "baseColor": 2, + "id": "minecraft:end_stone_bricks", + "nameZH": "末地石砖", + "nameEN": "Endstone bricks", + "icon": "end_stone_bricks.png", + "version": 0, + "idOld": "minecraft:end_bricks" + }, + { + "baseColor": 2, + "id": "minecraft:turtle_egg[eggs=4,hatch=0]", + "nameZH": "海龟蛋", + "nameEN": "Turtle egg", + "icon": "turtle_egg.png", + "version": 13, + "needGlass": true, + "wallUseable": false + }, + { + "baseColor": 2, + "id": "minecraft:ochre_froglight[axis=y]", + "nameZH": "赭黄蛙明灯", + "nameEN": "Ochre Froglight", + "icon": "ochre_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 3, + "id": "minecraft:mushroom_stem[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "蘑菇柄", + "nameEN": "Mushroom stem", + "icon": "mushroom_stem.png", + "version": 13, + "burnable": true + }, + { + "baseColor": 3, + "id": "minecraft:cobweb", + "nameZH": "蜘蛛网", + "nameEN": "Cobweb", + "icon": "cobweb.png", + "version": 0, + "idOld": "minecraft:web" + }, + { + "baseColor": 4, + "id": "minecraft:redstone_block", + "nameZH": "红石块", + "nameEN": "Redstone block", + "icon": "redstone_block.png", + "version": 0 + }, + { + "baseColor": 4, + "id": "minecraft:tnt[unstable=false]", + "nameZH": "TNT", + "nameEN": "TNT", + "icon": "tnt.png", + "version": 0, + "idOld": "minecraft:tnt[explode=false]", + "endermanPickable": true, + "burnable": true + }, + { + "baseColor": 5, + "id": "minecraft:ice", + "nameZH": "冰", + "nameEN": "Ice", + "icon": "ice.png", + "version": 0 + }, + { + "baseColor": 5, + "id": "minecraft:packed_ice", + "nameZH": "浮冰", + "nameEN": "Packed ice", + "icon": "packed_ice.png", + "version": 0 + }, + { + "baseColor": 5, + "id": "minecraft:blue_ice", + "nameZH": "蓝冰", + "nameEN": "Blue ice", + "icon": "blue_ice.png", + "version": 13 + }, + { + "baseColor": 6, + "id": "minecraft:iron_block", + "nameZH": "铁块", + "nameEN": "Iron block", + "icon": "iron_block.png", + "version": 0 + }, + { + "baseColor": 6, + "id": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", + "nameZH": "酿造台", + "nameEN": "brewing stand", + "icon": "brewing_stand.png", + "version": 0, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:heavy_weighted_pressure_plate[power=0]", + "nameZH": "重质测重压力板", + "nameEN": "Iron pressure plate", + "icon": "heavy_weighted_pressure_plate.png", + "version": 0, + "needGlass": true, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:iron_trapdoor[facing=north,half=top,open=false,powered=false,waterlogged=false]", + "nameZH": "铁活板门", + "nameEN": "Iron trapdoor", + "icon": "iron_trapdoor.png", + "version": 0, + "idOld": "minecraft:iron_trapdoor[facing=north,half=top,open=false]", + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:lantern[hanging=false]", + "nameZH": "灯笼", + "nameEN": "lantern", + "icon": "lantern.png", + "version": 14, + "wallUseable": false + }, + { + "baseColor": 6, + "id": "minecraft:grindstone[face=floor,facing=north]", + "nameZH": "砂轮", + "nameEN": "Grindstone", + "icon": "grindstone.png", + "version": 14, + "wallUseable": false + }, + { + "baseColor": 7, + "id": "minecraft:oak_leaves[distance=7,persistent=true]", + "nameZH": "橡树树叶", + "nameEN": "Oak leaves", + "icon": "oak_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=oak,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:spruce_leaves[distance=7,persistent=true]", + "nameZH": "云杉树叶", + "nameEN": "Spurce leaves", + "icon": "spruce_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=spruce,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:birch_leaves[distance=7,persistent=true]", + "nameZH": "白桦树叶", + "nameEN": "Brich leaves", + "icon": "birch_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:jungle_leaves[distance=7,persistent=true]", + "nameZH": "丛林树叶", + "nameEN": "Jungle leaves", + "icon": "jungle_leaves.png", + "version": 0, + "idOld": "minecraft:leaves[variant=jungle,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:acacia_leaves[distance=7,persistent=true]", + "nameZH": "金合欢树叶", + "nameEN": "Acacia leaves", + "icon": "acacia_leaves.png", + "version": 0, + "idOld": "minecraft:leaves2[variant=acacia,check_decay=false,decayable=false]" + }, + { + "baseColor": 7, + "id": "minecraft:dark_oak_leaves[distance=7,persistent=true]", + "nameZH": "深色橡树树叶", + "nameEN": "Dark oat leaves", + "icon": "dark_oak_leaves.png", + "version": 0, + "idOld": "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" + }, + { + "baseColor": 8, + "id": "minecraft:white_concrete", + "nameZH": "白色混凝土", + "nameEN": "White concrete", + "icon": "white_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:white_wool", + "nameZH": "白色羊毛", + "nameEN": "White wool", + "icon": "white_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:white_stained_glass", + "nameZH": "白色染色玻璃", + "nameEN": "White glass", + "icon": "white_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=white]" + }, + { + "baseColor": 8, + "id": "minecraft:snow_block", + "nameZH": "雪块", + "nameEN": "Snow", + "icon": "snow_block.png", + "version": 0, + "idOld": "minecraft:snow" + }, + { + "baseColor": 9, + "id": "minecraft:clay", + "nameZH": "黏土块", + "nameEN": "Clay block", + "icon": "clay.png", + "version": 0, + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:coarse_dirt", + "nameZH": "砂土", + "nameEN": "Coarse dirt", + "icon": "coarse_dirt.png", + "version": 13, + "idOld": "minecraft:dirt[variant=coarse_dirt,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:jungle_planks", + "nameZH": "丛林木板", + "nameEN": "Jungle plank", + "icon": "jungle_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=jungle]", + "burnable": true + }, + { + "baseColor": 10, + "id": "minecraft:brown_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "棕色蘑菇方块", + "nameEN": "Brown mushroom block", + "icon": "brown_mushroom_block.png", + "version": 0, + "idOld": "minecraft:brown_mushroom_block[variant=all_outside]" + }, + { + "baseColor": 10, + "id": "minecraft:dirt", + "nameZH": "泥土", + "nameEN": "Dirt", + "icon": "dirt.png", + "version": 0, + "idOld": "minecraft:dirt[variant=dirt,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 10, + "id": "minecraft:packed_mud", + "nameZH": "泥坯", + "nameEN": "Packed mud", + "icon": "packed_mud.png", + "version": 19 + }, + { + "baseColor": 11, + "id": "minecraft:cobblestone", + "nameZH": "圆石", + "nameEN": "Cobblestone", + "icon": "cobblestone.png", + "version": 0 + }, + { + "baseColor": 11, + "id": "minecraft:stone", + "nameZH": "石头", + "nameEN": "Stone", + "icon": "stone.png", + "version": 0, + "idOld": "minecraft:stone[variant=stone]" + }, + { + "baseColor": 11, + "id": "minecraft:smooth_stone", + "nameZH": "平滑石头", + "nameEN": "Smooth stone", + "icon": "smooth_stone.png", + "version": 13 + }, + { + "baseColor": 11, + "id": "minecraft:stone_bricks", + "nameZH": "石砖", + "nameEN": "Stone brick", + "icon": "stone_bricks.png", + "version": 0, + "idOld": "minecraft:stonebrick[variant=stonebrick]" + }, + { + "baseColor": 12, + "id": "minecraft:water[level=0]", + "nameZH": "水", + "nameEN": "Water", + "icon": "water.png", + "version": 0, + "wallUseable": false + }, + { + "baseColor": 13, + "id": "minecraft:oak_planks", + "nameZH": "橡木木板", + "nameEN": "Oak plank", + "icon": "oak_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=oak]", + "burnable": true + }, + { + "baseColor": 14, + "id": "minecraft:quartz_block", + "nameZH": "石英块", + "nameEN": "Quartz block", + "icon": "quartz_block.png", + "version": 0, + "idOld": "minecraft:quartz_block[variant=default]" + }, + { + "baseColor": 14, + "id": "minecraft:sea_lantern", + "nameZH": "海晶灯", + "nameEN": "Sea lantern", + "icon": "sea_lantern.png", + "version": 0 + }, + { + "baseColor": 14, + "id": "minecraft:target[power=0]", + "nameZH": "标靶", + "nameEN": "Target", + "icon": "target.png", + "version": 16 + }, + { + "baseColor": 15, + "id": "minecraft:orange_concrete", + "nameZH": "橙色混凝土", + "nameEN": "Orange concrete", + "icon": "orange_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:orange_wool", + "nameZH": "橙色羊毛", + "nameEN": "Orange wool", + "icon": "orange_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:orange_stained_glass", + "nameZH": "橙色染色玻璃", + "nameEN": "Orange glass", + "icon": "orange_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=orange]" + }, + { + "baseColor": 15, + "id": "minecraft:acacia_planks", + "nameZH": "金合欢木板", + "nameEN": "Acacia plank", + "icon": "acacia_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=acacia]", + "burnable": true + }, + { + "baseColor": 15, + "id": "minecraft:pumpkin", + "nameZH": "南瓜", + "nameEN": "Pumpkin", + "icon": "pumpkin.png", + "version": 0, + "idOld": "minecraft:pumpkin[variant=north]", + "endermanPickable": true + }, + { + "baseColor": 15, + "id": "minecraft:terracotta", + "nameZH": "陶瓦", + "nameEN": "Terracotta", + "icon": "terracotta.png", + "version": 0, + "idOld": "minecraft:hardened_clay" + }, + { + "baseColor": 15, + "id": "minecraft:smooth_red_sandstone", + "nameZH": "平滑红砂岩", + "nameEN": "Smooth red sandstone", + "icon": "smooth_red_sandstone.png", + "version": 0, + "idOld": "minecraft:red_sandstone[type=smooth_red_sandstone]" + }, + { + "baseColor": 15, + "id": "minecraft:honey_block", + "nameZH": "蜂蜜块", + "nameEN": "Honey block", + "icon": "honey_block.png", + "version": 15 + }, + { + "baseColor": 15, + "id": "minecraft:honeycomb_block", + "nameZH": "蜜脾块", + "nameEN": "Honey comb block", + "icon": "honeycomb_block.png", + "version": 15 + }, + { + "baseColor": 15, + "id": "minecraft:raw_copper_block", + "nameZH": "粗铜块", + "nameEN": "Raw copper block", + "icon": "raw_copper_block.png", + "version": 17 + }, + { + "baseColor": 15, + "id": "minecraft:waxed_copper_block", + "nameZH": "涂蜡铜块", + "nameEN": "Waxed copper", + "icon": "waxed_copper_block.png", + "version": 17 + }, + { + "baseColor": 15, + "id": "minecraft:waxed_cut_copper", + "nameZH": "涂蜡切制铜块", + "nameEN": "Waxed cut copper", + "icon": "waxed_cut_copper.png", + "version": 17 + }, + { + "baseColor": 16, + "id": "minecraft:magenta_concrete", + "nameZH": "品红色混凝土", + "nameEN": "Magenta concrete", + "icon": "magenta_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:magenta_wool", + "nameZH": "品红色羊毛", + "nameEN": "Magenta wool", + "icon": "magenta_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:magenta_stained_glass", + "nameZH": "品红色染色玻璃", + "nameEN": "Magenta glass", + "icon": "magenta_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=magenta]" + }, + { + "baseColor": 16, + "id": "minecraft:purpur_block", + "nameZH": "紫珀块", + "nameEN": "Purpur block", + "icon": "purpur_block.png", + "version": 0 + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_concrete", + "nameZH": "淡蓝色混凝土", + "nameEN": "Light blue concrete", + "icon": "light_blue_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=light_blue]" + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_wool", + "nameZH": "淡蓝色羊毛", + "nameEN": "light blue wool", + "icon": "light_blue_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=light_blue]" + }, + { + "baseColor": 17, + "id": "minecraft:light_blue_stained_glass", + "nameZH": "淡蓝色染色玻璃", + "nameEN": "Light blue glass", + "icon": "light_blue_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=light_blue]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_concrete", + "nameZH": "黄色混凝土", + "nameEN": "Yellow concrete", + "icon": "yellow_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_wool", + "nameZH": "黄色羊毛", + "nameEN": "Yellow wool", + "icon": "yellow_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:yellow_stained_glass", + "nameZH": "黄色染色玻璃", + "nameEN": "yellow glass", + "icon": "yellow_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=yellow]" + }, + { + "baseColor": 18, + "id": "minecraft:hay_block[axis=y]", + "nameZH": "干草捆", + "nameEN": "Hay block", + "icon": "hay_block.png", + "version": 0 + }, + { + "baseColor": 19, + "id": "minecraft:lime_concrete", + "nameZH": "黄绿色混凝土", + "nameEN": "Lime concrete", + "icon": "lime_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=lime]" + }, + { + "baseColor": 19, + "id": "minecraft:lime_wool", + "nameZH": "黄绿色羊毛", + "nameEN": "Lime wool", + "icon": "lime_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=lime]" + }, + { + "baseColor": 19, + "id": "minecraft:lime_stained_glass", + "nameZH": "黄绿色染色玻璃", + "nameEN": "Lime glass", + "icon": "lime_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=lime]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_concrete", + "nameZH": "粉红色混凝土", + "nameEN": "Pink concrete", + "icon": "pink_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_wool", + "nameZH": "粉红色羊毛", + "nameEN": "Pink wool", + "icon": "pink_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pink_stained_glass", + "nameZH": "粉红色染色玻璃", + "nameEN": "Pink glass", + "icon": "pink_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=pink]" + }, + { + "baseColor": 20, + "id": "minecraft:pearlescent_froglight[axis=y]", + "nameZH": "珠光蛙明灯", + "nameEN": "Verdant Froglight", + "icon": "pearlescent_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 21, + "id": "minecraft:gray_concrete", + "nameZH": "灰色混凝土", + "nameEN": "Gray concrete", + "icon": "gray_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=gray]" + }, + { + "baseColor": 21, + "id": "minecraft:gray_wool", + "nameZH": "灰色羊毛", + "nameEN": "Gray wool", + "icon": "gray_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=gray]", + "burnable": true + }, + { + "baseColor": 21, + "id": "minecraft:gray_stained_glass", + "nameZH": "灰色染色玻璃", + "nameEN": "Gray glass", + "icon": "gray_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=gray]" + }, + { + "baseColor": 21, + "id": "minecraft:tinted_glass", + "nameZH": "遮光玻璃", + "nameEN": "Tinted glass", + "icon": "tinted_glass.png", + "version": 17 + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_concrete", + "nameZH": "淡灰色混凝土", + "nameEN": "Light gray concrete", + "icon": "light_gray_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=silver]" + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_wool", + "nameZH": "淡灰色羊毛", + "nameEN": "Light gray wool", + "icon": "light_gray_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=silver]", + "burnable": true + }, + { + "baseColor": 22, + "id": "minecraft:light_gray_stained_glass", + "nameZH": "淡灰色染色玻璃", + "nameEN": "Light gray glass", + "icon": "light_gray_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=silver]" + }, + { + "baseColor": 23, + "id": "minecraft:cyan_concrete", + "nameZH": "青色混凝土", + "nameEN": "Cyan concrete", + "icon": "cyan_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=cyan]" + }, + { + "baseColor": 23, + "id": "minecraft:cyan_wool", + "nameZH": "青色羊毛", + "nameEN": "Cyan wool", + "icon": "cyan_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=cyan]", + "burnable": true + }, + { + "baseColor": 23, + "id": "minecraft:cyan_stained_glass", + "nameZH": "青色染色玻璃", + "nameEN": "Cyan glass", + "icon": "cyan_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=cyan]" + }, + { + "baseColor": 23, + "id": "minecraft:prismarine", + "nameZH": "海晶石", + "nameEN": "Prismarine", + "icon": "prismarine.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=prismarine]" + }, + { + "baseColor": 23, + "id": "minecraft:sculk_sensor[power=0,sculk_sensor_phase=inactive,waterlogged=false]", + "nameZH": "幽匿感测体", + "nameEN": "Sculk sensor", + "icon": "sculk_sensor_side.png", + "version": 19 + }, + { + "baseColor": 24, + "id": "minecraft:purple_concrete", + "nameZH": "紫色混凝土", + "nameEN": "Purple concrete", + "icon": "purple_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=purple]" + }, + { + "baseColor": 24, + "id": "minecraft:purple_wool", + "nameZH": "紫色羊毛", + "nameEN": "Purple wool", + "icon": "purple_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=purple]", + "burnable": true + }, + { + "baseColor": 24, + "id": "minecraft:purple_stained_glass", + "nameZH": "紫色染色玻璃", + "nameEN": "Purple glass", + "icon": "purple_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=purple]" + }, + { + "baseColor": 24, + "id": "minecraft:amethyst_block", + "nameZH": "紫水晶块", + "nameEN": "Amethyst block", + "icon": "amethyst_block.png", + "version": 17 + }, + { + "baseColor": 25, + "id": "minecraft:blue_concrete", + "nameZH": "蓝色混凝土", + "nameEN": "Blue concrete", + "icon": "blue_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=blue]" + }, + { + "baseColor": 25, + "id": "minecraft:blue_wool", + "nameZH": "蓝色羊毛", + "nameEN": "Blue wool", + "icon": "blue_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=blue]", + "burnable": true + }, + { + "baseColor": 25, + "id": "minecraft:blue_stained_glass", + "nameZH": "蓝色染色玻璃", + "nameEN": "Blue glass", + "icon": "blue_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=blue]" + }, + { + "baseColor": 26, + "id": "minecraft:brown_concrete", + "nameZH": "棕色混凝土", + "nameEN": "Brown concrete", + "icon": "brown_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=brown]" + }, + { + "baseColor": 26, + "id": "minecraft:brown_wool", + "nameZH": "棕色羊毛", + "nameEN": "Brown wool", + "icon": "brown_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=brown]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:brown_stained_glass", + "nameZH": "棕色染色玻璃", + "nameEN": "Brown glass", + "icon": "brown_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=brown]" + }, + { + "baseColor": 26, + "id": "minecraft:dark_oak_planks", + "nameZH": "深色橡木木板", + "nameEN": "Dark oak plank", + "icon": "dark_oak_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=dark_oak]", + "burnable": true + }, + { + "baseColor": 26, + "id": "minecraft:soul_sand", + "nameZH": "灵魂沙", + "nameEN": "Soul sand", + "icon": "soul_sand.png", + "version": 0 + }, + { + "baseColor": 26, + "id": "minecraft:soul_soil", + "nameZH": "灵魂土", + "nameEN": "Soul soil", + "icon": "soul_soil.png", + "version": 16 + }, + { + "baseColor": 27, + "id": "minecraft:green_concrete", + "nameZH": "绿色混凝土", + "nameEN": "Green concrete", + "icon": "green_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=green]" + }, + { + "baseColor": 27, + "id": "minecraft:green_wool", + "nameZH": "绿色羊毛", + "nameEN": "Green wool", + "icon": "green_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=green]", + "burnable": true + }, + { + "baseColor": 27, + "id": "minecraft:green_stained_glass", + "nameZH": "绿色染色玻璃", + "nameEN": "Green glass", + "icon": "green_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=green]" + }, + { + "baseColor": 27, + "id": "minecraft:dried_kelp_block", + "nameZH": "海带块", + "nameEN": "Kelp block", + "icon": "dried_kelp_block.png", + "version": 13 + }, + { + "baseColor": 28, + "id": "minecraft:red_concrete", + "nameZH": "红色混凝土", + "nameEN": "Red concrete", + "icon": "red_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=red]" + }, + { + "baseColor": 28, + "id": "minecraft:red_wool", + "nameZH": "红色羊毛", + "nameEN": "Red wool", + "icon": "red_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=red]", + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:red_stained_glass", + "nameZH": "红色染色玻璃", + "nameEN": "Red glass", + "icon": "red_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=red]" + }, + { + "baseColor": 28, + "id": "minecraft:bricks", + "nameZH": "红砖块", + "nameEN": "Bricks", + "icon": "bricks.png", + "version": 0, + "idOld": "minecraft:brick_block" + }, + { + "baseColor": 28, + "id": "minecraft:red_mushroom_block[east=true,west=true,north=true,south=true,up=true,down=true]", + "nameZH": "红色蘑菇方块", + "nameEN": "Red mushroom block", + "icon": "red_mushroom_block.png", + "version": 0, + "idOld": "minecraft:red_mushroom_block[variant=all_outside]", + "burnable": true + }, + { + "baseColor": 28, + "id": "minecraft:nether_wart_block", + "nameZH": "下界疣块", + "nameEN": "Nether wart block", + "icon": "nether_wart_block.png", + "version": 0 + }, + { + "baseColor": 28, + "id": "minecraft:shroomlight", + "nameZH": "菌光体", + "nameEN": "Shroomlight", + "icon": "shroomlight.png", + "version": 16, + "isGlowing": true + }, + { + "baseColor": 28, + "id": "minecraft:mangrove_planks", + "nameZH": "红树木板", + "nameEN": "Mangrove planks", + "icon": "mangrove_planks.png", + "version": 19, + "burnable": true + }, + { + "baseColor": 29, + "id": "minecraft:black_concrete", + "nameZH": "黑色混凝土", + "nameEN": "Black concrete", + "icon": "black_concrete.png", + "version": 0, + "idOld": "minecraft:concrete[color=black]" + }, + { + "baseColor": 29, + "id": "minecraft:black_wool", + "nameZH": "黑色羊毛", + "nameEN": "Black wool", + "icon": "black_wool.png", + "version": 0, + "idOld": "minecraft:wool[color=black]", + "burnable": true + }, + { + "baseColor": 29, + "id": "minecraft:black_stained_glass", + "nameZH": "黑色染色玻璃", + "nameEN": "Blakc glass", + "icon": "black_stained_glass.png", + "version": 0, + "idOld": "minecraft:stained_glass[color=black]" + }, + { + "baseColor": 29, + "id": "minecraft:obsidian", + "nameZH": "黑曜石", + "nameEN": "Obsidian", + "icon": "obsidian.png", + "version": 0 + }, + { + "baseColor": 29, + "id": "minecraft:coal_block", + "nameZH": "煤炭块", + "nameEN": "Coal block", + "icon": "coal_block.png", + "version": 0 + }, + { + "baseColor": 29, + "id": "minecraft:polished_basalt[axis=y]", + "nameZH": "磨制玄武岩", + "nameEN": "Polished basalt", + "icon": "polished_basalt.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:polished_blackstone", + "nameZH": "磨制黑石", + "nameEN": "Polished blackstone", + "icon": "polished_blackstone.png", + "version": 16 + }, + { + "baseColor": 29, + "id": "minecraft:sculk", + "nameZH": "幽匿块", + "nameEN": "Sculk block", + "icon": "sculk.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_catalyst[bloom=false]", + "nameZH": "幽匿催发体", + "nameEN": "Sculk catalyst", + "icon": "sculk_catalyst_top.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_shrieker[shrieking=false,waterlogged=false]", + "nameZH": "幽匿尖啸体", + "nameEN": "Sculk shrieker", + "icon": "sculk_shrieker_side.png", + "version": 19 + }, + { + "baseColor": 29, + "id": "minecraft:sculk_vein[down=true,east=false,north=false,south=false,up=false,waterlogged=false,west=false]", + "nameZH": "幽匿脉络", + "nameEN": "Sculk vein", + "icon": "sculk_vein.png", + "version": 19, + "needGlass": true + }, + { + "baseColor": 30, + "id": "minecraft:gold_block", + "nameZH": "金块", + "nameEN": "Gold block", + "icon": "gold_block.png", + "version": 0 + }, + { + "baseColor": 30, + "id": "minecraft:light_weighted_pressure_plate[power=0]", + "nameZH": "轻质测重压力板", + "nameEN": "Gold pressure plate", + "icon": "light_weighted_pressure_plate.png", + "version": 0, + "needGlass": true + }, + { + "baseColor": 30, + "id": "minecraft:raw_gold_block", + "nameZH": "粗金块", + "nameEN": "Raw gold block", + "icon": "raw_gold_block.png", + "version": 17 + }, + { + "baseColor": 31, + "id": "minecraft:diamond_block", + "nameZH": "钻石块", + "nameEN": "Diamond block", + "icon": "diamond_block.png", + "version": 0 + }, + { + "baseColor": 31, + "id": "minecraft:prismarine_bricks", + "nameZH": "海晶石砖", + "nameEN": "Prismarine bricks", + "icon": "prismarine_bricks.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=prismarine_bricks]" + }, + { + "baseColor": 31, + "id": "minecraft:dark_prismarine", + "nameZH": "暗海晶石", + "nameEN": "Dark prismarine", + "icon": "dark_prismarine.png", + "version": 0, + "idOld": "minecraft:prismarine[variant=dark_prismarine]" + }, + { + "baseColor": 32, + "id": "minecraft:lapis_block", + "nameZH": "青金石块", + "nameEN": "Lapis block", + "icon": "lapis_block.png", + "version": 0 + }, + { + "baseColor": 33, + "id": "minecraft:emerald_block", + "nameZH": "绿宝石块", + "nameEN": "Emerald block", + "icon": "emerald_block.png", + "version": 0 + }, + { + "baseColor": 34, + "id": "minecraft:podzol[snowy=false]", + "nameZH": "灰化土", + "nameEN": "Podzol", + "icon": "podzol.png", + "version": 0, + "idOld": "minecraft:dirt[variant=podzol,snowy=false]", + "endermanPickable": true + }, + { + "baseColor": 34, + "id": "minecraft:spruce_planks", + "nameZH": "云杉木板", + "nameEN": "Spruce plank", + "icon": "spruce_planks.png", + "version": 0, + "idOld": "minecraft:planks[variant=spruce]", + "burnable": true + }, + { + "baseColor": 34, + "id": "minecraft:campfire[facing=north,lit=true,signal_fire=false,waterlogged=false]", + "nameZH": "营火", + "nameEN": "Campfire", + "icon": "campfire.png", + "version": 14, + "isGlowing": true, + "wallUseable": false + }, + { + "baseColor": 35, + "id": "minecraft:netherrack", + "nameZH": "下界岩", + "nameEN": "Netherrack", + "icon": "netherrack.png", + "version": 0 + }, + { + "baseColor": 35, + "id": "minecraft:nether_bricks", + "nameZH": "下界砖块", + "nameEN": "Nether brick", + "icon": "nether_bricks.png", + "version": 0, + "idOld": "minecraft:nether_brick" + }, + { + "baseColor": 35, + "id": "minecraft:magma_block", + "nameZH": "岩浆块", + "nameEN": "Magma block", + "icon": "magma_block.png", + "version": 0, + "idOld": "minecraft:magma" + }, + { + "baseColor": 36, + "id": "minecraft:white_terracotta", + "nameZH": "白色陶瓦", + "nameEN": "White terracotta", + "icon": "white_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=white]" + }, + { + "baseColor": 36, + "id": "minecraft:calcite", + "nameZH": "方解石", + "nameEN": "Calcite", + "icon": "calcite.png", + "version": 17 + }, + { + "baseColor": 37, + "id": "minecraft:orange_terracotta", + "nameZH": "橙色陶瓦", + "nameEN": "Orange terracotta", + "icon": "orange_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=orange]" + }, + { + "baseColor": 38, + "id": "minecraft:magenta_terracotta", + "nameZH": "品红色陶瓦", + "nameEN": "Magenta terracotta", + "icon": "magenta_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=magenta]" + }, + { + "baseColor": 39, + "id": "minecraft:light_blue_terracotta", + "nameZH": "淡蓝色陶瓦", + "nameEN": "Light blue terracotta", + "icon": "light_blue_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=light_blue]" + }, + { + "baseColor": 40, + "id": "minecraft:yellow_terracotta", + "nameZH": "黄色陶瓦", + "nameEN": "Yellow terracotta", + "icon": "yellow_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=yellow]" + }, + { + "baseColor": 41, + "id": "minecraft:lime_terracotta", + "nameZH": "黄绿色陶瓦", + "nameEN": "Lime terracotta", + "icon": "lime_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=lime]" + }, + { + "baseColor": 42, + "id": "minecraft:pink_terracotta", + "nameZH": "粉红色陶瓦", + "nameEN": "Pink terracotta", + "icon": "pink_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=pink]" + }, + { + "baseColor": 43, + "id": "minecraft:gray_terracotta", + "nameZH": "灰色陶瓦", + "nameEN": "Gray terracotta", + "icon": "gray_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=gray]" + }, + { + "baseColor": 44, + "id": "minecraft:light_gray_terracotta", + "nameZH": "淡灰色陶瓦", + "nameEN": "Light gray terracotta", + "icon": "light_gray_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=silver]" + }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_copper", + "nameZH": "斑驳的涂蜡铜块", + "nameEN": "Waxed exposed copper", + "icon": "waxed_exposed_copper.png", + "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_cut_copper", + "nameZH": "斑驳的涂蜡切制铜块", + "nameEN": "Waxed exposed cut copper", + "icon": "waxed_exposed_cut_copper.png", + "version": 17 + }, + { + "baseColor": 44, + "id": "minecraft:mud_bricks", + "nameZH": "泥砖", + "nameEN": "Mud bricks", + "icon": "mud_bricks.png", + "version": 19 + }, + { + "baseColor": 45, + "id": "minecraft:cyan_terracotta", + "nameZH": "青色陶瓦", + "nameEN": "Cyan terracotta", + "icon": "cyan_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=cyan]" + }, + { + "baseColor": 45, + "id": "minecraft:mud", + "nameZH": "泥巴", + "nameEN": "Mud", + "icon": "mud.png", + "version": 19 + }, + { + "baseColor": 46, + "id": "minecraft:purple_terracotta", + "nameZH": "紫色陶瓦", + "nameEN": "Purple terracotta", + "icon": "purple_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=purple]" + }, + { + "baseColor": 47, + "id": "minecraft:blue_terracotta", + "nameZH": "蓝色陶瓦", + "nameEN": "Blue terracotta", + "icon": "blue_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=blue]" + }, + { + "baseColor": 48, + "id": "minecraft:brown_terracotta", + "nameZH": "棕色陶瓦", + "nameEN": "Brown terracotta", + "icon": "brown_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=brown]" + }, + { + "baseColor": 48, + "id": "minecraft:dripstone_block", + "nameZH": "滴水石块", + "nameEN": "DripStone Block", + "icon": "dripstone_block.png", + "version": 17 + }, + { + "baseColor": 49, + "id": "minecraft:green_terracotta", + "nameZH": "绿色陶瓦", + "nameEN": "Green terracotta", + "icon": "green_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=green]" + }, + { + "baseColor": 50, + "id": "minecraft:red_terracotta", + "nameZH": "红色陶瓦", + "nameEN": "Red terracotta", + "icon": "red_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=red]" + }, + { + "baseColor": 51, + "id": "minecraft:black_terracotta", + "nameZH": "黑色陶瓦", + "nameEN": "Black terracotta", + "icon": "black_terracotta.png", + "version": 0, + "idOld": "minecraft:stained_hardened_clay[color=black]" + }, + { + "baseColor": 52, + "id": "minecraft:crimson_nylium", + "nameZH": "绯红菌岩", + "nameEN": "Crimson nylium", + "icon": "crimson_nylium.png", + "version": 16, + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 53, + "id": "minecraft:crimson_planks", + "nameZH": "绯红木板", + "nameEN": "Crimson plank", + "icon": "crimson_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 53, + "id": "minecraft:stripped_crimson_stem[axis=y]", + "nameZH": "去皮绯红菌柄", + "nameEN": "Stripped crimson log", + "icon": "stripped_crimson_stem.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 54, + "id": "minecraft:crimson_hyphae[axis=y]", + "nameZH": "绯红菌核", + "nameEN": "Crimson hyphae", + "icon": "crimson_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 54, + "id": "minecraft:stripped_crimson_hyphae[axis=y]", + "nameZH": "去皮绯红菌核", + "nameEN": "Stripped crimson hyphae", + "icon": "stripped_crimson_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 55, + "id": "minecraft:warped_nylium", + "nameZH": "诡异菌岩", + "nameEN": "Warped nylium", + "icon": "warped_nylium.png", + "version": 16, + "endermanPickable": true, + "wallUseable": false + }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_copper", + "nameZH": "氧化的涂蜡铜块", + "nameEN": "Waxed oxided copper", + "icon": "waxed_oxidized_copper.png", + "version": 17 + }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_cut_copper", + "nameZH": "氧化的涂蜡切制铜块", + "nameEN": "Waxed oxided cut copper", + "icon": "waxed_oxidized_cut_copper.png", + "version": 17 + }, + { + "baseColor": 56, + "id": "minecraft:warped_planks", + "nameZH": "诡异木板", + "nameEN": "Warped plank", + "icon": "warped_planks.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:stripped_warped_stem[axis=y]", + "nameZH": "去皮诡异菌柄", + "nameEN": "Stripped warped log", + "icon": "stripped_warped_stem.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_copper", + "nameZH": "锈蚀的涂蜡铜块", + "nameEN": "Waxed weathered copper", + "icon": "waxed_weathered_copper.png", + "version": 17 + }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_cut_copper", + "nameZH": "锈蚀的涂蜡切制铜块", + "nameEN": "Waxed weathered cut copper", + "icon": "waxed_weathered_cut_copper.png", + "version": 17 + }, + { + "baseColor": 57, + "id": "minecraft:warped_hyphae[axis=y]", + "nameZH": "诡异菌核", + "nameEN": "Warped hyphae", + "icon": "warped_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 57, + "id": "minecraft:stripped_warped_hyphae[axis=y]", + "nameZH": "去皮诡异菌核", + "nameEN": "Stripped warped hyphae", + "icon": "stripped_warped_hyphae.png", + "version": 16, + "burnable": true + }, + { + "baseColor": 58, + "id": "minecraft:warped_wart_block", + "nameZH": "诡异疣块", + "nameEN": "Warped wart block", + "icon": "warped_wart_block.png", + "version": 16 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate", + "nameZH": "深板岩", + "nameEN": "Deepslate", + "icon": "deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:chiseled_deepslate", + "nameZH": "雕纹深板岩", + "nameEN": "Chiseled deepslate", + "icon": "chiseled_deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:polished_deepslate", + "nameZH": "磨制深板岩", + "nameEN": "Polished deepslate", + "icon": "polished_deepslate.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_bricks", + "nameZH": "深板岩砖", + "nameEN": "Deepslate bricks", + "icon": "deepslate_bricks.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:deepslate_tiles", + "nameZH": "深板岩瓦", + "nameEN": "Deepslate tiles", + "icon": "deepslate_tiles.png", + "version": 17 + }, + { + "baseColor": 59, + "id": "minecraft:cobbled_deepslate", + "nameZH": "深板岩圆石", + "nameEN": "Cobbled deepslate", + "icon": "cobbled_deepslate.png", + "version": 17 + }, + { + "baseColor": 60, + "id": "minecraft:raw_iron_block", + "nameZH": "粗铁块", + "nameEN": "Raw iron block", + "icon": "raw_iron_block.png", + "version": 17 + }, + { + "baseColor": 61, + "id": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", + "nameZH": "发光地衣", + "nameEN": "Glow lichen", + "icon": "glow_lichen.png", + "version": 17, + "needGlass": true, + "isGlowing": true, + "burnable": true, + "wallUseable": false + }, + { + "baseColor": 61, + "id": "minecraft:verdant_froglight[axis=y]", + "nameZH": "青翠蛙明灯", + "nameEN": "Verdant Froglight", + "icon": "verdant_froglight_top.png", + "version": 19, + "isGlowing": true + }, + { + "baseColor": 43, + "id": "minecraft:cherry_wood", + "nameZH": "樱花木头", + "nameEN": "Cherry wood", + "icon": "cherry_log.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 36, + "id": "minecraft:cherry_planks", + "nameZH": "樱花木板", + "nameEN": "Cherry planks", + "icon": "cherry_planks.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 42, + "id": "minecraft:stripped_cherry_wood[axis=y]", + "nameZH": "去皮樱花木头", + "nameEN": "Stripped cherry wood", + "icon": "stripped_cherry_log.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_planks", + "nameZH": "竹板", + "nameEN": "Bamboo planks", + "icon": "bamboo_planks.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 18, + "id": "minecraft:bamboo_block[axis=x]", + "nameZH": "竹块(侧面)", + "nameEN": "Bamboo block(axis=x)", + "icon": "bamboo_block.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 20, + "id": "minecraft:cherry_leaves[persistent=true]", + "nameZH": "樱花树叶", + "nameEN": "Cherry leaves", + "icon": "cherry_leaves.png", + "version": 20, + "burnable": true + }, + { + "baseColor": 50, + "id": "minecraft:decorated_pot", + "nameZH": "陶罐", + "nameEN": "Decorated pot", + "icon": "burn_pottery_pattern.png", + "version": 20 + } +] \ No newline at end of file diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index d598d7b8..ce3caa0d 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -11,6 +11,8 @@ find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) find_package(Boost COMPONENTS iostreams REQUIRED) +find_package(libzip REQUIRED) +find_package(tl-expected REQUIRED) #find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -52,7 +54,6 @@ set(SlopeCraft_SCL_sources TokiSlopeCraft_build.cpp TokiSlopeCraft_convert.cpp TokiSlopeCraft_cache.cpp - WaterItem.cpp imagePreprocess.cpp lossyCompressor.cpp simpleBlock.cpp @@ -91,6 +92,8 @@ set(SlopeCraft_SCL_link_libs Eigen3::Eigen Heu::Genetic Boost::iostreams + libzip::zip + tl::expected ${SC_zstd_target_name}) # link to dependents @@ -116,4 +119,44 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") PREFIX "") endif () +function(SC_create_SCL_block_list src_dir archive_path) + if (NOT EXISTS "${src_dir}/BlockList.json") + message(FATAL_ERROR "${src_dir}/BlockList.json doesn't exist, block list json is missing") + endif () + + cmake_path(GET archive_path PARENT_PATH archive_dir) + file(MAKE_DIRECTORY ${archive_dir}) + + if (EXISTS ${archive_path}) + file(REMOVE ${archive_path}) + endif () + + # file(GLOB_RECURSE file_list "${src_dir}/*.png") + # + # file(ARCHIVE_CREATE OUTPUT temp.zip PATHS ${src_dir} "${src_dir}/BlockList.json" FORMAT zip + # #COMPRESSION Zstd + # #COMPRESSION_LEVEL 9 + # ) + + find_program(z7_exe NAMES 7z REQUIRED + DOC "Find 7z to archive SlopeCraft block lists. 7z is required because file(ARCHIVE_CREATE in cmake too stupid to be used" + HINTS "C:/Program Files/7-Zip/7z.exe") + + execute_process(COMMAND ${z7_exe} a ${archive_path} -scsUTF-8 "${src_dir}/*" -tZIP + COMMAND_ERROR_IS_FATAL ANY) + + +endfunction() + +SC_create_SCL_block_list(${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks "${CMAKE_BINARY_DIR}/SCL_block_lists/FixedBlocks.zip") +SC_create_SCL_block_list(${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks "${CMAKE_BINARY_DIR}/SCL_block_lists/CustomBlocks.zip") + +add_executable(test_scl_load_blocklist tests/load_scl_blocklist.cpp) +target_link_libraries(test_scl_load_blocklist PRIVATE libzip::zip fmt::fmt tl::expected) +target_compile_features(test_scl_load_blocklist PRIVATE cxx_std_23) +if (${WIN32}) + DLLD_add_deploy(test_scl_load_blocklist BUILD_MODE) +endif () + + include(install.cmake) \ No newline at end of file diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 06e3d05c..5a64a90d 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -25,6 +25,8 @@ This file is part of SlopeCraft. #include "simpleBlock.h" #include #include +#include +#include using namespace SlopeCraft; @@ -47,8 +49,8 @@ Kernel::Kernel() {} using namespace SlopeCraft; -std::pair parse_block( - const nlohmann::json &jo, std::string_view image_dir) noexcept(false) { +std::pair parse_block(const nlohmann::json &jo) noexcept( + false) { simpleBlock ret; const int basecolor = jo.at("baseColor"); if (basecolor < 0 || basecolor >= 64) { @@ -58,12 +60,7 @@ std::pair parse_block( ret.id = jo.at("id"); ret.nameZH = jo.at("nameZH"); ret.nameEN = jo.at("nameEN"); - { - std::string filename = image_dir.data(); - filename += '/'; - filename += jo.at("icon"); - ret.imageFilename = filename; - } + ret.imageFilename = jo.at("icon"); ret.version = jo.at("version"); if (jo.contains("idOld")) { ret.idOld = jo.at("idOld"); @@ -90,47 +87,174 @@ std::pair parse_block( return {basecolor, ret}; } -BlockListInterface *impl_createBlockList(const char *filename, - const blockListOption &option, - std::string &errmsg) noexcept { - errmsg.reserve(4096); - errmsg.clear(); +// BlockListInterface *impl_createBlockList(const char *filename, +// const blockListOption &option, +// std::string &errmsg) noexcept { +// errmsg.reserve(4096); +// errmsg.clear(); +// +// BlockList *bl = new BlockList; +// using njson = nlohmann::json; +// try { +// std::ifstream ifs(filename); +// njson jo = njson::parse(ifs, nullptr, true, true); +// +// njson::array_t arr; +// if (jo.contains("FixedBlocks")) { +// arr = std::move(jo.at("FixedBlocks")); +// } else { +// arr = std::move(jo.at("CustomBlocks")); +// } +// +// // parse blocks +// for (size_t idx = 0; idx < arr.size(); idx++) { +// auto temp = parse_block(arr[idx], option.image_dir); +// +// auto ptr = new simpleBlock; +// *ptr = std::move(temp.second); +// bl->blocks().emplace(ptr, temp.first); +// } +// +// } catch (std::exception &e) { +// delete bl; +// errmsg += fmt::format( +// "Exception occured when parsing blocklist json: \"{}\"\n", e.what()); +// return nullptr; +// } +// +// // load images +// for (auto &pair : bl->blocks()) { +// pair.first->image.resize(16, 16); +// if (!option.callback_load_image(pair.first->getImageFilename(), +// pair.first->image.data())) { +// errmsg += fmt::format( +// "Failed to load image \"{}\", this error will be ignored.\n", +// pair.first->getImageFilename()); +// continue; +// } +// pair.first->image.transposeInPlace(); +// } +// +// return bl; +// } + +struct zip_deleter { + void operator()(zip_t *archive) const noexcept { + if (archive == nullptr) { + return; + } + zip_close(archive); + } +}; + +tl::expected, std::string> +impl_create_block_list_from_zip(const char *zip_path, + const blockListOption2 &option) noexcept { + int error_code = ZIP_ER_OK; + std::unique_ptr archive{ + zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; + if (archive == nullptr) { + return tl::make_unexpected( + fmt::format("Failed to open archive \"{}\" with libzip error code {}", + zip_path, error_code)); + } + if (error_code != ZIP_ER_OK) { + auto ret = tl::make_unexpected(fmt::format( + "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", + zip_path, zip_strerror(archive.get()), error_code)); + return ret; + } + + auto extract_file = + [zip_path, &archive]( + const char *filename, + std::vector &dest) -> tl::expected { + dest.clear(); + + int error_code = ZIP_ER_OK; + const int64_t index_i = + zip_name_locate(archive.get(), filename, ZIP_FL_UNCHANGED); + if (index_i < 0) { + return tl::make_unexpected(fmt::format( + "File \"{}\" doesn't exist in archive \"{}\"", filename, zip_path)); + } + const uint64_t index = uint64_t(index_i); + + zip_stat_t stat; + error_code = zip_stat_index(archive.get(), index, ZIP_FL_UNCHANGED, &stat); + if (error_code != ZIP_ER_OK) { + return tl::make_unexpected(fmt::format( + "Failed to get size of file \"{}\" in archive \"{}\" : \"{}\", " + "error code = {}", + filename, zip_path, zip_strerror(archive.get()), error_code)); + } + + const uint64_t file_size = stat.size; + dest.resize(file_size); + + auto file = zip_fopen(archive.get(), filename, ZIP_FL_UNCHANGED); + if (file == nullptr) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive \"{}\" : \"{}\" ", + filename, zip_path, zip_strerror(archive.get()))); + } + + const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); + if (read_bytes != int64_t(file_size)) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive \"{}\", expected " + "{} bytes, but extracted {} bytes : \"{}\" ", + filename, zip_path, file_size, read_bytes, + zip_strerror(archive.get()))); + } + return {}; + }; + + std::vector buffer; + { + auto err = extract_file("BlockList.json", buffer); + if (!err) { + return tl::make_unexpected(err.error()); + } + } BlockList *bl = new BlockList; + using njson = nlohmann::json; try { - std::ifstream ifs(filename); - njson jo = njson::parse(ifs, nullptr, true, true); - - njson::array_t arr; - if (jo.contains("FixedBlocks")) { - arr = std::move(jo.at("FixedBlocks")); - } else { - arr = std::move(jo.at("CustomBlocks")); + njson jo = njson::parse(buffer, nullptr, true, true); + if (!jo.is_array()) { + return tl::make_unexpected( + fmt::format("Json should contain an array directly")); } // parse blocks - for (size_t idx = 0; idx < arr.size(); idx++) { - auto temp = parse_block(arr[idx], option.image_dir); - - auto ptr = new simpleBlock; - *ptr = std::move(temp.second); - bl->blocks().emplace(ptr, temp.first); + for (size_t idx = 0; idx < jo.size(); idx++) { + auto [version, block] = parse_block(jo[idx]); + bl->blocks().emplace(std::make_unique(block), version); } - } catch (std::exception &e) { + } catch (const std::exception &e) { delete bl; - errmsg += fmt::format( - "Exception occured when parsing blocklist json: \"{}\"\n", e.what()); - return nullptr; + return tl::make_unexpected( + fmt::format("nlohmann json exception : {}", e.what())); } - // load images + std::string warnings; for (auto &pair : bl->blocks()) { + { + auto err = extract_file(pair.first->imageFilename.c_str(), buffer); + if (!err) { + warnings += + fmt::format("{}, required by {}", err.error(), pair.first->id); + continue; + } + } + pair.first->image.resize(16, 16); - if (!option.callback_load_image(pair.first->getImageFilename(), + if (!option.callback_load_image(buffer.data(), buffer.size(), pair.first->image.data())) { - errmsg += fmt::format( + warnings += fmt::format( "Failed to load image \"{}\", this error will be ignored.\n", pair.first->getImageFilename()); continue; @@ -138,7 +262,7 @@ BlockListInterface *impl_createBlockList(const char *filename, pair.first->image.transposeInPlace(); } - return bl; + return {{bl, warnings}}; } extern "C" { @@ -152,28 +276,27 @@ SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *filename, const blockListOption &option) { - const bool can_write_err = - (option.errmsg != nullptr) && (option.errmsg_capacity > 0); - - std::string errmsg; - - BlockListInterface *ret = impl_createBlockList(filename, option, errmsg); - - if (can_write_err) { - memset(option.errmsg, 0, option.errmsg_capacity); - const size_t copy_len = std::min(option.errmsg_capacity, errmsg.size()); - - memcpy(option.errmsg, errmsg.c_str(), copy_len); - if (option.errmsg_len_dest != nullptr) { - *option.errmsg_len_dest = copy_len; - } - } else { - if (option.errmsg_len_dest != nullptr) { - *option.errmsg_len_dest = 0; + const char *zip_filename, const blockListOption2 &option) { + auto res = impl_create_block_list_from_zip(zip_filename, option); + + auto write_to_buf = [&option](std::string_view errmsg) { + const bool can_write_err = + (option.errmsg != nullptr) && (option.errmsg_capacity > 0); + if (can_write_err) { + memset(option.errmsg, 0, option.errmsg_capacity); + const size_t len = std::min(option.errmsg_capacity, errmsg.size()); + memcpy(option.errmsg, errmsg.data(), len); + *option.errmsg_len_dest = len; } + }; + + if (!res) { + write_to_buf(res.error()); + return nullptr; } + auto [ret, warning] = res.value(); + write_to_buf(warning); return ret; } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 69c9ee5e..c0be9a15 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -51,7 +51,7 @@ using gameVersion = ::SCL_gameVersion; using workStatues = ::SCL_workStatues; using errorFlag = ::SCL_errorFlag; -}; // namespace SlopeCraft +} // namespace SlopeCraft namespace SlopeCraft { @@ -388,16 +388,16 @@ SCL_EXPORT void SCL_destroyKernel(Kernel *); [[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); -struct blockListOption { - const char *image_dir; - bool (*callback_load_image)(const char *, uint32_t *dst_row_major){nullptr}; +struct blockListOption2 { + bool (*callback_load_image)(const uint8_t *buffer, size_t bytes, + uint32_t *dst_row_major){nullptr}; char *errmsg{nullptr}; size_t errmsg_capacity{0}; size_t *errmsg_len_dest{nullptr}; }; [[nodiscard]] SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *filename, const blockListOption &option); + const char *zip_filename, const blockListOption2 &option); SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 5f4667ee..80279565 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -383,7 +383,7 @@ void TokiSlopeCraft::setRawImage(const ARGB *src, int rows, int cols, void TokiSlopeCraft::getBaseColorInARGB32(ARGB *const dest) const { if (dest == nullptr) return; - for (uchar base = 0; base < 64; base++) + for (uint8_t base = 0; base < 64; base++) dest[base] = ARGB32(255 * Basic.RGB(128 + base, 0), 255 * Basic.RGB(128 + base, 1), 255 * Basic.RGB(128 + base, 2), 255); diff --git a/SlopeCraftL/simpleBlock.cpp b/SlopeCraftL/simpleBlock.cpp index 1456589b..4e4959c9 100644 --- a/SlopeCraftL/simpleBlock.cpp +++ b/SlopeCraftL/simpleBlock.cpp @@ -35,69 +35,73 @@ simpleBlock::simpleBlock() { // wallUseable=true; } -bool simpleBlock::dealBlockId(const std::string &id, std::string &netBlockId, - stringList *proName, stringList *proVal) { - proName->clear(); - proVal->clear(); - if (id.back() != ']') { - netBlockId = id; - return false; - } - short ReadBeg = id.find('['); - // BlockId.indexOf('['); - short ReadEnd = id.find(']'); - // BlockId.indexOf(']'); - - if (ReadBeg <= 0 || ReadEnd <= 0 || ReadEnd <= ReadBeg) { - std::cerr << "方块 Id 格式出现错误:" << id; - return false; - } - - short ProIndex[2] = {-1, -1}, ProValIndex[2] = {-1, -1}; - - netBlockId = id.substr(0, ReadBeg); - // BlockId.mid(0,ReadBeg).toLower(); - - for (short read = ReadBeg; read <= ReadEnd; read++) { - switch (id.at(read)) { - case '[': // 代表找到了一个新的属性 - ProIndex[0] = read + 1; - continue; - - case '=': // 识别出了属性名,寻找属性值 - ProIndex[1] = read - 1; - ProValIndex[0] = read + 1; - continue; - - case ',': // 代表结束了一个属性,并找到了下一个属性 - ProValIndex[1] = read - 1; - proName->push_back( - id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); - // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); - proVal->push_back( - id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); - // BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); - ProIndex[0] = -1; - ProIndex[1] = -1; - ProValIndex[0] = -1; - ProValIndex[1] = -1; - - ProIndex[0] = read + 1; - continue; - case ']': - ProValIndex[1] = read - 1; - proName->push_back( - id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); - // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); - proVal->push_back( - id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); - // BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); - continue; - } - } - // qDebug()<back()<<'='<back(); - return true; -} +// bool simpleBlock::processBlockId(std::string_view id, std::string +// &netBlockId, +// std::vector &proName, +// std::vector &proVal) { +// proName.clear(); +// proVal.clear(); +// if (id.back() != ']') { +// netBlockId = id; +// return false; +// } +// short ReadBeg = id.find('['); +// // BlockId.indexOf('['); +// short ReadEnd = id.find(']'); +// // BlockId.indexOf(']'); +// +// if (ReadBeg <= 0 || ReadEnd <= 0 || ReadEnd <= ReadBeg) { +// std::cerr << "方块 Id 格式出现错误:" << id; +// return false; +// } +// +// short ProIndex[2] = {-1, -1}, ProValIndex[2] = {-1, -1}; +// +// netBlockId = id.substr(0, ReadBeg); +// // BlockId.mid(0,ReadBeg).toLower(); +// +// for (short read = ReadBeg; read <= ReadEnd; read++) { +// switch (id.at(read)) { +// case '[': // 代表找到了一个新的属性 +// ProIndex[0] = read + 1; +// continue; +// +// case '=': // 识别出了属性名,寻找属性值 +// ProIndex[1] = read - 1; +// ProValIndex[0] = read + 1; +// continue; +// +// case ',': // 代表结束了一个属性,并找到了下一个属性 +// ProValIndex[1] = read - 1; +// proName.push_back( +// id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); +// // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); +// proVal.push_back( +// id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); +// // +// BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); +// ProIndex[0] = -1; +// ProIndex[1] = -1; +// ProValIndex[0] = -1; +// ProValIndex[1] = -1; +// +// ProIndex[0] = read + 1; +// continue; +// case ']': +// ProValIndex[1] = read - 1; +// proName.push_back( +// id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); +// // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); +// proVal.push_back( +// id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); +// // +// BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); +// continue; +// } +// } +// // qDebug()<back()<<'='<back(); +// return true; +// } size_t BlockList::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) noexcept { @@ -107,7 +111,7 @@ size_t BlockList::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, size_t counter = 0; for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first; + dst[counter] = ptr.first.get(); dst_basecolor[counter] = ptr.second; counter++; if (counter >= capacity_in_elements) { @@ -125,7 +129,7 @@ size_t BlockList::get_blocks(const AbstractBlock **dst, uint8_t *dst_basecolor, size_t counter = 0; for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first; + dst[counter] = ptr.first.get(); dst_basecolor[counter] = ptr.second; counter++; if (counter >= capacity_in_elements) { @@ -135,12 +139,6 @@ size_t BlockList::get_blocks(const AbstractBlock **dst, uint8_t *dst_basecolor, return counter; } -void BlockList::clear() noexcept { - for (auto &ptr : this->m_blocks) { - delete ptr.first; - } - - this->m_blocks.clear(); -} +void BlockList::clear() noexcept { this->m_blocks.clear(); } BlockList::~BlockList() { this->clear(); } \ No newline at end of file diff --git a/SlopeCraftL/simpleBlock.h b/SlopeCraftL/simpleBlock.h index 4403b2f7..e5fb1c6a 100644 --- a/SlopeCraftL/simpleBlock.h +++ b/SlopeCraftL/simpleBlock.h @@ -30,8 +30,7 @@ using namespace SlopeCraft; #include #include #include - -typedef unsigned char uchar; +#include typedef std::vector stringList; @@ -40,7 +39,7 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { simpleBlock(); ~simpleBlock(){}; std::string id; - uchar version; + uint8_t version; std::string idOld; std::string nameZH; std::string nameEN; @@ -112,8 +111,9 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { *static_cast(dst) = *this; } - static bool dealBlockId(const std::string &id, std::string &netBlockId, - stringList *proName, stringList *proVal); + // static bool processBlockId(std::string_view id, std::string &netBlockId, + // std::vector &proName, + // std::vector &proVal); const char *idForVersion(SCL_gameVersion ver) const noexcept override { if (ver >= SCL_gameVersion::MC13) { @@ -130,7 +130,7 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { class BlockList : public ::SlopeCraft::BlockListInterface { private: - std::map m_blocks; + std::map, uint8_t> m_blocks; public: BlockList() = default; @@ -145,8 +145,9 @@ class BlockList : public ::SlopeCraft::BlockListInterface { size_t capacity_in_elements) const noexcept override; bool contains(const AbstractBlock *cp) const noexcept override { + const simpleBlock *ptr = dynamic_cast(cp); return this->m_blocks.contains( - static_cast(const_cast(cp))); + reinterpret_cast &>(ptr)); } public: diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp new file mode 100644 index 00000000..d938ee7c --- /dev/null +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +struct block_list { + public: + std::vector block_list_file; +}; + +tl::expected parse_archive(zip_t* archive) noexcept { + assert(archive != nullptr); + + auto read_file = + [archive](const char* filename, + std::vector& dest) -> tl::expected { + auto fp = zip_fopen(archive, filename, ZIP_FL_UNCHANGED); + if (fp == nullptr) { + return tl::unexpected( + fmt::format("Failed to open {}, last error: {}", filename, + zip_error_strerror(zip_get_error(archive)))); + } + const auto index = zip_name_locate(archive, filename, ZIP_FL_UNCHANGED); + assert(index >= 0); + + zip_stat_t stat{}; + if (zip_stat(archive, filename, ZIP_FL_UNCHANGED, &stat) != ZIP_ER_OK) { + return tl::unexpected( + fmt::format("Failed to open {}, last error: {}", filename, + zip_error_strerror(zip_get_error(archive)))); + } + + dest.resize(stat.size); + const auto bytes = zip_fread(fp, dest.data(), dest.size()); + if (bytes != int64_t(stat.size)) { + return tl::unexpected( + fmt::format("Failed to read {}, the file contains {} bytes, but {} " + "decoded. Last error: {}", + filename, stat.size, bytes, + zip_error_strerror(zip_get_error(archive)))); + } + return {}; + }; + + std::vector bytes{}; + auto res = read_file("BlockList.json", bytes); + assert(res); + + return ::block_list{bytes}; +} + +int main(int argc, char** argv) { + if (argc != 2) { + fmt::println("Must provide 1 arguments\n"); + return __LINE__; + } + + const char* archive_path = argv[1]; + fmt::println("Try parsing {}", archive_path); + + int ec = ZIP_ER_OK; + zip_t* archive = zip_open(archive_path, ZIP_RDONLY | ZIP_CHECKCONS, &ec); + if (archive == nullptr || ec != ZIP_ER_OK) { + fmt::println("Failed to open {}, error code = {}", archive_path, ec); + return __LINE__; + } + + // libzippp::ZipArchive archive{archive_path, ""}; + // if (archive.getZipHandle() == nullptr) { + // fmt::println("Failed to open {}", archive_path); + // return __LINE__; + // }; + // if (!archive.isOpen() || + // !archive.open(libzippp::ZipArchive::OpenMode::ReadOnly, true)) { + // fmt::println("Failed to open {}", archive_path); + // return __LINE__; + // } + // + auto list = parse_archive(archive).value(); + + fmt::println("BlockList.json: \n{}", + reinterpret_cast(list.block_list_file.data())); + + return 0; + // if (archive.getE) return 0; +} \ No newline at end of file From 6302b66c31fbf35ecab9563e4d53e184d3e38dd2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 20:27:59 +0800 Subject: [PATCH 0726/1123] add libpng_reader utility Signed-off-by: ToKiNoBug --- utilities/CMakeLists.txt | 7 +- utilities/libpngReader/CMakeLists.txt | 12 ++ utilities/libpngReader/libpng_reader.cpp | 156 +++++++++++++++++++++++ utilities/libpngReader/libpng_reader.h | 24 ++++ 4 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 utilities/libpngReader/CMakeLists.txt create mode 100644 utilities/libpngReader/libpng_reader.cpp create mode 100644 utilities/libpngReader/libpng_reader.h diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 04babc71..9dac3819 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -14,13 +14,14 @@ add_subdirectory(MapImageCvter) add_subdirectory(VersionDialog) add_subdirectory(VCLConfigLoader) add_subdirectory(FlatDiagram) +add_subdirectory(libpngReader) function(SC_process_boolean value_name) - if(${${value_name}}) + if (${${value_name}}) set(${value_name} "true" PARENT_SCOPE) - else() + else () set(${value_name} "false" PARENT_SCOPE) - endif() + endif () endfunction(SC_process_boolean value_name) SC_process_boolean(SlopeCraft_vectorize) diff --git a/utilities/libpngReader/CMakeLists.txt b/utilities/libpngReader/CMakeLists.txt new file mode 100644 index 00000000..22600d16 --- /dev/null +++ b/utilities/libpngReader/CMakeLists.txt @@ -0,0 +1,12 @@ +add_library(libpng_reader STATIC + libpng_reader.cpp + libpng_reader.h) + +find_package(tl-expected REQUIRED) +find_package(fmt REQUIRED) +find_package(PNG REQUIRED) + + +target_compile_features(libpng_reader PUBLIC cxx_std_23) +target_link_libraries(libpng_reader PUBLIC tl::expected fmt::fmt PNG::PNG) +target_include_directories(libpng_reader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp new file mode 100644 index 00000000..ef91649d --- /dev/null +++ b/utilities/libpngReader/libpng_reader.cpp @@ -0,0 +1,156 @@ +// +// Created by Joseph on 2024/4/8. +// + +#include "libpng_reader.h" +#include +#include + +struct read_buffer_wrapper { + const void *data; + int64_t offset{0}; + int64_t max_length; +}; + +void png_callback_read_data_from_memory(png_struct *png, png_byte *data, + size_t read_length) { + read_buffer_wrapper *const ioptr = + reinterpret_cast(png_get_io_ptr(png)); + const size_t can_read_bytes = ioptr->max_length - ioptr->offset; + if (can_read_bytes < read_length) { + png_error(png, "EOF"); + + // return; + } + + memcpy(data, (char *)(ioptr->data) + ioptr->offset, read_length); + ioptr->offset += read_length; +} + +std::tuple, std::string> +parse_png_into_argb32(std::span encoded, + std::vector &pixels) noexcept { + std::string warnings{}; + png_struct *png = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png == NULL) { + return {tl::make_unexpected("Failed to create png read struct."), warnings}; + } + + png_info *info = png_create_info_struct(png); + if (info == NULL) { + png_destroy_read_struct(&png, &info, NULL); + return {tl::make_unexpected("Failed to create png info struct."), warnings}; + } + + png_info *info_end = png_create_info_struct(png); + if (info_end == NULL) { + png_destroy_read_struct(&png, &info, &info_end); + return {tl::make_unexpected("Failed to create png info_end struct."), + warnings}; + } + + // make a ioptr for libpng + read_buffer_wrapper wrapper; + wrapper.data = encoded.data(); + wrapper.offset = 0; + wrapper.max_length = encoded.size_bytes(); + + png_set_read_fn(png, &wrapper, png_callback_read_data_from_memory); + + png_read_info(png, info); + + uint32_t width{0}, height{0}; + int bit_depth, color_type, interlace_method, compress_method, filter_method; + bool add_alpha = false; + + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, + &interlace_method, &compress_method, &filter_method); + + // cout << "\nwidth = " << width; + // cout << "\nheight = " << height; + // cout << "\nbit_depth = " << bit_depth; + // cout << "\ncolor_type = " << color_type << " ("; + + if (bit_depth > 8) { + png_set_strip_16(png); + } + if (bit_depth < 8) png_set_expand(png); + + switch (color_type) { + case PNG_COLOR_TYPE_GRAY: // fixed + png_set_gray_to_rgb(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_GRAY"; + break; + case PNG_COLOR_TYPE_PALETTE: // fixed + + png_set_palette_to_rgb(png); + png_set_bgr(png); + { + int num_trans = 0; + png_get_tRNS(png, info, NULL, &num_trans, NULL); + if (num_trans <= 0) { + add_alpha = true; + } + // cout << "num_trans = " << num_trans << endl; + } + + // cout << "PNG_COLOR_TYPE_PALETTE"; + break; + case PNG_COLOR_TYPE_RGB: // fixed + png_set_bgr(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_RGB"; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: // fixed + png_set_bgr(png); + // cout << "PNG_COLOR_TYPE_RGB_ALPHA"; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: // fixed + png_set_gray_to_rgb(png); + // png_set_swap_alpha(png); + // cout << "PNG_COLOR_TYPE_GRAY_ALPHA"; + break; + default: + png_destroy_read_struct(&png, &info, &info_end); + return { + tl::make_unexpected(fmt::format("Unknown color type {}", color_type)), + warnings}; + } + // cout << ")\n"; + // #warning here + + pixels.resize(height * width); + // img->resize(height, width); + + std::vector row_ptrs; + row_ptrs.resize(height); + + for (int r = 0; r < int(height); r++) { + row_ptrs[r] = reinterpret_cast(pixels.data() + r * width); + } + + png_read_image(png, row_ptrs.data()); + + if (add_alpha) { // add alpha manually + for (int r = 0; r < int(height); r++) { + uint8_t *const current_row = row_ptrs[r]; + for (int pixel_idx = width - 1; pixel_idx > 0; pixel_idx--) { + const uint8_t *const data_src = current_row + pixel_idx * 3; + uint8_t *const data_dest = current_row + pixel_idx * 4; + + for (int i = 2; i >= 0; i--) { + data_dest[i] = data_src[i]; + } + data_dest[3] = 0xFF; + } + current_row[3] = 0xFF; + } + } + + // png_destroy_info_struct(png, &info); + png_destroy_read_struct(&png, &info, &info_end); + + return {image_info{height, width}, warnings}; +} diff --git a/utilities/libpngReader/libpng_reader.h b/utilities/libpngReader/libpng_reader.h new file mode 100644 index 00000000..2761f216 --- /dev/null +++ b/utilities/libpngReader/libpng_reader.h @@ -0,0 +1,24 @@ +// +// Created by Joseph on 2024/4/8. +// + +#ifndef SLOPECRAFT_LIBPNG_READER_H +#define SLOPECRAFT_LIBPNG_READER_H + +#include +#include +#include +#include +#include +#include + +struct image_info { + uint32_t rows{0}; + uint32_t cols{0}; +}; + +[[nodiscard]] std::tuple, std::string> +parse_png_into_argb32(std::span png_file_in_bytes, + std::vector& pixels_row_major) noexcept; + +#endif // SLOPECRAFT_LIBPNG_READER_H From 1d78ce8f5570e7419c97b956ff6ac78f94698478 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 21:12:00 +0800 Subject: [PATCH 0727/1123] refactor BlockList in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 11 ++- SlopeCraftL/SlopeCraftL.cpp | 94 +++++++++++--------- SlopeCraftL/SlopeCraftL.h | 12 ++- SlopeCraftL/tests/load_scl_blocklist.cpp | 106 +++++++---------------- 4 files changed, 98 insertions(+), 125 deletions(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ce3caa0d..2728f394 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -4,6 +4,7 @@ include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) include(${CMAKE_SOURCE_DIR}/cmake/configure_zstd.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/configure_libpng.cmake) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) @@ -13,6 +14,7 @@ find_package(Heu REQUIRED) find_package(Boost COMPONENTS iostreams REQUIRED) find_package(libzip REQUIRED) find_package(tl-expected REQUIRED) +find_package(PNG REQUIRED) #find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -85,6 +87,7 @@ set(SlopeCraft_SCL_link_libs Schem MapImageCvter FlatDiagram + libpng_reader ZLIB::ZLIB OpenMP::OpenMP_CXX @@ -97,7 +100,7 @@ set(SlopeCraft_SCL_link_libs ${SC_zstd_target_name}) # link to dependents -target_link_libraries(SlopeCraftL PUBLIC $) +target_link_libraries(SlopeCraftL PRIVATE $) target_compile_options(SlopeCraftL PRIVATE ${SlopeCraft_vectorize_flags}) @@ -151,11 +154,13 @@ endfunction() SC_create_SCL_block_list(${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks "${CMAKE_BINARY_DIR}/SCL_block_lists/FixedBlocks.zip") SC_create_SCL_block_list(${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks "${CMAKE_BINARY_DIR}/SCL_block_lists/CustomBlocks.zip") + add_executable(test_scl_load_blocklist tests/load_scl_blocklist.cpp) -target_link_libraries(test_scl_load_blocklist PRIVATE libzip::zip fmt::fmt tl::expected) +target_link_libraries(test_scl_load_blocklist PRIVATE SlopeCraftL) target_compile_features(test_scl_load_blocklist PRIVATE cxx_std_23) if (${WIN32}) - DLLD_add_deploy(test_scl_load_blocklist BUILD_MODE) + DLLD_add_deploy(SlopeCraftL BUILD_MODE) + DLLD_add_deploy(test_scl_load_blocklist BUILD_MODE VERBOSE) endif () diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 5a64a90d..25037f01 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -20,13 +20,16 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "SlopeCraftL.h" -#include "TokiSlopeCraft.h" -#include "simpleBlock.h" #include #include #include #include +#include + +#include "SlopeCraftL.h" +#include "TokiSlopeCraft.h" +#include "simpleBlock.h" +#include "WriteStringDeliver.h" using namespace SlopeCraft; @@ -147,22 +150,23 @@ struct zip_deleter { } }; -tl::expected, std::string> -impl_create_block_list_from_zip(const char *zip_path, - const blockListOption2 &option) noexcept { +std::tuple, std::string> +impl_create_block_list_from_zip(const char *zip_path) noexcept { + std::string warnings{}; int error_code = ZIP_ER_OK; std::unique_ptr archive{ zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; if (archive == nullptr) { - return tl::make_unexpected( - fmt::format("Failed to open archive \"{}\" with libzip error code {}", - zip_path, error_code)); + return {tl::make_unexpected(fmt::format( + "Failed to open archive \"{}\" with libzip error code {}", + zip_path, error_code)), + warnings}; } if (error_code != ZIP_ER_OK) { auto ret = tl::make_unexpected(fmt::format( "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", zip_path, zip_strerror(archive.get()), error_code)); - return ret; + return {ret, warnings}; } auto extract_file = @@ -214,7 +218,7 @@ impl_create_block_list_from_zip(const char *zip_path, { auto err = extract_file("BlockList.json", buffer); if (!err) { - return tl::make_unexpected(err.error()); + return {tl::make_unexpected(err.error()), warnings}; } } @@ -224,8 +228,9 @@ impl_create_block_list_from_zip(const char *zip_path, try { njson jo = njson::parse(buffer, nullptr, true, true); if (!jo.is_array()) { - return tl::make_unexpected( - fmt::format("Json should contain an array directly")); + return {tl::make_unexpected( + fmt::format("Json should contain an array directly")), + warnings}; } // parse blocks @@ -236,11 +241,12 @@ impl_create_block_list_from_zip(const char *zip_path, } catch (const std::exception &e) { delete bl; - return tl::make_unexpected( - fmt::format("nlohmann json exception : {}", e.what())); + return {tl::make_unexpected( + fmt::format("nlohmann json exception : {}", e.what())), + warnings}; } // load images - std::string warnings; + std::vector buf_pixel; for (auto &pair : bl->blocks()) { { auto err = extract_file(pair.first->imageFilename.c_str(), buffer); @@ -252,17 +258,35 @@ impl_create_block_list_from_zip(const char *zip_path, } pair.first->image.resize(16, 16); - if (!option.callback_load_image(buffer.data(), buffer.size(), - pair.first->image.data())) { - warnings += fmt::format( - "Failed to load image \"{}\", this error will be ignored.\n", - pair.first->getImageFilename()); - continue; + { + auto [result, warns] = parse_png_into_argb32(buffer, buf_pixel); + warnings += warns; + + if (!result) { + fmt::format_to(std::back_insert_iterator{warnings}, + "Failed to load image \"{}\" because \"{}\"\n", + pair.first->getImageFilename(), result.error()); + // for (uint8_t byte : buffer) { + // printf("%02X ", int(byte)); + // } + // printf("\n"); + continue; + } + auto image_size = result.value(); + if (image_size.rows != 16 || image_size.cols != 16) { + fmt::format_to(std::back_insert_iterator{warnings}, + "{} has invalid shape, expected 16x16, but found {} " + "rows x {} cols.\n", + pair.first->getImageFilename(), image_size.rows, + image_size.cols); + continue; + } } - pair.first->image.transposeInPlace(); + assert(buf_pixel.size() == 16 * 16); + memcpy(pair.first->image.data(), buf_pixel.data(), 256); } - return {{bl, warnings}}; + return {bl, warnings}; } extern "C" { @@ -276,28 +300,16 @@ SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *zip_filename, const blockListOption2 &option) { - auto res = impl_create_block_list_from_zip(zip_filename, option); - - auto write_to_buf = [&option](std::string_view errmsg) { - const bool can_write_err = - (option.errmsg != nullptr) && (option.errmsg_capacity > 0); - if (can_write_err) { - memset(option.errmsg, 0, option.errmsg_capacity); - const size_t len = std::min(option.errmsg_capacity, errmsg.size()); - memcpy(option.errmsg, errmsg.data(), len); - *option.errmsg_len_dest = len; - } - }; + const char *zip_filename, const BlockListCreateOption &option) { + auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); + SlopeCraft::write(*option.warnings, warnings); if (!res) { - write_to_buf(res.error()); + SlopeCraft::write(*option.error, res.error()); return nullptr; } - auto [ret, warning] = res.value(); - write_to_buf(warning); - return ret; + return res.value(); } SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *) {} diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index c0be9a15..3960ce08 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -388,16 +388,14 @@ SCL_EXPORT void SCL_destroyKernel(Kernel *); [[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); -struct blockListOption2 { - bool (*callback_load_image)(const uint8_t *buffer, size_t bytes, - uint32_t *dst_row_major){nullptr}; - char *errmsg{nullptr}; - size_t errmsg_capacity{0}; - size_t *errmsg_len_dest{nullptr}; +struct BlockListCreateOption { + uint64_t version{SC_VERSION_U64}; + StringDeliver *warnings{nullptr}; + StringDeliver *error{nullptr}; }; [[nodiscard]] SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *zip_filename, const blockListOption2 &option); + const char *zip_filename, const BlockListCreateOption &option); SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *); diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp index d938ee7c..97295ebd 100644 --- a/SlopeCraftL/tests/load_scl_blocklist.cpp +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -1,88 +1,46 @@ -#include #include -#include -#include -#include -#include - -struct block_list { - public: - std::vector block_list_file; -}; - -tl::expected parse_archive(zip_t* archive) noexcept { - assert(archive != nullptr); - - auto read_file = - [archive](const char* filename, - std::vector& dest) -> tl::expected { - auto fp = zip_fopen(archive, filename, ZIP_FL_UNCHANGED); - if (fp == nullptr) { - return tl::unexpected( - fmt::format("Failed to open {}, last error: {}", filename, - zip_error_strerror(zip_get_error(archive)))); - } - const auto index = zip_name_locate(archive, filename, ZIP_FL_UNCHANGED); - assert(index >= 0); - - zip_stat_t stat{}; - if (zip_stat(archive, filename, ZIP_FL_UNCHANGED, &stat) != ZIP_ER_OK) { - return tl::unexpected( - fmt::format("Failed to open {}, last error: {}", filename, - zip_error_strerror(zip_get_error(archive)))); - } - - dest.resize(stat.size); - const auto bytes = zip_fread(fp, dest.data(), dest.size()); - if (bytes != int64_t(stat.size)) { - return tl::unexpected( - fmt::format("Failed to read {}, the file contains {} bytes, but {} " - "decoded. Last error: {}", - filename, stat.size, bytes, - zip_error_strerror(zip_get_error(archive)))); - } - return {}; - }; - - std::vector bytes{}; - auto res = read_file("BlockList.json", bytes); - assert(res); - - return ::block_list{bytes}; -} +#include +#include int main(int argc, char** argv) { if (argc != 2) { - fmt::println("Must provide 1 arguments\n"); + printf("Must provide 1 arguments\n"); return __LINE__; } const char* archive_path = argv[1]; - fmt::println("Try parsing {}", archive_path); + printf("Try parsing %s\n", archive_path); + SlopeCraft::BlockListInterface* blocklist{nullptr}; + { + std::string errmsg; + errmsg.resize(8192); + SlopeCraft::StringDeliver err_sd{errmsg.data(), errmsg.size()}; + + std::string warnings; + warnings.resize(8192); + SlopeCraft::StringDeliver warn_sd{warnings.data(), warnings.size()}; + SlopeCraft::BlockListCreateOption option{ + SC_VERSION_U64, + &warn_sd, + &err_sd, + }; + blocklist = SlopeCraft::SCL_createBlockList(archive_path, option); + errmsg.resize(err_sd.size); + warnings.resize(warn_sd.size); + + if (!warnings.empty()) { + printf("Warnings: %s\n", warnings.data()); + } - int ec = ZIP_ER_OK; - zip_t* archive = zip_open(archive_path, ZIP_RDONLY | ZIP_CHECKCONS, &ec); - if (archive == nullptr || ec != ZIP_ER_OK) { - fmt::println("Failed to open {}, error code = {}", archive_path, ec); - return __LINE__; + if (!errmsg.empty()) { + printf("Error: %s\n", errmsg.data()); + return __LINE__; + } } - // libzippp::ZipArchive archive{archive_path, ""}; - // if (archive.getZipHandle() == nullptr) { - // fmt::println("Failed to open {}", archive_path); - // return __LINE__; - // }; - // if (!archive.isOpen() || - // !archive.open(libzippp::ZipArchive::OpenMode::ReadOnly, true)) { - // fmt::println("Failed to open {}", archive_path); - // return __LINE__; - // } - // - auto list = parse_archive(archive).value(); - - fmt::println("BlockList.json: \n{}", - reinterpret_cast(list.block_list_file.data())); + printf("%s loaded successfully\n", archive_path); + SlopeCraft::SCL_destroyBlockList(blocklist); return 0; // if (archive.getE) return 0; -} \ No newline at end of file +} From 99f400f5fd4a97797b0e38f59dc61bbcaebf8aaa Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 21:12:23 +0800 Subject: [PATCH 0728/1123] fix wrong image in SCL Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/water.png | Bin 719 -> 550 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Blocks/FixedBlocks/water.png b/Blocks/FixedBlocks/water.png index cee211cc5ba4be731fcf0bf60414d361e0e7b72c..1ce7b8e8b746eb2742e2e71b66a1effa7a86fffd 100644 GIT binary patch delta 539 zcmV+$0_6SA1*QZciBL{Q4GJ0x0000DNk~Le0000G0000G2nGNE03Y-JVUZyhe*xG@ zL_t(IjZIV8Qo=wG>|LUSLph2t<}P~u46SCd0Z}04)F5g&~5`C9}zJ^P6YAq?})Mlo}XRb?_-w6x&vOaN z00wuvuJW^)Pg&_?mK9DXbtdkdCM65AMWJ^;7-#?kNtKpQuP2}fq|YXhl~oVLsY_;# zfD=mUNG6kswnHJwzf0z&z|BS(5+4khe?&oJ;@{r` z#Ypt61*PtAK1VEP7?skfM1{-x-6l%Z(R{0jECC&t?h3V8mmZ_fXk#+GJEZ1RWiz>d1hnCk;3r|EYS{B);O22|_M5 z{Q<+F38nu5D-=aYo2bfPCn5XLDa)8=UticVvt+9t9=yyxtqI0shtJO-6?JjANVm9* dF+UvQ_78oPLa*4o0&D;P002ovPDHLkV1hXi@}~d* delta 710 zcmV;%0y+Jr1kVK_iBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_>mzOe*%F? zL_t(YiItX5Px3$z#-EukEnqQVj9xT)_3StCv%a6igYj-Wl3=hP-9O`D-eKE{7&akn zcYZsaoqcA2o}QY205F*VtCe7}AXF701VISEb_?9x5SW4K6nK3V9OE||;Py823;?2g zAOeH{#HfzjR@XxSoCDTt!Ku7se^!GTcRL^@K}z}@BhWMg=Lnk(fmx37DFL6KnRi5L za1LMwyjLR;P?oy3-2&q=u-gfa@wWE$r7zy?1blr>dxIT2#{8X9hNn})kWVS|B0qV) zzh^jyAA?9g-s`jX>gW(J(&t4o&vmWQSWdf}LeP0x0;3TSqhQFJ7yyh$`iqqk@E0$Vc@e<9zo-52Qc`&>7V5yXZJT2RPUZRS sO^x Date: Mon, 8 Apr 2024 21:16:20 +0800 Subject: [PATCH 0729/1123] use DLLDeployer of new edition Signed-off-by: ToKiNoBug --- cmake/configure_DLLDeployer.cmake | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cmake/configure_DLLDeployer.cmake b/cmake/configure_DLLDeployer.cmake index 194852b6..c7121efd 100644 --- a/cmake/configure_DLLDeployer.cmake +++ b/cmake/configure_DLLDeployer.cmake @@ -1,5 +1,3 @@ - - function(SC_download url filename) if (EXISTS ${filename}) file(SIZE ${filename} size) @@ -21,17 +19,23 @@ function(SC_download url filename) endif () endfunction(SC_download) -set(DLLD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DLLDeployer) +set(DLLD_download_dir ${CMAKE_BINARY_DIR}/3rdParty/DLLDeployer) set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) set(QD_file ${DLLD_download_dir}/QtDeployer.cmake) if (${WIN32}) - SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/DLLDeployer.cmake - ${DLLD_file}) + file(DOWNLOAD https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/DLLDeployer.cmake + ${DLLD_file} + EXPECTED_HASH SHA512=6044ACEA50BFC9EACA37357BF2CD1497908905DAE0971F74B4BE4BAED6633420BDD38105FE21E47724B9653DEC4880BEBCA1341DC95AA9BD8144356C7DAB1899) + # SC_download(https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/DLLDeployer.cmake + # ${DLLD_file}) include(${DLLD_file}) endif () if (WIN32 OR APPLE) - SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake - ${QD_file}) + file(DOWNLOAD https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/QtDeployer.cmake + ${QD_file} + EXPECTED_HASH SHA512=7A6E7FEE90DEBC0A4E6BDC4CB65D87DF453E8B24C6ED9E188C174BF64C526CA232FA63211CA661E4B26D06A141291AB0AB3CC499B64775B23FC0E622E0CEA0B4) + # SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake + # ${QD_file}) include(${QD_file}) endif () From 7b30feb2bd5bc2014b475ee55c69c733652d9f72 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 8 Apr 2024 21:16:37 +0800 Subject: [PATCH 0730/1123] fix load_scl_blocklist Signed-off-by: ToKiNoBug --- SlopeCraftL/tests/load_scl_blocklist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp index 97295ebd..86d85e31 100644 --- a/SlopeCraftL/tests/load_scl_blocklist.cpp +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include int main(int argc, char** argv) { From f2ef2e67cb827e606b77d1f7f3382f4affd1ef4b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:22:05 +0800 Subject: [PATCH 0731/1123] make slopecraft adapt to new designing of block list Signed-off-by: ToKiNoBug --- Blocks/README.md | 41 +++--- SlopeCraft/BlockListDialog.cpp | 15 ++ SlopeCraft/BlockListDialog.h | 27 ++++ SlopeCraft/BlockListDialog.ui | 82 +++++++++++ SlopeCraft/CMakeLists.txt | 13 +- SlopeCraft/PreviewWind.cpp | 2 +- SlopeCraft/SCWind.cpp | 6 +- SlopeCraft/install.cmake | 91 ++++-------- SlopeCraftL/SlopeCraftL.cpp | 2 +- SlopeCraftL/SlopeCraftL.h | 7 +- SlopeCraftL/simpleBlock.h | 12 +- utilities/BlockListManager/Block.cpp | 2 +- .../BlockListManager/BlockListManager.cpp | 135 +++++++++--------- utilities/BlockListManager/BlockListManager.h | 15 +- utilities/libpngReader/libpng_reader.cpp | 1 - 15 files changed, 268 insertions(+), 183 deletions(-) create mode 100644 SlopeCraft/BlockListDialog.cpp create mode 100644 SlopeCraft/BlockListDialog.h create mode 100644 SlopeCraft/BlockListDialog.ui diff --git a/Blocks/README.md b/Blocks/README.md index 59130c68..b3a52954 100644 --- a/Blocks/README.md +++ b/Blocks/README.md @@ -1,25 +1,27 @@ # 方块列表 + 这个文件夹存储了方块列表相关。 **FixedBlocks.json**是软件固定的方块列表,是最基础的那部分。每个方块相应的图片都存储在**FixedBlocks**文件夹下。正常情况下无需任何改动。 -**CustomBlocks.json**是用户自定义的方块列表,允许用户灵活编辑。我在里面写了一些半砖方块,可以作为参考。**CustomBlocks**文件夹里有用户自定义方块的图片。 +**CustomBlocks.json**是用户自定义的方块列表,允许用户灵活编辑。我在里面写了一些半砖方块,可以作为参考。**CustomBlocks** +文件夹里有用户自定义方块的图片。 每个方块拥有以下属性: -| 属性名 | 类型 | 是否必填 | 默认值 | 说明 | -| :--------------: | :----: | :------: | :------: | -------------------------------------------------------------------------- | -| baseColor | byte | 是 | | 方块的地图基色 | -| id | string | 是 | | 方块 id,附上详细方块状态,如*minecraft:target[power=0]* | -| version | byte | 是 | | 方块最早出现的版本。0 代表 1.12 以前,12 代表 1.12,17 代表 1.17,以此类推 | -| nameZH | string | 是 | | 方块的中文名 | -| nameEN | string | 是 | | 方块的英文名 | -| icon | string | 是 | | 方块对应图片的文件名(仅文件名,如*cobblestone.png*) | -| idOld | string | 否 | 空字符串 | 方块在 1.12 的 id | -| needGlass | bool | 否 | false | 指示方块底部是否必须有其他方块(如灯笼) | -| isGlowing | bool | 否 | false | 指示方块是否发光 | -| endermanPickable | bool | 否 | false | 指示方块是否可以被末影人偷走 | -| burnable | bool | 否 | false | 指示方块是否可以被烧毁 | +| 属性名 | 类型 | 是否必填 | 默认值 | 说明 | +|:----------------:|:------:|:----:|:-----:|---------------------------------------------------| +| baseColor | byte | 是 | | 方块的地图基色 | +| id | string | 是 | | 方块 id,附上详细方块状态,如*minecraft:target[power=0]* | +| version | byte | 是 | | 方块最早出现的版本。0 代表 1.12 以前,12 代表 1.12,17 代表 1.17,以此类推 | +| nameZH | string | 是 | | 方块的中文名 | +| nameEN | string | 是 | | 方块的英文名 | +| icon | string | 是 | | 方块对应图片的文件名(仅文件名,如*cobblestone.png*) | +| idOld | string | 否 | 空字符串 | 方块在 1.12 的 id | +| needGlass | bool | 否 | false | 指示方块底部是否必须有其他方块(如灯笼) | +| isGlowing | bool | 否 | false | 指示方块是否发光 | +| endermanPickable | bool | 否 | false | 指示方块是否可以被末影人偷走 | +| burnable | bool | 否 | false | 指示方块是否可以被烧毁 | 其中选填项可以跳过不填,SlopeCraft 会自动补全为默认值。 @@ -27,16 +29,21 @@
# BlockList + Everything about blocklist is in this directory. -**FixedBlocks.json** stores all default blocks, acting as a fundamental blocklist to make sure that each basecolor has at least one block. Image of each block is stored in directory named **FixedBlocks**. Usually you don't need to change anything about fixed blocklist. +**FixedBlocks.json** stores all default blocks, acting as a fundamental blocklist to make sure that each +basecolor_widgets has at least one block. Image of each block is stored in directory named **FixedBlocks**. Usually you +don't need to change anything about fixed blocklist. -**CustomBlocks.json** stores all user custom blocks, enabling users to use their favorite blocks in map art. Some slab blocks have been already written in this file as examples. Each block should have a corresponding image in **CustomBlocks** directory. Different blocks can share single image file. +**CustomBlocks.json** stores all user custom blocks, enabling users to use their favorite blocks in map art. Some slab +blocks have been already written in this file as examples. Each block should have a corresponding image in * +*CustomBlocks** directory. Different blocks can share single image file. Each block has following attributes: | Name | Type | Is Compulsory Item | Default Value | Description | -| :--------------: | :----: | :----------------: | :-----------: |:-----------------------------------------------------------------------------------------------------------| +|:----------------:|:------:|:------------------:|:-------------:|:-----------------------------------------------------------------------------------------------------------| | baseColor | byte | Yes | | The base color of this block | | id | string | Yes | | Block id in minecraft with full blockstates, like *minecraft:target[power=0]* | | version | byte | Yes | | The earlist version when block is added. 0 means earlier than 1.12, 12 means 1.12, 17 means 1.17 and so on | diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp new file mode 100644 index 00000000..8887acba --- /dev/null +++ b/SlopeCraft/BlockListDialog.cpp @@ -0,0 +1,15 @@ +// +// Created by Joseph on 2024/4/9. +// + +#include "BlockListDialog.h" +#include "ui_BlockListDialog.h" + +BlockListDialog::BlockListDialog(QWidget *parent) + : QDialog{parent}, ui{new Ui::BlockListDialog} { + this->ui->setupUi(this); +} + +BlockListDialog::~BlockListDialog() { + // delete this->ui; +} diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h new file mode 100644 index 00000000..98ebbb4d --- /dev/null +++ b/SlopeCraft/BlockListDialog.h @@ -0,0 +1,27 @@ +// +// Created by Joseph on 2024/4/9. +// + +#ifndef SLOPECRAFT_BLOCKLISTDIALOG_H +#define SLOPECRAFT_BLOCKLISTDIALOG_H + +#include +#include + +class BlockListDialog; + +namespace Ui { +class BlockListDialog; +} + +class BlockListDialog : public QDialog { + Q_OBJECT + private: + std::unique_ptr ui; + + public: + explicit BlockListDialog(QWidget* parent); + ~BlockListDialog(); +}; + +#endif // SLOPECRAFT_BLOCKLISTDIALOG_H diff --git a/SlopeCraft/BlockListDialog.ui b/SlopeCraft/BlockListDialog.ui new file mode 100644 index 00000000..b1441e89 --- /dev/null +++ b/SlopeCraft/BlockListDialog.ui @@ -0,0 +1,82 @@ + + + BlockListDialog + + + + 0 + 0 + 687 + 481 + + + + 加载/删除方块列表 + + + + + + + + + + 0 + 0 + + + + + + + + 0 + + + + + + + + + + + + + - + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 确定 + + + + + + + 取消 + + + + + + + + + + diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 68e45e36..641eacf4 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -12,10 +12,10 @@ find_package(magic_enum REQUIRED) set(SlopeCraft_rc_files) -if(${WIN32}) +if (${WIN32}) configure_file(others/SlopeCraft.rc.in ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.rc) set(SlopeCraft_rc_files ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.rc) -endif() +endif () set(SlopeCraft_headers SCWind.h @@ -28,6 +28,7 @@ set(SlopeCraft_headers CopyableTableView.h TransparentStrategyWind.h CompressEffectViewer.h + BlockListDialog.h ) set(SlopeCraft_sources @@ -42,6 +43,7 @@ set(SlopeCraft_sources CopyableTableView.cpp TransparentStrategyWind.cpp CompressEffectViewer.cpp + BlockListDialog.cpp main.cpp ${SlopeCraft_rc_files}) @@ -52,6 +54,7 @@ set(SlopeCraft_uis AiCvterParameterDialog.ui TransparentStrategyWind.ui CompressEffectViewer.ui + BlockListDialog.ui ) set(SlopeCraft_ts_files @@ -70,7 +73,7 @@ qt_add_executable(SlopeCraft MANUAL_FINALIZATION ${SlopeCraft_project_files}) -target_compile_features(SlopeCraft PRIVATE cxx_std_20) +target_compile_features(SlopeCraft PRIVATE cxx_std_23) target_link_libraries(SlopeCraft PRIVATE Qt6::Core @@ -118,13 +121,13 @@ qt_add_resources(SlopeCraft "SC_translations" qt_finalize_executable(SlopeCraft) -if(${WIN32}) +if (${WIN32}) add_custom_target(SC_create_symlink_SC COMMAND mklink SlopeCraftL.dll "..\\SlopeCraftL\\SlopeCraftL.dll" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS SlopeCraftL COMMENT "Create symlink to SlopeCraftL.dll for SlopeCraft.exe") add_dependencies(SC_create_all_symlinks SC_create_symlink_SC) -endif() +endif () include(install.cmake) \ No newline at end of file diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index c87e6eaf..7655f2b7 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -200,7 +200,7 @@ QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { if (role == Qt::ItemDataRole::DecorationRole) { if (c == 0) { QImage img{16, 16, QImage::Format_ARGB32}; - mat.blk->getImage((uint32_t*)img.scanLine(0), true); + mat.blk->getImage((uint32_t*)img.scanLine(0)); return QIcon{QPixmap::fromImage(img)}; } } diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 1fb8bb05..b6da7c17 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -132,10 +132,8 @@ SCWind::SCWind(QWidget *parent) QDir::setCurrent(QCoreApplication::applicationDirPath()); - this->ui->blm->add_blocklist("./Blocks/FixedBlocks.json", - "./Blocks/FixedBlocks"); - this->ui->blm->add_blocklist("./Blocks/CustomBlocks.json", - "./Blocks/CustomBlocks"); + this->ui->blm->add_blocklist("./Blocks/FixedBlocks.zip"); + this->ui->blm->add_blocklist("./Blocks/CustomBlocks.zip"); this->ui->blm->finish_blocklist(); diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 373b5c34..befb0784 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -1,13 +1,21 @@ -file(GLOB SlopeCraft_install_jsons - "${CMAKE_SOURCE_DIR}/Blocks/*.json" - "${CMAKE_SOURCE_DIR}/Blocks/*.md") - -file(GLOB SlopeCraft_install_png_fixedblocks - "${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks/*.png") - -file(GLOB SlopeCraft_install_png_customblocks - "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") +#file(GLOB SlopeCraft_install_jsons +# "${CMAKE_SOURCE_DIR}/Blocks/*.json" +# "${CMAKE_SOURCE_DIR}/Blocks/*.md") +# +#file(GLOB SlopeCraft_install_png_fixedblocks +# "${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks/*.png") +# +#file(GLOB SlopeCraft_install_png_customblocks +# "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") + +file(GLOB SlopeCraft_block_list_archives + "${CMAKE_BINARY_DIR}/SCL_block_lists/*.zip") + +list(LENGTH SlopeCraft_block_list_archives num_archives) +if (${num_archives} LESS_EQUAL 0) + message(FATAL_ERROR "No archive preset found") +endif () file(GLOB SlopeCraft_install_presets "${CMAKE_CURRENT_SOURCE_DIR}/others/presets/*.sc_preset_json") @@ -33,23 +41,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") DESTINATION SlopeCraft.app/Contents/Resources RENAME SlopeCraft.icns) - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} + # Install all block list archives + install(FILES ${SlopeCraft_install_presets} DESTINATION SlopeCraft.app/Contents/MacOS/Blocks) - file(COPY ${SlopeCraft_install_jsons} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks) - - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/CustomBlocks) + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/) # Install presets install(FILES ${SlopeCraft_install_presets} @@ -82,17 +78,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") RUNTIME DESTINATION . ) - # # Run windeployqt at build time - # add_custom_target(Windeployqt-SlopeCraft - # COMMAND ${SlopeCraft_Qt_windeployqt_executable} SlopeCraft.exe ${SlopeCraft_windeployqt_flags_build} - # COMMAND_EXPAND_LISTS - # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # DEPENDS SlopeCraft) - # add_dependencies(SC_deploy_all Windeployqt-SlopeCraft) - # - # # Run windeployqt at install time - # install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/deploy_qt.cmake) - QD_add_deployqt(SlopeCraft BUILD_MODE FLAGS ${SlopeCraft_windeployqt_flags_build}) @@ -104,24 +89,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") INSTALL_MODE INSTALL_DESTINATION . IGNORE SlopeCraftL.dll) - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} + # Install all block list archives + install(FILES ${SlopeCraft_block_list_archives} DESTINATION Blocks) - file(COPY ${SlopeCraft_install_jsons} + file(COPY ${SlopeCraft_block_list_archives} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION Blocks/CustomBlocks) - file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) - # Install presets install(FILES ${SlopeCraft_install_presets} DESTINATION Blocks/Presets) @@ -140,24 +113,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") RUNTIME DESTINATION bin ) - # Install FixedBlocks.json, CustomBlocks.json and README.md - install(FILES ${SlopeCraft_install_jsons} + # Install all block list archives + install(FILES ${SlopeCraft_block_list_archives} DESTINATION bin/Blocks) - file(COPY ${SlopeCraft_install_jsons} + file(COPY ${SlopeCraft_block_list_archives} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks) - # Install all png files of fixedblocks - install(FILES ${SlopeCraft_install_png_fixedblocks} - DESTINATION bin/Blocks/FixedBlocks) - file(COPY ${SlopeCraft_install_png_fixedblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/FixedBlocks) - - # Install all png files of customblocks - install(FILES ${SlopeCraft_install_png_customblocks} - DESTINATION bin/Blocks/CustomBlocks) - file(COPY ${SlopeCraft_install_png_customblocks} - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Blocks/CustomBlocks) - install(FILES others/SlopeCraftIconNew.png DESTINATION share/pixmaps diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 25037f01..a158c60d 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -283,7 +283,7 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { } } assert(buf_pixel.size() == 16 * 16); - memcpy(pair.first->image.data(), buf_pixel.data(), 256); + memcpy(pair.first->image.data(), buf_pixel.data(), 256 * sizeof(uint32_t)); } return {bl, warnings}; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 3960ce08..6e5ee585 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -75,6 +75,11 @@ struct StringDeliver { constexpr bool is_valid() const noexcept { return this->data != nullptr && this->capacity > 0; } + + template + [[nodiscard]] static StringDeliver from_string(string_t &s) noexcept { + return StringDeliver{s.data(), s.size()}; + } }; class AbstractBlock { @@ -104,7 +109,7 @@ class AbstractBlock { constexpr int imageRows() const noexcept { return 16; } constexpr int imageCols() const noexcept { return 16; } - virtual void getImage(uint32_t *dest, bool is_row_major) const noexcept = 0; + virtual void getImage(uint32_t *dest_row_major) const noexcept = 0; /// set block id virtual void setId(const char *) noexcept = 0; diff --git a/SlopeCraftL/simpleBlock.h b/SlopeCraftL/simpleBlock.h index e5fb1c6a..cf7e7e5e 100644 --- a/SlopeCraftL/simpleBlock.h +++ b/SlopeCraftL/simpleBlock.h @@ -44,7 +44,7 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { std::string nameZH; std::string nameEN; std::string imageFilename; - Eigen::ArrayXX image; + Eigen::Array image; bool needGlass{false}; bool doGlow{false}; bool endermanPickable{false}; @@ -70,13 +70,9 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { return this->imageFilename.c_str(); } - void getImage(uint32_t *dest, bool is_row_major) const noexcept override { - if (is_row_major) { - Eigen::Map> map(dest, 16, 16); - map = this->image.transpose(); - } else { - memcpy(dest, this->image.data(), this->image.size() * sizeof(uint32_t)); - } + void getImage(uint32_t *dest_row_major) const noexcept override { + memcpy(dest_row_major, this->image.data(), + this->image.size() * sizeof(uint32_t)); } void setId(const char *_id) noexcept override { id = _id; }; diff --git a/utilities/BlockListManager/Block.cpp b/utilities/BlockListManager/Block.cpp index aad96056..6b1b5911 100644 --- a/utilities/BlockListManager/Block.cpp +++ b/utilities/BlockListManager/Block.cpp @@ -5,7 +5,7 @@ BlockWidget::BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk) this->setText(this->block->getNameZH()); QImage img{this->block->imageCols(), this->block->imageRows(), QImage::Format_ARGB32}; - this->block->getImage(reinterpret_cast(img.scanLine(0)), true); + this->block->getImage(reinterpret_cast(img.scanLine(0))); this->setIcon(QIcon{QPixmap::fromImage(img)}); }; diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 178419b6..351cf161 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -11,11 +11,8 @@ BlockListManager::~BlockListManager() {} void BlockListManager::setup_basecolors( const SlopeCraft::Kernel *kernel) noexcept { - for (auto bcp : this->basecolors) { - delete bcp; - } - this->basecolors.clear(); - this->basecolors.reserve(64); + this->basecolor_widgets.clear(); + this->basecolor_widgets.reserve(64); const int max_basecolor = SlopeCraft::SCL_maxBaseColor(); uint32_t bc_arr[64]; @@ -23,87 +20,81 @@ void BlockListManager::setup_basecolors( kernel->getBaseColorInARGB32(bc_arr); for (int bc = 0; bc <= max_basecolor; bc++) { - BaseColorWidget *bcw = new BaseColorWidget(this, bc); - this->layout()->addWidget(bcw); - this->basecolors.push_back(bcw); + std::unique_ptr bcw{new BaseColorWidget(this, bc)}; + this->layout()->addWidget(bcw.get()); bcw->setTitle(QString::fromUtf8(basecolor_names[bc].data())); - bcw->set_color(bc_arr[bc]); - connect(bcw, &BaseColorWidget::changed, [this]() { emit this->changed(); }); - } -} - -bool callback_load_image(const char *filename, uint32_t *dst_row_major) { - QImage img(QString::fromLocal8Bit(filename)); - - if (img.isNull()) { - return false; + connect(bcw.get(), &BaseColorWidget::changed, + [this]() { emit this->changed(); }); + this->basecolor_widgets.push_back(std::move(bcw)); } - - QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); - - memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); - return true; } -bool BlockListManager::impl_addblocklist( - const QString &filename, const QString &dirname, - std::unique_ptr - &dst) noexcept { +// bool callback_load_image(const char *filename, uint32_t *dst_row_major) { +// QImage img(QString::fromLocal8Bit(filename)); +// +// if (img.isNull()) { +// return false; +// } +// +// QImage another = img.convertedTo(QImage::Format_ARGB32).scaled(16, 16); +// +// memcpy(dst_row_major, another.scanLine(0), 16 * 16 * sizeof(uint32_t)); +// return true; +// } + +std::unique_ptr +BlockListManager::impl_addblocklist(const QString &filename) noexcept { std::string errmsg; - errmsg.resize(4096); - SlopeCraft::blockListOption opt; - opt.errmsg = errmsg.data(); - opt.errmsg_capacity = errmsg.size(); - size_t msg_len{0}; - opt.errmsg_len_dest = &msg_len; - - auto img_dir_local8bit = dirname.toLocal8Bit(); - opt.image_dir = img_dir_local8bit.data(); - - opt.callback_load_image = callback_load_image; + errmsg.resize(8192); + auto sd_err = SlopeCraft::StringDeliver::from_string(errmsg); + std::string warning; + warning.resize(8192); + auto sd_warn = SlopeCraft::StringDeliver::from_string(warning); + SlopeCraft::BlockListCreateOption option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::BlockListInterface *bli = - SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), opt); - - errmsg.resize(msg_len); + SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), option); + errmsg.resize(sd_err.size); + warning.resize(sd_warn.size); if (!errmsg.empty()) { - errmsg.append(QStringLiteral("\npwd: %1").arg(QFileInfo{"."}.absolutePath()).toLocal8Bit()); + errmsg.append(QStringLiteral("\npwd: %1") + .arg(QFileInfo{"."}.absolutePath()) + .toLocal8Bit()); if (bli == nullptr) { QMessageBox::critical(dynamic_cast(this->parent()), tr("解析方块列表失败"), QString::fromUtf8(errmsg.data())); - return false; + return {nullptr}; } else { QMessageBox::warning(dynamic_cast(this->parent()), tr("解析方块列表失败"), - QString::fromUtf8(errmsg.data())); + QString::fromUtf8(warning.data())); } } - dst.reset(bli); std::vector blockps; - std::vector basecolors; - basecolors.resize(dst->size()); - blockps.resize(dst->size()); + std::vector base_colors; + base_colors.resize(bli->size()); + blockps.resize(bli->size()); - dst->get_blocks(blockps.data(), basecolors.data(), blockps.size()); + bli->get_blocks(blockps.data(), base_colors.data(), blockps.size()); - for (size_t idx = 0; idx < dst->size(); idx++) { - this->basecolors[basecolors[idx]]->add_block(blockps[idx]); + for (size_t idx = 0; idx < bli->size(); idx++) { + this->basecolor_widgets[base_colors[idx]]->add_block(blockps[idx]); } - return true; + return std::unique_ptr{bli}; } -bool BlockListManager::add_blocklist(QString filename, - QString dirname) noexcept { - std::unique_ptr tmp; +bool BlockListManager::add_blocklist(QString filename) noexcept { + std::unique_ptr tmp = + this->impl_addblocklist(filename); - if (!this->impl_addblocklist(filename, dirname, tmp)) { + if (!tmp) { return false; } @@ -113,13 +104,13 @@ bool BlockListManager::add_blocklist(QString filename, } void BlockListManager::finish_blocklist() noexcept { - for (auto bcw : this->basecolors) { + for (auto &bcw : this->basecolor_widgets) { bcw->finish_blocks(); } } void BlockListManager::when_version_updated() noexcept { - for (auto bcw : this->basecolors) { + for (auto &bcw : this->basecolor_widgets) { bcw->when_version_updated(this->callback_get_version()); } } @@ -130,29 +121,29 @@ void BlockListManager::get_blocklist( enable_list.resize(64); block_list.resize(64); - for (int bc = 0; bc < (int)this->basecolors.size(); bc++) { - enable_list[bc] = this->basecolors[bc]->is_enabled(); - block_list[bc] = this->basecolors[bc]->selected_block(); + for (int bc = 0; bc < (int)this->basecolor_widgets.size(); bc++) { + enable_list[bc] = this->basecolor_widgets[bc]->is_enabled(); + block_list[bc] = this->basecolor_widgets[bc]->selected_block(); } - for (int bc = (int)this->basecolors.size(); bc < 64; bc++) { + for (int bc = (int)this->basecolor_widgets.size(); bc < 64; bc++) { enable_list[bc] = 0; block_list[bc] = nullptr; } } bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { - if (preset.values.size() != this->basecolors.size()) { + if (preset.values.size() != this->basecolor_widgets.size()) { QMessageBox::warning(dynamic_cast(this->parent()), tr("加载预设错误"), tr("预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符") .arg(preset.values.size()) - .arg(this->basecolors.size())); + .arg(this->basecolor_widgets.size())); return false; } for (int bc = 0; bc < (int)preset.values.size(); bc++) { - auto &bcw = this->basecolors[bc]; + auto &bcw = this->basecolor_widgets[bc]; bcw->set_enabled(preset.values[bc].first); @@ -175,8 +166,8 @@ bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, QMessageBox::StandardButton::Close}); if (ret == QMessageBox::StandardButton::Close) { - abort(); - return false; + exit(__LINE__); + // return false; } continue; } @@ -191,11 +182,13 @@ bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { blockListPreset BlockListManager::to_preset() const noexcept { blockListPreset ret; - ret.values.resize(this->basecolors.size()); - for (size_t basecolor = 0; basecolor < this->basecolors.size(); basecolor++) { - ret.values[basecolor].first = this->basecolors[basecolor]->is_enabled(); + ret.values.resize(this->basecolor_widgets.size()); + for (size_t basecolor = 0; basecolor < this->basecolor_widgets.size(); + basecolor++) { + ret.values[basecolor].first = + this->basecolor_widgets[basecolor]->is_enabled(); ret.values[basecolor].second = QString::fromUtf8( - this->basecolors[basecolor]->selected_block()->getId()); + this->basecolor_widgets[basecolor]->selected_block()->getId()); } return ret; } diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 0b535c88..dba4d537 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -32,7 +32,7 @@ class BlockListDeleter { class BlockListManager : public QWidget { Q_OBJECT private: - std::vector basecolors; + std::vector> basecolor_widgets; std::vector> blockslists; std::function callback_get_version{nullptr}; @@ -43,7 +43,7 @@ class BlockListManager : public QWidget { void setup_basecolors(const SlopeCraft::Kernel *kernel) noexcept; - bool add_blocklist(QString filename, QString dirname) noexcept; + bool add_blocklist(QString filename) noexcept; void finish_blocklist() noexcept; @@ -59,13 +59,13 @@ class BlockListManager : public QWidget { void when_version_updated() noexcept; void when_lang_updated(SCL_language lang) noexcept { - for (auto bcw : this->basecolors) { + for (auto &bcw : this->basecolor_widgets) { bcw->update_lang(lang); } } void select_block_by_callback(const select_callback_t &fun) noexcept { - for (auto bcw : this->basecolors) { + for (auto &bcw : this->basecolor_widgets) { bcw->select_by_callback(fun); } } @@ -79,16 +79,15 @@ class BlockListManager : public QWidget { blockListPreset to_preset() const noexcept; const BaseColorWidget *basecolorwidget_at(size_t basecolor) const noexcept { - return this->basecolors[basecolor]; + return this->basecolor_widgets[basecolor].get(); } signals: void changed(); private: - bool impl_addblocklist(const QString &filename, const QString &dirname, - std::unique_ptr &dst) noexcept; + std::unique_ptr + impl_addblocklist(const QString &filename) noexcept; }; #endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index ef91649d..4f1e721a 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -126,7 +126,6 @@ parse_png_into_argb32(std::span encoded, std::vector row_ptrs; row_ptrs.resize(height); - for (int r = 0; r < int(height); r++) { row_ptrs[r] = reinterpret_cast(pixels.data() + r * width); } From 0f4073e907cf57b780c06c5d7cad9198de8f03ba Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:38:00 +0800 Subject: [PATCH 0732/1123] rearrange all deps Signed-off-by: ToKiNoBug --- CMakeLists.txt | 13 ++++++------- SlopeCraftL/CMakeLists.txt | 6 ------ VisualCraft/CMakeLists.txt | 2 -- VisualCraftL/CMakeLists.txt | 4 +--- VisualCraftL/setup_zip_names.cmake | 4 +--- cmake/add_compiler_path_to_prefix.cmake | 8 ++++---- .../kompute.cmake} | 0 .../Eigen3.cmake} | 0 .../HeuristicFlow.cmake} | 0 .../VCL-test-images.cmake} | 0 .../_DLLDeployer.cmake} | 0 .../_DylibDeployer.cmake} | 2 +- .../_ResourceCreator.cmake} | 0 .../boost.cmake} | 0 .../cereal.cmake} | 0 .../cli11.cmake} | 0 .../fmtlib.cmake} | 0 .../libpng.cmake} | 0 .../libzip.cmake} | 0 .../magic_enum.cmake} | 0 .../nlohmann_json.cmake} | 0 .../{find_qt6.cmake => required_deps/qt6.cmake} | 0 .../tl-expected.cmake} | 0 .../vanilla_zips.cmake} | 0 .../xsimd.cmake} | 0 .../zstd.cmake} | 0 utilities/BlockListManager/CMakeLists.txt | 3 --- utilities/ColorManip/CMakeLists.txt | 9 --------- utilities/FlatDiagram/CMakeLists.txt | 3 --- utilities/GPUWrapper/CMakeLists.txt | 1 - utilities/GPUWrapper/OpenCL/CMakeLists.txt | 1 - utilities/MCDataVersion/CMakeLists.txt | 6 ++---- utilities/MapImageCvter/CMakeLists.txt | 6 ++---- utilities/Schem/CMakeLists.txt | 7 ++----- utilities/VersionDialog/CMakeLists.txt | 2 -- vccl/CMakeLists.txt | 16 ++++------------ vccl/add_test_vccl.cmake | 12 +++++------- 37 files changed, 28 insertions(+), 77 deletions(-) rename cmake/{configure_kompute.cmake => optional_deps/kompute.cmake} (100%) rename cmake/{find_Eigen3.cmake => required_deps/Eigen3.cmake} (100%) rename cmake/{find_HeuristicFlow.cmake => required_deps/HeuristicFlow.cmake} (100%) rename cmake/{configure_images.cmake => required_deps/VCL-test-images.cmake} (100%) rename cmake/{configure_DLLDeployer.cmake => required_deps/_DLLDeployer.cmake} (100%) rename cmake/{configure_DylibDeployer.cmake => required_deps/_DylibDeployer.cmake} (89%) rename cmake/{find_ResourceCreator.cmake => required_deps/_ResourceCreator.cmake} (100%) rename cmake/{configure_boost.cmake => required_deps/boost.cmake} (100%) rename cmake/{configure_cereal.cmake => required_deps/cereal.cmake} (100%) rename cmake/{configure_cli11.cmake => required_deps/cli11.cmake} (100%) rename cmake/{configure_fmtlib.cmake => required_deps/fmtlib.cmake} (100%) rename cmake/{configure_libpng.cmake => required_deps/libpng.cmake} (100%) rename cmake/{configure_libzip.cmake => required_deps/libzip.cmake} (100%) rename cmake/{configure_magic_enum.cmake => required_deps/magic_enum.cmake} (100%) rename cmake/{find_nlohmann_json.cmake => required_deps/nlohmann_json.cmake} (100%) rename cmake/{find_qt6.cmake => required_deps/qt6.cmake} (100%) rename cmake/{configure_tl_expected.cmake => required_deps/tl-expected.cmake} (100%) rename cmake/{configure_vanilla_zips.cmake => required_deps/vanilla_zips.cmake} (100%) rename cmake/{configure_xsimd.cmake => required_deps/xsimd.cmake} (100%) rename cmake/{configure_zstd.cmake => required_deps/zstd.cmake} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7857a840..c5d0c9a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,15 +67,14 @@ if (EXISTS ${CMAKE_SOURCE_DIR}/compile_commands.json) endif () # configure global dependencies ---------------------------------------------- -include(cmake/configure_libpng.cmake) + include(cmake/add_compiler_path_to_prefix.cmake) -include(cmake/find_nlohmann_json.cmake) -include(cmake/find_Eigen3.cmake) -include(cmake/find_HeuristicFlow.cmake) -include(cmake/find_qt6.cmake) -include(cmake/configure_DLLDeployer.cmake) -include(cmake/configure_DylibDeployer.cmake) +file(GLOB required_dep_cmake_files "${CMAKE_SOURCE_DIR}/cmake/required_deps/*.cmake") +foreach (file ${required_dep_cmake_files}) + include(${file}) +endforeach () + # Add compile options -------------------------------------------------------- # if don't vectorize, or no suitable flag found, this variable will be empty diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 2728f394..a626a670 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -1,11 +1,5 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) -include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_zstd.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_libpng.cmake) - find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index f4f1e539..cafb420f 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -122,8 +122,6 @@ qt_add_resources(VisualCraft "VC_translations" qt_finalize_executable(VisualCraft) -include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) - configure_file(vc-config-to-bin-dir.json.in vc-config.json) if (${WIN32}) diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index ef2ff9ae..0476a16d 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -77,9 +77,7 @@ add_library(VisualCraftL_static STATIC find_package(ZLIB 1.2.11 REQUIRED) find_package(libzip 1.7.0 REQUIRED) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) -find_package(fmt 9.1.0 REQUIRED) +find_package(fmt 10.0.0 REQUIRED) set(VCL_include_dirs ${SlopeCraft_Nlohmann_json_include_dir} diff --git a/VisualCraftL/setup_zip_names.cmake b/VisualCraftL/setup_zip_names.cmake index bd1b912f..8e8ccfac 100644 --- a/VisualCraftL/setup_zip_names.cmake +++ b/VisualCraftL/setup_zip_names.cmake @@ -1,7 +1,5 @@ set(VCL_app_files - ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) + ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) foreach (mcver RANGE 12 20) set(VCL_current_var_name VCL_resource_${mcver}) diff --git a/cmake/add_compiler_path_to_prefix.cmake b/cmake/add_compiler_path_to_prefix.cmake index 17b958e7..6c4ff588 100644 --- a/cmake/add_compiler_path_to_prefix.cmake +++ b/cmake/add_compiler_path_to_prefix.cmake @@ -1,6 +1,6 @@ -if(NOT DEFINED CMAKE_CXX_COMPILER) +if (NOT DEFINED CMAKE_CXX_COMPILER) message(FATAL_ERROR "Cpp compiler not found : CMAKE_CXX_COMPILER is not defined.") -endif() +endif () # message("CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}") cmake_path(GET CMAKE_CXX_COMPILER PARENT_PATH temp) @@ -8,13 +8,13 @@ cmake_path(GET temp PARENT_PATH temp) list(FIND CMAKE_PREFIX_PATH temp out_temp) -if(${out_temp} LESS 0) +if (NOT ${temp} IN_LIST CMAKE_PREFIX_PATH) message(STATUS "Added the installation prefix of compiler to CMAKE_PREFIX_PATH") list(APPEND CMAKE_PREFIX_PATH ${temp}) # set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${temp}) message("CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") -endif() +endif () unset(temp) unset(out_temp) diff --git a/cmake/configure_kompute.cmake b/cmake/optional_deps/kompute.cmake similarity index 100% rename from cmake/configure_kompute.cmake rename to cmake/optional_deps/kompute.cmake diff --git a/cmake/find_Eigen3.cmake b/cmake/required_deps/Eigen3.cmake similarity index 100% rename from cmake/find_Eigen3.cmake rename to cmake/required_deps/Eigen3.cmake diff --git a/cmake/find_HeuristicFlow.cmake b/cmake/required_deps/HeuristicFlow.cmake similarity index 100% rename from cmake/find_HeuristicFlow.cmake rename to cmake/required_deps/HeuristicFlow.cmake diff --git a/cmake/configure_images.cmake b/cmake/required_deps/VCL-test-images.cmake similarity index 100% rename from cmake/configure_images.cmake rename to cmake/required_deps/VCL-test-images.cmake diff --git a/cmake/configure_DLLDeployer.cmake b/cmake/required_deps/_DLLDeployer.cmake similarity index 100% rename from cmake/configure_DLLDeployer.cmake rename to cmake/required_deps/_DLLDeployer.cmake diff --git a/cmake/configure_DylibDeployer.cmake b/cmake/required_deps/_DylibDeployer.cmake similarity index 89% rename from cmake/configure_DylibDeployer.cmake rename to cmake/required_deps/_DylibDeployer.cmake index 9c48969e..5be08553 100644 --- a/cmake/configure_DylibDeployer.cmake +++ b/cmake/required_deps/_DylibDeployer.cmake @@ -2,7 +2,7 @@ if (NOT APPLE) return() endif () -include(${CMAKE_CURRENT_LIST_DIR}/configure_DLLDeployer.cmake) +include(_DLLDeployer.cmake) set(DylibD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DylibDeployer.cmake) set(DylibD_file ${DylibD_download_dir}/DylibDeployer.cmake) diff --git a/cmake/find_ResourceCreator.cmake b/cmake/required_deps/_ResourceCreator.cmake similarity index 100% rename from cmake/find_ResourceCreator.cmake rename to cmake/required_deps/_ResourceCreator.cmake diff --git a/cmake/configure_boost.cmake b/cmake/required_deps/boost.cmake similarity index 100% rename from cmake/configure_boost.cmake rename to cmake/required_deps/boost.cmake diff --git a/cmake/configure_cereal.cmake b/cmake/required_deps/cereal.cmake similarity index 100% rename from cmake/configure_cereal.cmake rename to cmake/required_deps/cereal.cmake diff --git a/cmake/configure_cli11.cmake b/cmake/required_deps/cli11.cmake similarity index 100% rename from cmake/configure_cli11.cmake rename to cmake/required_deps/cli11.cmake diff --git a/cmake/configure_fmtlib.cmake b/cmake/required_deps/fmtlib.cmake similarity index 100% rename from cmake/configure_fmtlib.cmake rename to cmake/required_deps/fmtlib.cmake diff --git a/cmake/configure_libpng.cmake b/cmake/required_deps/libpng.cmake similarity index 100% rename from cmake/configure_libpng.cmake rename to cmake/required_deps/libpng.cmake diff --git a/cmake/configure_libzip.cmake b/cmake/required_deps/libzip.cmake similarity index 100% rename from cmake/configure_libzip.cmake rename to cmake/required_deps/libzip.cmake diff --git a/cmake/configure_magic_enum.cmake b/cmake/required_deps/magic_enum.cmake similarity index 100% rename from cmake/configure_magic_enum.cmake rename to cmake/required_deps/magic_enum.cmake diff --git a/cmake/find_nlohmann_json.cmake b/cmake/required_deps/nlohmann_json.cmake similarity index 100% rename from cmake/find_nlohmann_json.cmake rename to cmake/required_deps/nlohmann_json.cmake diff --git a/cmake/find_qt6.cmake b/cmake/required_deps/qt6.cmake similarity index 100% rename from cmake/find_qt6.cmake rename to cmake/required_deps/qt6.cmake diff --git a/cmake/configure_tl_expected.cmake b/cmake/required_deps/tl-expected.cmake similarity index 100% rename from cmake/configure_tl_expected.cmake rename to cmake/required_deps/tl-expected.cmake diff --git a/cmake/configure_vanilla_zips.cmake b/cmake/required_deps/vanilla_zips.cmake similarity index 100% rename from cmake/configure_vanilla_zips.cmake rename to cmake/required_deps/vanilla_zips.cmake diff --git a/cmake/configure_xsimd.cmake b/cmake/required_deps/xsimd.cmake similarity index 100% rename from cmake/configure_xsimd.cmake rename to cmake/required_deps/xsimd.cmake diff --git a/cmake/configure_zstd.cmake b/cmake/required_deps/zstd.cmake similarity index 100% rename from cmake/configure_zstd.cmake rename to cmake/required_deps/zstd.cmake diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index a57505bd..26951333 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -10,9 +10,6 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) -# include_directories(${CMAKE_SOURCE_DIR}) -include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) - set(BlockListManager_header_files BlockListManager.h BaseColor.h diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index afbb2ca8..02938ce6 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -1,16 +1,8 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) -# set(CMAKE_CXX_STANDARD 20) -# set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# include_directories(../SlopeCraftL) find_package(OpenMP REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_boost.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_xsimd.cmake) find_package(cereal REQUIRED) find_package(xsimd REQUIRED) find_package(Boost REQUIRED) @@ -69,7 +61,6 @@ if (${OpenCL_FOUND}) add_executable(test_algo tests/test_algo.cpp) target_link_libraries(test_algo PRIVATE OpenMP::OpenMP_CXX ColorManip) - include(${CMAKE_SOURCE_DIR}/cmake/configure_cli11.cmake) target_include_directories(test_algo PRIVATE ${cli11_include_dir}) foreach (_algo r R H X l L) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index 2d738e80..53ee38d1 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -1,9 +1,6 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) -include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) find_package(Eigen3 REQUIRED) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) add_library(FlatDiagram STATIC diff --git a/utilities/GPUWrapper/CMakeLists.txt b/utilities/GPUWrapper/CMakeLists.txt index 0ec0e4fa..0167c58e 100644 --- a/utilities/GPUWrapper/CMakeLists.txt +++ b/utilities/GPUWrapper/CMakeLists.txt @@ -6,7 +6,6 @@ add_library(GPUInterface STATIC target_include_directories(GPUInterface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_features(GPUInterface PUBLIC cxx_std_20) -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) target_link_libraries(GPUInterface PUBLIC fmt::fmt) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 34be996f..602e929f 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -2,7 +2,6 @@ find_package(OpenCL 3.0 REQUIRED) message(STATUS "Configuring OpenCL") -include(${CMAKE_SOURCE_DIR}/cmake/find_ResourceCreator.cmake) include(${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/ResourceCreator.cmake) target_sources(GPUInterface PRIVATE diff --git a/utilities/MCDataVersion/CMakeLists.txt b/utilities/MCDataVersion/CMakeLists.txt index cdc727f8..d7cfb6b5 100644 --- a/utilities/MCDataVersion/CMakeLists.txt +++ b/utilities/MCDataVersion/CMakeLists.txt @@ -5,8 +5,6 @@ add_library(MCDataVersion STATIC MCDataVersion.cpp ) -include(${CMAKE_SOURCE_DIR}/cmake/configure_magic_enum.cmake) - find_package(magic_enum REQUIRED) target_link_libraries(MCDataVersion PUBLIC magic_enum::magic_enum) @@ -14,6 +12,6 @@ target_compile_features(MCDataVersion PRIVATE cxx_std_20) target_include_directories(MCDataVersion INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(MCDataVersion PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() \ No newline at end of file +endif () \ No newline at end of file diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index 129278a9..223bb027 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -1,8 +1,6 @@ set(CMAKE_CXX_STANDARD 20) find_package(OpenMP REQUIRED) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) find_package(cereal REQUIRED) add_library(MapImageCvter @@ -25,6 +23,6 @@ target_compile_options(MapImageCvter PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_features(MapImageCvter PUBLIC cxx_std_20) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(MapImageCvter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() \ No newline at end of file +endif () \ No newline at end of file diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 19b472db..c9427848 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -11,11 +11,8 @@ add_library(Schem mushroom.cpp) find_package(Eigen3 REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_cereal.cmake) find_package(cereal REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_magic_enum.cmake) find_package(magic_enum REQUIRED) # target_compile_options(Schem BEFORE PUBLIC -std=c++17) @@ -28,6 +25,6 @@ target_link_libraries(Schem PUBLIC target_compile_features(Schem PUBLIC cxx_std_20) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(Schem PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() \ No newline at end of file +endif () \ No newline at end of file diff --git a/utilities/VersionDialog/CMakeLists.txt b/utilities/VersionDialog/CMakeLists.txt index 7ac24917..649289d4 100644 --- a/utilities/VersionDialog/CMakeLists.txt +++ b/utilities/VersionDialog/CMakeLists.txt @@ -29,8 +29,6 @@ add_library(VersionDialog STATIC target_include_directories(VersionDialog INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(VersionDialog PUBLIC Qt::Widgets Qt::Core Qt::Network) target_compile_features(VersionDialog PUBLIC cxx_std_20) - -include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) target_include_directories(VersionDialog PRIVATE ${SlopeCraft_Nlohmann_json_include_dir}) # translation diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index f19d3b0c..0dda0002 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -3,12 +3,10 @@ project(vccl VERSION ${SlopeCraft_version} LANGUAGES CXX) set(vccl_win_sources) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") configure_file(others/vccl.rc.in others/vccl.rc) set(vccl_win_sources ${CMAKE_CURRENT_BINARY_DIR}/others/vccl.rc) -endif() - -include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) +endif () configure_file(vccl-config-to-bin-dir.json.in vccl-config.json) @@ -19,8 +17,6 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) find_package(fmt REQUIRED) find_package(magic_enum REQUIRED) @@ -34,10 +30,6 @@ qt_add_executable(vccl ) target_link_libraries(vccl PRIVATE VisualCraftL Qt6::Core Qt6::Gui fmt::fmt magic_enum::magic_enum) - -include(${CMAKE_SOURCE_DIR}/cmake/configure_cli11.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/find_nlohmann_json.cmake) - target_include_directories(vccl PRIVATE ${cli11_include_dir} ${SlopeCraft_Nlohmann_json_include_dir}) find_package(OpenMP REQUIRED) @@ -55,14 +47,14 @@ set_target_properties(vccl PROPERTIES MACOSX_BUNDLE TRUE ) -if(${WIN32}) +if (${WIN32}) add_custom_target(SC_create_symlink_VCCL COMMAND mklink VisualCraftL.dll "..\\VisualCraftL\\VisualCraftL.dll" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS VisualCraftL COMMENT "Create symlink to VisualCraftL.dll for vccl.exe") add_dependencies(SC_create_all_symlinks SC_create_symlink_VCCL) -endif() +endif () include(install.cmake) diff --git a/vccl/add_test_vccl.cmake b/vccl/add_test_vccl.cmake index 4dc98211..208c7ef9 100644 --- a/vccl/add_test_vccl.cmake +++ b/vccl/add_test_vccl.cmake @@ -1,5 +1,3 @@ -include(${CMAKE_SOURCE_DIR}/cmake/configure_vanilla_zips.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/configure_images.cmake) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_vccl_images) @@ -62,12 +60,12 @@ foreach (_layers RANGE 1 3 1) # message(STATUS ${test_name}) add_test(NAME ${test_name} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # COMMAND vccl --bsl ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json --rp ${zip_file} --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${VCL_test_images} --dither=${_dither} -j1 --out-image --benchmark --prefix ${test_name} --gpu --disable-config - COMMAND vccl --img ${test_source_images} --mcver ${_ver} --face ${_face} --layers ${_layers} --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --lite --nbt ${generate_schem} ${gpu_flags} - COMMAND_EXPAND_LISTS - ) + # COMMAND vccl --bsl ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json --rp ${zip_file} --mcver ${_ver} --face ${_face} --layers ${_layers} --img ${VCL_test_images} --dither=${_dither} -j1 --out-image --benchmark --prefix ${test_name} --gpu --disable-config + COMMAND vccl --img ${test_source_images} --mcver ${_ver} --face ${_face} --layers ${_layers} --dither=${_dither} -j20 --out-image --benchmark --prefix ${test_name} --lite --nbt ${generate_schem} ${gpu_flags} + COMMAND_EXPAND_LISTS + ) # endforeach (_dither ${dither}) From 4180f1965c9c7b784cb162df9290dbf17502411e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:47:23 +0800 Subject: [PATCH 0733/1123] fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 7e614ef6..91a4fe67 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -36,7 +36,9 @@ jobs: - name: Install deps with vcpkg shell: cmd - run: vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid + run: | + curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" + vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' From 0bcc58b3be141ce204fab8d7ab9a8254ac17141f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:47:51 +0800 Subject: [PATCH 0734/1123] [CI] install 7zip Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index a4a8d6ab..1a06be22 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: - sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libexpected-dev + sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libexpected-dev p7zip-full - name: Install xsimd run: | diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 6fdc243d..9dbfd198 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -39,7 +39,7 @@ jobs: run: brew install ninja - name: Install dependencies run: | - brew install libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt + brew install libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip # - name: Find liblzma and libzstd dylibs # run: | From 8fab28aa194bb83b3c7e6f77e4419c6cebe2371f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:52:18 +0800 Subject: [PATCH 0735/1123] [CI][mac] fix download DylibDeployer Signed-off-by: ToKiNoBug --- cmake/required_deps/_DLLDeployer.cmake | 40 ++++++++++++------------ cmake/required_deps/_DylibDeployer.cmake | 14 +++++---- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/cmake/required_deps/_DLLDeployer.cmake b/cmake/required_deps/_DLLDeployer.cmake index c7121efd..06eb5eab 100644 --- a/cmake/required_deps/_DLLDeployer.cmake +++ b/cmake/required_deps/_DLLDeployer.cmake @@ -1,23 +1,23 @@ -function(SC_download url filename) - if (EXISTS ${filename}) - file(SIZE ${filename} size) - if (${size} GREATER 0) - return() - endif () - - file(REMOVE ${filename}) - endif () - - message(STATUS "Downloading ${url} ...") - file(DOWNLOAD ${url} ${filename} - SHOW_PROGRESS - REQUIRED) - - file(SIZE ${filename} size) - if (${size} LESS_EQUAL 0) - message(FATAL_ERROR "Failed to download ${filename} from ${url}, downloaded file is empty") - endif () -endfunction(SC_download) +#function(SC_download url filename) +# if (EXISTS ${filename}) +# file(SIZE ${filename} size) +# if (${size} GREATER 0) +# return() +# endif () +# +# file(REMOVE ${filename}) +# endif () +# +# message(STATUS "Downloading ${url} ...") +# file(DOWNLOAD ${url} ${filename} +# SHOW_PROGRESS +# REQUIRED) +# +# file(SIZE ${filename} size) +# if (${size} LESS_EQUAL 0) +# message(FATAL_ERROR "Failed to download ${filename} from ${url}, downloaded file is empty") +# endif () +#endfunction(SC_download) set(DLLD_download_dir ${CMAKE_BINARY_DIR}/3rdParty/DLLDeployer) set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) diff --git a/cmake/required_deps/_DylibDeployer.cmake b/cmake/required_deps/_DylibDeployer.cmake index 5be08553..1214d911 100644 --- a/cmake/required_deps/_DylibDeployer.cmake +++ b/cmake/required_deps/_DylibDeployer.cmake @@ -2,15 +2,17 @@ if (NOT APPLE) return() endif () -include(_DLLDeployer.cmake) - set(DylibD_download_dir ${CMAKE_SOURCE_DIR}/3rdParty/DylibDeployer.cmake) set(DylibD_file ${DylibD_download_dir}/DylibDeployer.cmake) -SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/DylibDeployer.cmake - ${DylibD_file}) +file(DOWNLOAD https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/DylibDeployer.cmake + ${DylibD_file} + EXPECTED_HASH SHA512=22D8E28508C424EA724294B58A22559747E33D0529358582E5497D613074204D3584FACB4FBBC85ACC3DBDA5CA67F666C7BFEE2BBF2DC02129871E354B5BC25B +) include(${DylibD_file}) set(Codesigner_file ${DylibD_download_dir}/Codesigner.cmake) -SC_download(https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/Codesigner.cmake - ${Codesigner_file}) +file(DOWNLOAD https://github.com/SlopeCraft/DylibDeployer.cmake/releases/download/v1.0.2/Codesigner.cmake + ${Codesigner_file} + EXPECTED_HASH SHA512=2095462FB94B5F7D25953EED7ECDBA89A412B31E8C48B31CA328445106498EC088C08F35CA0C4498D6D22C60D8A26605D506DAA29E1A3D276316C5FD7FFE015E +) include(${Codesigner_file}) \ No newline at end of file From a03fa6b4d2fb3f9d8c304d895c4f578b3d6a02d0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 20:59:43 +0800 Subject: [PATCH 0736/1123] [CI][win] fix installing boost[iostreams] Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 91a4fe67..a065f153 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -37,6 +37,7 @@ jobs: - name: Install deps with vcpkg shell: cmd run: | + mkdir C:/vcpkg/downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid From 79f55fee741708076da463c8dcea609f9c0f90e9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:01:59 +0800 Subject: [PATCH 0737/1123] fix build with vulkan Signed-off-by: ToKiNoBug --- utilities/GPUWrapper/Vulkan/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index 26f59c1f..fec0d629 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -1,16 +1,11 @@ -include(${CMAKE_SOURCE_DIR}/cmake/find_ResourceCreator.cmake) -include(${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/ResourceCreator.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/find_Eigen3.cmake) - find_package(Vulkan COMPONENTS glslc REQUIRED) find_package(Eigen3 REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_kompute.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/optional_deps/kompute.cmake) find_package(kompute REQUIRED) -include(${CMAKE_SOURCE_DIR}/cmake/configure_tl_expected.cmake) find_package(tl-expected REQUIRED) target_sources(GPUInterface PRIVATE GPU_interface.cpp) From f556f23b9552733c28a9912f108b727e874d2677 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:13:59 +0800 Subject: [PATCH 0738/1123] fix downloading ResourceCreator Signed-off-by: ToKiNoBug --- cmake/required_deps/_ResourceCreator.cmake | 27 ++++++---------------- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 1 - 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/cmake/required_deps/_ResourceCreator.cmake b/cmake/required_deps/_ResourceCreator.cmake index 391fde21..e5f6d0a8 100644 --- a/cmake/required_deps/_ResourceCreator.cmake +++ b/cmake/required_deps/_ResourceCreator.cmake @@ -1,23 +1,10 @@ -# https://github.com/isRyven/ResourceCreator.cmake.git -set(SlopeCraft_rc_creator_found OFF) -if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/.git) - set(SlopeCraft_rc_creator_found TRUE) - return() -endif() - -message(STATUS "Cloning ResourceCreator.cmake...") -execute_process( - COMMAND git clone "https://github.com/SlopeCraft/ResourceCreator.cmake.git" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty - COMMAND_ERROR_IS_FATAL ANY -) - -execute_process( - COMMAND git checkout v0.0.0 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake - COMMAND_ERROR_IS_FATAL ANY +message(STATUS "Downloading ResourceCreator.cmake...") +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/3rdParty/") +set(SC_RC_location "${CMAKE_BINARY_DIR}/3rdParty/ResourceCreator.cmake") +file(DOWNLOAD "https://github.com/SlopeCraft/ResourceCreator.cmake/releases/download/v0.0.0/ResourceCreator.cmake" + ${SC_RC_location} + EXPECTED_HASH SHA512=241799A7BCC3A0AF1BD32FFD350EEEF0751D4D86DA7F11CFA6BD8F979E150F1585E9F55CBBBBAAB5C59C7379F5F93C27BF8E414BB0A603DFC5D07136C37EC6FA ) - -set(SlopeCraft_rc_creator_found TRUE) \ No newline at end of file +include(${SC_RC_location}) \ No newline at end of file diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 602e929f..02e2708f 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -2,7 +2,6 @@ find_package(OpenCL 3.0 REQUIRED) message(STATUS "Configuring OpenCL") -include(${CMAKE_SOURCE_DIR}/3rdParty/ResourceCreator.cmake/ResourceCreator.cmake) target_sources(GPUInterface PRIVATE OCLWrapper.h From d018a0f424567cef02b76b271207da2e3d4f54f1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:19:38 +0800 Subject: [PATCH 0739/1123] fix build with vulkan Signed-off-by: ToKiNoBug --- cmake/optional_deps/kompute.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/optional_deps/kompute.cmake b/cmake/optional_deps/kompute.cmake index bd2466fe..ed119c0f 100644 --- a/cmake/optional_deps/kompute.cmake +++ b/cmake/optional_deps/kompute.cmake @@ -1,4 +1,4 @@ -include(${CMAKE_SOURCE_DIR}/cmake/configure_fmtlib.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../required_deps/fmtlib.cmake) find_package(Vulkan REQUIRED) From 8998175eaa7cea004920b2e613c5cfd82f0df1c3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:21:48 +0800 Subject: [PATCH 0740/1123] [CI] fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a065f153..7cb96ca7 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -37,7 +37,7 @@ jobs: - name: Install deps with vcpkg shell: cmd run: | - mkdir C:/vcpkg/downloads + mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid From f0e2289fa5b0f3c546eae8ae16f88be849a37264 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:28:27 +0800 Subject: [PATCH 0741/1123] [CI] fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 7cb96ca7..48dcef30 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -142,7 +142,6 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Install ninja run: | choco install ninja @@ -193,6 +192,8 @@ jobs: $GPU_API=$env:GPU_API $env:path=$env:NEW_PATH echo "env:path = $env:path" + mkdir C:\vcpkg\downloads + curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid From 2b1cdf269181e8ec5edf9a5d7ca975e5a672eb32 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:35:23 +0800 Subject: [PATCH 0742/1123] [CI] fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- cmake/required_deps/nlohmann_json.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 48dcef30..c5ca6c11 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -39,7 +39,7 @@ jobs: run: | mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid + vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' @@ -194,7 +194,7 @@ jobs: echo "env:path = $env:path" mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected - name: Install OpenCL with vcpkg diff --git a/cmake/required_deps/nlohmann_json.cmake b/cmake/required_deps/nlohmann_json.cmake index 52f61f76..f7612c93 100644 --- a/cmake/required_deps/nlohmann_json.cmake +++ b/cmake/required_deps/nlohmann_json.cmake @@ -23,7 +23,7 @@ if (${SlopeCraft_download_njson}) file(DOWNLOAD "https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp" ${CMAKE_SOURCE_DIR}/3rdParty/nlohmann/json.hpp - HASH 9bea4c8066ef4a1c206b2be5a36302f8926f7fdc6087af5d20b417d0cf103ea6 + EXPECTED_HASH SHA512=DA77FA48CA883DACF5CE147B2354E9D957AD66EDF72A7103FF5A8611C5CDA77B64F1F0CA60491295574EE158CECCCFE7797CD36FAAC5B47E75687400AC60769D SHOW_PROGRESS) message(STATUS "nlohmann json downloaded") From 1c347a0f16a258f01882244bc6adb19b71fb07f9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:39:25 +0800 Subject: [PATCH 0743/1123] [CI] update tag of tl-expected Signed-off-by: ToKiNoBug --- cmake/required_deps/tl-expected.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/tl-expected.cmake b/cmake/required_deps/tl-expected.cmake index ab7d0925..6ffdf7d8 100644 --- a/cmake/required_deps/tl-expected.cmake +++ b/cmake/required_deps/tl-expected.cmake @@ -4,7 +4,7 @@ message(STATUS "Downloading tl-expected...") FetchContent_Declare(tl-expected GIT_REPOSITORY https://github.com/TartanLlama/expected.git - GIT_TAG v1.1 + GIT_TAG v1.1.0 OVERRIDE_FIND_PACKAGE) FetchContent_MakeAvailable(tl-expected) find_package(tl-expected CONFIG REQUIRED) From a69e15e0e5b7071dab1366873b4f908423387e58 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 21:44:53 +0800 Subject: [PATCH 0744/1123] [CI][win] install 7z Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c5ca6c11..337ded9d 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -164,10 +164,12 @@ jobs: echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - - name: Install ninja + - name: Install ninja and 7z run: | choco install ninja ninja --version + choco install 7zip --pre + 7z - name: Make dirs run: | @@ -194,7 +196,7 @@ jobs: echo "env:path = $env:path" mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected magic-enum - name: Install OpenCL with vcpkg From 16b3236601a99ad5a0f39f8f1b9a3dcad8632a8a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 22:03:07 +0800 Subject: [PATCH 0745/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 337ded9d..0932de6b 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -33,6 +33,7 @@ jobs: run: | choco install ninja ninja --version + where 7z - name: Install deps with vcpkg shell: cmd @@ -164,12 +165,10 @@ jobs: echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV - - name: Install ninja and 7z + - name: Install ninja run: | choco install ninja ninja --version - choco install 7zip --pre - 7z - name: Make dirs run: | From d7dd2bc7958fd721a1677c71c83db9e69194cdc3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 23:36:12 +0800 Subject: [PATCH 0746/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 0932de6b..d2b446d3 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -31,9 +31,9 @@ jobs: - name: Install ninja run: | + where 7z choco install ninja ninja --version - where 7z - name: Install deps with vcpkg shell: cmd From acb0f11751ef29c79866580d699820a9df5c862c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 23:40:50 +0800 Subject: [PATCH 0747/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index d2b446d3..4a5540e3 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -31,7 +31,7 @@ jobs: - name: Install ninja run: | - where 7z + C:\Program Files\7-Zip\7z.exe choco install ninja ninja --version From 743e2086e99783897cee27a3278555ba81fef85a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 23:42:13 +0800 Subject: [PATCH 0748/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 4a5540e3..fc9348b5 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -30,8 +30,9 @@ jobs: echo "env:GPU_API = $env:GPU_API" - name: Install ninja + shell: cmd run: | - C:\Program Files\7-Zip\7z.exe + "C:\Program Files\7-Zip\7z.exe" choco install ninja ninja --version From 819ea3644f7ea49d05e7991296ae8e723cb61172 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 9 Apr 2024 23:43:58 +0800 Subject: [PATCH 0749/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index fc9348b5..ae8c5ea2 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -162,7 +162,7 @@ jobs: $exclude_key_words="perl","Strawberry" $new_path="" foreach($p in $env:path.split(';')) {$exclude=$false; foreach($ekw in $exclude_key_words) {if($p.contains($ekw)) {$exclude=$true;break;}}if(-not($exclude)) {$new_path="$new_path;$p"}} - $env:path="$basedir/bin/mingw64/bin;$new_path" + $env:path="$basedir/bin/mingw64/bin;C:/Program Files/7-Zip;$new_path" echo "New path : $env:path.split(';')" echo "NEW_PATH=$env:path" >> $env:GITHUB_ENV From 193bbe217757024bd9b57d3ccf56b00b55b7230f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 12:06:47 +0800 Subject: [PATCH 0750/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index ae8c5ea2..3c5314d2 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -222,7 +222,7 @@ jobs: $basedir=(pwd).path.replace("\\","/") $BUILD_TYPE=$env:BUILD_TYPE $GPU_API=$env:GPU_API - $env:path="$basedir/bin/mingw64/bin;$env:path" + $env:path="$basedir/bin/mingw64/bin;C:/Program Files/7-Zip;$env:path" echo "env:path = $env:path" mkdir build mkdir install From 163b547cdb358884268639175619c462f3449722 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 12:16:20 +0800 Subject: [PATCH 0751/1123] [CI][win] try to fix windows build Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index a626a670..ab1e39a2 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -136,6 +136,7 @@ function(SC_create_SCL_block_list src_dir archive_path) # ) find_program(z7_exe NAMES 7z REQUIRED + HINTS "C:/Program Files/7-Zip/7z.exe;/usr/bin/7z" DOC "Find 7z to archive SlopeCraft block lists. 7z is required because file(ARCHIVE_CREATE in cmake too stupid to be used" HINTS "C:/Program Files/7-Zip/7z.exe") From 1bbcd54b91b57cad13385251de7f5c6bc5ab3f43 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 12:24:59 +0800 Subject: [PATCH 0752/1123] [CI][mac] restore macos-arm64 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 263 +++++++++++++----------- 1 file changed, 140 insertions(+), 123 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 68e9e7b1..774b9690 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -7,132 +7,149 @@ on: - dev jobs: - nothing: - runs-on: macos-latest + clang: + runs-on: macos-latest-xlarge + strategy: + matrix: + build_type: [ Debug, Release ] + gpu_api: [ None, Vulkan ] + env: + BUILD_TYPE: ${{ matrix.build_type }} + GPU_API: ${{ matrix.gpu_api }} + steps: - - name: checkout - run: echo "rua" + - name: pwd + run: pwd + + - name: Checkout repository + uses: actions/checkout@v4 + # - name: Check env + # run: | + # whoami + # pwd + # ls $HOME + # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l + + - name: Install dependencies + run: | + brew install llvm boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip + + #https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz + - name: Install qt6.6.0-static + run: | + curl -JL -o ~/Downloads/qt6.6.0-static-arm64-apple-darwin.tar.xz https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz + cd ~/Downloads + tar xzf qt6.6.0-static-arm64-apple-darwin.tar.xz + chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/bin/* + chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/libexec/* + + - name: Install Vulkan sdk + if: matrix.gpu_api == 'Vulkan' + run: | + brew install molten-vk vulkan-headers vulkan-loader vulkan-tools glslang shaderc + whereis glslc + glslc --version + + - name: Configure CMake + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-static-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + - name: Build + run: | + cd build + cmake --build . --parallel + # - name: CPack + # run: | + # cd build + # cpack -G ZIP + - name: Install + run: | + cd build + cmake --install . + + # - name: Fix VisualCraft.app + # run: | + # cd build/install + # cd VisualCraft.app/Contents/Frameworks + # cp /opt/homebrew/lib/libzstd.1.dylib . + # cp /opt/homebrew/lib/liblzma.5.dylib . + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib + # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib + # cd ../../.. + # codesign --force --deep --sign=- VisualCraft.app + + - name: Compress as zip + run: | + cd build + 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* + + - name: Get short SHA + run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang + path: build/SlopeCraft*.zip + # nothing: + # runs-on: macos-latest + # steps: + # - name: checkout + # run: echo "rua" + + # clang-x86_64-to-arm64: + # runs-on: macos-latest + # steps: + # - name: Install dependents + # run: | + # brew remove zlib + # brew install cmake xz p7zip llvm ninja + # vcpkg install --triplet=arm64-osx zlib zstd + # wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz + # tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz + # mv qt6.6.0-static-x86_64-apple-darwin $HOME + # + # + # #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost + # + # - name: Checkout repository + # uses: actions/checkout@v4 + # + # - name: Cross compile qtbase 6.6.2 + # run: | + # cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME + # mkdir $HOME/qt6.6.2-x86_64-mac-to-arm64-mac + # git clone https://github.com/qt/qtbase.git qtbase --recursive + # cd qtbase + # git checkout v6.6.2 + # mkdir build + # cd build + # ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx + # cmake --build . --parallel + # cmake --install . + # rm -rf ./* + # + # - name: Cross compile qttools 6.6.2 + # run: | + # git clone https://github.com/qt/qttools.git qttools --recursive + # cd qttools + # git checkout v6.6.2 + # mkdir build + # cd build + # $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. + # cmake --build . --parallel + # cmake --install . + # rm -rf ./* + # + # - name: Compress installed Qt binaries + # run: | + # tar cvf qt6.6.2-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/* + # xz -9 qt6.6.2-x86_64-mac-to-arm64-mac.tar -T0 + # + # - name: Upload Qt6.6.2-host-x86_64-mac-target-arm64-mac + # uses: actions/upload-artifact@v3 + # with: + # name: Qt6.6.2-host-x86_64-mac-target-arm64-mac + # path: qt6.6.2-x86_64-mac-to-arm64-mac.tar.xz -# clang-x86_64-to-arm64: -# runs-on: macos-latest -# steps: -# - name: Install dependents -# run: | -# brew remove zlib -# brew install cmake xz p7zip llvm ninja -# vcpkg install --triplet=arm64-osx zlib zstd -# wget https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-x86_64-apple-darwin/qt6.6.0-static-x86_64-apple-darwin.tar.xz -# tar xf qt6.6.0-static-x86_64-apple-darwin.tar.xz -# mv qt6.6.0-static-x86_64-apple-darwin $HOME -# -# -# #vcpkg install --triplet=arm64-osx zlib zstd libzip eigen3 xsimd libpng boost -# -# - name: Checkout repository -# uses: actions/checkout@v4 -# -# - name: Cross compile qtbase 6.6.2 -# run: | -# cp cmake/tool_chain_files/x86_64-mac-to-arm64-mac.cmake $HOME -# mkdir $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -# git clone https://github.com/qt/qtbase.git qtbase --recursive -# cd qtbase -# git checkout v6.6.2 -# mkdir build -# cd build -# ../configure -shared -release -nomake examples -nomake tests -prefix $HOME/qt6.6.2-x86_64-mac-to-arm64-mac -qt-host-path $HOME/qt6.6.0-static-x86_64-apple-darwin -platform macx-clang -- -DCMAKE_TOOLCHAIN_FILE=$HOME/x86_64-mac-to-arm64-mac.cmake -DCMAKE_PREFIX_PATH=/usr/local/share/vcpkg/installed/arm64-osx -# cmake --build . --parallel -# cmake --install . -# rm -rf ./* -# -# - name: Cross compile qttools 6.6.2 -# run: | -# git clone https://github.com/qt/qttools.git qttools --recursive -# cd qttools -# git checkout v6.6.2 -# mkdir build -# cd build -# $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/bin/qt-configure-module .. -# cmake --build . --parallel -# cmake --install . -# rm -rf ./* -# -# - name: Compress installed Qt binaries -# run: | -# tar cvf qt6.6.2-x86_64-mac-to-arm64-mac.tar $HOME/qt6.6.2-x86_64-mac-to-arm64-mac/* -# xz -9 qt6.6.2-x86_64-mac-to-arm64-mac.tar -T0 -# -# - name: Upload Qt6.6.2-host-x86_64-mac-target-arm64-mac -# uses: actions/upload-artifact@v3 -# with: -# name: Qt6.6.2-host-x86_64-mac-target-arm64-mac -# path: qt6.6.2-x86_64-mac-to-arm64-mac.tar.xz -# clang: -# runs-on: self-hosted -# strategy: -# matrix: -# build_type: [ Debug, Release ] -# gpu_api: [ None ] -# env: -# BUILD_TYPE: ${{ matrix.build_type }} -# GPU_API: ${{ matrix.gpu_api }} -# -# steps: -# - name: pwd -# run: pwd -# -# - name: Checkout repository -# uses: actions/checkout@v4 -# # - name: Check env -# # run: | -# # whoami -# # pwd -# # ls $HOME -# # ls $HOME/Documents/cpp/qt/qt6.6.0-static -l -# -# - name: Install dependencies -# run: | -# brew install boost -# -# - name: Configure CMake -# run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Documents/cpp/qt/qt6.6.0-static" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -# - name: Build -# run: | -# cd build -# cmake --build . --parallel -# # - name: CPack -# # run: | -# # cd build -# # cpack -G ZIP -# - name: Install -# run: | -# cd build -# cmake --install . -# -# # - name: Fix VisualCraft.app -# # run: | -# # cd build/install -# # cd VisualCraft.app/Contents/Frameworks -# # cp /opt/homebrew/lib/libzstd.1.dylib . -# # cp /opt/homebrew/lib/liblzma.5.dylib . -# # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/xz/lib/liblzma.5.dylib @loader_path/liblzma.5.dylib -# # install_name_tool libzip.5.dylib -change @loader_path/../../../../opt/zstd/lib/libzstd.1.dylib @loader_path/libzstd.1.dylib -# # cd ../../.. -# # codesign --force --deep --sign=- VisualCraft.app -# -# - name: Compress as zip -# run: | -# cd build -# 7z a SlopeCraft-5.2.1-macOS-Apple-Silicon.zip -tzip -mx=9 -mmt -m0=XZ -snl ./install/* -# -# - name: Get short SHA -# run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV -# - name: Upload Artifacts -# uses: actions/upload-artifact@v3 -# with: -# name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang -# path: build/SlopeCraft*.zip From ba186f48d288956028df760e3b3f5a88d9d3e8a8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 12:42:10 +0800 Subject: [PATCH 0753/1123] [CI][win] try to find 7z Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 5 +---- cmake/optional_deps/7z.cmake | 11 +++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 cmake/optional_deps/7z.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ab1e39a2..ad225cf4 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -135,10 +135,7 @@ function(SC_create_SCL_block_list src_dir archive_path) # #COMPRESSION_LEVEL 9 # ) - find_program(z7_exe NAMES 7z REQUIRED - HINTS "C:/Program Files/7-Zip/7z.exe;/usr/bin/7z" - DOC "Find 7z to archive SlopeCraft block lists. 7z is required because file(ARCHIVE_CREATE in cmake too stupid to be used" - HINTS "C:/Program Files/7-Zip/7z.exe") + include(${CMAKE_SOURCE_DIR}/cmake/optional_deps/7z.cmake) execute_process(COMMAND ${z7_exe} a ${archive_path} -scsUTF-8 "${src_dir}/*" -tZIP COMMAND_ERROR_IS_FATAL ANY) diff --git a/cmake/optional_deps/7z.cmake b/cmake/optional_deps/7z.cmake new file mode 100644 index 00000000..f1364d35 --- /dev/null +++ b/cmake/optional_deps/7z.cmake @@ -0,0 +1,11 @@ +find_program(z7_exe NAMES 7z 7za 7zr REQUIRED + HINTS "C:/Program Files/7-Zip/7z.exe;/usr/bin/7z" + DOC "Find 7z to archive SlopeCraft block lists. 7z is required because file(ARCHIVE_CREATE in cmake too stupid to be used" +) + +if (NOT z7_exe) + message(FATAL_ERROR "7z not found, downloading...") + +endif () + +list(GET z7_exe 0 z7_exe) \ No newline at end of file From 8ad7eef353fc6b4a559151e00792b80f2921d5b6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 15:59:19 +0800 Subject: [PATCH 0754/1123] [CI][win] download 7z if not found Signed-off-by: ToKiNoBug --- cmake/optional_deps/7z.cmake | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/cmake/optional_deps/7z.cmake b/cmake/optional_deps/7z.cmake index f1364d35..f989fcee 100644 --- a/cmake/optional_deps/7z.cmake +++ b/cmake/optional_deps/7z.cmake @@ -1,11 +1,30 @@ -find_program(z7_exe NAMES 7z 7za 7zr REQUIRED - HINTS "C:/Program Files/7-Zip/7z.exe;/usr/bin/7z" +find_program(z7_exe NAMES 7z 7za 7zr QUIET + HINTS "C:/Program Files/7-Zip/7z.exe;/usr/bin/7z;" DOC "Find 7z to archive SlopeCraft block lists. 7z is required because file(ARCHIVE_CREATE in cmake too stupid to be used" ) -if (NOT z7_exe) - message(FATAL_ERROR "7z not found, downloading...") +if (z7_exe) + return() +endif () + +message(STATUS "7z not found, downloading...") +if (${WIN32}) + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/3rdParty") + file(DOWNLOAD "https://7-zip.org/a/7z2404-extra.7z" + "${CMAKE_BINARY_DIR}/3rdParty/7z2404-extra.7z" + EXPECTED_HASH SHA512=459C9CEFB6587BD0836CAABC106265CFBABA57D1C00F9444F0FD9A6773E199080DDF02ABB7D8E2FD461C484F61D07E0363E1448ADEDADF6E274DAED96CA4A5E6) + file(ARCHIVE_EXTRACT INPUT "${CMAKE_BINARY_DIR}/3rdParty/7z2404-extra.7z" + DESTINATION "${CMAKE_BINARY_DIR}/3rdParty/7z" + PATTERNS 7za.dll 7za.exe 7zxa.dll + VERBOSE) + set(z7_exe "${CMAKE_BINARY_DIR}/3rdParty/7z/7za.exe") + if (NOT EXISTS ${z7_exe}) + message(FATAL_ERROR "Failed to extract 7z2404-extra.7z, ${z7_exe} doesn't exist") + endif () + return() endif () -list(GET z7_exe 0 z7_exe) \ No newline at end of file +message(FATAL_ERROR "Install 7z with your package manager") + +#list(GET z7_exe 0 z7_exe) \ No newline at end of file From 5700e4bc4da5cfd1a220e1250a37e82506dffdee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 16:01:05 +0800 Subject: [PATCH 0755/1123] [CI][mac] update macos runner Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 6 +++--- .github/workflows/macos-build-x64.yml | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 774b9690..44402098 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -8,7 +8,7 @@ on: jobs: clang: - runs-on: macos-latest-xlarge + runs-on: macos-14 strategy: matrix: build_type: [ Debug, Release ] @@ -18,8 +18,8 @@ jobs: GPU_API: ${{ matrix.gpu_api }} steps: - - name: pwd - run: pwd + - name: Check environment + run: uname -r - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 9dbfd198..4ae2740f 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -8,7 +8,7 @@ on: jobs: clang: - runs-on: macos-latest + runs-on: macos-13 strategy: matrix: build_type: [ Debug, Release ] @@ -19,6 +19,8 @@ jobs: GPU_API: ${{ matrix.gpu_api }} VECTORIZE: ${{ matrix.vectorize }} steps: + - name: Check environment + run: uname -r # - name: brew upgrade & update # run: | # brew update From 901b1f8887b7f9e3bf24709bea7c930724ef9ba2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 16:47:26 +0800 Subject: [PATCH 0756/1123] [CI][mac] fix installation of qt static Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 6 +++++- .github/workflows/macos-build-x64.yml | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 44402098..72b8206c 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -19,7 +19,10 @@ jobs: steps: - name: Check environment - run: uname -r + run: | + uname -r + brew install screenfetch + screenfetch - name: Checkout repository uses: actions/checkout@v4 @@ -40,6 +43,7 @@ jobs: curl -JL -o ~/Downloads/qt6.6.0-static-arm64-apple-darwin.tar.xz https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz cd ~/Downloads tar xzf qt6.6.0-static-arm64-apple-darwin.tar.xz + ls -l chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/bin/* chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/libexec/* diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 4ae2740f..1ee820eb 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -20,7 +20,10 @@ jobs: VECTORIZE: ${{ matrix.vectorize }} steps: - name: Check environment - run: uname -r + run: | + uname -r + brew install screenfetch + screenfetch # - name: brew upgrade & update # run: | # brew update From 7904911dacb8a9239521fd100023a53a9c3c9bf1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 16:52:17 +0800 Subject: [PATCH 0757/1123] [CI][mac] fix installation of qt static Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 72b8206c..65174b97 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -44,8 +44,8 @@ jobs: cd ~/Downloads tar xzf qt6.6.0-static-arm64-apple-darwin.tar.xz ls -l - chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/bin/* - chmod +x ~/Downloads/qt6.6.0-static-arm64-apple-darwin/libexec/* + chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/bin/* + chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/libexec/* - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' @@ -55,7 +55,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-static-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build From e20653c9dbc864b2d3de9645e9d0d5de250e257f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 17:04:48 +0800 Subject: [PATCH 0758/1123] [CI][mac] fix arm64 build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 65174b97..c991fa82 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -55,7 +55,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 - name: Build run: | cd build From 3f513083decbbe6d28af2ece8376d67da04fd0c9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 17:14:25 +0800 Subject: [PATCH 0759/1123] [CI][mac] fix arm64 build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index c991fa82..aeabdf15 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -55,7 +55,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build From d516753ac9cce37d40484cb39851dbba4f883d72 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 10 Apr 2024 17:38:08 +0800 Subject: [PATCH 0760/1123] [CI][mac] fix arm64 build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index aeabdf15..904da150 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -40,12 +40,13 @@ jobs: #https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz - name: Install qt6.6.0-static run: | - curl -JL -o ~/Downloads/qt6.6.0-static-arm64-apple-darwin.tar.xz https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz - cd ~/Downloads - tar xzf qt6.6.0-static-arm64-apple-darwin.tar.xz - ls -l - chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/bin/* - chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/libexec/* + brew install qt@6 + # curl -JL -o ~/Downloads/qt6.6.0-static-arm64-apple-darwin.tar.xz https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz + # cd ~/Downloads + # tar xzf qt6.6.0-static-arm64-apple-darwin.tar.xz + # ls -l + # chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/bin/* + # chmod +x ~/Downloads/qt6.6.0-arm64-apple-darwin/libexec/* - name: Install Vulkan sdk if: matrix.gpu_api == 'Vulkan' From 13832b2d4fac4b8b6db9dfe01f4bba2b839af25a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 17:05:16 +0800 Subject: [PATCH 0761/1123] remove singleton mapColor2Gray Signed-off-by: ToKiNoBug --- .../BlockListManager/BlockListManager.cpp | 130 +++++++++--------- .../GAConverter/GAConverter.cpp | 55 ++++---- .../GAConverter/GAConverter.h | 16 +-- .../GAConverter/GACvterDefines.hpp | 8 +- .../ExternalConverters/GAConverter/uiPack.h | 9 +- 5 files changed, 105 insertions(+), 113 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 351cf161..7a65e614 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -3,7 +3,7 @@ #include #include -extern std::string_view basecolor_names[64]; +extern const std::string_view basecolor_names[64]; BlockListManager::BlockListManager(QWidget *parent) : QWidget(parent) {} @@ -193,67 +193,67 @@ blockListPreset BlockListManager::to_preset() const noexcept { return ret; } -std::string_view basecolor_names[64] = {"00 None", - "01 Grass", - "02 Sand", - "03 Wool", - "04 Fire", - "05 Ice", - "06 Metal", - "07 Plant", - "08 Snow", - "09 Clay", - "10 Dirt", - "11 Stone", - "12 Water", - "13 Wood", - "14 Quartz", - "15 ColorOrange", - "16 ColorMagenta", - "17 ColorLightBlue", - "18 ColorYellow", - "19 ColorLime", - "20 ColorPink", - "21 ColorGray", - "22 ColorLightGray", - "23 ColorCyan", - "24 ColorPurple", - "25 ColorBlue", - "26 ColorBrown", - "27 ColorGreen", - "28 ColorRed", - "29 ColorBlack", - "30 Gold", - "31 Diamond", - "32 Lapis", - "33 Emerald", - "34 Podzol", - "35 Nether", - "36 TerracottaWhite", - "37 TerracottaOrange", - "38 TerracottaMagenta", - "39 TerracottaLightBlue", - "40 TerracottaYellow", - "41 TerracottaLime", - "42 TerracottaPink", - "43 TerracottaGray", - "44 TerracottaLightGray", - "45 TerracottaCyan", - "46 TerracottaPurple", - "47 TerracottaBlue", - "48 TerracottaBrown", - "49 TerracottaGreen", - "50 TerracottaRed", - "51 TerracottaBlack", - "52 CrimsonNylium", - "53 CrimsonStem", - "54 CrimsonHyphae", - "55 WarpedNylium", - "56 WarpedStem", - "57 WarpedHyphae", - "58 WarpedWartBlock", - "59 Deepslate", - "60 RawIron", - "61 GlowLichen", - "Unknown", - "Unknown"}; \ No newline at end of file +const std::string_view basecolor_names[64] = {"00 None", + "01 Grass", + "02 Sand", + "03 Wool", + "04 Fire", + "05 Ice", + "06 Metal", + "07 Plant", + "08 Snow", + "09 Clay", + "10 Dirt", + "11 Stone", + "12 Water", + "13 Wood", + "14 Quartz", + "15 ColorOrange", + "16 ColorMagenta", + "17 ColorLightBlue", + "18 ColorYellow", + "19 ColorLime", + "20 ColorPink", + "21 ColorGray", + "22 ColorLightGray", + "23 ColorCyan", + "24 ColorPurple", + "25 ColorBlue", + "26 ColorBrown", + "27 ColorGreen", + "28 ColorRed", + "29 ColorBlack", + "30 Gold", + "31 Diamond", + "32 Lapis", + "33 Emerald", + "34 Podzol", + "35 Nether", + "36 TerracottaWhite", + "37 TerracottaOrange", + "38 TerracottaMagenta", + "39 TerracottaLightBlue", + "40 TerracottaYellow", + "41 TerracottaLime", + "42 TerracottaPink", + "43 TerracottaGray", + "44 TerracottaLightGray", + "45 TerracottaCyan", + "46 TerracottaPurple", + "47 TerracottaBlue", + "48 TerracottaBrown", + "49 TerracottaGreen", + "50 TerracottaRed", + "51 TerracottaBlack", + "52 CrimsonNylium", + "53 CrimsonStem", + "54 CrimsonHyphae", + "55 WarpedNylium", + "56 WarpedStem", + "57 WarpedHyphae", + "58 WarpedWartBlock", + "59 Deepslate", + "60 RawIron", + "61 GlowLichen", + "Unknown", + "Unknown"}; \ No newline at end of file diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.cpp b/utilities/ExternalConverters/GAConverter/GAConverter.cpp index 942c02cd..957ad6c4 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.cpp +++ b/utilities/ExternalConverters/GAConverter/GAConverter.cpp @@ -32,7 +32,8 @@ using namespace GACvter; namespace GACvter { -mapColor2Gray_LUT_t mapColor2Gray; +// #error "Fix singleton here" +// mapColor2Gray_LUT_t mapColor2Gray; const mutateMap_t mutateMap = GACvter::makeMutateMap(); @@ -48,39 +49,31 @@ inline ARGB mapColor2ARGB32(const mapColor_t mC) noexcept { return ARGB32(rgb(0), rgb(1), rgb(2), (mC < 4) ? 0 : 255); } -} // namespace GACvter +} // namespace GACvter GAConverter::GAConverter() { this->setTournamentSize(3); } -void GACvter::updateMapColor2GrayLUT() { - static std::mutex lock; - - if (!lock.try_lock()) { // there's another thread writting currently. Just - // wait until it finishes. - lock.lock(); - lock.unlock(); - return; - } else { - for (int row = 0; row < 256; row++) { - const mapColor_t mC = index2mapColor(row); - const float r = SlopeCraft::BasicRGB4External(0)[row]; - const float g = SlopeCraft::BasicRGB4External(1)[row]; - const float b = SlopeCraft::BasicRGB4External(2)[row]; - mapColor2Gray[mC] = GrayMax * RGB2Gray_Gamma(r, g, b); - } - lock.unlock(); +mapColor2Gray_LUT_t GACvter::updateMapColor2GrayLUT() { + mapColor2Gray_LUT_t result{}; + result.fill(0); + for (int row = 0; row < 256; row++) { + const mapColor_t mC = index2mapColor(row); + const float r = SlopeCraft::BasicRGB4External(0)[row]; + const float g = SlopeCraft::BasicRGB4External(1)[row]; + const float b = SlopeCraft::BasicRGB4External(2)[row]; + result[mC] = GrayMax * RGB2Gray_Gamma(r, g, b); } + return result; } template void privateMutateFun(const Var_t *parent, Var_t *child, const CvterInfo *arg) noexcept { - constexpr float ratio = 0.01; constexpr float Threshold = ratio * 2 - 1; *child = *parent; - if constexpr (strong //&& false - ) { // strong mutation + if constexpr (strong //&& false + ) { // strong mutation static Eigen::ArrayXXf randMat(arg->rawImageCache.rows(), arg->rawImageCache.cols()); randMat.setRandom(); @@ -91,7 +84,7 @@ void privateMutateFun(const Var_t *parent, Var_t *child, mutateMap(parent->operator()(idx), heu::randIdx(OrderMax - 1)); } } - } else { // weak mutation + } else { // weak mutation const int idx = heu::randIdx(parent->size()); child->operator()(idx) = mutateMap(parent->operator()(idx), heu::randIdx(OrderMax - 1)); @@ -99,10 +92,9 @@ void privateMutateFun(const Var_t *parent, Var_t *child, } void GACvter::iFun(Var_t *v, const CvterInfo *arg) noexcept { - v->setZero(arg->rawImageCache.rows(), arg->rawImageCache.cols()); - if (heu::randD() < 1.0 / 3) { // generate by random + if (heu::randD() < 1.0 / 3) { // generate by random std::unordered_map iniToolCpy = arg->iniTool; for (auto &i : iniToolCpy) { @@ -113,14 +105,14 @@ void GACvter::iFun(Var_t *v, const CvterInfo *arg) noexcept { v->operator()(i) = iniToolCpy[arg->rawImageCache(i)]; } - } else { // generate by seed and mutation + } else { // generate by seed and mutation - if (heu::randD() < 0.4) { // strong mutation + if (heu::randD() < 0.4) { // strong mutation privateMutateFun(&arg->seeds[heu::randIdx(arg->seeds.size())], v, arg); - } else { // weak mutation + } else { // weak mutation privateMutateFun(&arg->seeds[heu::randIdx(arg->seeds.size())], v, arg); @@ -129,10 +121,9 @@ void GACvter::iFun(Var_t *v, const CvterInfo *arg) noexcept { } void GACvter::fFun(const Var_t *v, const CvterInfo *arg, double *f) noexcept { - GrayImage gray(arg->rawImageCache.rows(), arg->rawImageCache.cols()), edged; for (int64_t i = 0; i < arg->rawImageCache.size(); i++) { - gray(i) = mapColor2Gray[arg->colorMap(i).mapColor(v->operator()(i))]; + gray(i) = arg->mapColor2Gray[arg->colorMap(i).mapColor(v->operator()(i))]; } applyGaussian(gray, &edged, Gaussian); @@ -146,7 +137,6 @@ void GACvter::fFun(const Var_t *v, const CvterInfo *arg, double *f) noexcept { void GACvter::cFun(const Var_t *p1, const Var_t *p2, Var_t *c1, Var_t *c2, const CvterInfo *arg) noexcept { - const uint32_t rows = arg->rawImageCache.rows(); const uint32_t cols = arg->rawImageCache.cols(); const uint32_t rS = heu::randD(1, rows - 2); @@ -174,7 +164,6 @@ void GACvter::cFun(const Var_t *p1, const Var_t *p2, Var_t *c1, Var_t *c2, void GACvter::mFun(const Var_t *parent, Var_t *child, const CvterInfo *arg) noexcept { - if (arg->strongMutation) { privateMutateFun(parent, child, arg); } else { @@ -215,6 +204,8 @@ void GACvter::GAConverter::setRawImage(const EImage &src) noexcept { for (int i = 0; i < this->_args.rawImageCache.size(); i++) { this->_args.colorMap(i) = colorHash[this->_args.rawImageCache(i)]; } + + this->_args.mapColor2Gray = updateMapColor2GrayLUT(); } void GACvter::GAConverter::setSeeds( diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.h b/utilities/ExternalConverters/GAConverter/GAConverter.h index de726410..a3166d16 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.h +++ b/utilities/ExternalConverters/GAConverter/GAConverter.h @@ -35,7 +35,7 @@ void cFun(const Var_t *, const Var_t *, Var_t *, Var_t *, const CvterInfo *) noexcept; void mFun(const Var_t *, Var_t *, const CvterInfo *) noexcept; -void updateMapColor2GrayLUT(); +[[nodiscard]] mapColor2Gray_LUT_t updateMapColor2GrayLUT(); class GAConverter : private heu::SOGA; -public: + public: GAConverter(); void setUiPack(const uiPack &) noexcept; @@ -67,8 +67,8 @@ class GAConverter } void setRawImage(const EImage &) noexcept; - void - setSeeds(const std::vector *> &) noexcept; + void setSeeds( + const std::vector *> &) noexcept; using Base_t::option; using Base_t::setOption; @@ -77,7 +77,7 @@ class GAConverter void resultImage(EImage *); -private: + private: friend void ::GACvter::iFun(Var_t *, const CvterInfo *) noexcept; friend void ::GACvter::fFun(const Var_t *, const CvterInfo *, double *) noexcept; @@ -93,7 +93,7 @@ class GAConverter static constexpr std::clock_t reportInterval = 2 * CLOCKS_PER_SEC; -protected: + protected: template inline void __impl_recordFitness() noexcept { Base_t::template __impl_recordFitness(); @@ -109,6 +109,6 @@ class GAConverter } }; -} // namespace GACvter +} // namespace GACvter -#endif // SCL_GACVTER_GACONVERTER_H +#endif // SCL_GACVTER_GACONVERTER_H diff --git a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp index 5558cd58..27fcaf7c 100644 --- a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp +++ b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp @@ -45,7 +45,7 @@ using GrayImage = Eigen::ArrayXX; using mapColor_t = uint8_t; using order_t = uint8_t; -const order_t OrderMax = 4; +constexpr order_t OrderMax = 4; using mutateMap_t = Eigen::Array; @@ -64,7 +64,7 @@ const Eigen::Array Gaussian = {{2, 4, 5, 4, 2}, {5, 12, 15, 12, 5}, {4, 9, 12, 9, 4}, {2, 4, 5, 4, 2}}; -const int GauSum = Gaussian.sum(); +// const int GauSum = Gaussian.sum(); inline mutateMap_t makeMutateMap() { mutateMap_t res; @@ -133,6 +133,6 @@ void EImg2GrayImg(const EImage &e, GrayImage *gImg) noexcept { } } } -} // namespace GACvter +} // namespace GACvter -#endif // GACVTERDEFINES_H +#endif // GACVTERDEFINES_H diff --git a/utilities/ExternalConverters/GAConverter/uiPack.h b/utilities/ExternalConverters/GAConverter/uiPack.h index fe404a08..b6d59231 100644 --- a/utilities/ExternalConverters/GAConverter/uiPack.h +++ b/utilities/ExternalConverters/GAConverter/uiPack.h @@ -36,15 +36,16 @@ using uiPack = ::uiPack; struct CvterInfo { EImage rawImageCache; heu::MatrixDynamicSize - colorMap; // the relationship between pixels and sortColor s + colorMap; // the relationship between pixels and sortColor s std::clock_t prevClock; bool strongMutation; GrayImage edgeFeatureMap; - std::vector seeds; // seeds to initialize population + std::vector seeds; // seeds to initialize population std::unordered_map iniTool; uiPack ui; + mapColor2Gray_LUT_t mapColor2Gray{}; }; -} // namespace GACvter +} // namespace GACvter -#endif // UIPACK_H +#endif // UIPACK_H From 3982788d8fa581fb4ab9afbc847a3ccc8f67ed5f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 17:07:21 +0800 Subject: [PATCH 0762/1123] use more unique ptr Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft.cpp | 26 +++++++++++------------- SlopeCraftL/TokiSlopeCraft.h | 4 ++-- utilities/BlockListManager/BaseColor.cpp | 2 +- utilities/BlockListManager/BaseColor.h | 2 +- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 80279565..0be9e32c 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -51,22 +51,22 @@ std::mutex SCL_internal_lock; // const colorset_allowed_t &libImageCvt::ImageCvter::allowed_colorset = // TokiSlopeCraft::Allowed; -TokiSlopeCraft::TokiSlopeCraft() : image_cvter{Basic, Allowed} { +TokiSlopeCraft::TokiSlopeCraft() + : image_cvter{Basic, Allowed}, + glassBuilder{new PrimGlassBuilder}, + Compressor{new LossyCompressor} { kernelStep = step::nothing; this->image_cvter.clear_images(); this->image_cvter.clear_color_hash(); // rawImage.setZero(0, 0); - - glassBuilder = new PrimGlassBuilder; - Compressor = new LossyCompressor; // GAConverter = new GACvter::GAConverter; - setProgressRangeSet([](void *, int, int, int) {}); - setProgressAdd([](void *, int) {}); - setKeepAwake([](void *) {}); - setReportError([](void *, errorFlag, const char *) {}); - setReportWorkingStatue([](void *, workStatues) {}); - setAlgoProgressAdd([](void *, int) {}); - setAlgoProgressRangeSet([](void *, int, int, int) {}); + this->progressRangeSet = [](void *, int, int, int) {}; + this->progressAdd = [](void *, int) {}; + this->keepAwake = [](void *) {}; + this->reportError = [](void *, errorFlag, const char *) {}; + this->reportWorkingStatue = [](void *, workStatues) {}; + this->algoProgressAdd = [](void *, int) {}; + this->algoProgressRangeSet = [](void *, int, int, int) {}; glassBuilder->windPtr = &wind; glassBuilder->progressAddPtr = &this->algoProgressAdd; @@ -90,8 +90,6 @@ TokiSlopeCraft::TokiSlopeCraft() : image_cvter{Basic, Allowed} { } TokiSlopeCraft::~TokiSlopeCraft() { - delete Compressor; - delete glassBuilder; // delete GAConverter; ::SCL_internal_lock.lock(); @@ -309,7 +307,7 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, return false; } - GACvter::updateMapColor2GrayLUT(); + // GACvter::updateMapColor2GrayLUT(); reporter->reportWorkingStatue(reporter->wind, workStatues::none); for (auto kernel_ptr : TokiSlopeCraft::kernel_hash_set) { diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 0dc10491..17318468 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -310,8 +310,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { libMapImageCvt::MapImageCvter image_cvter; // std::array size3D; // x,y,z - PrimGlassBuilder *glassBuilder; - LossyCompressor *Compressor; + std::unique_ptr glassBuilder; + std::unique_ptr Compressor; // std::shared_ptr GAConverter{nullptr}; diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index c03ddaa8..8ac2d6e0 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -9,7 +9,7 @@ BaseColorWidget::BaseColorWidget(QWidget* parent, uint8_t _basecolor) connect(this->ui->cb_enable, &QCheckBox::toggled, this, &BaseColorWidget::changed); }; -BaseColorWidget::~BaseColorWidget() { delete this->ui; }; +BaseColorWidget::~BaseColorWidget(){}; void BaseColorWidget::set_color(uint32_t color) noexcept { QPalette pl; diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index 19f4b3de..e02c09b4 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -17,7 +17,7 @@ using select_callback_t = std::function ui; const uint8_t basecolor{255}; std::vector blocks; From e1a9cb9ab7bdf3e2fe570a1eaf108e960e9f0515 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 17:47:59 +0800 Subject: [PATCH 0763/1123] use pch for SCL and SC Signed-off-by: ToKiNoBug --- SlopeCraft/CMakeLists.txt | 1 + SlopeCraftL/CMakeLists.txt | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 641eacf4..c822e992 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -74,6 +74,7 @@ qt_add_executable(SlopeCraft ${SlopeCraft_project_files}) target_compile_features(SlopeCraft PRIVATE cxx_std_23) +target_precompile_headers(SlopeCraft PRIVATE ${SlopeCraft_headers}) target_link_libraries(SlopeCraft PRIVATE Qt6::Core diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ad225cf4..03ea569a 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") ${CMAKE_CURRENT_BINARY_DIR}/others/SlopeCraftL.rc) endif () -set(SlopeCraft_SCL_sources +set(Slope_SCL_internal_headers ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h # AiCvterOpt.h @@ -35,10 +35,14 @@ set(SlopeCraft_SCL_sources lossyCompressor.h simpleBlock.h - SlopeCraftL.h SlopeCraftL_global.h WriteStringDeliver.h +) +set(SlopeCraft_SCL_sources + + + SlopeCraftL.h # AiCvterOpt.cpp Colors.cpp ColorSource.cpp @@ -55,7 +59,10 @@ set(SlopeCraft_SCL_sources simpleBlock.cpp SlopeCraftL.cpp + #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} + Colorset.cpp + Colorset.h ) # add this definations to both targets @@ -64,7 +71,8 @@ add_definitions(-DSLOPECRAFTL_LIBRARY) add_library(SlopeCraftL SHARED ${SlopeCraft_SCL_sources}) # add_library(SlopeCraftL_C SHARED ${SlopeCraft_SCL_sources}) -target_compile_features(SlopeCraftL PRIVATE cxx_std_20) +target_compile_features(SlopeCraftL PRIVATE cxx_std_23) +target_precompile_headers(SlopeCraftL PRIVATE ${SlopeCraft_SCL_internal_headers}) target_include_directories(SlopeCraftL INTERFACE $ $) From c0db27b1025aedda96cb87df8125040d30929440 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 21:58:17 +0800 Subject: [PATCH 0764/1123] remove colorset singleton in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 6 +- SlopeCraftL/Colors.cpp | 26 ++-- SlopeCraftL/Colorset.cpp | 9 ++ SlopeCraftL/Colorset.h | 28 ++++ SlopeCraftL/SlopeCraftL.cpp | 20 +-- SlopeCraftL/SlopeCraftL.h | 8 ++ SlopeCraftL/TokiSlopeCraft.cpp | 130 ++++++++++-------- SlopeCraftL/TokiSlopeCraft.h | 48 +++---- SlopeCraftL/TokiSlopeCraft_build.cpp | 61 ++++---- SlopeCraftL/TokiSlopeCraft_cache.cpp | 16 ++- SlopeCraftL/TokiSlopeCraft_convert.cpp | 7 +- SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 38 ++--- .../ExternalConverterStaticInterface.h | 12 +- .../GAConverter/CMakeLists.txt | 11 +- .../GAConverter/GAConverter.cpp | 2 +- .../GAConverter/sortColor.cpp | 16 ++- .../GAConverter/sortColor.h | 11 +- .../ExternalConverters/GAConverter/uiPack.h | 1 + 18 files changed, 260 insertions(+), 190 deletions(-) create mode 100644 SlopeCraftL/Colorset.cpp create mode 100644 SlopeCraftL/Colorset.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 03ea569a..6898c8d6 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -9,6 +9,7 @@ find_package(Boost COMPONENTS iostreams REQUIRED) find_package(libzip REQUIRED) find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) +find_package(cereal REQUIRED) #find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -37,6 +38,7 @@ set(Slope_SCL_internal_headers simpleBlock.h SlopeCraftL_global.h WriteStringDeliver.h + Colorset.h ) set(SlopeCraft_SCL_sources @@ -58,11 +60,10 @@ set(SlopeCraft_SCL_sources lossyCompressor.cpp simpleBlock.cpp SlopeCraftL.cpp + Colorset.cpp #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} - Colorset.cpp - Colorset.h ) # add this definations to both targets @@ -99,6 +100,7 @@ set(SlopeCraft_SCL_link_libs Boost::iostreams libzip::zip tl::expected + cereal::cereal ${SC_zstd_target_name}) # link to dependents diff --git a/SlopeCraftL/Colors.cpp b/SlopeCraftL/Colors.cpp index 9e3d8e55..5b07ba0e 100644 --- a/SlopeCraftL/Colors.cpp +++ b/SlopeCraftL/Colors.cpp @@ -31,24 +31,24 @@ This file is part of SlopeCraft. // TokiColor::Basic = &TokiSlopeCraft::Basic; namespace SlopeCraft { -int colorCount4External() { return TokiSlopeCraft::Allowed.color_count(); } +// int colorCount4External() { return TokiSlopeCraft::Allowed.color_count(); } extern Eigen::Map BasicRGB4External(int channel) { return Eigen::Map( - &TokiSlopeCraft::Basic.RGB_mat()(0, channel), - TokiSlopeCraft::Basic.color_count()); + &color_set::basic->RGB_mat()(0, channel), + color_set::basic->color_count()); } -Eigen::Map AllowedRGB4External(int channel) { - return Eigen::Map( - TokiSlopeCraft::Allowed.rgb_data(channel), colorCount4External()); -} - -extern Eigen::Map> -AllowedMapList4External() { - return Eigen::Map>( - TokiSlopeCraft::Allowed.map_data(), colorCount4External()); -} +// Eigen::Map AllowedRGB4External(int channel) { +// return Eigen::Map( +// TokiSlopeCraft::Allowed.rgb_data(channel), colorCount4External()); +// } +// +// extern Eigen::Map> +// AllowedMapList4External() { +// return Eigen::Map>( +// TokiSlopeCraft::Allowed.map_data(), colorCount4External()); +// } } // end namespace SlopeCraft diff --git a/SlopeCraftL/Colorset.cpp b/SlopeCraftL/Colorset.cpp new file mode 100644 index 00000000..ccfcf1cd --- /dev/null +++ b/SlopeCraftL/Colorset.cpp @@ -0,0 +1,9 @@ +// +// Created by joseph on 4/12/24. +// + +#include "Colorset.h" +#include "SCLDefines.h" + +const std::unique_ptr color_set::basic{ + new colorset_basic_t{RGBBasicSource}}; \ No newline at end of file diff --git a/SlopeCraftL/Colorset.h b/SlopeCraftL/Colorset.h new file mode 100644 index 00000000..6d3053a8 --- /dev/null +++ b/SlopeCraftL/Colorset.h @@ -0,0 +1,28 @@ +// +// Created by joseph on 4/12/24. +// + +#ifndef SLOPECRAFT_COLORSET_H +#define SLOPECRAFT_COLORSET_H + +#include +#include +#include +#include +#include +#include +#include "simpleBlock.h" +#include "Colors.h" +#include "SlopeCraftL.h" + +struct color_set { + static const std::unique_ptr basic; + + colorset_allowed_t allowed_colorset; + + SlopeCraft::gameVersion mc_version{SCL_gameVersion::MC17}; + SlopeCraft::mapTypes map_type{SCL_mapTypes::Slope}; + std::vector palette{}; +}; + +#endif // SLOPECRAFT_COLORSET_H diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index a158c60d..2c149a8a 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -349,12 +349,12 @@ double SCL_EXPORT SCL_getMutationProb(const AiCvterOpt *a) { return a->mutationProb; } -SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, - const float **const gdata, - const float **const bdata, - const uint8_t **mapdata, int *num) { - TokiSlopeCraft::getColorMapPtrs(rdata, gdata, bdata, mapdata, num); -} +// SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, +// const float **const gdata, +// const float **const bdata, +// const uint8_t **mapdata, int *num) { +// TokiSlopeCraft::getColorMapPtrs(rdata, gdata, bdata, mapdata, num); +// } SCL_EXPORT const float *SCL_getBasicColorMapPtrs() { return TokiSlopeCraft::getBasicColorMapPtrs(); @@ -381,8 +381,8 @@ SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { SCL_EXPORT uint8_t SCL_maxBaseColor() { return 61; } -SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) { - return TokiSlopeCraft::getBlockPalette(blkpp, capacity); -} +// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, +// size_t capacity) { +// return TokiSlopeCraft::getBlockPalette(blkpp, capacity); +// } } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 6e5ee585..5844a5c8 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -154,6 +154,14 @@ class BlockListInterface { virtual bool contains(const AbstractBlock *) const noexcept = 0; }; +struct ColorMapPtrs { + const float *r_data; + const float *g_data; + const float *b_data; + const uint8_t *map_data; + int num_colors; +}; + class Kernel { public: Kernel(); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 0be9e32c..e399d9cc 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -26,18 +26,20 @@ This file is part of SlopeCraft. #undef RGB #endif -const Eigen::Array TokiSlopeCraft::DitherMapLR = { - {0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, {3.0 / 16.0, 5.0 / 16.0, 1.0 / 16.0}}; -const Eigen::Array TokiSlopeCraft::DitherMapRL = { - {7.0 / 16.0, 0.0 / 16.0, 0.0 / 16.0}, {1.0 / 16.0, 5.0 / 16.0, 3.0 / 16.0}}; - -const colorset_basic_t TokiSlopeCraft::Basic(SlopeCraft::RGBBasicSource); -colorset_allowed_t TokiSlopeCraft::Allowed; - -gameVersion TokiSlopeCraft::mcVer{ - SCL_gameVersion::MC17}; // 12,13,14,15,16,17,18,19,20 -mapTypes TokiSlopeCraft::mapType; -std::vector TokiSlopeCraft::blockPalette(0); +// const Eigen::Array TokiSlopeCraft::DitherMapLR = { +// {0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, {3.0 / 16.0, 5.0 / 16.0, 1.0 +// / 16.0}}; +// const Eigen::Array TokiSlopeCraft::DitherMapRL = { +// {7.0 / 16.0, 0.0 / 16.0, 0.0 / 16.0}, {1.0 / 16.0, 5.0 / 16.0, 3.0 +// / 16.0}}; + +// const colorset_basic_t TokiSlopeCraft::Basic(SlopeCraft::RGBBasicSource); +// colorset_allowed_t TokiSlopeCraft::Allowed; +// +// gameVersion TokiSlopeCraft::mcVer{ +// SCL_gameVersion::MC17}; // 12,13,14,15,16,17,18,19,20 +// mapTypes TokiSlopeCraft::mapType; +// std::vector TokiSlopeCraft::blockPalette(0); std::unordered_set TokiSlopeCraft::kernel_hash_set; @@ -52,7 +54,8 @@ std::mutex SCL_internal_lock; // TokiSlopeCraft::Allowed; TokiSlopeCraft::TokiSlopeCraft() - : image_cvter{Basic, Allowed}, + : colorset{}, + image_cvter{*color_set::basic, colorset.allowed_colorset}, glassBuilder{new PrimGlassBuilder}, Compressor{new LossyCompressor} { kernelStep = step::nothing; @@ -143,12 +146,19 @@ void TokiSlopeCraft::decreaseStep(step _step) { kernelStep = _step; } +ColorMapPtrs TokiSlopeCraft::getAllowedColorMapPtrs() const noexcept { + const auto &allowed = this->colorset.allowed_colorset; + return {allowed.rgb_data(0), allowed.rgb_data(1), allowed.rgb_data(2), + allowed.map_data(), allowed.color_count()}; +} + void TokiSlopeCraft::trySkipStep(step s) { if (this->kernelStep >= s) { return; } - if (Allowed.color_count() != 0 && blockPalette.size() != 0) { + if (this->colorset.allowed_colorset.color_count() != 0 && + this->colorset.palette.size() != 0) { this->kernelStep = step::wait4Image; } } @@ -181,7 +191,7 @@ const AiCvterOpt *TokiSlopeCraft::aiCvterOpt() const { return &AiOpt; } bool TokiSlopeCraft::setType(mapTypes type, gameVersion ver, const bool *allowedBaseColor, const AbstractBlock *const *const palettes) { - return __impl_setType(type, ver, allowedBaseColor, palettes, this); + return this->__impl_setType(type, ver, allowedBaseColor, palettes, this); } bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, @@ -198,37 +208,38 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, } */ - TokiSlopeCraft::mapType = type; - TokiSlopeCraft::mcVer = ver; + this->colorset.map_type = type; + this->colorset.mc_version = ver; - Allowed.need_find_side = (TokiSlopeCraft::mapType == mapTypes::Slope); + this->colorset.allowed_colorset.need_find_side = + (this->colorset.map_type == mapTypes::Slope); - TokiSlopeCraft::blockPalette.resize(64); + this->colorset.palette.resize(64); // cerr<<__FILE__<<__LINE__<colorset.palette[i].clear(); continue; } - palettes[i]->copyTo(&TokiSlopeCraft::blockPalette[i]); + palettes[i]->copyTo(&this->colorset.palette[i]); - if (TokiSlopeCraft::blockPalette[i].id.find(':') == - TokiSlopeCraft::blockPalette[i].id.npos) { - TokiSlopeCraft::blockPalette[i].id = - "minecraft:" + TokiSlopeCraft::blockPalette[i].id; + if (this->colorset.palette[i].id.find(':') == + this->colorset.palette[i].id.npos) { + this->colorset.palette[i].id = + "minecraft:" + this->colorset.palette[i].id; } - if (TokiSlopeCraft::blockPalette[i].idOld.empty()) { - TokiSlopeCraft::blockPalette[i].idOld = blockPalette[i].id; + if (this->colorset.palette[i].idOld.empty()) { + this->colorset.palette[i].idOld = this->colorset.palette[i].id; } - if (TokiSlopeCraft::blockPalette[i].idOld.size() > 0 && - (TokiSlopeCraft::blockPalette[i].idOld.find(':') == - TokiSlopeCraft::blockPalette[i].idOld.npos)) { - TokiSlopeCraft::blockPalette[i].idOld = - "minecraft:" + TokiSlopeCraft::blockPalette[i].idOld; + if (this->colorset.palette[i].idOld.size() > 0 && + (this->colorset.palette[i].idOld.find(':') == + this->colorset.palette[i].idOld.npos)) { + this->colorset.palette[i].idOld = + "minecraft:" + this->colorset.palette[i].idOld; } } @@ -256,13 +267,12 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, MIndex[index] = false; continue; } - if ((int)mcVer < + if ((int)this->colorset.mc_version < baseColorVer(index2baseColor(index))) { // 版本低于基色版本 MIndex[index] = false; continue; } - if (TokiSlopeCraft::blockPalette[index2baseColor(index)] - .id.empty()) { // 空 id + if (this->colorset.palette[index2baseColor(index)].id.empty()) { // 空 id MIndex[index] = false; continue; } @@ -274,31 +284,35 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, MIndex[index] = false; continue; }*/ - if (is_vanilla_static() && + if (this->isVanilla() && (index2depth(index) >= 3)) { // 可实装的地图画不允许第四种阴影 MIndex[index] = false; continue; } if (index2baseColor(index) == 12) { // 如果是水且非墙面 - if (is_flat_static() && index2depth(index) != 2) { // 平板且水深不是 1 格 + if (this->isFlat() && index2depth(index) != 2) { // 平板且水深不是 1 格 MIndex[index] = false; continue; } } else { - if (is_flat_static() && index2depth(index) != 1) { // 平板且阴影不为 1 + if (this->isFlat() && index2depth(index) != 1) { // 平板且阴影不为 1 MIndex[index] = false; continue; } } } - if (!TokiSlopeCraft::Allowed.apply_allowed(Basic, MIndex)) { - std::string msg = "Too few usable color(s) : only " + - std::to_string(Allowed.color_count()) + " colors\n"; + if (!this->colorset.allowed_colorset.apply_allowed(*color_set::basic, + MIndex)) { + std::string msg = + "Too few usable color(s) : only " + + std::to_string(this->colorset.allowed_colorset.color_count()) + + " colors\n"; msg += "Avaliable base color(s) : "; - for (int idx = 0; idx < Allowed.color_count(); idx++) { - msg += std::to_string(Allowed.Map(idx)) + ", "; + for (int idx = 0; idx < this->colorset.allowed_colorset.color_count(); + idx++) { + msg += std::to_string(this->colorset.allowed_colorset.Map(idx)) + ", "; } reporter->reportError(reporter->wind, errorFlag::USEABLE_COLOR_TOO_FEW, @@ -326,7 +340,7 @@ uint16_t TokiSlopeCraft::getColorCount() const { "the map type and gameversion"); return 0; } - return Allowed.color_count(); + return this->colorset.allowed_colorset.color_count(); } void TokiSlopeCraft::getAvailableColors(ARGB *const ARGBDest, @@ -336,21 +350,22 @@ void TokiSlopeCraft::getAvailableColors(ARGB *const ARGBDest, *num = getColorCount(); } - for (int idx = 0; idx < TokiSlopeCraft::Allowed.color_count(); idx++) { + for (int idx = 0; idx < this->colorset.allowed_colorset.color_count(); + idx++) { if (mapColorDest != nullptr) { - mapColorDest[idx] = Allowed.Map(idx); + mapColorDest[idx] = this->colorset.allowed_colorset.Map(idx); } if (ARGBDest != nullptr) { ARGB r, g, b, a; - if (mapColor2baseColor(Allowed.Map(idx)) != 0) + if (mapColor2baseColor(this->colorset.allowed_colorset.Map(idx)) != 0) a = 255; else a = 0; - r = ARGB(Allowed.RGB(idx, 0) * 255); - g = ARGB(Allowed.RGB(idx, 1) * 255); - b = ARGB(Allowed.RGB(idx, 2) * 255); + r = ARGB(this->colorset.allowed_colorset.RGB(idx, 0) * 255); + g = ARGB(this->colorset.allowed_colorset.RGB(idx, 1) * 255); + b = ARGB(this->colorset.allowed_colorset.RGB(idx, 2) * 255); ARGBDest[idx] = (a << 24) | (r << 16) | (g << 8) | (b); } @@ -382,9 +397,9 @@ void TokiSlopeCraft::getBaseColorInARGB32(ARGB *const dest) const { if (dest == nullptr) return; for (uint8_t base = 0; base < 64; base++) - dest[base] = - ARGB32(255 * Basic.RGB(128 + base, 0), 255 * Basic.RGB(128 + base, 1), - 255 * Basic.RGB(128 + base, 2), 255); + dest[base] = ARGB32(255 * color_set::basic->RGB(128 + base, 0), + 255 * color_set::basic->RGB(128 + base, 1), + 255 * color_set::basic->RGB(128 + base, 2), 255); } int64_t TokiSlopeCraft::sizePic(short dim) const { @@ -458,7 +473,8 @@ std::array TokiSlopeCraft::LUT_mapcolor_to_argb() std::array argbLUT; for (int idx = 0; idx < 256; idx++) { argbLUT[idx] = - RGB2ARGB(Basic.RGB(idx, 0), Basic.RGB(idx, 1), Basic.RGB(idx, 2)); + RGB2ARGB(color_set::basic->RGB(idx, 0), color_set::basic->RGB(idx, 1), + color_set::basic->RGB(idx, 2)); } return argbLUT; } @@ -534,7 +550,7 @@ int64_t TokiSlopeCraft::getBlockCounts(std::vector *dest) const { // map ele_t in schem to index in blockPalette(material index) std::vector map_ele_to_material; { - map_ele_to_material.resize(TokiSlopeCraft::blockPalette.size()); + map_ele_to_material.resize(this->colorset.palette.size()); std::fill(map_ele_to_material.begin(), map_ele_to_material.end(), -1); for (int ele = 1; ele < this->schem.palette_size(); ele++) { @@ -544,9 +560,9 @@ int64_t TokiSlopeCraft::getBlockCounts(std::vector *dest) const { TokiSlopeCraft::find_block_for_idx(ele - 1, blkid); assert(sbp != nullptr); - int64_t idx = sbp - TokiSlopeCraft::blockPalette.data(); + int64_t idx = sbp - this->colorset.palette.data(); assert(idx >= 0); - assert(idx < (int64_t)TokiSlopeCraft::blockPalette.size()); + assert(idx < (int64_t)this->colorset.palette.size()); map_ele_to_material[ele] = idx; } diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 17318468..f3fa27ad 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -52,6 +52,7 @@ This file is part of SlopeCraft. #include #include #include "WriteStringDeliver.h" +#include "Colorset.h" #include #include @@ -85,13 +86,13 @@ class NBTWriter; class TokiSlopeCraft : public ::SlopeCraft::Kernel { public: - static const colorset_basic_t Basic; - static colorset_allowed_t Allowed; + // static const colorset_basic_t Basic; + // static colorset_allowed_t Allowed; - static void getColorMapPtrs(const float **const rdata, - const float **const gdata, - const float **const bdata, const uint8_t **, - int *); + [[nodiscard]] ColorMapPtrs getAllowedColorMapPtrs() const noexcept; + + // void getColorMapPtrs(const float **const rdata, const float **const gdata, + // const float **const bdata, const uint8_t **, int *); // full palette static const float *getBasicColorMapPtrs(); @@ -138,9 +139,9 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { const AbstractBlock *const *const) override; private: - static bool __impl_setType(mapTypes, gameVersion, const bool[64], - const AbstractBlock *const *const, - const TokiSlopeCraft *reporter) noexcept; + bool __impl_setType(mapTypes, gameVersion, const bool[64], + const AbstractBlock *const *const, + const TokiSlopeCraft *reporter) noexcept; public: void getBaseColorInARGB32(unsigned int *const) const override; @@ -164,14 +165,12 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { int getImageRows() const override; int getImageCols() const override; - bool isVanilla() const override { return is_vanilla_static(); } - static inline bool is_vanilla_static() noexcept { - return mapType != SCL_mapTypes::FileOnly; + bool isVanilla() const override { + return this->colorset.map_type != SCL_mapTypes::FileOnly; } - bool isFlat() const override { return is_flat_static(); } - static inline bool is_flat_static() noexcept { - return mapType == SCL_mapTypes::Flat; + bool isFlat() const override { + return this->colorset.map_type == SCL_mapTypes::Flat; } // can do in converted: @@ -296,15 +295,16 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void (*reportError)(void *, errorFlag, const char *); void (*reportWorkingStatue)(void *, workStatues); - static gameVersion mcVer; // 12,13,14,15,16,17 - static mapTypes mapType; - static std::vector blockPalette; + // static gameVersion mcVer; // 12,13,14,15,16,17 + // static mapTypes mapType; + // static std::vector blockPalette; private: static std::unordered_set kernel_hash_set; public: step kernelStep; + color_set colorset; // convertAlgo ConvertAlgo; libMapImageCvt::MapImageCvter image_cvter; @@ -407,8 +407,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { private: // determined by mcver, map type and allowed colorest - static std::vector type_hash() noexcept; - static std::string type_dir_of(std::string_view root_cache_dir) noexcept; + std::vector type_hash() const noexcept; + std::string type_dir_of(std::string_view root_cache_dir) const noexcept; inline std::string current_type_dir() const noexcept { return type_dir_of(this->cache_dir.value()); } @@ -464,14 +464,14 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { uint64_t build_task_hash, build_cache_ir *ir = nullptr) noexcept; - static const simpleBlock *find_block_for_idx(int idx, - std::string_view blkid) noexcept; + const simpleBlock *find_block_for_idx(int idx, + std::string_view blkid) const noexcept; std::array LUT_mapcolor_to_argb() const noexcept; public: - static int getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) noexcept; + int getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) const noexcept; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 14f2aa90..d8c243ff 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -19,7 +19,6 @@ This file is part of SlopeCraft. github:https://github.com/SlopeCraft/SlopeCraft bilibili:https://space.bilibili.com/351429231 */ -#include #include #include "TokiSlopeCraft.h" @@ -59,16 +58,16 @@ std::string TokiSlopeCraft::impl_make_tests( return "File name should ends with \".nbt\""; } libSchem::Schem test; - test.set_MC_major_version_number(::TokiSlopeCraft::mcVer); + test.set_MC_major_version_number(this->colorset.mc_version); test.set_MC_version_number( - MCDataVersion::suggested_version(::TokiSlopeCraft::mcVer)); + MCDataVersion::suggested_version(this->colorset.mc_version)); // const simpleBlock ** realSrc=(const simpleBlock **)src; std::vector realSrc; std::vector realBaseColor; realSrc.clear(); realBaseColor.clear(); for (size_t idx = 0; idx < option.block_count; idx++) { - if (option.block_ptrs[idx]->getVersion() > (int)mcVer) { + if (option.block_ptrs[idx]->getVersion() > (int)this->colorset.mc_version) { continue; } realSrc.emplace_back( @@ -88,7 +87,7 @@ std::string TokiSlopeCraft::impl_make_tests( ids.reserve(realSrc.size() + 1); ids.emplace_back("minecraft:air"); for (auto i : realSrc) { - ids.emplace_back(i->idForVersion(TokiSlopeCraft::mcVer)); + ids.emplace_back(i->idForVersion(this->colorset.mc_version)); } test.set_block_id(ids.data(), ids.size()); @@ -175,9 +174,9 @@ std::vector TokiSlopeCraft::schem_block_id_list() temp.reserve(64); temp.emplace_back("minecraft:air"); - for (const auto &block : TokiSlopeCraft::blockPalette) { + for (const auto &block : this->colorset.palette) { std::string_view id_at_curversion = - block.idForVersion(TokiSlopeCraft::mcVer); + block.idForVersion(this->colorset.mc_version); if ("minecraft:air" == id_at_curversion) { break; } else { @@ -214,9 +213,9 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { schem.set_block_id(temp); } - schem.set_MC_major_version_number(TokiSlopeCraft::mcVer); + schem.set_MC_major_version_number(this->colorset.mc_version); schem.set_MC_version_number(MCDataVersion::MCDataVersion_t( - TokiSlopeCraft::mcVersion2VersionNumber(TokiSlopeCraft::mcVer))); + TokiSlopeCraft::mcVersion2VersionNumber(this->colorset.mc_version))); // cerr << "ready to build" << endl; @@ -358,19 +357,19 @@ schem.z_range()}); Build.resize(tempSize3D); // Base(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 // 对应空气 - int x = 0, y = 0, z = 0; - int yLow = 0; + // int x = 0, y = 0, z = 0; + // int yLow = 0; // cerr << WaterList.size() << " water columns in map\n"; for (auto it = WaterList.begin(); it != WaterList.end(); it++) // 水柱周围的玻璃 { - x = TokiCol(it->first) + 1; - z = TokiRow(it->first); - y = waterHigh(it->second); - yLow = waterLow(it->second); + const int x = TokiCol(it->first) + 1; + const int z = TokiRow(it->first); + const int y = waterHigh(it->second); + const int yLow = waterLow(it->second); schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 - for (short yDynamic = yLow; yDynamic <= y; yDynamic++) { + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { schem(x - 1, yDynamic, z - 0) = 1; schem(x + 1, yDynamic, z + 0) = 1; schem(x + 0, yDynamic, z - 1) = 1; @@ -385,13 +384,14 @@ schem.z_range()}); Build.resize(tempSize3D); { for (short c = 0; c < sizePic(1); c++) { if (Base(r + 1, c) == 12 || Base(r + 1, c) == 0) continue; - x = c + 1; - y = LowMap(r + 1, c); - z = r + 1; - if (y >= 1 && blockPalette[Base(r + 1, c)].needGlass) + const int x = c + 1; + const int y = LowMap(r + 1, c); + const int z = r + 1; + if (y >= 1 && this->colorset.palette[Base(r + 1, c)].needGlass) schem(x, y - 1, z) = 0 + 1; - if ((fireProof && blockPalette[Base(r + 1, c)].burnable) || - (endermanProof && blockPalette[Base(r + 1, c)].endermanPickable)) { + if ((fireProof && this->colorset.palette[Base(r + 1, c)].burnable) || + (endermanProof && + this->colorset.palette[Base(r + 1, c)].endermanPickable)) { if (y >= 1 && schem(x, y - 1, z) == 0) schem(x, y - 1, z) = 0 + 1; if (x >= 1 && schem(x - 1, y, z) == 0) schem(x - 1, y, z) = 0 + 1; if (z >= 1 && schem(x, y, z - 1) == 0) schem(x, y, z - 1) = 0 + 1; @@ -411,11 +411,11 @@ schem.z_range()}); Build.resize(tempSize3D); progressAdd(wind, sizePic(2)); for (auto it = WaterList.cbegin(); it != WaterList.cend(); ++it) { - x = TokiCol(it->first) + 1; - z = TokiRow(it->first); - y = waterHigh(it->second); - yLow = waterLow(it->second); - for (short yDynamic = yLow; yDynamic <= y; yDynamic++) { + const int x = TokiCol(it->first) + 1; + const int z = TokiRow(it->first); + const int y = waterHigh(it->second); + const int yLow = waterLow(it->second); + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { schem(x, yDynamic, z) = 13; } } @@ -425,7 +425,7 @@ schem.z_range()}); Build.resize(tempSize3D); } void TokiSlopeCraft::makeBridge() { - if (mapType != mapTypes::Slope) return; + if (this->colorset.map_type != mapTypes::Slope) return; if (this->build_opt.glassMethod != glassBridgeSettings::withBridge) return; int step = sizePic(2) / schem.y_range(); @@ -596,7 +596,6 @@ int TokiSlopeCraft::getSchemPalette(const char **dest_id, } #include -#include std::string TokiSlopeCraft::export_flat_diagram( std::string_view filename, @@ -606,7 +605,7 @@ std::string TokiSlopeCraft::export_flat_diagram( "structure."; } - if (TokiSlopeCraft::mapType != SCL_mapTypes::Flat) { + if (this->colorset.map_type != SCL_mapTypes::Flat) { return "Only flat maps can be exported to flat diagram."; } @@ -637,7 +636,7 @@ std::string TokiSlopeCraft::export_flat_diagram( if (blkp == nullptr) { std::string blkid_full; blkid_full.reserve(64 * 2048); - for (const auto &blk : TokiSlopeCraft::blockPalette) { + for (const auto &blk : this->colorset.palette) { blkid_full += blk.id; blkid_full.push_back('\n'); } diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 6eb52ab0..37d3ac7a 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -106,13 +106,13 @@ uint64_t to_short_hash(std::span full_hash) noexcept { */ } // type hash and dir ------------------------------------ -std::vector TokiSlopeCraft::type_hash() noexcept { +std::vector TokiSlopeCraft::type_hash() const noexcept { // Chocobo1::SHA3_512 hash; boost::uuids::detail::sha1 hash; - SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mapType); - SC_HASH_ADD_DATA(hash, TokiSlopeCraft::mcVer); + SC_HASH_ADD_DATA(hash, this->colorset.map_type); + SC_HASH_ADD_DATA(hash, this->colorset.mc_version); - TokiSlopeCraft::Allowed.hash_add_data(hash); + this->colorset.allowed_colorset.hash_add_data(hash); boost::uuids::detail::sha1::digest_type digest; hash.get_digest(digest); @@ -122,8 +122,9 @@ std::vector TokiSlopeCraft::type_hash() noexcept { return {dig.begin(), dig.end()}; } -std::string TokiSlopeCraft::type_dir_of(std::string_view cache_dir) noexcept { - return fmt::format("{}/{:x}", cache_dir, to_short_hash(type_hash())); +std::string TokiSlopeCraft::type_dir_of( + std::string_view cache_dir) const noexcept { + return fmt::format("{}/{:x}", cache_dir, to_short_hash(this->type_hash())); } std::string TokiSlopeCraft::type_hash_filename() const noexcept { @@ -209,7 +210,8 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, return false; } - libMapImageCvt::MapImageCvter temp{Basic, Allowed}; + libMapImageCvt::MapImageCvter temp{*color_set::basic, + this->colorset.allowed_colorset}; const uint64_t expected_hash = this->image_cvter.task_hash(algo, dither); const std::string filename = this->convert_cache_filename_of( convert_dir(this->current_type_dir(), expected_hash)); diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp index 5573270b..f06066eb 100644 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ b/SlopeCraftL/TokiSlopeCraft_convert.cpp @@ -180,7 +180,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, continue; } - switch (mcVer) { + switch (this->colorset.mc_version) { case SCL_gameVersion::MC12: case SCL_gameVersion::MC13: break; @@ -191,7 +191,8 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, case SCL_gameVersion::MC18: case SCL_gameVersion::MC19: case SCL_gameVersion::MC20: - MapFile.writeInt("DataVersion", mcVersion2VersionNumber(mcVer)); + MapFile.writeInt("DataVersion", + mcVersion2VersionNumber(this->colorset.mc_version)); break; default: cerr << "Wrong game version!\n"; @@ -209,7 +210,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, MapFile.writeByte("unlimitedTracking", 0); MapFile.writeInt("xCenter", 0); MapFile.writeInt("zCenter", 0); - switch (mcVer) { + switch (this->colorset.mc_version) { case SCL_gameVersion::MC12: MapFile.writeByte("dimension", 114); MapFile.writeShort("height", 128); diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index e5097f74..a7c9ad24 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -25,20 +25,20 @@ This file is part of SlopeCraft. const char *TokiSlopeCraft::getSCLVersion() { return SC_VERSION_STR; } -void TokiSlopeCraft::getColorMapPtrs(const float **const r, - const float **const g, - const float **const b, - const unsigned char **m, int *rows) { - if (r != nullptr) *r = TokiSlopeCraft::Allowed.rgb_data(0); - if (g != nullptr) *g = TokiSlopeCraft::Allowed.rgb_data(1); - if (b != nullptr) *b = TokiSlopeCraft::Allowed.rgb_data(2); - - if (m != nullptr) *m = TokiSlopeCraft::Allowed.map_data(); - if (rows != nullptr) *rows = TokiSlopeCraft::Allowed.color_count(); -} +// void TokiSlopeCraft::getColorMapPtrs(const float **const r, +// const float **const g, +// const float **const b, +// const unsigned char **m, int *rows) { +// if (r != nullptr) *r = TokiSlopeCraft::Allowed.rgb_data(0); +// if (g != nullptr) *g = TokiSlopeCraft::Allowed.rgb_data(1); +// if (b != nullptr) *b = TokiSlopeCraft::Allowed.rgb_data(2); +// +// if (m != nullptr) *m = TokiSlopeCraft::Allowed.map_data(); +// if (rows != nullptr) *rows = TokiSlopeCraft::Allowed.color_count(); +// } const float *TokiSlopeCraft::getBasicColorMapPtrs() { - return TokiSlopeCraft::Basic.RGB_mat().data(); + return color_set::basic->RGB_mat().data(); } uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { @@ -64,13 +64,13 @@ uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { #include const simpleBlock *TokiSlopeCraft::find_block_for_idx( - int idx, std::string_view blkid) noexcept { + int idx, std::string_view blkid) const noexcept { if (idx < 0) { return nullptr; } - if (idx < (int)TokiSlopeCraft::blockPalette.size()) { - return &TokiSlopeCraft::blockPalette[idx]; + if (idx < (int)this->colorset.palette.size()) { + return &this->colorset.palette[idx]; } // the block must be mushroom @@ -117,9 +117,9 @@ const simpleBlock *TokiSlopeCraft::find_block_for_idx( } int TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) noexcept { - const size_t palette_size = std::min( - SCL_maxBaseColor() + 1, TokiSlopeCraft::blockPalette.size()); + size_t capacity) const noexcept { + const size_t palette_size = + std::min(SCL_maxBaseColor() + 1, this->colorset.palette.size()); if (blkpp == nullptr || capacity <= 0) { return palette_size; } @@ -129,7 +129,7 @@ int TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, break; } - blkpp[idx] = &TokiSlopeCraft::blockPalette[idx]; + blkpp[idx] = &this->colorset.palette[idx]; } for (size_t idx = palette_size; idx < capacity; idx++) { diff --git a/utilities/ExternalConverters/ExternalConverterStaticInterface.h b/utilities/ExternalConverters/ExternalConverterStaticInterface.h index 2302aaef..c9f66a95 100644 --- a/utilities/ExternalConverters/ExternalConverterStaticInterface.h +++ b/utilities/ExternalConverters/ExternalConverterStaticInterface.h @@ -40,11 +40,11 @@ extern int colorCount4External(); extern Eigen::Map BasicRGB4External(int channel); -extern Eigen::Map AllowedRGB4External(int channel); +// extern Eigen::Map AllowedRGB4External(int channel); +// +// extern Eigen::Map> +// AllowedMapList4External(); -extern Eigen::Map> -AllowedMapList4External(); +} // namespace SlopeCraft -} // namespace SlopeCraft - -#endif // EXTERNAL_CONVERTER_STATIC_INTERFACE_H \ No newline at end of file +#endif // EXTERNAL_CONVERTER_STATIC_INTERFACE_H \ No newline at end of file diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index 31535c78..97e4753e 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -19,17 +19,18 @@ set(SlopeCraft_GAConverter_sources add_library(GAConverter STATIC ${SlopeCraft_GAConverter_sources}) -target_include_directories(GAConverter PUBLIC - ../../ColorManip -) +target_link_libraries(GAConverter PUBLIC ColorManip) +#target_include_directories(GAConverter PUBLIC +# ../../ColorManip +#) find_package(Eigen3 REQUIRED) target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen Heu::Genetic) target_compile_features(GAConverter PRIVATE cxx_std_20) -if(CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(GAConverter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() +endif () # target_compile_options(GAConverter BEFORE PUBLIC "-std=c++17") \ No newline at end of file diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.cpp b/utilities/ExternalConverters/GAConverter/GAConverter.cpp index 957ad6c4..676119f1 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.cpp +++ b/utilities/ExternalConverters/GAConverter/GAConverter.cpp @@ -197,7 +197,7 @@ void GACvter::GAConverter::setRawImage(const EImage &src) noexcept { this->_args.iniTool.reserve(colorHash.size()); for (auto &i : colorHash) { - i.second.calculate(i.first); + i.second.calculate(i.first, *this->_args.allowed_colorset); this->_args.iniTool[i.first] = 0; } diff --git a/utilities/ExternalConverters/GAConverter/sortColor.cpp b/utilities/ExternalConverters/GAConverter/sortColor.cpp index 4d133e38..9e98e9f4 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.cpp +++ b/utilities/ExternalConverters/GAConverter/sortColor.cpp @@ -21,21 +21,22 @@ This file is part of SlopeCraft. */ #include "sortColor.h" +#include "../../../SlopeCraftL/Colors.h" using namespace GACvter; using namespace SlopeCraft; sortColor::sortColor() noexcept {} -void sortColor::calculate(ARGB rgb) noexcept { +void sortColor::calculate(ARGB rgb, + const colorset_allowed_t& allowed) noexcept { const float r = getR(rgb) / 255.0f, g = getG(rgb) / 255.0f, b = getB(rgb) / 255.0f; - auto diffR = SlopeCraft::AllowedRGB4External(0) - r; - // SlopeCraft::Allowed4External.col(0)-r; - // SlopeCraft::Allowed4External.col(0)-r; - auto diffG = SlopeCraft::AllowedRGB4External(1) - g; - auto diffB = SlopeCraft::AllowedRGB4External(2) - b; + // auto diffR = SlopeCraft::AllowedRGB4External(0) - r; + auto diffR = allowed.rgb(0) - r; + auto diffG = allowed.rgb(1) - g; + auto diffB = allowed.rgb(2) - b; TempVectorXf diff = diffR.square() + diffG.square() + diffB.square(); @@ -43,7 +44,8 @@ void sortColor::calculate(ARGB rgb) noexcept { int tempIdx = 0; // errors[o]= diff.minCoeff(&tempIdx); - mapCs[o] = SlopeCraft::AllowedMapList4External()[tempIdx]; + mapCs[o] = allowed.Map( + tempIdx); // SlopeCraft::AllowedMapList4External()[tempIdx]; // Converter::mapColorSrc->operator[](tempIdx); diff[tempIdx] = heu::internal::pinfF; } diff --git a/utilities/ExternalConverters/GAConverter/sortColor.h b/utilities/ExternalConverters/GAConverter/sortColor.h index edbcfd61..6572d6e0 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.h +++ b/utilities/ExternalConverters/GAConverter/sortColor.h @@ -24,14 +24,15 @@ This file is part of SlopeCraft. #define SORTCOLOR_H #include "GACvterDefines.hpp" +#include "../../SlopeCraftL/Colors.h" namespace GACvter { class sortColor { -public: + public: sortColor() noexcept; - void calculate(ARGB) noexcept; + void calculate(ARGB, const colorset_allowed_t& allowed) noexcept; inline mapColor_t mapColor(order_t o) const noexcept { return mapCs[o]; } /* @@ -40,10 +41,10 @@ class sortColor { } */ -private: + private: std::array mapCs; // std::array errors; }; -} // namespace GACvter -#endif // SORTCOLOR_H +} // namespace GACvter +#endif // SORTCOLOR_H diff --git a/utilities/ExternalConverters/GAConverter/uiPack.h b/utilities/ExternalConverters/GAConverter/uiPack.h index b6d59231..c2cd22f3 100644 --- a/utilities/ExternalConverters/GAConverter/uiPack.h +++ b/utilities/ExternalConverters/GAConverter/uiPack.h @@ -44,6 +44,7 @@ struct CvterInfo { std::unordered_map iniTool; uiPack ui; mapColor2Gray_LUT_t mapColor2Gray{}; + const colorset_allowed_t* allowed_colorset{nullptr}; }; } // namespace GACvter From 2c92e535d5b0885f19c949b712297de8285d3764 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 23:23:29 +0800 Subject: [PATCH 0765/1123] update SlopeCraft to adapt SCL Signed-off-by: ToKiNoBug --- SlopeCraft/PreviewWind.cpp | 4 ++-- SlopeCraftL/SlopeCraftL.h | 19 +++++++++++-------- SlopeCraftL/TokiSlopeCraft.h | 4 ++-- SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 7655f2b7..980bc974 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -55,9 +55,9 @@ void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { } std::vector blkp_arr; { - int num = SlopeCraft::SCL_getBlockPalette(nullptr, 0); + const size_t num = kernel->getBlockPalette(nullptr, 0); blkp_arr.resize(num); - SlopeCraft::SCL_getBlockPalette(blkp_arr.data(), blkp_arr.size()); + kernel->getBlockPalette(blkp_arr.data(), blkp_arr.size()); } this->mat_list.resize(blkp_arr.size()); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 5844a5c8..667e21a8 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -192,9 +192,12 @@ class Kernel { virtual const AiCvterOpt *aiCvterOpt() const = 0; + virtual size_t getBlockPalette(const AbstractBlock **buf, + size_t buf_capacity) const noexcept = 0; + // can do in nothing: /// real size of kernel - virtual unsigned long long size() = 0; + virtual size_t size() = 0; /// revert to a previous step virtual void decreaseStep(::SCL_step) = 0; @@ -440,17 +443,17 @@ SCL_EXPORT uint8_t SCL_maxAvailableVersion(); SCL_EXPORT const char *SCL_getSCLVersion(); -SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, - const float **const gdata, - const float **const bdata, const uint8_t **, - int *); -// full palette +// SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, +// const float **const gdata, +// const float **const bdata, const uint8_t +// **, int *); +// full palette SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); SCL_EXPORT uint8_t SCL_maxBaseColor(); -SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, - size_t capacity_in_elements); +// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, +// size_t capacity_in_elements); // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index f3fa27ad..82dba71f 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -470,8 +470,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { std::array LUT_mapcolor_to_argb() const noexcept; public: - int getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) const noexcept; + size_t getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) const noexcept override; }; // bool compressFile(const char *sourcePath, const char *destPath); diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index a7c9ad24..aa7cd336 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -116,8 +116,8 @@ const simpleBlock *TokiSlopeCraft::find_block_for_idx( return blkp; } -int TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) const noexcept { +size_t TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, + size_t capacity) const noexcept { const size_t palette_size = std::min(SCL_maxBaseColor() + 1, this->colorset.palette.size()); if (blkpp == nullptr || capacity <= 0) { From 956cb1dc409fafabd315d457f84149069fb803dd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 12 Apr 2024 23:31:43 +0800 Subject: [PATCH 0766/1123] remove mutable global variables in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft.cpp | 69 +++++----------------------------- SlopeCraftL/TokiSlopeCraft.h | 7 ---- 2 files changed, 9 insertions(+), 67 deletions(-) diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index e399d9cc..fdf018af 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -26,32 +26,9 @@ This file is part of SlopeCraft. #undef RGB #endif -// const Eigen::Array TokiSlopeCraft::DitherMapLR = { -// {0.0 / 16.0, 0.0 / 16.0, 7.0 / 16.0}, {3.0 / 16.0, 5.0 / 16.0, 1.0 -// / 16.0}}; -// const Eigen::Array TokiSlopeCraft::DitherMapRL = { -// {7.0 / 16.0, 0.0 / 16.0, 0.0 / 16.0}, {1.0 / 16.0, 5.0 / 16.0, 3.0 -// / 16.0}}; - -// const colorset_basic_t TokiSlopeCraft::Basic(SlopeCraft::RGBBasicSource); -// colorset_allowed_t TokiSlopeCraft::Allowed; +// std::unordered_set TokiSlopeCraft::kernel_hash_set; // -// gameVersion TokiSlopeCraft::mcVer{ -// SCL_gameVersion::MC17}; // 12,13,14,15,16,17,18,19,20 -// mapTypes TokiSlopeCraft::mapType; -// std::vector TokiSlopeCraft::blockPalette(0); - -std::unordered_set TokiSlopeCraft::kernel_hash_set; - -std::mutex SCL_internal_lock; - -// template <> -// const colorset_basic_t &libImageCvt::ImageCvter::basic_colorset = -// TokiSlopeCraft::Basic; -// -// template <> -// const colorset_allowed_t &libImageCvt::ImageCvter::allowed_colorset = -// TokiSlopeCraft::Allowed; +// std::mutex SCL_internal_lock; TokiSlopeCraft::TokiSlopeCraft() : colorset{}, @@ -80,25 +57,9 @@ TokiSlopeCraft::TokiSlopeCraft() Compressor->progressAddPtr = &this->algoProgressAdd; Compressor->progressRangeSetPtr = &this->algoProgressRangeSet; Compressor->keepAwakePtr = &this->keepAwake; - - ::SCL_internal_lock.lock(); - TokiSlopeCraft::kernel_hash_set.emplace(this); - for (auto kptr : kernel_hash_set) { - if (kptr->kernelStep >= step::wait4Image) { - this->kernelStep = step::wait4Image; - break; - } - } - ::SCL_internal_lock.unlock(); } -TokiSlopeCraft::~TokiSlopeCraft() { - // delete GAConverter; - - ::SCL_internal_lock.lock(); - TokiSlopeCraft::kernel_hash_set.erase(this); - ::SCL_internal_lock.unlock(); -} +TokiSlopeCraft::~TokiSlopeCraft() {} /// function ptr to window object void TokiSlopeCraft::setWindPtr(void *_w) { @@ -191,14 +152,6 @@ const AiCvterOpt *TokiSlopeCraft::aiCvterOpt() const { return &AiOpt; } bool TokiSlopeCraft::setType(mapTypes type, gameVersion ver, const bool *allowedBaseColor, const AbstractBlock *const *const palettes) { - return this->__impl_setType(type, ver, allowedBaseColor, palettes, this); -} - -bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, - const bool allowedBaseColor[64], - const AbstractBlock *const *const palettes, - const TokiSlopeCraft *reporter) noexcept { - ::SCL_internal_lock.lock(); /* if (kernelStep < colorSetReady) { @@ -245,7 +198,7 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, // cerr<<__FILE__<<__LINE__<reportWorkingStatue(reporter->wind, workStatues::collectingColors); + this->reportWorkingStatue(this->wind, workStatues::collectingColors); Eigen::ArrayXi baseColorVer(64); // 基色对应的版本 baseColorVer.setConstant((int)SCL_gameVersion::FUTURE); @@ -315,21 +268,17 @@ bool TokiSlopeCraft::__impl_setType(mapTypes type, gameVersion ver, msg += std::to_string(this->colorset.allowed_colorset.Map(idx)) + ", "; } - reporter->reportError(reporter->wind, errorFlag::USEABLE_COLOR_TOO_FEW, - msg.data()); - ::SCL_internal_lock.unlock(); + this->reportError(this->wind, errorFlag::USEABLE_COLOR_TOO_FEW, msg.data()); return false; } // GACvter::updateMapColor2GrayLUT(); - reporter->reportWorkingStatue(reporter->wind, workStatues::none); - for (auto kernel_ptr : TokiSlopeCraft::kernel_hash_set) { - kernel_ptr->image_cvter.on_color_set_changed(); - kernel_ptr->kernelStep = SCL_step::wait4Image; - } + this->reportWorkingStatue(this->wind, workStatues::none); + this->image_cvter.on_color_set_changed(); + + this->kernelStep = SCL_step::wait4Image; - ::SCL_internal_lock.unlock(); return true; } diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 82dba71f..1dcd1a86 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -295,13 +295,6 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void (*reportError)(void *, errorFlag, const char *); void (*reportWorkingStatue)(void *, workStatues); - // static gameVersion mcVer; // 12,13,14,15,16,17 - // static mapTypes mapType; - // static std::vector blockPalette; - - private: - static std::unordered_set kernel_hash_set; - public: step kernelStep; color_set colorset; From 0323b06bed23ee63bda1e2703cf3dfd39bb0b643 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 13 Apr 2024 10:42:22 +0800 Subject: [PATCH 0767/1123] fix linux and macos build Signed-off-by: ToKiNoBug --- SlopeCraftL/TokiSlopeCraft.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 1dcd1a86..d0d825a7 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -124,7 +124,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void setReportError(void (*)(void *, errorFlag, const char *)) override; /// a function ptr to report working statue especially when busy void setReportWorkingStatue(void (*)(void *, workStatues)) override; - unsigned long long size() override { return sizeof(TokiSlopeCraft); } + size_t size() override { return sizeof(TokiSlopeCraft); } // void destroy() override { delete this; } void decreaseStep(step) override; bool makeTests(const AbstractBlock **, const unsigned char *, const char *, From 7aa24d1cd477c2e589408d7b95e791c73e3cc559 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Apr 2024 22:11:48 +0800 Subject: [PATCH 0768/1123] reimplement image conversion Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 + SlopeCraftL/Colorset.h | 7 + SlopeCraftL/SlopeCraftL.cpp | 10 ++ SlopeCraftL/SlopeCraftL.h | 117 +++++++++++-- SlopeCraftL/TokiSlopeCraft.cpp | 2 +- SlopeCraftL/TokiSlopeCraft.h | 11 +- SlopeCraftL/color_table.cpp | 181 +++++++++++++++++++++ SlopeCraftL/color_table.h | 75 +++++++++ SlopeCraftL/imagePreprocess.cpp | 4 +- utilities/ColorManip/colorset_maptical.hpp | 9 +- utilities/ColorManip/imageConvert.hpp | 2 + utilities/MapImageCvter/MapImageCvter.h | 1 + 12 files changed, 390 insertions(+), 31 deletions(-) create mode 100644 SlopeCraftL/color_table.cpp create mode 100644 SlopeCraftL/color_table.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 6898c8d6..da05d966 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -64,6 +64,8 @@ set(SlopeCraft_SCL_sources #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} + color_table.cpp + color_table.h ) # add this definations to both targets diff --git a/SlopeCraftL/Colorset.h b/SlopeCraftL/Colorset.h index 6d3053a8..60154386 100644 --- a/SlopeCraftL/Colorset.h +++ b/SlopeCraftL/Colorset.h @@ -15,6 +15,13 @@ #include "Colors.h" #include "SlopeCraftL.h" +#define mapColor2Index(mapColor) (64 * ((mapColor) % 4) + ((mapColor) / 4)) +#define index2mapColor(index) (4 * ((index) % 64) + ((index) / 64)) +#define mapColor2baseColor(mapColor) ((mapColor) >> 2) +#define index2baseColor(index) (mapColor2baseColor(index2mapColor(index))) +#define mapColor2depth(mapColor) ((mapColor) % 4) +#define index2depth(index) (mapColor2depth(index2mapColor(index))) + struct color_set { static const std::unique_ptr basic; diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 2c149a8a..fcd6b081 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -381,6 +381,16 @@ SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { SCL_EXPORT uint8_t SCL_maxBaseColor() { return 61; } +#include "color_table.h" +SCL_EXPORT color_table *SCL_create_color_table( + const color_table_create_info &args) { + auto opt = color_table_impl::create(args); + if (opt) { + return new color_table_impl{std::move(opt.value())}; + } + return nullptr; +} + // SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, // size_t capacity) { // return TokiSlopeCraft::getBlockPalette(blkpp, capacity); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 667e21a8..ad58830a 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -56,7 +56,7 @@ using errorFlag = ::SCL_errorFlag; namespace SlopeCraft { struct AiCvterOpt { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; size_t popSize{50}; size_t maxGeneration{200}; size_t maxFailTimes{50}; @@ -154,7 +154,7 @@ class BlockListInterface { virtual bool contains(const AbstractBlock *) const noexcept = 0; }; -struct ColorMapPtrs { +struct color_map_ptrs { const float *r_data; const float *g_data; const float *b_data; @@ -162,6 +162,83 @@ struct ColorMapPtrs { int num_colors; }; +struct const_image_reference { + const uint32_t *data{nullptr}; + size_t rows{0}; + size_t cols{0}; +}; + +class converted_image { + public: + virtual size_t rows() const noexcept = 0; + virtual size_t cols() const noexcept = 0; + inline size_t height() const noexcept { return this->rows(); } + inline size_t width() const noexcept { return this->cols(); } + inline size_t size() const noexcept { return this->rows() * this->cols(); } + + inline size_t size_in_bytes() const noexcept { + return sizeof(uint32_t) * this->rows() * this->cols(); + } + + virtual void get_original_image(uint32_t *buffer) const noexcept = 0; + // virtual void get_dithered_image(uint32_t *buffer) const noexcept = 0; + virtual void get_converted_image(uint32_t *buffer) const noexcept = 0; +}; + +class structure_3D { + public: + virtual size_t shape_x() const noexcept = 0; + virtual size_t shape_y() const noexcept = 0; + virtual size_t shape_z() const noexcept = 0; + virtual size_t palette_length() const noexcept = 0; + virtual void get_palette(const char **buffer_block_id) const noexcept = 0; +}; + +struct progress_callbacks { + void *widget{nullptr}; + void (*set_range)(void *, int, int, int){nullptr}; + void (*add)(void *, int){nullptr}; +}; + +struct ui_callbacks { + void *wind{nullptr}; + void (*keep_awake)(void *){nullptr}; + void (*report_error)(void *, errorFlag, const char *){nullptr}; + void (*report_working_statue)(void *, workStatues){nullptr}; +}; + +struct convert_option { + uint64_t caller_api_version{SC_VERSION_U64}; + SCL_convertAlgo algo{SCL_convertAlgo::RGB_Better}; + bool dither{false}; + AiCvterOpt ai_cvter_opt{}; + progress_callbacks progress{}; + ui_callbacks ui{}; +}; + +class color_table { + public: + virtual ~color_table() = default; + [[nodiscard]] virtual color_map_ptrs colors() const noexcept = 0; + [[nodiscard]] virtual ::SCL_mapTypes map_type() const noexcept = 0; + + [[nodiscard]] inline bool is_vanilla() const noexcept { + return this->map_type() != SCL_mapTypes::FileOnly; + } + + [[nodiscard]] inline bool is_flat() const noexcept { + return this->map_type() == SCL_mapTypes::Flat; + } + + [[nodiscard]] virtual ::SCL_gameVersion mc_version() const noexcept = 0; + [[nodiscard]] virtual size_t num_blocks() const noexcept = 0; + virtual void visit_blocks(void (*)(const AbstractBlock *, void *custom_data), + void *custom_data) const = 0; + + [[nodiscard]] virtual converted_image *convert_image( + const_image_reference original_img, + const convert_option &option) const noexcept = 0; +}; class Kernel { public: Kernel(); @@ -304,7 +381,7 @@ class Kernel { virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, bool expected_col_major) const = 0; struct build_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; uint16_t maxAllowedHeight{256}; uint16_t bridgeInterval{3}; compressSettings compressMethod{::SCL_compressSettings::noCompress}; @@ -338,7 +415,7 @@ class Kernel { size_t dest_capacity) const noexcept = 0; struct litematic_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; const char *litename_utf8 = "by SlopeCraft"; const char *region_name_utf8 = "by SlopeCraft"; }; @@ -347,7 +424,7 @@ class Kernel { const litematic_options &option) const noexcept = 0; struct vanilla_structure_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; bool is_air_structure_void{true}; }; virtual bool exportAsStructure( @@ -355,7 +432,7 @@ class Kernel { const vanilla_structure_options &option) const noexcept = 0; struct WE_schem_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; int offset[3] = {0, 0, 0}; int we_offset[3] = {0, 0, 0}; const char *const *required_mods_name_utf8{nullptr}; @@ -366,7 +443,7 @@ class Kernel { const WE_schem_options &option) const noexcept = 0; struct flag_diagram_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; // 0 or negative number means no split lines int32_t split_line_row_margin{0}; @@ -381,7 +458,7 @@ class Kernel { const flag_diagram_options &option) const noexcept = 0; struct test_blocklist_options { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; const AbstractBlock *const *block_ptrs{nullptr}; const uint8_t *basecolors{nullptr}; size_t block_count{0}; @@ -398,14 +475,26 @@ class Kernel { extern "C" { namespace SlopeCraft { -[[nodiscard]] SCL_EXPORT Kernel *SCL_createKernel(); +[[deprecated]] [[nodiscard]] SCL_EXPORT Kernel *SCL_createKernel(); SCL_EXPORT void SCL_destroyKernel(Kernel *); +struct color_table_create_info { + ::SCL_mapTypes map_type; + ::SCL_gameVersion mc_version; + bool basecolor_allow_LUT[64]; + const AbstractBlock *blocks[64]; + ui_callbacks callbacks; +}; + +[[nodiscard]] SCL_EXPORT color_table *SCL_create_color_table( + const color_table_create_info &); +SCL_EXPORT void SCL_destroy_color_table(color_table *); + [[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); struct BlockListCreateOption { - uint64_t version{SC_VERSION_U64}; + uint64_t caller_api_version{SC_VERSION_U64}; StringDeliver *warnings{nullptr}; StringDeliver *error{nullptr}; }; @@ -439,7 +528,7 @@ SCL_EXPORT void SCL_preprocessImage( SCL_EXPORT bool SCL_haveTransparentPixel(const uint32_t *ARGB32, const uint64_t imageSize); -SCL_EXPORT uint8_t SCL_maxAvailableVersion(); +SCL_EXPORT SCL_gameVersion SCL_maxAvailableVersion(); SCL_EXPORT const char *SCL_getSCLVersion(); @@ -450,10 +539,10 @@ SCL_EXPORT const char *SCL_getSCLVersion(); // full palette SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); -SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); +// SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); SCL_EXPORT uint8_t SCL_maxBaseColor(); -// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, -// size_t capacity_in_elements); +// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, +// size_t capacity_in_elements); // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index fdf018af..90d33a49 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -107,7 +107,7 @@ void TokiSlopeCraft::decreaseStep(step _step) { kernelStep = _step; } -ColorMapPtrs TokiSlopeCraft::getAllowedColorMapPtrs() const noexcept { +color_map_ptrs TokiSlopeCraft::getAllowedColorMapPtrs() const noexcept { const auto &allowed = this->colorset.allowed_colorset; return {allowed.rgb_data(0), allowed.rgb_data(1), allowed.rgb_data(2), allowed.map_data(), allowed.color_count()}; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index d0d825a7..8fd86098 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -69,13 +69,6 @@ namespace SlopeCraft using namespace SlopeCraft; #include -#define mapColor2Index(mapColor) (64 * ((mapColor) % 4) + ((mapColor) / 4)) -#define index2mapColor(index) (4 * ((index) % 64) + ((index) / 64)) -#define mapColor2baseColor(mapColor) ((mapColor) >> 2) -#define index2baseColor(index) (mapColor2baseColor(index2mapColor(index))) -#define mapColor2depth(mapColor) ((mapColor) % 4) -#define index2depth(index) (mapColor2depth(index2mapColor(index))) - class PrimGlassBuilder; class LossyCompressor; @@ -89,7 +82,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // static const colorset_basic_t Basic; // static colorset_allowed_t Allowed; - [[nodiscard]] ColorMapPtrs getAllowedColorMapPtrs() const noexcept; + [[nodiscard]] color_map_ptrs getAllowedColorMapPtrs() const noexcept; // void getColorMapPtrs(const float **const rdata, const float **const gdata, // const float **const bdata, const uint8_t **, int *); @@ -283,7 +276,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // friend void * allowedRGB(); // friend void * allowedMap(); enum ColorSpace { R = 'R', H = 'H', L = 'L', X = 'X' }; - static const Eigen::Array DitherMapLR, DitherMapRL; + // static const Eigen::Array DitherMapLR, DitherMapRL; static const uint32_t reportRate = 100; void *wind; diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp new file mode 100644 index 00000000..1fdc0d3f --- /dev/null +++ b/SlopeCraftL/color_table.cpp @@ -0,0 +1,181 @@ +// +// Created by joseph on 4/15/24. +// + +#include "color_table.h" +#include + +std::optional color_table_impl::create( + const color_table_create_info &args) noexcept { + color_table_impl result; + result.mc_version_ = args.mc_version; + result.map_type_ = args.map_type; + result.allowed.need_find_side = (args.map_type == mapTypes::Slope); + + auto report_err = [&args](errorFlag flag, std::string_view msg) { + if (args.callbacks.report_error) { + args.callbacks.report_error(args.callbacks.wind, flag, msg.data()); + } + }; + + auto report_woring_status = [&args](workStatues ws) { + if (args.callbacks.report_working_statue) { + args.callbacks.report_working_statue(args.callbacks.wind, ws); + } + }; + + // block palette + { + for (size_t i = 0; i < 64; i++) { + if (args.blocks[i] == nullptr) { + result.blocks[i].clear(); + continue; + } + args.blocks[i]->copyTo(&result.blocks[i]); + // fix block id to prevent potential errors + { + if (result.blocks[i].id.find(':') == result.blocks[i].id.npos) { + result.blocks[i].id = "minecraft:" + result.blocks[i].id; + } + + if (result.blocks[i].idOld.empty()) { + result.blocks[i].idOld = result.blocks[i].id; + } + + if (result.blocks[i].idOld.size() > 0 && + (result.blocks[i].idOld.find(':') == result.blocks[i].idOld.npos)) { + result.blocks[i].idOld = "minecraft:" + result.blocks[i].idOld; + } + } + } + } + + report_woring_status(workStatues::collectingColors); + + Eigen::ArrayXi baseColorVer(64); // 基色对应的版本 + baseColorVer.setConstant((int)SCL_gameVersion::FUTURE); + baseColorVer.segment(0, 52).setConstant((int)SCL_gameVersion::ANCIENT); + baseColorVer.segment(52, 7).setConstant((int)SCL_gameVersion::MC16); + baseColorVer.segment(59, 3).setConstant((int)SCL_gameVersion::MC17); + + std::array m_index; + for (short index = 0; index < 256; index++) { + m_index[index] = + true; // 默认可以使用这种颜色,逐次判断各个不可以使用的条件 + + if (!args.basecolor_allow_LUT[index2baseColor( + index)]) { // 在 allowedBaseColor 中被禁止 + m_index[index] = false; + continue; + } + if (index2baseColor(index) == 0) { // 空气禁用 + m_index[index] = false; + continue; + } + if ((int)result.mc_version_ < + baseColorVer(index2baseColor(index))) { // 版本低于基色版本 + m_index[index] = false; + continue; + } + if (result.blocks[index2baseColor(index)].id.empty()) { // 空 id + m_index[index] = false; + continue; + } + /* + if ((mapType == mapTypes::Wall) && + !blockPalette[index2baseColor(index)] + .wallUseable) { //墙面像素画且当前方块不适合墙面 + + m_index[index] = false; + continue; + }*/ + if (result.is_vanilla() && + (index2depth(index) >= 3)) { // 可实装的地图画不允许第四种阴影 + m_index[index] = false; + continue; + } + if (index2baseColor(index) == 12) { // 如果是水且非墙面 + if (result.is_flat() && index2depth(index) != 2) { // 平板且水深不是 1 格 + m_index[index] = false; + continue; + } + } else { + if (result.is_flat() && index2depth(index) != 1) { // 平板且阴影不为 1 + m_index[index] = false; + continue; + } + } + } + + if (!result.allowed.apply_allowed(*color_set::basic, m_index)) { + std::string msg = fmt::format( + "Too few usable color(s) : only {} colors\nAvaliable base color(s) : ", + result.allowed.color_count()); + + for (int idx = 0; idx < result.allowed.color_count(); idx++) { + msg += std::to_string(result.allowed.Map(idx)) + ", "; + } + + report_err(errorFlag::USEABLE_COLOR_TOO_FEW, msg); + return std::nullopt; + } + + report_woring_status(workStatues::none); + + return result; +} + +converted_image_impl::converted_image_impl( + const colorset_allowed_t &allowed_colorset) + : converter{*color_set::basic, allowed_colorset} {} + +converted_image *color_table_impl::convert_image( + const_image_reference original_img, + const convert_option &option) const noexcept { + converted_image_impl cvted{this->allowed}; + + const auto algo = (option.algo == convertAlgo::gaCvter) + ? convertAlgo::RGB_Better + : option.algo; + // auto report_err = [&option](errorFlag flag, std::string_view msg) { + // if (option.ui.report_error) { + // option.ui.report_error(option.ui.wind, flag, msg.data()); + // } + // }; + + auto report_woring_status = [&option](workStatues ws) { + if (option.ui.report_working_statue) { + option.ui.report_working_statue(option.ui.wind, ws); + } + }; + + auto progress_range = [&option](int min, int max, int val) { + if (option.progress.set_range) { + option.progress.set_range(option.progress.widget, min, max, val); + } + }; + + // auto progress_add = [&option](int delta) { + // if (option.progress.add) { + // option.progress.add(option.progress.widget, delta); + // } + // }; + cvted.converter.set_raw_image(original_img.data, original_img.rows, + original_img.cols, false); + { + heu::GAOption opt; + opt.crossoverProb = option.ai_cvter_opt.crossoverProb; + opt.mutateProb = option.ai_cvter_opt.mutationProb; + opt.maxGenerations = option.ai_cvter_opt.maxGeneration; + opt.maxFailTimes = option.ai_cvter_opt.maxFailTimes; + opt.populationSize = option.ai_cvter_opt.popSize; + // here opt is passed as a const ptr, it won't be changed in this function + // call + cvted.converter.convert_image(algo, option.dither, &opt); + } + + progress_range(0, 4 * cvted.size(), 4 * cvted.size()); + report_woring_status(workStatues::none); + + return new converted_image_impl{std::move(cvted)}; +} \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h new file mode 100644 index 00000000..39d610e8 --- /dev/null +++ b/SlopeCraftL/color_table.h @@ -0,0 +1,75 @@ +// +// Created by joseph on 4/15/24. +// + +#ifndef SLOPECRAFT_COLOR_TABLE_H +#define SLOPECRAFT_COLOR_TABLE_H + +#include "SlopeCraftL.h" +#include "Colorset.h" +#include "simpleBlock.h" +#include +#include + +class color_table_impl : public SlopeCraft::color_table { + private: + colorset_allowed_t allowed; + SCL_mapTypes map_type_; + SCL_gameVersion mc_version_; + std::array blocks; + + public: + color_map_ptrs colors() const noexcept override { + return color_map_ptrs{.r_data = allowed.rgb_data(0), + .g_data = allowed.rgb_data(1), + .b_data = allowed.rgb_data(2), + .map_data = allowed.map_data(), + .num_colors = allowed.color_count()}; + } + + SCL_mapTypes map_type() const noexcept override { return this->map_type_; } + + SCL_gameVersion mc_version() const noexcept override { + return this->mc_version_; + } + + size_t num_blocks() const noexcept override { return this->blocks.size(); } + + void visit_blocks(void (*fun)(const AbstractBlock *, void *custom_data), + void *custom_data) const override { + for (auto &blk : this->blocks) { + fun(static_cast(&blk), custom_data); + } + } + + [[nodiscard]] converted_image *convert_image( + const_image_reference original_img, + const convert_option &option) const noexcept override; + + static std::optional create( + const color_table_create_info &args) noexcept; +}; + +class converted_image_impl : public converted_image { + public: + converted_image_impl(converted_image_impl &&) = default; + explicit converted_image_impl(const colorset_allowed_t &allowed_colorset); + using eimg_row_major = + Eigen::Array; + libMapImageCvt::MapImageCvter converter; + + size_t rows() const noexcept final { return this->converter.rows(); } + size_t cols() const noexcept final { return this->converter.cols(); } + + void get_original_image(uint32_t *buffer) const noexcept final { + Eigen::Map buf{buffer, static_cast(this->rows()), + static_cast(this->cols())}; + buf = this->converter.raw_image(); + } + // void get_dithered_image(uint32_t *buffer) const noexcept final {} + void get_converted_image(uint32_t *buffer) const noexcept final { + this->converter.converted_image(buffer, nullptr, nullptr, false); + } +}; + +#endif // SLOPECRAFT_COLOR_TABLE_H diff --git a/SlopeCraftL/imagePreprocess.cpp b/SlopeCraftL/imagePreprocess.cpp index 717d814c..50f2df87 100644 --- a/SlopeCraftL/imagePreprocess.cpp +++ b/SlopeCraftL/imagePreprocess.cpp @@ -92,7 +92,9 @@ SCL_EXPORT bool SCL_haveTransparentPixel(const uint32_t *ARGB32, return false; } -unsigned char SCL_EXPORT SCL_maxAvailableVersion() { return 19; } +SCL_gameVersion SCL_EXPORT SCL_maxAvailableVersion() { + return SCL_gameVersion::MC20; +} #ifndef SCL_CAPI } // namespace SlopeCraft diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 503a54f8..51d716ce 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -199,11 +199,7 @@ class alignas(32) colorset_maptical_allowed { inline const uint8_t *map_data() const noexcept { return __map.data(); } bool apply_allowed(const colorset_maptical_basic &src, - const bool *const allow_list) noexcept { - if (allow_list == nullptr) { - return false; - } - + std::span allow_list) noexcept { const int new_color_count = allow_list_counter(allow_list); if (new_color_count <= 3) { @@ -251,7 +247,8 @@ class alignas(32) colorset_maptical_allowed { } private: - inline int allow_list_counter(const bool *const allow_list) const noexcept { + inline int allow_list_counter( + std::span allow_list) const noexcept { int result = 0; for (int idx = 0; idx < 256; idx++) { const int base = (idx & 0b111111); diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index cb2e7e34..ee5dc68c 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -98,6 +98,8 @@ class ImageCvter : public GPU_wrapper_wrapper { ImageCvter(const basic_colorset_t &basic, const allowed_colorset_t &allowed) : basic_colorset{basic}, allowed_colorset{allowed} {} + ImageCvter(ImageCvter &&) = default; + protected: const basic_colorset_t &basic_colorset; const allowed_colorset_t &allowed_colorset; diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 0a48e043..d8615a6d 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -54,6 +54,7 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { MapImageCvter(const Base_t::basic_colorset_t &basic, const Base_t::allowed_colorset_t &allowed); + MapImageCvter(MapImageCvter &&) = default; ~MapImageCvter() = default; From fea4021b9ca0af073d6478cc1da039214551a4c6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 17:10:05 +0800 Subject: [PATCH 0769/1123] reimplement 3d structure building Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 30 +- SlopeCraft/SCWind.h | 2 +- SlopeCraftL/SlopeCraftL.cpp | 12 +- SlopeCraftL/SlopeCraftL.h | 184 ++++++---- SlopeCraftL/TokiSlopeCraft.cpp | 8 +- SlopeCraftL/TokiSlopeCraft.h | 4 +- SlopeCraftL/TokiSlopeCraft_build.cpp | 16 +- SlopeCraftL/TokiSlopeCraft_convert.cpp | 14 +- SlopeCraftL/color_table.cpp | 321 +++++++++++++++--- SlopeCraftL/color_table.h | 65 +++- SlopeCraftL/simpleBlock.h | 2 +- SlopeCraftL/tests/load_scl_blocklist.cpp | 4 +- .../BlockListManager/BlockListManager.cpp | 11 +- utilities/BlockListManager/BlockListManager.h | 7 +- utilities/SC_GlobalEnums.h | 10 +- utilities/Schem/Schem.cpp | 6 +- 16 files changed, 516 insertions(+), 180 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index b6da7c17..8d446caa 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -73,7 +73,7 @@ SCWind::SCWind(QWidget *parent) [](void *_this, ::SCL_errorFlag err, const char *msg) { reinterpret_cast(_this)->report_error(err, msg); }); - this->kernel->setReportWorkingStatue([](void *_this, ::SCL_workStatues ws) { + this->kernel->setReportWorkingStatue([](void *_this, ::SCL_workStatus ws) { SCWind *const wind = reinterpret_cast(_this); const QString status_str = SCWind::workStatus_to_string(ws); @@ -981,33 +981,33 @@ const QString &SCWind::default_wind_title() noexcept { return title; } -QString SCWind::workStatus_to_string(::SCL_workStatues status) noexcept { +QString SCWind::workStatus_to_string(::SCL_workStatus status) noexcept { switch (status) { - case SlopeCraft::workStatues::none: + case SlopeCraft::workStatus::none: break; - case SlopeCraft::workStatues::buidingHeighMap: + case SlopeCraft::workStatus::buidingHeighMap: return tr("正在构建高度矩阵"); - case SlopeCraft::workStatues::building3D: + case SlopeCraft::workStatus::building3D: return tr("正在构建三维结构"); - case SlopeCraft::workStatues::collectingColors: + case SlopeCraft::workStatus::collectingColors: return tr("正在收集整张图片的颜色"); - case SlopeCraft::workStatues::compressing: + case SlopeCraft::workStatus::compressing: return tr("正在压缩立体地图画"); - case SlopeCraft::workStatues::constructingBridges: + case SlopeCraft::workStatus::constructingBridges: return tr("正在为立体地图画搭桥"); - case SlopeCraft::workStatues::converting: + case SlopeCraft::workStatus::converting: return tr("正在匹配颜色"); - case SlopeCraft::workStatues::dithering: + case SlopeCraft::workStatus::dithering: return tr("正在使用抖动仿色"); - case SlopeCraft::workStatues::flippingToWall: + case SlopeCraft::workStatus::flippingToWall: return tr("正在将平板地图画变为墙面地图画"); - case SlopeCraft::workStatues::writing3D: + case SlopeCraft::workStatus::writing3D: return tr("正在写入三维结构"); - case SlopeCraft::workStatues::writingBlockPalette: + case SlopeCraft::workStatus::writingBlockPalette: return tr("正在写入方块列表"); - case SlopeCraft::workStatues::writingMapDataFiles: + case SlopeCraft::workStatus::writingMapDataFiles: return tr("正在写入地图数据文件"); - case SlopeCraft::workStatues::writingMetaInfo: + case SlopeCraft::workStatus::writingMetaInfo: return tr("正在写入基础信息"); } diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index c1c17719..9c911c52 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -36,7 +36,7 @@ class SCWind : public QMainWindow { static const QString& default_wind_title() noexcept; - static QString workStatus_to_string(::SCL_workStatues) noexcept; + static QString workStatus_to_string(::SCL_workStatus) noexcept; const static QString update_url; diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index fcd6b081..095e6989 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -30,6 +30,7 @@ This file is part of SlopeCraft. #include "TokiSlopeCraft.h" #include "simpleBlock.h" #include "WriteStringDeliver.h" +#include "color_table.h" using namespace SlopeCraft; @@ -90,7 +91,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( return {basecolor, ret}; } -// BlockListInterface *impl_createBlockList(const char *filename, +// block_list_interface *impl_createBlockList(const char *filename, // const blockListOption &option, // std::string &errmsg) noexcept { // errmsg.reserve(4096); @@ -150,7 +151,7 @@ struct zip_deleter { } }; -std::tuple, std::string> +std::tuple, std::string> impl_create_block_list_from_zip(const char *zip_path) noexcept { std::string warnings{}; int error_code = ZIP_ER_OK; @@ -299,8 +300,8 @@ SCL_EXPORT void SCL_destroyKernel(Kernel *k) { SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } -SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *zip_filename, const BlockListCreateOption &option) { +SCL_EXPORT block_list_interface *SCL_createBlockList( + const char *zip_filename, const block_list_create_info &option) { auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); SlopeCraft::write(*option.warnings, warnings); @@ -312,7 +313,7 @@ SCL_EXPORT BlockListInterface *SCL_createBlockList( return res.value(); } -SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *) {} +SCL_EXPORT void SCL_destroyBlockList(block_list_interface *) {} SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt() { return new AiCvterOpt; } void SCL_EXPORT SCL_destroyAiCvterOpt(AiCvterOpt *a) { delete a; } @@ -381,7 +382,6 @@ SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { SCL_EXPORT uint8_t SCL_maxBaseColor() { return 61; } -#include "color_table.h" SCL_EXPORT color_table *SCL_create_color_table( const color_table_create_info &args) { auto opt = color_table_impl::create(args); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index ad58830a..dd7c7669 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -48,7 +48,7 @@ using compressSettings = ::SCL_compressSettings; using convertAlgo = ::SCL_convertAlgo; using glassBridgeSettings = ::SCL_glassBridgeSettings; using gameVersion = ::SCL_gameVersion; -using workStatues = ::SCL_workStatues; +using workStatus = ::SCL_workStatus; using errorFlag = ::SCL_errorFlag; } // namespace SlopeCraft @@ -140,18 +140,19 @@ class AbstractBlock { virtual const char *idForVersion(SCL_gameVersion ver) const noexcept = 0; }; -class BlockListInterface { +class block_list_interface { public: - BlockListInterface() = default; - virtual ~BlockListInterface() = default; - virtual size_t size() const noexcept = 0; - virtual size_t get_blocks(AbstractBlock **, uint8_t *, - size_t capacity_in_elements) noexcept = 0; + block_list_interface() = default; + virtual ~block_list_interface() = default; + [[nodiscard]] virtual size_t size() const noexcept = 0; + [[nodiscard]] virtual size_t get_blocks( + AbstractBlock **, uint8_t *, size_t capacity_in_elements) noexcept = 0; - virtual size_t get_blocks(const AbstractBlock **, uint8_t *, - size_t capacity_in_elements) const noexcept = 0; + [[nodiscard]] virtual size_t get_blocks( + const AbstractBlock **, uint8_t *, + size_t capacity_in_elements) const noexcept = 0; - virtual bool contains(const AbstractBlock *) const noexcept = 0; + [[nodiscard]] virtual bool contains(const AbstractBlock *) const noexcept = 0; }; struct color_map_ptrs { @@ -162,21 +163,92 @@ struct color_map_ptrs { int num_colors; }; +struct progress_callbacks { + void *widget{nullptr}; + void (*cb_set_range)(void *, int, int, int){nullptr}; + void (*cb_add)(void *, int){nullptr}; + + inline void set_range(int min, int max, int val) const { + if (this->cb_set_range) { + this->cb_set_range(this->widget, min, max, val); + } + } + inline void add(int delta) const { + if (this->cb_add) { + this->cb_add(this->widget, delta); + } + } +}; + +struct ui_callbacks { + void *wind{nullptr}; + void (*cb_keep_awake)(void *){nullptr}; + void (*cb_report_error)(void *, errorFlag, const char *){nullptr}; + void (*cb_report_working_status)(void *, workStatus){nullptr}; + + inline void keep_awake() const { + if (this->cb_keep_awake) { + this->cb_keep_awake(this->wind); + } + } + + inline void report_error(errorFlag e, const char *msg) const { + if (this->cb_report_error) { + this->cb_report_error(this->wind, e, msg); + } + } + inline void report_working_status(workStatus ws) const { + if (this->cb_report_working_status) { + this->cb_report_working_status(this->wind, ws); + } + } +}; + +struct convert_option { + uint64_t caller_api_version{SC_VERSION_U64}; + SCL_convertAlgo algo{SCL_convertAlgo::RGB_Better}; + bool dither{false}; + AiCvterOpt ai_cvter_opt{}; + progress_callbacks progress{}; + ui_callbacks ui{}; +}; + +struct build_options { + uint64_t caller_api_version{SC_VERSION_U64}; + uint16_t maxAllowedHeight{256}; + uint16_t bridgeInterval{3}; + compressSettings compressMethod{::SCL_compressSettings::noCompress}; + glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; + bool fire_proof{false}; + bool enderman_proof{false}; + + // added in v5.1.0 + bool connect_mushrooms{false}; + + ui_callbacks ui; + progress_callbacks main_progressbar; + progress_callbacks sub_progressbar; +}; + struct const_image_reference { const uint32_t *data{nullptr}; size_t rows{0}; size_t cols{0}; }; +class structure_3D; class converted_image { public: - virtual size_t rows() const noexcept = 0; - virtual size_t cols() const noexcept = 0; - inline size_t height() const noexcept { return this->rows(); } - inline size_t width() const noexcept { return this->cols(); } - inline size_t size() const noexcept { return this->rows() * this->cols(); } + virtual ~converted_image() = default; + [[nodiscard]] virtual size_t rows() const noexcept = 0; + [[nodiscard]] virtual size_t cols() const noexcept = 0; + [[nodiscard]] inline size_t height() const noexcept { return this->rows(); } + [[nodiscard]] inline size_t width() const noexcept { return this->cols(); } + [[nodiscard]] inline size_t size() const noexcept { + return this->rows() * this->cols(); + } - inline size_t size_in_bytes() const noexcept { + [[nodiscard]] inline size_t size_in_bytes() const noexcept { return sizeof(uint32_t) * this->rows() * this->cols(); } @@ -187,35 +259,14 @@ class converted_image { class structure_3D { public: - virtual size_t shape_x() const noexcept = 0; - virtual size_t shape_y() const noexcept = 0; - virtual size_t shape_z() const noexcept = 0; - virtual size_t palette_length() const noexcept = 0; + virtual ~structure_3D() = default; + [[nodiscard]] virtual size_t shape_x() const noexcept = 0; + [[nodiscard]] virtual size_t shape_y() const noexcept = 0; + [[nodiscard]] virtual size_t shape_z() const noexcept = 0; + [[nodiscard]] virtual size_t palette_length() const noexcept = 0; virtual void get_palette(const char **buffer_block_id) const noexcept = 0; }; -struct progress_callbacks { - void *widget{nullptr}; - void (*set_range)(void *, int, int, int){nullptr}; - void (*add)(void *, int){nullptr}; -}; - -struct ui_callbacks { - void *wind{nullptr}; - void (*keep_awake)(void *){nullptr}; - void (*report_error)(void *, errorFlag, const char *){nullptr}; - void (*report_working_statue)(void *, workStatues){nullptr}; -}; - -struct convert_option { - uint64_t caller_api_version{SC_VERSION_U64}; - SCL_convertAlgo algo{SCL_convertAlgo::RGB_Better}; - bool dither{false}; - AiCvterOpt ai_cvter_opt{}; - progress_callbacks progress{}; - ui_callbacks ui{}; -}; - class color_table { public: virtual ~color_table() = default; @@ -238,7 +289,11 @@ class color_table { [[nodiscard]] virtual converted_image *convert_image( const_image_reference original_img, const convert_option &option) const noexcept = 0; + + [[nodiscard]] virtual structure_3D *build( + const converted_image &, const build_options &) const noexcept = 0; }; + class Kernel { public: Kernel(); @@ -263,7 +318,7 @@ class Kernel { virtual void setReportError(void (*)(void *, ::SCL_errorFlag, const char *)) = 0; /// a function ptr to report working statue especially when busy - virtual void setReportWorkingStatue(void (*)(void *, ::SCL_workStatues)) = 0; + virtual void setReportWorkingStatue(void (*)(void *, ::SCL_workStatus)) = 0; virtual void setAiCvterOpt(const AiCvterOpt *) = 0; @@ -483,7 +538,7 @@ struct color_table_create_info { ::SCL_gameVersion mc_version; bool basecolor_allow_LUT[64]; const AbstractBlock *blocks[64]; - ui_callbacks callbacks; + ui_callbacks ui; }; [[nodiscard]] SCL_EXPORT color_table *SCL_create_color_table( @@ -493,31 +548,31 @@ SCL_EXPORT void SCL_destroy_color_table(color_table *); [[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); -struct BlockListCreateOption { +struct block_list_create_info { uint64_t caller_api_version{SC_VERSION_U64}; StringDeliver *warnings{nullptr}; StringDeliver *error{nullptr}; }; -[[nodiscard]] SCL_EXPORT BlockListInterface *SCL_createBlockList( - const char *zip_filename, const BlockListCreateOption &option); - -SCL_EXPORT void SCL_destroyBlockList(BlockListInterface *); - -[[deprecated]] [[nodiscard]] SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt(); -[[deprecated]] SCL_EXPORT void SCL_destroyAiCvterOpt(AiCvterOpt *); - -[[deprecated]] SCL_EXPORT void SCL_setPopSize(AiCvterOpt *, uint32_t p); -[[deprecated]] SCL_EXPORT void SCL_setMaxGeneration(AiCvterOpt *, uint32_t p); -[[deprecated]] SCL_EXPORT void SCL_setMaxFailTimes(AiCvterOpt *, uint32_t p); -[[deprecated]] SCL_EXPORT void SCL_setCrossoverProb(AiCvterOpt *, double p); -[[deprecated]] SCL_EXPORT void SCL_setMutationProb(AiCvterOpt *, double p); - -[[deprecated]] SCL_EXPORT uint32_t SCL_getPopSize(const AiCvterOpt *); -[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxGeneration(const AiCvterOpt *); -[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxFailTimes(const AiCvterOpt *); -[[deprecated]] SCL_EXPORT double SCL_getCrossoverProb(const AiCvterOpt *); -[[deprecated]] SCL_EXPORT double SCL_getMutationProb(const AiCvterOpt *); +[[nodiscard]] SCL_EXPORT block_list_interface *SCL_createBlockList( + const char *zip_filename, const block_list_create_info &option); + +SCL_EXPORT void SCL_destroyBlockList(block_list_interface *); + +//[[deprecated]] [[nodiscard]] SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt(); +//[[deprecated]] SCL_EXPORT void SCL_destroyAiCvterOpt(AiCvterOpt *); +// +//[[deprecated]] SCL_EXPORT void SCL_setPopSize(AiCvterOpt *, uint32_t p); +//[[deprecated]] SCL_EXPORT void SCL_setMaxGeneration(AiCvterOpt *, uint32_t p); +//[[deprecated]] SCL_EXPORT void SCL_setMaxFailTimes(AiCvterOpt *, uint32_t p); +//[[deprecated]] SCL_EXPORT void SCL_setCrossoverProb(AiCvterOpt *, double p); +//[[deprecated]] SCL_EXPORT void SCL_setMutationProb(AiCvterOpt *, double p); +// +//[[deprecated]] SCL_EXPORT uint32_t SCL_getPopSize(const AiCvterOpt *); +//[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxGeneration(const AiCvterOpt *); +//[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxFailTimes(const AiCvterOpt *); +//[[deprecated]] SCL_EXPORT double SCL_getCrossoverProb(const AiCvterOpt *); +//[[deprecated]] SCL_EXPORT double SCL_getMutationProb(const AiCvterOpt *); SCL_EXPORT void SCL_preprocessImage( uint32_t *ARGB32ptr, const uint64_t imageSize, @@ -540,6 +595,7 @@ SCL_EXPORT const char *SCL_getSCLVersion(); SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); // SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); + SCL_EXPORT uint8_t SCL_maxBaseColor(); // SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, // size_t capacity_in_elements); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 90d33a49..78e1ab48 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -44,7 +44,7 @@ TokiSlopeCraft::TokiSlopeCraft() this->progressAdd = [](void *, int) {}; this->keepAwake = [](void *) {}; this->reportError = [](void *, errorFlag, const char *) {}; - this->reportWorkingStatue = [](void *, workStatues) {}; + this->reportWorkingStatue = [](void *, workStatus) {}; this->algoProgressAdd = [](void *, int) {}; this->algoProgressRangeSet = [](void *, int, int, int) {}; @@ -98,7 +98,7 @@ void TokiSlopeCraft::setReportError(void (*re)(void *, errorFlag, reportError = re; } /// a function ptr to report working statue especially when busy -void TokiSlopeCraft::setReportWorkingStatue(void (*rws)(void *, workStatues)) { +void TokiSlopeCraft::setReportWorkingStatue(void (*rws)(void *, workStatus)) { reportWorkingStatue = rws; } @@ -198,7 +198,7 @@ bool TokiSlopeCraft::setType(mapTypes type, gameVersion ver, // cerr<<__FILE__<<__LINE__<reportWorkingStatue(this->wind, workStatues::collectingColors); + this->reportWorkingStatue(this->wind, workStatus::collectingColors); Eigen::ArrayXi baseColorVer(64); // 基色对应的版本 baseColorVer.setConstant((int)SCL_gameVersion::FUTURE); @@ -274,7 +274,7 @@ bool TokiSlopeCraft::setType(mapTypes type, gameVersion ver, // GACvter::updateMapColor2GrayLUT(); - this->reportWorkingStatue(this->wind, workStatues::none); + this->reportWorkingStatue(this->wind, workStatus::none); this->image_cvter.on_color_set_changed(); this->kernelStep = SCL_step::wait4Image; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 8fd86098..b7e001f2 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -116,7 +116,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { /// a function ptr to report error when something wrong happens void setReportError(void (*)(void *, errorFlag, const char *)) override; /// a function ptr to report working statue especially when busy - void setReportWorkingStatue(void (*)(void *, workStatues)) override; + void setReportWorkingStatue(void (*)(void *, workStatus)) override; size_t size() override { return sizeof(TokiSlopeCraft); } // void destroy() override { delete this; } void decreaseStep(step) override; @@ -286,7 +286,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { void (*algoProgressRangeSet)(void *, int, int, int); void (*algoProgressAdd)(void *, int); void (*reportError)(void *, errorFlag, const char *); - void (*reportWorkingStatue)(void *, workStatues); + void (*reportWorkingStatue)(void *, workStatus); public: step kernelStep; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index d8c243ff..5e7743a5 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -143,7 +143,7 @@ std::string TokiSlopeCraft::exportAsLitematic( "structure."); return "Too hasty! export litematic after you built!"; } - reportWorkingStatue(wind, workStatues::writingMetaInfo); + reportWorkingStatue(wind, workStatus::writingMetaInfo); progressRangeSet(wind, 0, 100 + schem.size(), 0); libSchem::litematic_info info; @@ -163,7 +163,7 @@ std::string TokiSlopeCraft::exportAsLitematic( } progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatues::none); + reportWorkingStatue(wind, workStatus::none); return ""; } @@ -228,7 +228,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { this->build_opt = option; - reportWorkingStatue(wind, workStatues::buidingHeighMap); + reportWorkingStatue(wind, workStatus::buidingHeighMap); progressRangeSet(wind, 0, 9 * sizePic(2), 0); // cerr << "start makeHeight" << endl; @@ -241,14 +241,14 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "makeHeight finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 5 * sizePic(2)); - reportWorkingStatue(wind, workStatues::building3D); + reportWorkingStatue(wind, workStatus::building3D); // cerr << "start buildHeight" << endl; buildHeight(this->build_opt.fire_proof, this->build_opt.enderman_proof, Base, HighMap, LowMap, WaterList); // cerr << "buildHeight finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 8 * sizePic(2)); - reportWorkingStatue(wind, workStatues::constructingBridges); + reportWorkingStatue(wind, workStatus::constructingBridges); // cerr << "start makeBridge" << endl; makeBridge(); } @@ -259,7 +259,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "makeBridge finished" << endl; progressRangeSet(wind, 0, 9 * sizePic(2), 9 * sizePic(2)); - reportWorkingStatue(wind, workStatues::none); + reportWorkingStatue(wind, workStatus::none); kernelStep = SCL_step::builded; @@ -476,7 +476,7 @@ std::string TokiSlopeCraft::exportAsStructure( return "Too hasty! export structure after you built!"; } - reportWorkingStatue(wind, workStatues::writingMetaInfo); + reportWorkingStatue(wind, workStatus::writingMetaInfo); progressRangeSet(wind, 0, 100 + schem.size(), 0); errorFlag flag = errorFlag::NO_ERROR_OCCUR; @@ -490,7 +490,7 @@ std::string TokiSlopeCraft::exportAsStructure( } progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatues::none); + reportWorkingStatue(wind, workStatus::none); return ""; } diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp index f06066eb..d56aff43 100644 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ b/SlopeCraftL/TokiSlopeCraft_convert.cpp @@ -38,7 +38,7 @@ bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { // TokiColor::convertAlgo() = algo; progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatues::converting); + reportWorkingStatue(wind, workStatus::converting); { heu::GAOption opt; @@ -90,13 +90,13 @@ bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { progressRangeSet(wind, 0, 4 * sizePic(2), 0); - reportWorkingStatue(wind, workStatues::collectingColors); + reportWorkingStatue(wind, workStatus::collectingColors); pushToHash(); keepAwake(wind); progressRangeSet(wind, 0, 4 * sizePic(2), 1 * sizePic(2)); - reportWorkingStatue(wind, workStatues::converting); + reportWorkingStatue(wind, workStatus::converting); applyTokiColor(); keepAwake(wind); @@ -109,7 +109,7 @@ bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { ditheredImage = this->rawImage; if (dither) { - reportWorkingStatue(wind, workStatues::dithering); + reportWorkingStatue(wind, workStatus::dithering); Dither(); } */ @@ -117,7 +117,7 @@ bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { progressRangeSet(wind, 0, 4 * sizePic(2), 4 * sizePic(2)); keepAwake(wind); - reportWorkingStatue(wind, workStatues::none); + reportWorkingStatue(wind, workStatus::none); kernelStep = SCL_step::converted; return true; @@ -158,7 +158,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, int offset[2] = {0, 0}; // r,c int currentIndex = indexStart; - reportWorkingStatue(wind, workStatues::writingMapDataFiles); + reportWorkingStatue(wind, workStatus::writingMapDataFiles); for (int c = 0; c < cols; c++) { for (int r = 0; r < rows; r++) { @@ -274,7 +274,7 @@ std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, } } - reportWorkingStatue(wind, workStatues::none); + reportWorkingStatue(wind, workStatus::none); return failed_file_list; } diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 1fdc0d3f..42e41d75 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -3,6 +3,10 @@ // #include "color_table.h" +#include "WaterItem.h" +#include "HeightLine.h" +#include "lossyCompressor.h" +#include "PrimGlassBuilder.h" #include std::optional color_table_impl::create( @@ -13,15 +17,7 @@ std::optional color_table_impl::create( result.allowed.need_find_side = (args.map_type == mapTypes::Slope); auto report_err = [&args](errorFlag flag, std::string_view msg) { - if (args.callbacks.report_error) { - args.callbacks.report_error(args.callbacks.wind, flag, msg.data()); - } - }; - - auto report_woring_status = [&args](workStatues ws) { - if (args.callbacks.report_working_statue) { - args.callbacks.report_working_statue(args.callbacks.wind, ws); - } + args.ui.report_error(flag, msg.data()); }; // block palette @@ -50,7 +46,7 @@ std::optional color_table_impl::create( } } - report_woring_status(workStatues::collectingColors); + args.ui.report_working_status(workStatus::collectingColors); Eigen::ArrayXi baseColorVer(64); // 基色对应的版本 baseColorVer.setConstant((int)SCL_gameVersion::FUTURE); @@ -120,46 +116,41 @@ std::optional color_table_impl::create( return std::nullopt; } - report_woring_status(workStatues::none); + args.ui.report_working_status(workStatus::none); return result; } -converted_image_impl::converted_image_impl( - const colorset_allowed_t &allowed_colorset) - : converter{*color_set::basic, allowed_colorset} {} +structure_3D *color_table_impl::build( + const converted_image &cvted, const build_options &option) const noexcept { + auto opt = structure_3D_impl::create( + *this, dynamic_cast(cvted), option); + if (opt) { + return new structure_3D_impl{std::move(opt.value())}; + } + return nullptr; +} + +std::vector color_table_impl::block_id_list() const noexcept { + std::vector dest; + dest.reserve(this->blocks.size()); + for (auto &blk : this->blocks) { + dest.emplace_back(blk.id); + } + return dest; +} + +converted_image_impl::converted_image_impl(const color_table_impl &table) + : converter{*color_set::basic, table.allowed} {} converted_image *color_table_impl::convert_image( const_image_reference original_img, const convert_option &option) const noexcept { - converted_image_impl cvted{this->allowed}; + converted_image_impl cvted{*this}; const auto algo = (option.algo == convertAlgo::gaCvter) ? convertAlgo::RGB_Better : option.algo; - // auto report_err = [&option](errorFlag flag, std::string_view msg) { - // if (option.ui.report_error) { - // option.ui.report_error(option.ui.wind, flag, msg.data()); - // } - // }; - - auto report_woring_status = [&option](workStatues ws) { - if (option.ui.report_working_statue) { - option.ui.report_working_statue(option.ui.wind, ws); - } - }; - - auto progress_range = [&option](int min, int max, int val) { - if (option.progress.set_range) { - option.progress.set_range(option.progress.widget, min, max, val); - } - }; - - // auto progress_add = [&option](int delta) { - // if (option.progress.add) { - // option.progress.add(option.progress.widget, delta); - // } - // }; cvted.converter.set_raw_image(original_img.data, original_img.rows, original_img.cols, false); { @@ -169,13 +160,259 @@ converted_image *color_table_impl::convert_image( opt.maxGenerations = option.ai_cvter_opt.maxGeneration; opt.maxFailTimes = option.ai_cvter_opt.maxFailTimes; opt.populationSize = option.ai_cvter_opt.popSize; - // here opt is passed as a const ptr, it won't be changed in this function - // call + cvted.converter.convert_image(algo, option.dither, &opt); } - progress_range(0, 4 * cvted.size(), 4 * cvted.size()); - report_woring_status(workStatues::none); + option.progress.set_range(0, 4 * cvted.size(), 4 * cvted.size()); + option.ui.report_working_status(workStatus::none); return new converted_image_impl{std::move(cvted)}; +} + +std::optional +converted_image_impl::height_info(const build_options &option) const noexcept { + // + // std::unordered_map water_list; + + Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); + + const bool allow_lossless_compress = + int(option.compressMethod) & int(SCL_compressSettings::NaturalOnly); + + if (((map_color - 4 * (map_color / 4)) >= 3).any()) { + std::string msg = + "Fatal error : SlopeCraftL found map color with depth 3 in a " + "vanilla map.\n Map contents (map color matrix in col-major) :\n["; + for (int c = 0; c < map_color.cols(); c++) { + for (int r = 0; r < map_color.rows(); r++) { + fmt::format_to(std::back_insert_iterator{msg}, "{},", map_color(r, c)); + } + msg += ";\n"; + } + msg += "];\n"; + option.ui.report_error(errorFlag::DEPTH_3_IN_VANILLA_MAP, msg.c_str()); + return std::nullopt; + } + + Eigen::ArrayXXi base, high_map, low_map; + base.setZero(this->rows(), this->cols()); + high_map.setZero(this->rows(), this->cols()); + low_map.setZero(this->rows(), this->cols()); + std::unordered_map water_list; + + LossyCompressor compressor; + for (int64_t c = 0; c < map_color.cols(); c++) { + // cerr << "Coloumn " << c << '\n'; + HeightLine HL; + // getTokiColorPtr(c,&src[0]); + HL.make(map_color.col(c), allow_lossless_compress); + + if (HL.maxHeight() > option.maxAllowedHeight && + (option.compressMethod == compressSettings::ForcedOnly || + option.compressMethod == compressSettings::Both)) { + std::vector ptr(map_color.rows()); + + this->converter.col_TokiColor_ptrs(c, ptr.data()); + // getTokiColorPtr(c, &ptr[0]); + + compressor.setSource(HL.getBase(), &ptr[0]); + bool success = + compressor.compress(option.maxAllowedHeight, allow_lossless_compress); + if (!success) { + option.ui.report_error( + SCL_errorFlag::LOSSYCOMPRESS_FAILED, + fmt::format("Failed to compress the 3D structure at column {}.", c) + .data()); + return std::nullopt; + } + Eigen::ArrayXi temp; + HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); + map_color.col(c) = temp; + } + base.col(c) = HL.getBase(); + high_map.col(c) = HL.getHighLine(); + low_map.col(c) = HL.getLowLine(); + + auto hl_water_list = HL.getWaterMap(); + water_list.reserve(water_list.size() + hl_water_list.size()); + for (const auto &[r, water_item] : hl_water_list) { + water_list.emplace(TokiRC(r, c), water_item); + } + + option.main_progressbar.add(4 * this->size()); + } + + return height_maps{.map_color = map_color, + .base = base, + .high_map = high_map, + .low_map = low_map, + .water_list = water_list}; +} + +std::optional structure_3D_impl::create( + const color_table_impl &table, const converted_image_impl &cvted, + const build_options &option) noexcept { + if (option.maxAllowedHeight < 14) { + option.ui.report_error( + errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, + fmt::format("Max allowed height should be >= 14, but found {}", + option.maxAllowedHeight) + .c_str()); + return std::nullopt; + } + structure_3D_impl ret; + // set up basic infos + { + ret.schem.set_MC_major_version_number(table.mc_version_); + ret.schem.set_MC_version_number( + MCDataVersion::suggested_version(table.mc_version_)); + auto id = table.block_id_list(); + ret.schem.set_block_id(id); + } + + build_options fixed_opt = option; + if (table.is_flat() || !table.is_vanilla()) { + fixed_opt.compressMethod = compressSettings::noCompress; + fixed_opt.glassMethod = glassBridgeSettings::noBridge; + } + option.ui.report_working_status(workStatus::buidingHeighMap); + option.main_progressbar.set_range(0, 9 * cvted.size(), 0); + { + std::unordered_map water_list; + option.main_progressbar.add(cvted.size()); + } + + Eigen::ArrayXi map_color, base_color, high_map, low_map; + std::unordered_map water_list; + { + auto opt = cvted.height_info(fixed_opt); + if (!opt) { + return std::nullopt; + } + map_color = std::move(opt.value().map_color); + base_color = std::move(opt.value().base); + high_map = std::move(opt.value().high_map); + low_map = std::move(opt.value().low_map); + water_list = std::move(opt.value().water_list); + } + + ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, 2 + cvted.rows()); + ret.schem.set_zero(); + // make 3D + { + // base_color(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) + // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 + // 对应空气 + + for (auto it = water_list.begin(); it != water_list.end(); + it++) // 水柱周围的玻璃 + { + const int x = TokiCol(it->first) + 1; + const int z = TokiRow(it->first); + const int y = waterHigh(it->second); + const int yLow = waterLow(it->second); + ret.schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { + ret.schem(x - 1, yDynamic, z - 0) = 1; + ret.schem(x + 1, yDynamic, z + 0) = 1; + ret.schem(x + 0, yDynamic, z - 1) = 1; + ret.schem(x + 0, yDynamic, z + 1) = 1; + } + if (yLow >= 1) ret.schem(x, yLow - 1, z) = 1; // 柱底玻璃 + } + + option.main_progressbar.add(cvted.size()); + + for (uint32_t r = -1; r < cvted.rows(); r++) // 普通方块 + { + for (uint32_t c = 0; c < cvted.cols(); c++) { + if (base_color(r + 1, c) == 12 || base_color(r + 1, c) == 0) continue; + const int x = c + 1; + const int y = low_map(r + 1, c); + const int z = r + 1; + if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) + ret.schem(x, y - 1, z) = 0 + 1; + if ((option.fire_proof && + table.blocks[base_color(r + 1, c)].burnable) || + (option.enderman_proof && + table.blocks[base_color(r + 1, c)].endermanPickable)) { + if (y >= 1 && ret.schem(x, y - 1, z) == 0) + ret.schem(x, y - 1, z) = 0 + 1; + if (x >= 1 && ret.schem(x - 1, y, z) == 0) + ret.schem(x - 1, y, z) = 0 + 1; + if (z >= 1 && ret.schem(x, y, z - 1) == 0) + ret.schem(x, y, z - 1) = 0 + 1; + if (y + 1 < ret.schem.y_range() && ret.schem(x, y + 1, z) == 0) + ret.schem(x, y + 1, z) = 0 + 1; + if (x + 1 < ret.schem.x_range() && ret.schem(x + 1, y, z) == 0) + ret.schem(x + 1, y, z) = 0 + 1; + if (z + 1 < ret.schem.z_range() && ret.schem(x, y, z + 1) == 0) + ret.schem(x, y, z + 1) = 0 + 1; + } + + ret.schem(x, y, z) = base_color(r + 1, c) + 1; + } + option.main_progressbar.add(cvted.cols()); + } + + option.main_progressbar.add(cvted.size()); + + for (auto it = water_list.cbegin(); it != water_list.cend(); ++it) { + const int x = TokiCol(it->first) + 1; + const int z = TokiRow(it->first); + const int y = waterHigh(it->second); + const int yLow = waterLow(it->second); + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { + ret.schem(x, yDynamic, z) = 13; + } + } + } + option.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); + // build bridges + if (table.map_type() == mapTypes::Slope && + fixed_opt.glassMethod == glassBridgeSettings::withBridge) { + option.ui.report_working_status(workStatus::constructingBridges); + + option.sub_progressbar.set_range(0, 100, 0); + const int step = cvted.size() / ret.schem.y_range(); + + PrimGlassBuilder glass_builder; + option.ui.keep_awake(); + for (uint32_t y = 0; y < ret.schem.y_range(); y++) { + option.sub_progressbar.add(step); + if (y % (fixed_opt.bridgeInterval + 1) == 0) { + std::array start, extension; // x,z,y + start[0] = 0; + start[1] = 0; + start[2] = y; + extension[0] = ret.schem.x_range(); + extension[1] = ret.schem.z_range(); + extension[2] = 1; + TokiMap targetMap = + ySlice2TokiMap_u16(ret.schem.tensor(), start, extension); + glassMap glass; + // cerr << "Construct glass bridge at y=" << y << endl; + glass = glass_builder.makeBridge(targetMap); + for (int r = 0; r < glass.rows(); r++) + for (int c = 0; c < glass.cols(); c++) + if (ret.schem(r, y, c) == PrimGlassBuilder::air && + glass(r, c) == PrimGlassBuilder::glass) + ret.schem(r, y, c) = PrimGlassBuilder::glass; + } else { + continue; + } + } + option.ui.keep_awake(); + option.sub_progressbar.set_range(0, 100, 100); + } + + if (fixed_opt.connect_mushrooms) { + ret.schem.process_mushroom_states(); + } + option.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); + option.ui.report_working_status(workStatus::none); + + ret.map_color = std::move(map_color); + return ret; } \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 39d610e8..fcbca45d 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -5,21 +5,22 @@ #ifndef SLOPECRAFT_COLOR_TABLE_H #define SLOPECRAFT_COLOR_TABLE_H +#include +#include #include "SlopeCraftL.h" #include "Colorset.h" #include "simpleBlock.h" -#include -#include +#include "Schem/Schem.h" +#include "WaterItem.h" class color_table_impl : public SlopeCraft::color_table { - private: + public: colorset_allowed_t allowed; SCL_mapTypes map_type_; SCL_gameVersion mc_version_; std::array blocks; - public: - color_map_ptrs colors() const noexcept override { + color_map_ptrs colors() const noexcept final { return color_map_ptrs{.r_data = allowed.rgb_data(0), .g_data = allowed.rgb_data(1), .b_data = allowed.rgb_data(2), @@ -27,16 +28,16 @@ class color_table_impl : public SlopeCraft::color_table { .num_colors = allowed.color_count()}; } - SCL_mapTypes map_type() const noexcept override { return this->map_type_; } + SCL_mapTypes map_type() const noexcept final { return this->map_type_; } - SCL_gameVersion mc_version() const noexcept override { + SCL_gameVersion mc_version() const noexcept final { return this->mc_version_; } - size_t num_blocks() const noexcept override { return this->blocks.size(); } + size_t num_blocks() const noexcept final { return this->blocks.size(); } void visit_blocks(void (*fun)(const AbstractBlock *, void *custom_data), - void *custom_data) const override { + void *custom_data) const final { for (auto &blk : this->blocks) { fun(static_cast(&blk), custom_data); } @@ -44,16 +45,21 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] converted_image *convert_image( const_image_reference original_img, - const convert_option &option) const noexcept override; + const convert_option &option) const noexcept final; + + [[nodiscard]] structure_3D *build(const converted_image &, + const build_options &) const noexcept final; - static std::optional create( + [[nodiscard]] static std::optional create( const color_table_create_info &args) noexcept; + + [[nodiscard]] std::vector block_id_list() const noexcept; }; class converted_image_impl : public converted_image { public: converted_image_impl(converted_image_impl &&) = default; - explicit converted_image_impl(const colorset_allowed_t &allowed_colorset); + explicit converted_image_impl(const color_table_impl &table); using eimg_row_major = Eigen::Array; libMapImageCvt::MapImageCvter converter; @@ -70,6 +76,41 @@ class converted_image_impl : public converted_image { void get_converted_image(uint32_t *buffer) const noexcept final { this->converter.converted_image(buffer, nullptr, nullptr, false); } + + struct height_maps { + Eigen::ArrayXXi map_color; + Eigen::ArrayXXi base; + Eigen::ArrayXXi high_map; + Eigen::ArrayXXi low_map; + std::unordered_map water_list; + }; + std::optional height_info( + const build_options &option) const noexcept; +}; + +class structure_3D_impl : public structure_3D { + private: + libSchem::Schem schem; + + Eigen::ArrayXXi map_color; // map color may be modified by lossy + // compression,so we store the modified one + + public: + size_t shape_x() const noexcept final { return this->schem.x_range(); } + size_t shape_y() const noexcept final { return this->schem.y_range(); } + size_t shape_z() const noexcept final { return this->schem.z_range(); } + size_t palette_length() const noexcept final { + return this->schem.palette_size(); + } + void get_palette(const char **buffer_block_id) const noexcept final { + for (size_t i = 0; i < this->palette_length(); i++) { + buffer_block_id[i] = this->schem.palette()[i].c_str(); + } + } + + static std::optional create( + const color_table_impl &, const converted_image_impl &cvted, + const build_options &option) noexcept; }; #endif // SLOPECRAFT_COLOR_TABLE_H diff --git a/SlopeCraftL/simpleBlock.h b/SlopeCraftL/simpleBlock.h index cf7e7e5e..3688cb79 100644 --- a/SlopeCraftL/simpleBlock.h +++ b/SlopeCraftL/simpleBlock.h @@ -124,7 +124,7 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { // simpleBlock& operator =(const simpleBlock &); }; -class BlockList : public ::SlopeCraft::BlockListInterface { +class BlockList : public ::SlopeCraft::block_list_interface { private: std::map, uint8_t> m_blocks; diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp index 86d85e31..eb403f53 100644 --- a/SlopeCraftL/tests/load_scl_blocklist.cpp +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -10,7 +10,7 @@ int main(int argc, char** argv) { const char* archive_path = argv[1]; printf("Try parsing %s\n", archive_path); - SlopeCraft::BlockListInterface* blocklist{nullptr}; + SlopeCraft::block_list_interface* blocklist{nullptr}; { std::string errmsg; errmsg.resize(8192); @@ -19,7 +19,7 @@ int main(int argc, char** argv) { std::string warnings; warnings.resize(8192); SlopeCraft::StringDeliver warn_sd{warnings.data(), warnings.size()}; - SlopeCraft::BlockListCreateOption option{ + SlopeCraft::block_list_create_info option{ SC_VERSION_U64, &warn_sd, &err_sd, diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 7a65e614..dd22e73b 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -44,7 +44,7 @@ void BlockListManager::setup_basecolors( // return true; // } -std::unique_ptr +std::unique_ptr BlockListManager::impl_addblocklist(const QString &filename) noexcept { std::string errmsg; errmsg.resize(8192); @@ -52,9 +52,9 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { std::string warning; warning.resize(8192); auto sd_warn = SlopeCraft::StringDeliver::from_string(warning); - SlopeCraft::BlockListCreateOption option{SC_VERSION_U64, &sd_warn, &sd_err}; + SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; - SlopeCraft::BlockListInterface *bli = + SlopeCraft::block_list_interface *bli = SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), option); errmsg.resize(sd_err.size); @@ -87,11 +87,12 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { this->basecolor_widgets[base_colors[idx]]->add_block(blockps[idx]); } - return std::unique_ptr{bli}; + return std::unique_ptr{ + bli}; } bool BlockListManager::add_blocklist(QString filename) noexcept { - std::unique_ptr tmp = + std::unique_ptr tmp = this->impl_addblocklist(filename); if (!tmp) { diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index dba4d537..ad1dd2dd 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -24,7 +24,7 @@ QString serialize_preset(const blockListPreset &preset) noexcept; class BlockListDeleter { public: - void operator()(SlopeCraft::BlockListInterface *ptr) noexcept { + void operator()(SlopeCraft::block_list_interface *ptr) noexcept { SlopeCraft::SCL_destroyBlockList(ptr); } }; @@ -33,7 +33,8 @@ class BlockListManager : public QWidget { Q_OBJECT private: std::vector> basecolor_widgets; - std::vector> + std::vector< + std::unique_ptr> blockslists; std::function callback_get_version{nullptr}; @@ -86,7 +87,7 @@ class BlockListManager : public QWidget { void changed(); private: - std::unique_ptr + std::unique_ptr impl_addblocklist(const QString &filename) noexcept; }; diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index e125c377..b0a9a356 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -82,13 +82,13 @@ enum class SCL_colorSpace : char { enum class SCL_compressSettings : int { /// don't compress - noCompress = 0, + noCompress = 0b00, /// compress in lossless only - NaturalOnly = 1, + NaturalOnly = 0b01, /// compress in lossy only - ForcedOnly = 2, + ForcedOnly = 0b10, /// compress with both lossless and lossy - Both = 3 + Both = 0b11 }; enum class SCL_glassBridgeSettings : int { @@ -161,7 +161,7 @@ enum class SCL_errorFlag : int { }; -enum class SCL_workStatues : int { +enum class SCL_workStatus : int { /// waiting none = -1, diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 8939a216..93d1c165 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -373,7 +373,7 @@ bool Schem::export_litematic(std::string_view filename, // progressRangeSet(wind, 0, 100 + Build.size(), 100); - // reportWorkingStatue(wind, workStatues::writingBlockPalette); + // reportWorkingStatue(wind, workStatus::writingBlockPalette); // write block palette lite.writeListHead("BlockStatePalette", NBT::Compound, this->palette_size()); @@ -528,7 +528,7 @@ bool Schem::export_structure(std::string_view filename, } /* - reportWorkingStatue(wind, workStatues::writingMetaInfo); + reportWorkingStatue(wind, workStatus::writingMetaInfo); progressRangeSet(wind, 0, 100 + Build.size(), 0); */ @@ -551,7 +551,7 @@ bool Schem::export_structure(std::string_view filename, file.writeInt("This should never be shown", y_range()); file.writeInt("This should never be shown", z_range()); } - // reportWorkingStatue(wind, workStatues::writingBlockPalette); + // reportWorkingStatue(wind, workStatus::writingBlockPalette); file.writeListHead("palette", NBT::Compound, palette_size()); { std::string pure_block_id; From 09795dd36264ca0cc179984e35c69174447f2b0b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 19:00:50 +0800 Subject: [PATCH 0770/1123] rename simpleBlock and BlockList Signed-off-by: ToKiNoBug --- Blocks/README.md | 2 +- SlopeCraftL/CMakeLists.txt | 6 +- SlopeCraftL/Colorset.h | 4 +- SlopeCraftL/SlopeCraftL.cpp | 20 +-- SlopeCraftL/TokiSlopeCraft.cpp | 3 +- SlopeCraftL/TokiSlopeCraft.h | 6 +- SlopeCraftL/TokiSlopeCraft_build.cpp | 10 +- SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 4 +- SlopeCraftL/color_table.cpp | 1 + SlopeCraftL/color_table.h | 6 +- SlopeCraftL/mc_block.cpp | 76 +++++++++++ SlopeCraftL/{simpleBlock.h => mc_block.h} | 34 ++--- SlopeCraftL/simpleBlock.cpp | 144 --------------------- 13 files changed, 123 insertions(+), 193 deletions(-) create mode 100644 SlopeCraftL/mc_block.cpp rename SlopeCraftL/{simpleBlock.h => mc_block.h} (88%) delete mode 100644 SlopeCraftL/simpleBlock.cpp diff --git a/Blocks/README.md b/Blocks/README.md index b3a52954..53641cf1 100644 --- a/Blocks/README.md +++ b/Blocks/README.md @@ -28,7 +28,7 @@

-# BlockList +# block_list Everything about blocklist is in this directory. diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index da05d966..5731d2b0 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -35,7 +35,7 @@ set(Slope_SCL_internal_headers WaterItem.h lossyCompressor.h - simpleBlock.h + mc_block.h SlopeCraftL_global.h WriteStringDeliver.h Colorset.h @@ -58,7 +58,7 @@ set(SlopeCraft_SCL_sources TokiSlopeCraft_cache.cpp imagePreprocess.cpp lossyCompressor.cpp - simpleBlock.cpp + mc_block.cpp SlopeCraftL.cpp Colorset.cpp @@ -142,7 +142,7 @@ function(SC_create_SCL_block_list src_dir archive_path) # file(GLOB_RECURSE file_list "${src_dir}/*.png") # - # file(ARCHIVE_CREATE OUTPUT temp.zip PATHS ${src_dir} "${src_dir}/BlockList.json" FORMAT zip + # file(ARCHIVE_CREATE OUTPUT temp.zip PATHS ${src_dir} "${src_dir}/block_list.json" FORMAT zip # #COMPRESSION Zstd # #COMPRESSION_LEVEL 9 # ) diff --git a/SlopeCraftL/Colorset.h b/SlopeCraftL/Colorset.h index 60154386..54aa9b30 100644 --- a/SlopeCraftL/Colorset.h +++ b/SlopeCraftL/Colorset.h @@ -11,7 +11,7 @@ #include #include #include -#include "simpleBlock.h" +#include "mc_block.h" #include "Colors.h" #include "SlopeCraftL.h" @@ -29,7 +29,7 @@ struct color_set { SlopeCraft::gameVersion mc_version{SCL_gameVersion::MC17}; SlopeCraft::mapTypes map_type{SCL_mapTypes::Slope}; - std::vector palette{}; + std::vector palette{}; }; #endif // SLOPECRAFT_COLORSET_H diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 095e6989..4e1eba8a 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -28,13 +28,13 @@ This file is part of SlopeCraft. #include "SlopeCraftL.h" #include "TokiSlopeCraft.h" -#include "simpleBlock.h" +#include "mc_block.h" #include "WriteStringDeliver.h" #include "color_table.h" using namespace SlopeCraft; -// AbstractBlock *AbstractBlock::create() { return new simpleBlock; } +// AbstractBlock *AbstractBlock::create() { return new mc_block; } void AbstractBlock::clear() noexcept { setBurnable(false); @@ -53,9 +53,9 @@ Kernel::Kernel() {} using namespace SlopeCraft; -std::pair parse_block(const nlohmann::json &jo) noexcept( +std::pair parse_block(const nlohmann::json &jo) noexcept( false) { - simpleBlock ret; + mc_block ret; const int basecolor = jo.at("baseColor"); if (basecolor < 0 || basecolor >= 64) { throw std::runtime_error{fmt::format("Invalid base color: {}", basecolor)}; @@ -97,7 +97,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( // errmsg.reserve(4096); // errmsg.clear(); // -// BlockList *bl = new BlockList; +// block_list *bl = new block_list; // using njson = nlohmann::json; // try { // std::ifstream ifs(filename); @@ -114,7 +114,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( // for (size_t idx = 0; idx < arr.size(); idx++) { // auto temp = parse_block(arr[idx], option.image_dir); // -// auto ptr = new simpleBlock; +// auto ptr = new mc_block; // *ptr = std::move(temp.second); // bl->blocks().emplace(ptr, temp.first); // } @@ -217,13 +217,13 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { std::vector buffer; { - auto err = extract_file("BlockList.json", buffer); + auto err = extract_file("block_list.json", buffer); if (!err) { return {tl::make_unexpected(err.error()), warnings}; } } - BlockList *bl = new BlockList; + block_list *bl = new block_list; using njson = nlohmann::json; try { @@ -237,7 +237,7 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { // parse blocks for (size_t idx = 0; idx < jo.size(); idx++) { auto [version, block] = parse_block(jo[idx]); - bl->blocks().emplace(std::make_unique(block), version); + bl->blocks().emplace(std::make_unique(block), version); } } catch (const std::exception &e) { @@ -297,7 +297,7 @@ SCL_EXPORT void SCL_destroyKernel(Kernel *k) { delete static_cast(k); } -SCL_EXPORT AbstractBlock *SCL_createBlock() { return new simpleBlock; } +SCL_EXPORT AbstractBlock *SCL_createBlock() { return new mc_block; } SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } SCL_EXPORT block_list_interface *SCL_createBlockList( diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 78e1ab48..62424c04 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -505,8 +505,7 @@ int64_t TokiSlopeCraft::getBlockCounts(std::vector *dest) const { for (int ele = 1; ele < this->schem.palette_size(); ele++) { std::string_view blkid = this->schem.palette()[ele]; - const simpleBlock *sbp = - TokiSlopeCraft::find_block_for_idx(ele - 1, blkid); + const mc_block *sbp = TokiSlopeCraft::find_block_for_idx(ele - 1, blkid); assert(sbp != nullptr); int64_t idx = sbp - this->colorset.palette.data(); diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index b7e001f2..96d0c240 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -38,7 +38,7 @@ This file is part of SlopeCraft. #include "Colors.h" #include "SCLDefines.h" #include "WaterItem.h" -#include "simpleBlock.h" +#include "mc_block.h" #include #include "PrimGlassBuilder.h" @@ -450,8 +450,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { uint64_t build_task_hash, build_cache_ir *ir = nullptr) noexcept; - const simpleBlock *find_block_for_idx(int idx, - std::string_view blkid) const noexcept; + const mc_block *find_block_for_idx(int idx, + std::string_view blkid) const noexcept; std::array LUT_mapcolor_to_argb() const noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 5e7743a5..64cf0c1d 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -61,8 +61,8 @@ std::string TokiSlopeCraft::impl_make_tests( test.set_MC_major_version_number(this->colorset.mc_version); test.set_MC_version_number( MCDataVersion::suggested_version(this->colorset.mc_version)); - // const simpleBlock ** realSrc=(const simpleBlock **)src; - std::vector realSrc; + // const mc_block ** realSrc=(const mc_block **)src; + std::vector realSrc; std::vector realBaseColor; realSrc.clear(); realBaseColor.clear(); @@ -70,8 +70,7 @@ std::string TokiSlopeCraft::impl_make_tests( if (option.block_ptrs[idx]->getVersion() > (int)this->colorset.mc_version) { continue; } - realSrc.emplace_back( - static_cast(option.block_ptrs[idx])); + realSrc.emplace_back(static_cast(option.block_ptrs[idx])); realBaseColor.emplace_back(option.basecolors[idx]); } @@ -631,8 +630,7 @@ std::string TokiSlopeCraft::export_flat_diagram( continue; } std::string_view id = this->schem.palette()[pblkid]; - const simpleBlock *blkp = - TokiSlopeCraft::find_block_for_idx(pblkid - 1, id); + const mc_block *blkp = TokiSlopeCraft::find_block_for_idx(pblkid - 1, id); if (blkp == nullptr) { std::string blkid_full; blkid_full.reserve(64 * 2048); diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp index aa7cd336..c28799aa 100644 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp @@ -63,7 +63,7 @@ uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { #include #include -const simpleBlock *TokiSlopeCraft::find_block_for_idx( +const mc_block *TokiSlopeCraft::find_block_for_idx( int idx, std::string_view blkid) const noexcept { if (idx < 0) { return nullptr; @@ -103,7 +103,7 @@ const simpleBlock *TokiSlopeCraft::find_block_for_idx( break; } - const simpleBlock *blkp = find_block_for_idx(expected_basecolor, {}); + const mc_block *blkp = find_block_for_idx(expected_basecolor, {}); if (blkp == nullptr) { return nullptr; diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 42e41d75..7b1c5920 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -377,6 +377,7 @@ std::optional structure_3D_impl::create( option.sub_progressbar.set_range(0, 100, 0); const int step = cvted.size() / ret.schem.y_range(); +#warning "todo: Use prograss_callback in PrimGlassBuilder" PrimGlassBuilder glass_builder; option.ui.keep_awake(); for (uint32_t y = 0; y < ret.schem.y_range(); y++) { diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index fcbca45d..91a73ee1 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -9,7 +9,7 @@ #include #include "SlopeCraftL.h" #include "Colorset.h" -#include "simpleBlock.h" +#include "mc_block.h" #include "Schem/Schem.h" #include "WaterItem.h" @@ -18,7 +18,7 @@ class color_table_impl : public SlopeCraft::color_table { colorset_allowed_t allowed; SCL_mapTypes map_type_; SCL_gameVersion mc_version_; - std::array blocks; + std::array blocks; color_map_ptrs colors() const noexcept final { return color_map_ptrs{.r_data = allowed.rgb_data(0), @@ -91,7 +91,7 @@ class converted_image_impl : public converted_image { class structure_3D_impl : public structure_3D { private: libSchem::Schem schem; - + Eigen::ArrayXXi map_color; // map color may be modified by lossy // compression,so we store the modified one diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp new file mode 100644 index 00000000..a86ee38c --- /dev/null +++ b/SlopeCraftL/mc_block.cpp @@ -0,0 +1,76 @@ +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include "mc_block.h" + +mc_block::mc_block() { + // id = ""; + // version = 0; + // idOld = ""; + // needGlass = false; + // doGlow = false; + // endermanPickable = false; + // burnable = false; + + image.resize(16, 16); + // wallUseable=true; +} + +size_t block_list::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, + size_t capacity_in_elements) noexcept { + if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { + return 0; + } + + size_t counter = 0; + for (auto &ptr : this->m_blocks) { + dst[counter] = ptr.first.get(); + dst_basecolor[counter] = ptr.second; + counter++; + if (counter >= capacity_in_elements) { + return counter; + } + } + return counter; +} + +size_t block_list::get_blocks(const AbstractBlock **dst, uint8_t *dst_basecolor, + size_t capacity_in_elements) const noexcept { + if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { + return 0; + } + + size_t counter = 0; + for (auto &ptr : this->m_blocks) { + dst[counter] = ptr.first.get(); + dst_basecolor[counter] = ptr.second; + counter++; + if (counter >= capacity_in_elements) { + return counter; + } + } + return counter; +} + +void block_list::clear() noexcept { this->m_blocks.clear(); } + +block_list::~block_list() { this->clear(); } \ No newline at end of file diff --git a/SlopeCraftL/simpleBlock.h b/SlopeCraftL/mc_block.h similarity index 88% rename from SlopeCraftL/simpleBlock.h rename to SlopeCraftL/mc_block.h index 3688cb79..b20a097f 100644 --- a/SlopeCraftL/simpleBlock.h +++ b/SlopeCraftL/mc_block.h @@ -34,16 +34,16 @@ using namespace SlopeCraft; typedef std::vector stringList; -class simpleBlock : public ::SlopeCraft::AbstractBlock { +class mc_block : public ::SlopeCraft::AbstractBlock { public: - simpleBlock(); - ~simpleBlock(){}; - std::string id; - uint8_t version; - std::string idOld; - std::string nameZH; - std::string nameEN; - std::string imageFilename; + mc_block(); + ~mc_block(){}; + std::string id{}; + uint8_t version{0}; + std::string idOld{}; + std::string nameZH{}; + std::string nameEN{}; + std::string imageFilename{}; Eigen::Array image; bool needGlass{false}; bool doGlow{false}; @@ -104,7 +104,7 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { } void copyTo(AbstractBlock *dst) const noexcept override { - *static_cast(dst) = *this; + *static_cast(dst) = *this; } // static bool processBlockId(std::string_view id, std::string &netBlockId, @@ -121,16 +121,16 @@ class simpleBlock : public ::SlopeCraft::AbstractBlock { } return this->getIdOld(); }; - // simpleBlock& operator =(const simpleBlock &); + // mc_block& operator =(const mc_block &); }; -class BlockList : public ::SlopeCraft::block_list_interface { +class block_list : public ::SlopeCraft::block_list_interface { private: - std::map, uint8_t> m_blocks; + std::map, uint8_t> m_blocks; public: - BlockList() = default; - ~BlockList(); + block_list() = default; + ~block_list(); public: size_t size() const noexcept override { return m_blocks.size(); } @@ -141,9 +141,9 @@ class BlockList : public ::SlopeCraft::block_list_interface { size_t capacity_in_elements) const noexcept override; bool contains(const AbstractBlock *cp) const noexcept override { - const simpleBlock *ptr = dynamic_cast(cp); + const mc_block *ptr = dynamic_cast(cp); return this->m_blocks.contains( - reinterpret_cast &>(ptr)); + reinterpret_cast &>(ptr)); } public: diff --git a/SlopeCraftL/simpleBlock.cpp b/SlopeCraftL/simpleBlock.cpp deleted file mode 100644 index 4e4959c9..00000000 --- a/SlopeCraftL/simpleBlock.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "simpleBlock.h" - -simpleBlock::simpleBlock() { - id = ""; - version = 0; - idOld = ""; - needGlass = false; - doGlow = false; - endermanPickable = false; - burnable = false; - - image.resize(16, 16); - // wallUseable=true; -} - -// bool simpleBlock::processBlockId(std::string_view id, std::string -// &netBlockId, -// std::vector &proName, -// std::vector &proVal) { -// proName.clear(); -// proVal.clear(); -// if (id.back() != ']') { -// netBlockId = id; -// return false; -// } -// short ReadBeg = id.find('['); -// // BlockId.indexOf('['); -// short ReadEnd = id.find(']'); -// // BlockId.indexOf(']'); -// -// if (ReadBeg <= 0 || ReadEnd <= 0 || ReadEnd <= ReadBeg) { -// std::cerr << "方块 Id 格式出现错误:" << id; -// return false; -// } -// -// short ProIndex[2] = {-1, -1}, ProValIndex[2] = {-1, -1}; -// -// netBlockId = id.substr(0, ReadBeg); -// // BlockId.mid(0,ReadBeg).toLower(); -// -// for (short read = ReadBeg; read <= ReadEnd; read++) { -// switch (id.at(read)) { -// case '[': // 代表找到了一个新的属性 -// ProIndex[0] = read + 1; -// continue; -// -// case '=': // 识别出了属性名,寻找属性值 -// ProIndex[1] = read - 1; -// ProValIndex[0] = read + 1; -// continue; -// -// case ',': // 代表结束了一个属性,并找到了下一个属性 -// ProValIndex[1] = read - 1; -// proName.push_back( -// id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); -// // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); -// proVal.push_back( -// id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); -// // -// BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); -// ProIndex[0] = -1; -// ProIndex[1] = -1; -// ProValIndex[0] = -1; -// ProValIndex[1] = -1; -// -// ProIndex[0] = read + 1; -// continue; -// case ']': -// ProValIndex[1] = read - 1; -// proName.push_back( -// id.substr(ProIndex[0], ProIndex[1] - ProIndex[0] + 1)); -// // BlockId.mid(ProIndex[0],ProIndex[1]-ProIndex[0]+1).toLower()); -// proVal.push_back( -// id.substr(ProValIndex[0], ProValIndex[1] - ProValIndex[0] + 1)); -// // -// BlockId.mid(ProValIndex[0],ProValIndex[1]-ProValIndex[0]+1).toLower()); -// continue; -// } -// } -// // qDebug()<back()<<'='<back(); -// return true; -// } - -size_t BlockList::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, - size_t capacity_in_elements) noexcept { - if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { - return 0; - } - - size_t counter = 0; - for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first.get(); - dst_basecolor[counter] = ptr.second; - counter++; - if (counter >= capacity_in_elements) { - return counter; - } - } - return counter; -} - -size_t BlockList::get_blocks(const AbstractBlock **dst, uint8_t *dst_basecolor, - size_t capacity_in_elements) const noexcept { - if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { - return 0; - } - - size_t counter = 0; - for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first.get(); - dst_basecolor[counter] = ptr.second; - counter++; - if (counter >= capacity_in_elements) { - return counter; - } - } - return counter; -} - -void BlockList::clear() noexcept { this->m_blocks.clear(); } - -BlockList::~BlockList() { this->clear(); } \ No newline at end of file From 85d0785bea21a0117eb8bbd49315cdb3757e5382 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 19:34:22 +0800 Subject: [PATCH 0771/1123] refactor WaterItem.h Signed-off-by: ToKiNoBug --- SlopeCraftL/HeightLine.cpp | 53 ++++++++++---------- SlopeCraftL/HeightLine.h | 12 ++--- SlopeCraftL/PrimGlassBuilder.cpp | 74 ++++++++++++++-------------- SlopeCraftL/PrimGlassBuilder.h | 22 ++++----- SlopeCraftL/TokiSlopeCraft.h | 17 ++++--- SlopeCraftL/TokiSlopeCraft_build.cpp | 22 ++++----- SlopeCraftL/WaterItem.h | 61 ++++++++++++++--------- SlopeCraftL/color_table.cpp | 28 ++++++----- SlopeCraftL/color_table.h | 2 +- 9 files changed, 152 insertions(+), 139 deletions(-) diff --git a/SlopeCraftL/HeightLine.cpp b/SlopeCraftL/HeightLine.cpp index a53d3423..71c27df6 100644 --- a/SlopeCraftL/HeightLine.cpp +++ b/SlopeCraftL/HeightLine.cpp @@ -35,30 +35,28 @@ float HeightLine::make(const TokiColor **src, float sumDiff = 0; Eigen::ArrayXi mapColorCol(g.rows()); - for (uint16_t r = 0; r < g.rows(); r++) { - + for (uint32_t r = 0; r < g.rows(); r++) { if (src[r] == nullptr) { std::cerr << "Fatal Error! nullptr found in src\n"; return 0; } switch (g(r)) { - case 0: - mapColorCol(r) = src[r]->Result; - sumDiff += src[r]->ResultDiff; - break; - case 1: - mapColorCol(r) = src[r]->sideResult[0]; - sumDiff += src[r]->sideSelectivity[0]; - break; - default: - mapColorCol(r) = src[r]->sideResult[1]; - sumDiff += src[r]->sideSelectivity[1]; - break; + case 0: + mapColorCol(r) = src[r]->Result; + sumDiff += src[r]->ResultDiff; + break; + case 1: + mapColorCol(r) = src[r]->sideResult[0]; + sumDiff += src[r]->sideSelectivity[0]; + break; + default: + mapColorCol(r) = src[r]->sideResult[1]; + sumDiff += src[r]->sideSelectivity[1]; + break; } } - if (dst != nullptr) - *dst = mapColorCol; + if (dst != nullptr) *dst = mapColorCol; make(mapColorCol, allowNaturalCompress); return sumDiff; @@ -68,7 +66,7 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, bool allowNaturalCompress) { ///////////////////////1 waterMap.clear(); - const uint16_t picRows = mapColorCol.rows(); + const uint32_t picRows = mapColorCol.rows(); base.setConstant(1 + picRows, 11); HighLine.setZero(1 + picRows); LowLine.setZero(1 + picRows); @@ -95,7 +93,7 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, base(0) = 0; dealedDepth(1) = 0; } - for (uint16_t r = 1; r < picRows; r++) { + for (uint32_t r = 1; r < picRows; r++) { if (base(r + 1) == 0) { dealedDepth(r + 1) = 0; continue; @@ -106,7 +104,7 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, } } ///////////////////////3 - for (uint16_t r = 0; r < picRows; r++) { + for (uint32_t r = 0; r < picRows; r++) { // HighMap.row(r+1)=HighMap.row(r)+dealedDepth.row(r+1); HighLine(r + 1) = HighLine(r) + dealedDepth(r + 1); } @@ -116,10 +114,10 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, /* LowMap(TokiRow(it->first),TokiCol(it->first))= HighMap(TokiRow(it->first),TokiCol(it->first)) - -WaterColumnSize[rawShadow(TokiRow(it->first)-1,TokiCol(it->first))]+1; + -WATER_COLUMN_SIZE[rawShadow(TokiRow(it->first)-1,TokiCol(it->first))]+1; */ LowLine(it->first) = - HighLine(it->first) - WaterColumnSize[rawShadow(it->first - 1)] + 1; + HighLine(it->first) - WATER_COLUMN_SIZE[rawShadow(it->first - 1)] + 1; } /////////////////5 HighLine -= LowLine.minCoeff(); @@ -137,15 +135,14 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, } } -uint16_t HeightLine::maxHeight() const { +uint32_t HeightLine::maxHeight() const { return HighLine.maxCoeff() - LowLine.minCoeff() + 1; } void HeightLine::updateWaterMap() { waterMap.clear(); - for (uint16_t r = 1; r < base.rows(); r++) { - if (base(r) != 12) - continue; + for (uint32_t r = 1; r < base.rows(); r++) { + if (base(r) != 12) continue; waterMap[r] = TokiWater(HighLine(r) - 1, LowLine(r)); } } @@ -155,7 +152,7 @@ const Eigen::ArrayXi &HeightLine::getLowLine() const { return LowLine; } const Eigen::ArrayXi &HeightLine::getBase() const { return base; } -const std::map &HeightLine::getWaterMap() const { +const std::map &HeightLine::getWaterMap() const { return waterMap; } @@ -164,7 +161,7 @@ EImage HeightLine::toImg() const { EImage img(maxHeight(), HighLine.size()); img.setConstant(AirColor); short y = 0, r = rMax - y; - for (uint16_t x = 0; x < HighLine.size(); x++) { + for (uint32_t x = 0; x < HighLine.size(); x++) { y = HighLine(x); r = rMax - y; if (base(x)) { @@ -253,7 +250,7 @@ Base.setConstant(sizePic(0)+1,sizePic(1),11); { LowMap(TokiRow(it->first),TokiCol(it->first))= HighMap(TokiRow(it->first),TokiCol(it->first)) - -WaterColumnSize[rawShadow(TokiRow(it->first)-1,TokiCol(it->first))]+1; + -WATER_COLUMN_SIZE[rawShadow(TokiRow(it->first)-1,TokiCol(it->first))]+1; } cerr<<"LowMap updated"< class HeightLine { -public: + public: HeightLine(); float make(const TokiColor *[], const Eigen::Array &, bool allowNaturalCompress, Eigen::ArrayXi *dst = nullptr); void make(const Eigen::ArrayXi &mapColorCol, bool allowNaturalCompress); void updateWaterMap(); - uint16_t maxHeight() const; + uint32_t maxHeight() const; const Eigen::ArrayXi &getHighLine() const; const Eigen::ArrayXi &getLowLine() const; const Eigen::ArrayXi &getBase() const; - const std::map &getWaterMap() const; + const std::map &getWaterMap() const; EImage toImg() const; static const ARGB BlockColor; @@ -51,11 +51,11 @@ class HeightLine { static const ARGB WaterColor; static const ARGB greyColor; -private: + private: Eigen::ArrayXi base; Eigen::ArrayXi HighLine; Eigen::ArrayXi LowLine; - std::map waterMap; + std::map waterMap; }; -#endif // HEIGHTLINE_H +#endif // HEIGHTLINE_H diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/PrimGlassBuilder.cpp index d6d0c60e..05bb3e52 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/PrimGlassBuilder.cpp @@ -26,7 +26,7 @@ const ARGB airColor = ARGB32(255, 255, 255); const ARGB targetColor = ARGB32(0, 0, 0); const ARGB glassColor = ARGB32(192, 192, 192); -const std::vector *edge::vertexes = nullptr; +const std::vector *edge::vertexes = nullptr; edge::edge() { // beg=TokiRC(0,0); @@ -39,26 +39,26 @@ edge::edge() { edge::edge(uint32_t _begIdx, uint32_t _endIdx) { begIdx = _begIdx; endIdx = _endIdx; - int r1 = TokiRow(beg()), c1 = TokiCol(beg()); - int r2 = TokiRow(end()), c2 = TokiCol(end()); + // const int r1 =beg().row,c1=; TokiRow(beg()), c1 = TokiCol(beg()); + // int r2 = TokiRow(end()), c2 = TokiCol(end()); - int rowSpan = r1 - r2; - int colSpan = c1 - c2; + const int rowSpan = beg().row - end().row; + const int colSpan = beg().col - end().col; lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); } -TokiPos edge::beg() const { return vertexes->at(begIdx); } +row_col_pos edge::beg() const { return vertexes->at(begIdx); } -TokiPos edge::end() const { return vertexes->at(endIdx); } +row_col_pos edge::end() const { return vertexes->at(endIdx); } pairedEdge::pairedEdge() { first = TokiRC(0, 0); second = TokiRC(0, 0); lengthSquare = 0; } -pairedEdge::pairedEdge(TokiPos A, TokiPos B) { - int r1 = TokiRow(A), c1 = TokiCol(A); - int r2 = TokiRow(B), c2 = TokiCol(B); +pairedEdge::pairedEdge(row_col_pos A, row_col_pos B) { + int r1 = A.row, c1 = A.col; + int r2 = B.row, c2 = B.col; first = A; second = B; int rowSpan = r1 - r2; @@ -80,7 +80,7 @@ pairedEdge::pairedEdge(const edge &src) { lengthSquare = src.lengthSquare; } /* -bool edge::connectWith(TokiPos P) const { +bool edge::connectWith(row_col_pos P) const { return pairedEdge(*this).connectWith(P); } @@ -89,15 +89,15 @@ void edge::drawEdge(glassMap & map, bool drawHead) const { return; } */ -bool pairedEdge::connectWith(TokiPos P) const { +bool pairedEdge::connectWith(row_col_pos P) const { return (first == P) || (second == P); } void pairedEdge::drawEdge(glassMap &map, bool drawHead) const { if (lengthSquare <= 2) return; float length = sqrt(lengthSquare); - Eigen::Vector2f startPoint(TokiRow(first), TokiCol(first)); - Eigen::Vector2f endPoint(TokiRow(second), TokiCol(second)); + Eigen::Vector2f startPoint(first.row, first.col); + Eigen::Vector2f endPoint(second.row, second.col); Eigen::Vector2f step = (endPoint - startPoint) / ceil(2.0 * length); Eigen::Vector2f cur; int stepCount = ceil(2.0 * length); @@ -115,9 +115,9 @@ void pairedEdge::drawEdge(glassMap &map, bool drawHead) const { if (r >= 0 && r < map.rows() && c >= 0 && c < map.cols()) map(r, c) = PrimGlassBuilder::glass; } - map(TokiRow(first), TokiCol(first)) = + map(first.row, first.col) = (drawHead ? PrimGlassBuilder::target : PrimGlassBuilder::air); - map(TokiRow(second), TokiCol(second)) = + map(second.row, second.col) = (drawHead ? PrimGlassBuilder::target : PrimGlassBuilder::air); } @@ -253,27 +253,27 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, for (auto it = tree.cbegin(); it != tree.cend(); it++) it->drawEdge(result); for (auto it = targetPoints.cbegin(); it != targetPoints.cend(); it++) - result(TokiRow(*it), TokiCol(*it)) = 0; + result(it->row, it->col) = 0; if (walkable != nullptr) *walkable = result; for (auto it = targetPoints.cbegin(); it != targetPoints.cend(); it++) { - result(TokiRow(*it), TokiCol(*it)) = 0; + result(it->row, it->col) = 0; if (walkable != nullptr) - walkable->operator()(TokiRow(*it), TokiCol(*it)) = blockType::target; + walkable->operator()(it->row, it->col) = blockType::target; } return result; } pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, - TokiPos offset1, + row_col_pos offset1, const PrimGlassBuilder *map2, - TokiPos offset2) { + row_col_pos offset2) { if (map1->targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) return pairedEdge(); - uint16_t offsetR1 = TokiRow(offset1), offsetC1 = TokiCol(offset1); - uint16_t offsetR2 = TokiRow(offset2), offsetC2 = TokiCol(offset2); + uint16_t offsetR1 = offset1.row, offsetC1 = offset1.col; + uint16_t offsetR2 = offset2.row, offsetC2 = offset2.col; uint16_t r1, r2, c1, c2; @@ -286,10 +286,10 @@ pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, it++) for (auto jt = map2->targetPoints.cbegin(); jt != map2->targetPoints.cend(); jt++) { - r1 = offsetR1 + TokiRow(*it); - c1 = offsetC1 + TokiCol(*it); - r2 = offsetR2 + TokiRow(*jt); - c2 = offsetC2 + TokiCol(*jt); + r1 = offsetR1 + it->row; + c1 = offsetC1 + it->col; + r2 = offsetR2 + jt->row; + c2 = offsetC2 + jt->col; current = pairedEdge(r1, c1, r2, c2); if (current.lengthSquare <= 2) return current; @@ -341,8 +341,8 @@ void PrimGlassBuilder::runPrim() { std::cerr << "Error: failed to find valid edge!\n"; break; } - // TokiPos z=selectedEdge->beg(); - // TokiPos w=selectedEdge->end(); + // row_col_pos z=selectedEdge->beg(); + // row_col_pos w=selectedEdge->end(); bool fz = isFound[(selectedEdge)->begIdx]; bool fw = isFound[(selectedEdge)->endIdx]; @@ -364,7 +364,7 @@ void PrimGlassBuilder::runPrim() { // 从找到的第一条边开始,寻找长度最小的可行边 for (auto it = selectedEdge; it != edges.end();) { // if(selectedEdge->lengthSquare<=2)break; - // TokiPos x=it->beg(),y=it->end(); + // row_col_pos x=it->beg(),y=it->end(); bool fx = isFound[(it)->begIdx]; bool fy = isFound[(it)->endIdx]; if (fx && fy) { @@ -386,8 +386,8 @@ void PrimGlassBuilder::runPrim() { // 并从集合 unsearched 中删除选中边的两个端点, // 向集合 found 中加入选中边的两个端点 { - // TokiPos x=selectedEdge->beg(); - // TokiPos y=selectedEdge->end(); + // row_col_pos x=selectedEdge->beg(); + // row_col_pos y=selectedEdge->end(); isFound[(selectedEdge)->begIdx] = true; isFound[(selectedEdge)->endIdx] = true; foundCount++; @@ -418,7 +418,7 @@ EImage TokiMap2EImage(const TokiMap &tm) { glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, walkableMap *walkable) { - std::list target1, target2; + std::list target1, target2; target1.clear(); target2.clear(); for (int r = 0; r < map1.rows(); r++) @@ -450,14 +450,14 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, if (walkable != nullptr) *walkable = result; for (auto t = target1.cbegin(); t != target1.cend(); t++) { - result(TokiRow(*t), TokiCol(*t)) = PrimGlassBuilder::air; + result(t->row, t->col) = PrimGlassBuilder::air; if (walkable != nullptr) - walkable->operator()(TokiRow(*t), TokiCol(*t)) = PrimGlassBuilder::target; + walkable->operator()(t->row, t->col) = PrimGlassBuilder::target; } for (auto t = target2.cbegin(); t != target2.cend(); t++) { - result(TokiRow(*t), TokiCol(*t)) = PrimGlassBuilder::air; + result(t->row, t->col) = PrimGlassBuilder::air; if (walkable != nullptr) - walkable->operator()(TokiRow(*t), TokiCol(*t)) = PrimGlassBuilder::target; + walkable->operator()(t->row, t->col) = PrimGlassBuilder::target; } return result; } diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/PrimGlassBuilder.h index 49f19b14..cfb5683b 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/PrimGlassBuilder.h @@ -52,29 +52,29 @@ class edge { edge(); edge(uint32_t begIdx, uint32_t endIdx); // edge(uint32_t begIdx,uint32_t endIdx); - // edge(TokiPos,TokiPos); + // edge(row_col_pos,row_col_pos); // edge(uint16_t r1,uint16_t c1,uint16_t r2,uint16_t c2); uint32_t begIdx; uint32_t endIdx; int lengthSquare; - static const std::vector *vertexes; + static const std::vector *vertexes; - TokiPos beg() const; - TokiPos end() const; - bool connectWith(TokiPos) const; + row_col_pos beg() const; + row_col_pos end() const; + bool connectWith(row_col_pos) const; void drawEdge(glassMap &, bool drawHead = false) const; }; -class pairedEdge : public std::pair { +class pairedEdge : public std::pair { public: pairedEdge(); - pairedEdge(TokiPos, TokiPos); + pairedEdge(row_col_pos, row_col_pos); pairedEdge(uint16_t r1, uint16_t c1, uint16_t r2, uint16_t c2); pairedEdge(const edge &); int lengthSquare; - bool connectWith(TokiPos) const; + bool connectWith(row_col_pos) const; void drawEdge(glassMap &, bool drawHead = false) const; }; @@ -109,16 +109,16 @@ class PrimGlassBuilder { void (**keepAwakePtr)(void *); private: - std::vector targetPoints; + std::vector targetPoints; std::list edges; std::vector tree; void addEdgesToGraph(); void runPrim(); glassMap make4SingleMap(const TokiMap &_targetMap, walkableMap *walkable); static pairedEdge connectSingleMaps(const PrimGlassBuilder *map1, - TokiPos offset1, + row_col_pos offset1, const PrimGlassBuilder *map2, - TokiPos offset2); + row_col_pos offset2); }; inline tf::ObjectPool pgb; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 96d0c240..f5757250 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -307,7 +307,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { Eigen::ArrayXXi Base; Eigen::ArrayXXi HighMap; Eigen::ArrayXXi LowMap; - std::unordered_map WaterList; + std::unordered_map WaterList; */ build_options build_opt; @@ -326,14 +326,15 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // for build // void makeHeight_old();//构建 HighMap 和 LowMap - void makeHeight_new(Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, - Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList); + void makeHeight_new( + Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, + std::unordered_map &WaterList); // void makeHeightInLine(const uint16_t c); - void buildHeight( - bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, - const Eigen::ArrayXXi &HighMap, const Eigen::ArrayXXi &LowMap, - const std::unordered_map &WaterList); // 构建 Build + void buildHeight(bool fireProof, bool endermanProof, + const Eigen::ArrayXXi &Base, const Eigen::ArrayXXi &HighMap, + const Eigen::ArrayXXi &LowMap, + const std::unordered_map + &WaterList); // 构建 Build void makeBridge(); // for Litematic /* diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 64cf0c1d..9fe75388 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -233,7 +233,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "start makeHeight" << endl; { Eigen::ArrayXXi Base, HighMap, LowMap; - std::unordered_map WaterList; + std::unordered_map WaterList; progressAdd(wind, sizePic(2)); makeHeight_new(Base, HighMap, LowMap, WaterList); @@ -267,7 +267,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { void TokiSlopeCraft::makeHeight_new( Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList) { + std::unordered_map &WaterList) { Base.setZero(sizePic(0) + 1, sizePic(1)); HighMap.setZero(sizePic(0) + 1, sizePic(1)); LowMap.setZero(sizePic(0) + 1, sizePic(1)); @@ -345,7 +345,7 @@ void TokiSlopeCraft::makeHeight_new( void TokiSlopeCraft::buildHeight( bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, const Eigen::ArrayXXi &, const Eigen::ArrayXXi &LowMap, - const std::unordered_map &WaterList) { + const std::unordered_map &WaterList) { /* { std::array tempSize3D({schem.x_range(), schem.y_range(), @@ -363,10 +363,10 @@ schem.z_range()}); Build.resize(tempSize3D); for (auto it = WaterList.begin(); it != WaterList.end(); it++) // 水柱周围的玻璃 { - const int x = TokiCol(it->first) + 1; - const int z = TokiRow(it->first); - const int y = waterHigh(it->second); - const int yLow = waterLow(it->second); + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { schem(x - 1, yDynamic, z - 0) = 1; @@ -410,10 +410,10 @@ schem.z_range()}); Build.resize(tempSize3D); progressAdd(wind, sizePic(2)); for (auto it = WaterList.cbegin(); it != WaterList.cend(); ++it) { - const int x = TokiCol(it->first) + 1; - const int z = TokiRow(it->first); - const int y = waterHigh(it->second); - const int yLow = waterLow(it->second); + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { schem(x, yDynamic, z) = 13; } diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/WaterItem.h index e1d7ce42..31797522 100644 --- a/SlopeCraftL/WaterItem.h +++ b/SlopeCraftL/WaterItem.h @@ -23,33 +23,46 @@ This file is part of SlopeCraft. #ifndef WATERITEM_H #define WATERITEM_H -#include - -using TokiPos = uint32_t; -// typedef unsigned int TokiPos; -// typedef unsigned int waterItem; -using waterItem = uint32_t; -constexpr TokiPos TokiRC(int row, int col) { // 前16bit存储row,后16bit存储col - /*unsigned int u; - *((int16_t*)&u)=row; - *(((int16_t*)&u)+1)=col; - return u;*/ - return (row << 16) | (col & 0x0000FFFF); +#include +#include + +struct row_col_pos { + int32_t row; + int32_t col; + + [[nodiscard]] inline bool operator==(row_col_pos b) const noexcept { + return (this->row == b.row) && (this->col == b.col); + } +}; + +template <> +struct std::hash { + size_t operator()(row_col_pos pos) const noexcept { + return std::hash{}(reinterpret_cast(pos)); + } +}; + +constexpr row_col_pos TokiRC(int row, int col) { + return row_col_pos{.row = static_cast(row), + .col = static_cast(col)}; } -constexpr int16_t TokiRow(TokiPos pos) { return pos >> 16; } -constexpr int16_t TokiCol(TokiPos pos) { return pos & 0x0000FFFF; } +struct water_y_range { + int high_y; + int low_y; +}; -constexpr TokiPos nullPos = TokiRC(-1, -1); -constexpr waterItem nullWater = TokiRC(-32768, -32768); -constexpr int16_t WaterColumnSize[3] = {11, 6, 1}; +constexpr water_y_range TokiWater(int h, int l) { + return water_y_range{.high_y = h, .low_y = l}; +} -constexpr waterItem (*TokiWater)(int, int) = TokiRC; -constexpr int16_t (*waterHigh)(waterItem) = TokiRow; -constexpr int16_t (*waterLow)(waterItem) = TokiCol; -/* -waterItem TokiWater(int16_t high,int16_t -low);//前两字节存储high,后两字节存储low int16_t waterHigh(waterItem); int16_t -waterLow(waterItem);*/ +[[nodiscard]] inline bool operator==(water_y_range a, + water_y_range b) noexcept { + return (a.high_y == b.high_y) && (a.low_y == b.low_y); +} + +constexpr water_y_range nullWater = + water_y_range{.high_y = INT_MIN, .low_y = INT_MIN}; +constexpr int32_t WATER_COLUMN_SIZE[3] = {11, 6, 1}; #endif // WATERITEM_H diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 7b1c5920..497b9df9 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -173,7 +173,7 @@ converted_image *color_table_impl::convert_image( std::optional converted_image_impl::height_info(const build_options &option) const noexcept { // - // std::unordered_map water_list; + // std::unordered_map water_list; Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); @@ -199,7 +199,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { base.setZero(this->rows(), this->cols()); high_map.setZero(this->rows(), this->cols()); low_map.setZero(this->rows(), this->cols()); - std::unordered_map water_list; + std::unordered_map water_list; LossyCompressor compressor; for (int64_t c = 0; c < map_color.cols(); c++) { @@ -237,7 +237,9 @@ converted_image_impl::height_info(const build_options &option) const noexcept { auto hl_water_list = HL.getWaterMap(); water_list.reserve(water_list.size() + hl_water_list.size()); for (const auto &[r, water_item] : hl_water_list) { - water_list.emplace(TokiRC(r, c), water_item); + water_list.emplace( + row_col_pos{static_cast(r), static_cast(c)}, + water_item); } option.main_progressbar.add(4 * this->size()); @@ -279,12 +281,12 @@ std::optional structure_3D_impl::create( option.ui.report_working_status(workStatus::buidingHeighMap); option.main_progressbar.set_range(0, 9 * cvted.size(), 0); { - std::unordered_map water_list; + std::unordered_map water_list; option.main_progressbar.add(cvted.size()); } Eigen::ArrayXi map_color, base_color, high_map, low_map; - std::unordered_map water_list; + std::unordered_map water_list; { auto opt = cvted.height_info(fixed_opt); if (!opt) { @@ -308,10 +310,10 @@ std::optional structure_3D_impl::create( for (auto it = water_list.begin(); it != water_list.end(); it++) // 水柱周围的玻璃 { - const int x = TokiCol(it->first) + 1; - const int z = TokiRow(it->first); - const int y = waterHigh(it->second); - const int yLow = waterLow(it->second); + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; ret.schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { ret.schem(x - 1, yDynamic, z - 0) = 1; @@ -359,10 +361,10 @@ std::optional structure_3D_impl::create( option.main_progressbar.add(cvted.size()); for (auto it = water_list.cbegin(); it != water_list.cend(); ++it) { - const int x = TokiCol(it->first) + 1; - const int z = TokiRow(it->first); - const int y = waterHigh(it->second); - const int yLow = waterLow(it->second); + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { ret.schem(x, yDynamic, z) = 13; } diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 91a73ee1..5ae76daf 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -82,7 +82,7 @@ class converted_image_impl : public converted_image { Eigen::ArrayXXi base; Eigen::ArrayXXi high_map; Eigen::ArrayXXi low_map; - std::unordered_map water_list; + std::unordered_map water_list; }; std::optional height_info( const build_options &option) const noexcept; From c287113f1ceae2b2a1a66c436f1fc499c7cad42b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 19:45:02 +0800 Subject: [PATCH 0772/1123] remove TokiRC Signed-off-by: ToKiNoBug --- SlopeCraftL/PrimGlassBuilder.cpp | 51 ++++++++++++++++------------ SlopeCraftL/PrimGlassBuilder.h | 7 ++-- SlopeCraftL/TokiSlopeCraft_build.cpp | 2 +- SlopeCraftL/WaterItem.h | 5 --- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/PrimGlassBuilder.cpp index 05bb3e52..f251cce1 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/PrimGlassBuilder.cpp @@ -51,10 +51,11 @@ row_col_pos edge::beg() const { return vertexes->at(begIdx); } row_col_pos edge::end() const { return vertexes->at(endIdx); } -pairedEdge::pairedEdge() { - first = TokiRC(0, 0); - second = TokiRC(0, 0); - lengthSquare = 0; +pairedEdge::pairedEdge() + : std::pair{{0, 0}, {0, 0}}, lengthSquare{0} { + // first = TokiRC(0, 0); + // second = TokiRC(0, 0); + // lengthSquare = 0; } pairedEdge::pairedEdge(row_col_pos A, row_col_pos B) { int r1 = A.row, c1 = A.col; @@ -66,9 +67,9 @@ pairedEdge::pairedEdge(row_col_pos A, row_col_pos B) { lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); } -pairedEdge::pairedEdge(uint16_t r1, uint16_t c1, uint16_t r2, uint16_t c2) { - first = TokiRC(r1, c1); - second = TokiRC(r2, c2); +pairedEdge::pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2) { + first = row_col_pos{static_cast(r1), static_cast(c1)}; + second = row_col_pos{static_cast(r2), static_cast(c2)}; int rowSpan = r1 - r2; int colSpan = c1 - c2; lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); @@ -163,15 +164,23 @@ glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, for (int r = 0; r < rowCount; r++) for (int c = 0; c < colCount; c++) { if (r + 1 < rowCount) { - pairedEdge temp = connectSingleMaps( - algos[r][c], TokiRC(unitL * r, unitL * c), algos[r + 1][c], - TokiRC(unitL * (r + 1), unitL * c)); + pairedEdge temp = + connectSingleMaps(algos[r][c], + row_col_pos{static_cast(unitL * r), + static_cast(unitL * c)}, + algos[r + 1][c], + row_col_pos{static_cast(unitL * (r + 1)), + static_cast(unitL * c)}); if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } if (c + 1 < colCount) { pairedEdge temp = connectSingleMaps( - algos[r][c], TokiRC(unitL * r, unitL * c), algos[r][c + 1], - TokiRC(unitL * r, unitL * (c + 1))); + algos[r][c], + row_col_pos{static_cast(unitL * r), + static_cast(unitL * c)}, + algos[r][c + 1], + row_col_pos{static_cast(unitL * r), + static_cast(unitL * (c + 1))}); if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } } @@ -234,7 +243,7 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, _targetMap(r, c - 1)) continue; else - targetPoints.emplace_back(TokiRC(r, c)); + targetPoints.emplace_back(row_col_pos{r, c}); } } @@ -272,10 +281,10 @@ pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, if (map1->targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) return pairedEdge(); - uint16_t offsetR1 = offset1.row, offsetC1 = offset1.col; - uint16_t offsetR2 = offset2.row, offsetC2 = offset2.col; + uint32_t offsetR1 = offset1.row, offsetC1 = offset1.col; + uint32_t offsetR2 = offset2.row, offsetC2 = offset2.col; - uint16_t r1, r2, c1, c2; + uint32_t r1, r2, c1, c2; pairedEdge current; @@ -408,8 +417,8 @@ void PrimGlassBuilder::runPrim() { EImage TokiMap2EImage(const TokiMap &tm) { EImage result(tm.rows(), tm.cols()); result.setConstant(airColor); - for (uint16_t r = 0; r < tm.rows(); r++) - for (uint16_t c = 0; c < tm.cols(); c++) { + for (uint32_t r = 0; r < tm.rows(); r++) + for (uint32_t c = 0; c < tm.cols(); c++) { if (tm(r, c) == 1) result(r, c) = glassColor; if (tm(r, c) > 1) result(r, c) = targetColor; } @@ -424,9 +433,9 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, for (int r = 0; r < map1.rows(); r++) for (int c = 0; c < map1.cols(); c++) { if (map1(r, c) >= PrimGlassBuilder::target) - target1.emplace_back(TokiRC(r, c)); + target1.emplace_back(row_col_pos{r, c}); if (map2(r, c) >= PrimGlassBuilder::target) - target2.emplace_back(TokiRC(r, c)); + target2.emplace_back(row_col_pos{r, c}); } std::list linkEdges; linkEdges.clear(); @@ -477,7 +486,7 @@ TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { return impl_ySlice2TokiMap(raw); } -TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { +TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { return impl_ySlice2TokiMap(raw); } diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/PrimGlassBuilder.h index cfb5683b..e9c00030 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/PrimGlassBuilder.h @@ -51,9 +51,6 @@ class edge { public: edge(); edge(uint32_t begIdx, uint32_t endIdx); - // edge(uint32_t begIdx,uint32_t endIdx); - // edge(row_col_pos,row_col_pos); - // edge(uint16_t r1,uint16_t c1,uint16_t r2,uint16_t c2); uint32_t begIdx; uint32_t endIdx; int lengthSquare; @@ -70,7 +67,7 @@ class pairedEdge : public std::pair { public: pairedEdge(); pairedEdge(row_col_pos, row_col_pos); - pairedEdge(uint16_t r1, uint16_t c1, uint16_t r2, uint16_t c2); + pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2); pairedEdge(const edge &); int lengthSquare; @@ -81,7 +78,7 @@ class pairedEdge : public std::pair { [[deprecated]] TokiMap ySlice2TokiMap( const Eigen::Tensor &) noexcept; [[deprecated]] TokiMap ySlice2TokiMap_u16( - const Eigen::Tensor &) noexcept; + const Eigen::Tensor &) noexcept; TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, std::span start_xzy, std::span extension_xzy) noexcept; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 9fe75388..5dd66a76 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -329,7 +329,7 @@ void TokiSlopeCraft::makeHeight_new( auto HLM = &HL.getWaterMap(); for (auto it = HLM->cbegin(); it != HLM->cend(); it++) { - WaterList[TokiRC(it->first, c)] = it->second; + WaterList[row_col_pos{static_cast(it->first), c}] = it->second; } progressAdd(wind, 4 * sizePic(0)); diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/WaterItem.h index 31797522..b181b8ca 100644 --- a/SlopeCraftL/WaterItem.h +++ b/SlopeCraftL/WaterItem.h @@ -42,11 +42,6 @@ struct std::hash { } }; -constexpr row_col_pos TokiRC(int row, int col) { - return row_col_pos{.row = static_cast(row), - .col = static_cast(col)}; -} - struct water_y_range { int high_y; int low_y; From 48446e2385f03fdcb3cd3327a10d3ec9f3da3527 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 19:46:07 +0800 Subject: [PATCH 0773/1123] rename row_col_pos to rc_pos Signed-off-by: ToKiNoBug --- SlopeCraftL/PrimGlassBuilder.cpp | 62 ++++++++++++++-------------- SlopeCraftL/PrimGlassBuilder.h | 20 ++++----- SlopeCraftL/TokiSlopeCraft.h | 10 ++--- SlopeCraftL/TokiSlopeCraft_build.cpp | 8 ++-- SlopeCraftL/WaterItem.h | 8 ++-- SlopeCraftL/color_table.cpp | 11 +++-- SlopeCraftL/color_table.h | 2 +- 7 files changed, 60 insertions(+), 61 deletions(-) diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/PrimGlassBuilder.cpp index f251cce1..d35b51cd 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/PrimGlassBuilder.cpp @@ -26,7 +26,7 @@ const ARGB airColor = ARGB32(255, 255, 255); const ARGB targetColor = ARGB32(0, 0, 0); const ARGB glassColor = ARGB32(192, 192, 192); -const std::vector *edge::vertexes = nullptr; +const std::vector *edge::vertexes = nullptr; edge::edge() { // beg=TokiRC(0,0); @@ -47,17 +47,17 @@ edge::edge(uint32_t _begIdx, uint32_t _endIdx) { lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); } -row_col_pos edge::beg() const { return vertexes->at(begIdx); } +rc_pos edge::beg() const { return vertexes->at(begIdx); } -row_col_pos edge::end() const { return vertexes->at(endIdx); } +rc_pos edge::end() const { return vertexes->at(endIdx); } pairedEdge::pairedEdge() - : std::pair{{0, 0}, {0, 0}}, lengthSquare{0} { + : std::pair{{0, 0}, {0, 0}}, lengthSquare{0} { // first = TokiRC(0, 0); // second = TokiRC(0, 0); // lengthSquare = 0; } -pairedEdge::pairedEdge(row_col_pos A, row_col_pos B) { +pairedEdge::pairedEdge(rc_pos A, rc_pos B) { int r1 = A.row, c1 = A.col; int r2 = B.row, c2 = B.col; first = A; @@ -68,8 +68,8 @@ pairedEdge::pairedEdge(row_col_pos A, row_col_pos B) { } pairedEdge::pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2) { - first = row_col_pos{static_cast(r1), static_cast(c1)}; - second = row_col_pos{static_cast(r2), static_cast(c2)}; + first = rc_pos{static_cast(r1), static_cast(c1)}; + second = rc_pos{static_cast(r2), static_cast(c2)}; int rowSpan = r1 - r2; int colSpan = c1 - c2; lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); @@ -81,7 +81,7 @@ pairedEdge::pairedEdge(const edge &src) { lengthSquare = src.lengthSquare; } /* -bool edge::connectWith(row_col_pos P) const { +bool edge::connectWith(rc_pos P) const { return pairedEdge(*this).connectWith(P); } @@ -90,7 +90,7 @@ void edge::drawEdge(glassMap & map, bool drawHead) const { return; } */ -bool pairedEdge::connectWith(row_col_pos P) const { +bool pairedEdge::connectWith(rc_pos P) const { return (first == P) || (second == P); } @@ -166,21 +166,21 @@ glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, if (r + 1 < rowCount) { pairedEdge temp = connectSingleMaps(algos[r][c], - row_col_pos{static_cast(unitL * r), - static_cast(unitL * c)}, + rc_pos{static_cast(unitL * r), + static_cast(unitL * c)}, algos[r + 1][c], - row_col_pos{static_cast(unitL * (r + 1)), - static_cast(unitL * c)}); + rc_pos{static_cast(unitL * (r + 1)), + static_cast(unitL * c)}); if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } if (c + 1 < colCount) { - pairedEdge temp = connectSingleMaps( - algos[r][c], - row_col_pos{static_cast(unitL * r), - static_cast(unitL * c)}, - algos[r][c + 1], - row_col_pos{static_cast(unitL * r), - static_cast(unitL * (c + 1))}); + pairedEdge temp = + connectSingleMaps(algos[r][c], + rc_pos{static_cast(unitL * r), + static_cast(unitL * c)}, + algos[r][c + 1], + rc_pos{static_cast(unitL * r), + static_cast(unitL * (c + 1))}); if (temp.lengthSquare > 2) interRegionEdges.emplace(temp); } } @@ -243,7 +243,7 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, _targetMap(r, c - 1)) continue; else - targetPoints.emplace_back(row_col_pos{r, c}); + targetPoints.emplace_back(rc_pos{r, c}); } } @@ -275,9 +275,9 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, } pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, - row_col_pos offset1, + rc_pos offset1, const PrimGlassBuilder *map2, - row_col_pos offset2) { + rc_pos offset2) { if (map1->targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) return pairedEdge(); @@ -350,8 +350,8 @@ void PrimGlassBuilder::runPrim() { std::cerr << "Error: failed to find valid edge!\n"; break; } - // row_col_pos z=selectedEdge->beg(); - // row_col_pos w=selectedEdge->end(); + // rc_pos z=selectedEdge->beg(); + // rc_pos w=selectedEdge->end(); bool fz = isFound[(selectedEdge)->begIdx]; bool fw = isFound[(selectedEdge)->endIdx]; @@ -373,7 +373,7 @@ void PrimGlassBuilder::runPrim() { // 从找到的第一条边开始,寻找长度最小的可行边 for (auto it = selectedEdge; it != edges.end();) { // if(selectedEdge->lengthSquare<=2)break; - // row_col_pos x=it->beg(),y=it->end(); + // rc_pos x=it->beg(),y=it->end(); bool fx = isFound[(it)->begIdx]; bool fy = isFound[(it)->endIdx]; if (fx && fy) { @@ -395,8 +395,8 @@ void PrimGlassBuilder::runPrim() { // 并从集合 unsearched 中删除选中边的两个端点, // 向集合 found 中加入选中边的两个端点 { - // row_col_pos x=selectedEdge->beg(); - // row_col_pos y=selectedEdge->end(); + // rc_pos x=selectedEdge->beg(); + // rc_pos y=selectedEdge->end(); isFound[(selectedEdge)->begIdx] = true; isFound[(selectedEdge)->endIdx] = true; foundCount++; @@ -427,15 +427,15 @@ EImage TokiMap2EImage(const TokiMap &tm) { glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, walkableMap *walkable) { - std::list target1, target2; + std::list target1, target2; target1.clear(); target2.clear(); for (int r = 0; r < map1.rows(); r++) for (int c = 0; c < map1.cols(); c++) { if (map1(r, c) >= PrimGlassBuilder::target) - target1.emplace_back(row_col_pos{r, c}); + target1.emplace_back(rc_pos{r, c}); if (map2(r, c) >= PrimGlassBuilder::target) - target2.emplace_back(row_col_pos{r, c}); + target2.emplace_back(rc_pos{r, c}); } std::list linkEdges; linkEdges.clear(); diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/PrimGlassBuilder.h index e9c00030..ada32d2b 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/PrimGlassBuilder.h @@ -55,23 +55,23 @@ class edge { uint32_t endIdx; int lengthSquare; - static const std::vector *vertexes; + static const std::vector *vertexes; - row_col_pos beg() const; - row_col_pos end() const; - bool connectWith(row_col_pos) const; + rc_pos beg() const; + rc_pos end() const; + bool connectWith(rc_pos) const; void drawEdge(glassMap &, bool drawHead = false) const; }; -class pairedEdge : public std::pair { +class pairedEdge : public std::pair { public: pairedEdge(); - pairedEdge(row_col_pos, row_col_pos); + pairedEdge(rc_pos, rc_pos); pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2); pairedEdge(const edge &); int lengthSquare; - bool connectWith(row_col_pos) const; + bool connectWith(rc_pos) const; void drawEdge(glassMap &, bool drawHead = false) const; }; @@ -106,16 +106,16 @@ class PrimGlassBuilder { void (**keepAwakePtr)(void *); private: - std::vector targetPoints; + std::vector targetPoints; std::list edges; std::vector tree; void addEdgesToGraph(); void runPrim(); glassMap make4SingleMap(const TokiMap &_targetMap, walkableMap *walkable); static pairedEdge connectSingleMaps(const PrimGlassBuilder *map1, - row_col_pos offset1, + rc_pos offset1, const PrimGlassBuilder *map2, - row_col_pos offset2); + rc_pos offset2); }; inline tf::ObjectPool pgb; diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index f5757250..6cd0349a 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -307,7 +307,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { Eigen::ArrayXXi Base; Eigen::ArrayXXi HighMap; Eigen::ArrayXXi LowMap; - std::unordered_map WaterList; + std::unordered_map WaterList; */ build_options build_opt; @@ -326,14 +326,14 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { // for build // void makeHeight_old();//构建 HighMap 和 LowMap - void makeHeight_new( - Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList); + void makeHeight_new(Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, + Eigen::ArrayXXi &LowMap, + std::unordered_map &WaterList); // void makeHeightInLine(const uint16_t c); void buildHeight(bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, const Eigen::ArrayXXi &HighMap, const Eigen::ArrayXXi &LowMap, - const std::unordered_map + const std::unordered_map &WaterList); // 构建 Build void makeBridge(); // for Litematic diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index 5dd66a76..ee7ef329 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -233,7 +233,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "start makeHeight" << endl; { Eigen::ArrayXXi Base, HighMap, LowMap; - std::unordered_map WaterList; + std::unordered_map WaterList; progressAdd(wind, sizePic(2)); makeHeight_new(Base, HighMap, LowMap, WaterList); @@ -267,7 +267,7 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { void TokiSlopeCraft::makeHeight_new( Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList) { + std::unordered_map &WaterList) { Base.setZero(sizePic(0) + 1, sizePic(1)); HighMap.setZero(sizePic(0) + 1, sizePic(1)); LowMap.setZero(sizePic(0) + 1, sizePic(1)); @@ -329,7 +329,7 @@ void TokiSlopeCraft::makeHeight_new( auto HLM = &HL.getWaterMap(); for (auto it = HLM->cbegin(); it != HLM->cend(); it++) { - WaterList[row_col_pos{static_cast(it->first), c}] = it->second; + WaterList[rc_pos{static_cast(it->first), c}] = it->second; } progressAdd(wind, 4 * sizePic(0)); @@ -345,7 +345,7 @@ void TokiSlopeCraft::makeHeight_new( void TokiSlopeCraft::buildHeight( bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, const Eigen::ArrayXXi &, const Eigen::ArrayXXi &LowMap, - const std::unordered_map &WaterList) { + const std::unordered_map &WaterList) { /* { std::array tempSize3D({schem.x_range(), schem.y_range(), diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/WaterItem.h index b181b8ca..6dbcd5b6 100644 --- a/SlopeCraftL/WaterItem.h +++ b/SlopeCraftL/WaterItem.h @@ -26,18 +26,18 @@ This file is part of SlopeCraft. #include #include -struct row_col_pos { +struct rc_pos { int32_t row; int32_t col; - [[nodiscard]] inline bool operator==(row_col_pos b) const noexcept { + [[nodiscard]] inline bool operator==(rc_pos b) const noexcept { return (this->row == b.row) && (this->col == b.col); } }; template <> -struct std::hash { - size_t operator()(row_col_pos pos) const noexcept { +struct std::hash { + size_t operator()(rc_pos pos) const noexcept { return std::hash{}(reinterpret_cast(pos)); } }; diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 497b9df9..1e135d92 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -173,7 +173,7 @@ converted_image *color_table_impl::convert_image( std::optional converted_image_impl::height_info(const build_options &option) const noexcept { // - // std::unordered_map water_list; + // std::unordered_map water_list; Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); @@ -199,7 +199,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { base.setZero(this->rows(), this->cols()); high_map.setZero(this->rows(), this->cols()); low_map.setZero(this->rows(), this->cols()); - std::unordered_map water_list; + std::unordered_map water_list; LossyCompressor compressor; for (int64_t c = 0; c < map_color.cols(); c++) { @@ -238,8 +238,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { water_list.reserve(water_list.size() + hl_water_list.size()); for (const auto &[r, water_item] : hl_water_list) { water_list.emplace( - row_col_pos{static_cast(r), static_cast(c)}, - water_item); + rc_pos{static_cast(r), static_cast(c)}, water_item); } option.main_progressbar.add(4 * this->size()); @@ -281,12 +280,12 @@ std::optional structure_3D_impl::create( option.ui.report_working_status(workStatus::buidingHeighMap); option.main_progressbar.set_range(0, 9 * cvted.size(), 0); { - std::unordered_map water_list; + std::unordered_map water_list; option.main_progressbar.add(cvted.size()); } Eigen::ArrayXi map_color, base_color, high_map, low_map; - std::unordered_map water_list; + std::unordered_map water_list; { auto opt = cvted.height_info(fixed_opt); if (!opt) { diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 5ae76daf..a118e9f5 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -82,7 +82,7 @@ class converted_image_impl : public converted_image { Eigen::ArrayXXi base; Eigen::ArrayXXi high_map; Eigen::ArrayXXi low_map; - std::unordered_map water_list; + std::unordered_map water_list; }; std::optional height_info( const build_options &option) const noexcept; From 4ce5a55352e6808c810fdf558d21702f369c92a4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 19:57:02 +0800 Subject: [PATCH 0774/1123] rename row_col_pos to rc_pos Signed-off-by: ToKiNoBug --- SlopeCraftL/HeightLine.cpp | 10 +++++++--- SlopeCraftL/WaterItem.h | 9 ++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/SlopeCraftL/HeightLine.cpp b/SlopeCraftL/HeightLine.cpp index 71c27df6..e2b5df9a 100644 --- a/SlopeCraftL/HeightLine.cpp +++ b/SlopeCraftL/HeightLine.cpp @@ -79,6 +79,7 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, Eigen::ArrayXi rawShadow = mapColorCol - 4 * (mapColorCol / 4); if ((rawShadow >= 3).any()) { +#warning "TODO: Fix this error handling" std::cerr << "Fatal Error: depth=3 in vanilla map!" << std::endl; std::cerr << "SlopeCraft will crash." << std::endl; exit(1); @@ -100,7 +101,9 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, } if (base(r + 1) == 12) { dealedDepth(r + 1) = 0; - waterMap[r + 1] = nullWater; + if (waterMap.contains(r + 1)) { + waterMap.erase(r + 1); + } } } ///////////////////////3 @@ -130,7 +133,8 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, LowLine = OC.getLowLine(); } for (auto it = waterMap.begin(); it != waterMap.end(); it++) { - waterMap[it->first] = TokiWater(HighLine(it->first), LowLine(it->first)); + waterMap[it->first] = + water_y_range{HighLine(it->first), LowLine(it->first)}; HighLine(it->first) += 1; } } @@ -143,7 +147,7 @@ void HeightLine::updateWaterMap() { waterMap.clear(); for (uint32_t r = 1; r < base.rows(); r++) { if (base(r) != 12) continue; - waterMap[r] = TokiWater(HighLine(r) - 1, LowLine(r)); + waterMap[r] = water_y_range{HighLine(r) - 1, LowLine(r)}; } } diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/WaterItem.h index 6dbcd5b6..d1eb2a58 100644 --- a/SlopeCraftL/WaterItem.h +++ b/SlopeCraftL/WaterItem.h @@ -46,18 +46,13 @@ struct water_y_range { int high_y; int low_y; }; - -constexpr water_y_range TokiWater(int h, int l) { - return water_y_range{.high_y = h, .low_y = l}; -} - [[nodiscard]] inline bool operator==(water_y_range a, water_y_range b) noexcept { return (a.high_y == b.high_y) && (a.low_y == b.low_y); } -constexpr water_y_range nullWater = - water_y_range{.high_y = INT_MIN, .low_y = INT_MIN}; +// constexpr water_y_range nullWater = +// water_y_range{.high_y = INT_MIN, .low_y = INT_MIN}; constexpr int32_t WATER_COLUMN_SIZE[3] = {11, 6, 1}; #endif // WATERITEM_H From 226458ca6af64198b18d34c301143e74f5ab8b40 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 20:17:51 +0800 Subject: [PATCH 0775/1123] rename OptiChain and HeightLine Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 12 +- SlopeCraftL/Colorset.h | 1 + SlopeCraftL/SlopeCraftL.cpp | 2 +- SlopeCraftL/TokiSlopeCraft.cpp | 4 +- SlopeCraftL/TokiSlopeCraft.h | 10 +- SlopeCraftL/TokiSlopeCraft_build.cpp | 8 +- SlopeCraftL/color_table.cpp | 18 +- .../{HeightLine.cpp => height_line.cpp} | 50 ++-- SlopeCraftL/{HeightLine.h => height_line.h} | 6 +- SlopeCraftL/lossyCompressor.cpp | 26 +- SlopeCraftL/lossyCompressor.h | 8 +- .../{OptiChain.cpp => optimize_chain.cpp} | 222 ++++++++---------- SlopeCraftL/{OptiChain.h => optimize_chain.h} | 63 ++--- ...lassBuilder.cpp => prim_glass_builder.cpp} | 50 ++-- ...rimGlassBuilder.h => prim_glass_builder.h} | 11 +- 15 files changed, 239 insertions(+), 252 deletions(-) rename SlopeCraftL/{HeightLine.cpp => height_line.cpp} (85%) rename SlopeCraftL/{HeightLine.h => height_line.h} (96%) rename SlopeCraftL/{OptiChain.cpp => optimize_chain.cpp} (54%) rename SlopeCraftL/{OptiChain.h => optimize_chain.h} (62%) rename SlopeCraftL/{PrimGlassBuilder.cpp => prim_glass_builder.cpp} (91%) rename SlopeCraftL/{PrimGlassBuilder.h => prim_glass_builder.h} (92%) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 5731d2b0..b11a4fca 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -26,10 +26,10 @@ set(Slope_SCL_internal_headers # AiCvterOpt.h Colors.h - HeightLine.h + height_line.h - OptiChain.h - PrimGlassBuilder.h + optimize_chain.h + prim_glass_builder.h SCLDefines.h TokiSlopeCraft.h WaterItem.h @@ -48,9 +48,9 @@ set(SlopeCraft_SCL_sources # AiCvterOpt.cpp Colors.cpp ColorSource.cpp - HeightLine.cpp - OptiChain.cpp - PrimGlassBuilder.cpp + height_line.cpp + optimize_chain.cpp + prim_glass_builder.cpp TokiSlopeCraft.cpp TokiSlopeCraft_static_funs.cpp TokiSlopeCraft_build.cpp diff --git a/SlopeCraftL/Colorset.h b/SlopeCraftL/Colorset.h index 54aa9b30..dcbd8bcc 100644 --- a/SlopeCraftL/Colorset.h +++ b/SlopeCraftL/Colorset.h @@ -22,6 +22,7 @@ #define mapColor2depth(mapColor) ((mapColor) % 4) #define index2depth(index) (mapColor2depth(index2mapColor(index))) +#warning "TODO: Remove this struct" struct color_set { static const std::unique_ptr basic; diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 4e1eba8a..3bb42741 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -58,7 +58,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( mc_block ret; const int basecolor = jo.at("baseColor"); if (basecolor < 0 || basecolor >= 64) { - throw std::runtime_error{fmt::format("Invalid base color: {}", basecolor)}; + throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; } ret.id = jo.at("id"); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp index 62424c04..a605dcbb 100644 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ b/SlopeCraftL/TokiSlopeCraft.cpp @@ -33,8 +33,8 @@ This file is part of SlopeCraft. TokiSlopeCraft::TokiSlopeCraft() : colorset{}, image_cvter{*color_set::basic, colorset.allowed_colorset}, - glassBuilder{new PrimGlassBuilder}, - Compressor{new LossyCompressor} { + glassBuilder{new prim_glass_builder}, + Compressor{new lossy_compressor} { kernelStep = step::nothing; this->image_cvter.clear_images(); this->image_cvter.clear_color_hash(); diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 6cd0349a..44f03da5 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -41,7 +41,7 @@ This file is part of SlopeCraft. #include "mc_block.h" #include -#include "PrimGlassBuilder.h" +#include "prim_glass_builder.h" #include "lossyCompressor.h" #include @@ -69,8 +69,8 @@ namespace SlopeCraft using namespace SlopeCraft; #include -class PrimGlassBuilder; -class LossyCompressor; +class prim_glass_builder; +class lossy_compressor; namespace NBT { template @@ -296,8 +296,8 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { libMapImageCvt::MapImageCvter image_cvter; // std::array size3D; // x,y,z - std::unique_ptr glassBuilder; - std::unique_ptr Compressor; + std::unique_ptr glassBuilder; + std::unique_ptr Compressor; // std::shared_ptr GAConverter{nullptr}; diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index ee7ef329..a463fbc4 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -297,7 +297,7 @@ void TokiSlopeCraft::makeHeight_new( for (uint16_t c = 0; c < sizePic(1); c++) { // cerr << "Coloumn " << c << '\n'; - HeightLine HL; + height_line HL; // getTokiColorPtr(c,&src[0]); HL.make(this->mapPic.col(c), allowNaturalCompress); @@ -448,9 +448,9 @@ void TokiSlopeCraft::makeBridge() { glass = glassBuilder->makeBridge(targetMap); for (int r = 0; r < glass.rows(); r++) for (int c = 0; c < glass.cols(); c++) - if (schem(r, y, c) == PrimGlassBuilder::air && - glass(r, c) == PrimGlassBuilder::glass) - schem(r, y, c) = PrimGlassBuilder::glass; + if (schem(r, y, c) == prim_glass_builder::air && + glass(r, c) == prim_glass_builder::glass) + schem(r, y, c) = prim_glass_builder::glass; } else { continue; } diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 1e135d92..8120a10a 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -4,9 +4,9 @@ #include "color_table.h" #include "WaterItem.h" -#include "HeightLine.h" +#include "height_line.h" #include "lossyCompressor.h" -#include "PrimGlassBuilder.h" +#include "prim_glass_builder.h" #include std::optional color_table_impl::create( @@ -201,10 +201,10 @@ converted_image_impl::height_info(const build_options &option) const noexcept { low_map.setZero(this->rows(), this->cols()); std::unordered_map water_list; - LossyCompressor compressor; + lossy_compressor compressor; for (int64_t c = 0; c < map_color.cols(); c++) { // cerr << "Coloumn " << c << '\n'; - HeightLine HL; + height_line HL; // getTokiColorPtr(c,&src[0]); HL.make(map_color.col(c), allow_lossless_compress); @@ -378,8 +378,8 @@ std::optional structure_3D_impl::create( option.sub_progressbar.set_range(0, 100, 0); const int step = cvted.size() / ret.schem.y_range(); -#warning "todo: Use prograss_callback in PrimGlassBuilder" - PrimGlassBuilder glass_builder; +#warning "todo: Use prograss_callback in prim_glass_builder" + prim_glass_builder glass_builder; option.ui.keep_awake(); for (uint32_t y = 0; y < ret.schem.y_range(); y++) { option.sub_progressbar.add(step); @@ -398,9 +398,9 @@ std::optional structure_3D_impl::create( glass = glass_builder.makeBridge(targetMap); for (int r = 0; r < glass.rows(); r++) for (int c = 0; c < glass.cols(); c++) - if (ret.schem(r, y, c) == PrimGlassBuilder::air && - glass(r, c) == PrimGlassBuilder::glass) - ret.schem(r, y, c) = PrimGlassBuilder::glass; + if (ret.schem(r, y, c) == prim_glass_builder::air && + glass(r, c) == prim_glass_builder::glass) + ret.schem(r, y, c) = prim_glass_builder::glass; } else { continue; } diff --git a/SlopeCraftL/HeightLine.cpp b/SlopeCraftL/height_line.cpp similarity index 85% rename from SlopeCraftL/HeightLine.cpp rename to SlopeCraftL/height_line.cpp index e2b5df9a..5f170555 100644 --- a/SlopeCraftL/HeightLine.cpp +++ b/SlopeCraftL/height_line.cpp @@ -20,18 +20,18 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "HeightLine.h" +#include "height_line.h" -const ARGB HeightLine::BlockColor = ARGB32(0, 0, 0); -const ARGB HeightLine::AirColor = ARGB32(255, 255, 255); -const ARGB HeightLine::WaterColor = ARGB32(0, 64, 255); -const ARGB HeightLine::greyColor = ARGB32(192, 192, 192); +const ARGB height_line::BlockColor = ARGB32(0, 0, 0); +const ARGB height_line::AirColor = ARGB32(255, 255, 255); +const ARGB height_line::WaterColor = ARGB32(0, 64, 255); +const ARGB height_line::greyColor = ARGB32(192, 192, 192); -HeightLine::HeightLine() {} +height_line::height_line() {} -float HeightLine::make(const TokiColor **src, - const Eigen::Array &g, - bool allowNaturalCompress, Eigen::ArrayXi *dst) { +float height_line::make(const TokiColor **src, + const Eigen::Array &g, + bool allowNaturalCompress, Eigen::ArrayXi *dst) { float sumDiff = 0; Eigen::ArrayXi mapColorCol(g.rows()); @@ -62,8 +62,8 @@ float HeightLine::make(const TokiColor **src, return sumDiff; } -void HeightLine::make(const Eigen::ArrayXi &mapColorCol, - bool allowNaturalCompress) { +void height_line::make(const Eigen::ArrayXi &mapColorCol, + bool allowNaturalCompress) { ///////////////////////1 waterMap.clear(); const uint32_t picRows = mapColorCol.rows(); @@ -127,10 +127,10 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, LowLine -= LowLine.minCoeff(); if (allowNaturalCompress) { - OptiChain OC(base, HighLine, LowLine); - OC.divideAndCompress(); - HighLine = OC.getHighLine(); - LowLine = OC.getLowLine(); + optimize_chain OC(base, HighLine, LowLine); + OC.divide_and_compress(); + HighLine = OC.high_line(); + LowLine = OC.low_line(); } for (auto it = waterMap.begin(); it != waterMap.end(); it++) { waterMap[it->first] = @@ -139,11 +139,11 @@ void HeightLine::make(const Eigen::ArrayXi &mapColorCol, } } -uint32_t HeightLine::maxHeight() const { +uint32_t height_line::maxHeight() const { return HighLine.maxCoeff() - LowLine.minCoeff() + 1; } -void HeightLine::updateWaterMap() { +void height_line::updateWaterMap() { waterMap.clear(); for (uint32_t r = 1; r < base.rows(); r++) { if (base(r) != 12) continue; @@ -151,16 +151,16 @@ void HeightLine::updateWaterMap() { } } -const Eigen::ArrayXi &HeightLine::getHighLine() const { return HighLine; } -const Eigen::ArrayXi &HeightLine::getLowLine() const { return LowLine; } +const Eigen::ArrayXi &height_line::getHighLine() const { return HighLine; } +const Eigen::ArrayXi &height_line::getLowLine() const { return LowLine; } -const Eigen::ArrayXi &HeightLine::getBase() const { return base; } +const Eigen::ArrayXi &height_line::getBase() const { return base; } -const std::map &HeightLine::getWaterMap() const { +const std::map &height_line::getWaterMap() const { return waterMap; } -EImage HeightLine::toImg() const { +EImage height_line::toImg() const { const short rMax = maxHeight() - 1; EImage img(maxHeight(), HighLine.size()); img.setConstant(AirColor); @@ -272,11 +272,11 @@ Base.setConstant(sizePic(0)+1,sizePic(1),11); if(compressMethod==NaturalOnly) { //执行高度压缩 - OptiChain::Base=Base; + optimize_chain::Base=Base; for(int c=0;c #include #include -class HeightLine { +class height_line { public: - HeightLine(); + height_line(); float make(const TokiColor *[], const Eigen::Array &, bool allowNaturalCompress, Eigen::ArrayXi *dst = nullptr); diff --git a/SlopeCraftL/lossyCompressor.cpp b/SlopeCraftL/lossyCompressor.cpp index e91ebd3e..4451648f 100644 --- a/SlopeCraftL/lossyCompressor.cpp +++ b/SlopeCraftL/lossyCompressor.cpp @@ -31,7 +31,7 @@ const double initializeNonZeroRatio = 0.05; constexpr uint16_t popSize = 50; uint16_t maxFailTimes = 30; -uint16_t LossyCompressor::maxGeneration = 600; +uint16_t lossy_compressor::maxGeneration = 600; constexpr double crossoverProb = 0.9; constexpr double mutateProb = 0.01; constexpr uint32_t reportRate = 50; @@ -46,7 +46,7 @@ struct args_t : public heu::FixedDiscreteBox { const TokiColor **src; bool allowNaturalCompress; size_t maxHeight; - const LossyCompressor *ptr; + const lossy_compressor *ptr; std::clock_t prevClock; }; @@ -64,7 +64,7 @@ void iFun(Var_t *v, const args_t *arg) { } void fFun(const Var_t *v, const args_t *arg, double *fitness) { - HeightLine HL; + height_line HL; const TokiColor **src = arg->src; const bool allowNaturalCompress = arg->allowNaturalCompress; float meanColorDiff = HL.make(src, *v, allowNaturalCompress); @@ -91,21 +91,21 @@ class solver_t if (curClock - prevClock >= CLOCKS_PER_SEC / 2) { prevClock = curClock; (*(this->_args.ptr->progressRangeSetPtr))( - *(this->_args.ptr->windPtr), 0, LossyCompressor::maxGeneration, + *(this->_args.ptr->windPtr), 0, lossy_compressor::maxGeneration, this->generation()); } } } }; -LossyCompressor::LossyCompressor() : solver{new solver_t{}} { +lossy_compressor::lossy_compressor() : solver{new solver_t{}} { solver->setTournamentSize(3); } -LossyCompressor::~LossyCompressor() {} +lossy_compressor::~lossy_compressor() {} -void LossyCompressor::setSource(const Eigen::ArrayXi &_base, - const TokiColor **src) { +void lossy_compressor::setSource(const Eigen::ArrayXi &_base, + const TokiColor **src) { source.resize(_base.rows() - 1); for (uint16_t idx = 0; idx < _base.rows() - 1; idx++) { @@ -117,8 +117,8 @@ void LossyCompressor::setSource(const Eigen::ArrayXi &_base, // std::cerr<<"source set\n"; } -void LossyCompressor::runGenetic(uint16_t maxHeight, - bool allowNaturalCompress) { +void lossy_compressor::runGenetic(uint16_t maxHeight, + bool allowNaturalCompress) { { heu::GAOption opt; opt.crossoverProb = crossoverProb; @@ -143,7 +143,7 @@ void LossyCompressor::runGenetic(uint16_t maxHeight, solver->run(); } -bool LossyCompressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { +bool lossy_compressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { (*progressRangeSetPtr)(*windPtr, 0, maxGeneration, 0); // std::cerr<<"Genetic algorithm started\n"; @@ -162,10 +162,10 @@ bool LossyCompressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { return tryTimes < 3; } -const Eigen::ArrayX &LossyCompressor::getResult() const { +const Eigen::ArrayX &lossy_compressor::getResult() const { return this->solver->result(); } -double LossyCompressor::resultFitness() const { +double lossy_compressor::resultFitness() const { return this->solver->bestFitness(); } diff --git a/SlopeCraftL/lossyCompressor.h b/SlopeCraftL/lossyCompressor.h index d18be7f5..e4389e3a 100644 --- a/SlopeCraftL/lossyCompressor.h +++ b/SlopeCraftL/lossyCompressor.h @@ -33,17 +33,17 @@ This file is part of SlopeCraft. #include #include "Colors.h" -#include "HeightLine.h" +#include "height_line.h" #include "SCLDefines.h" #include "WaterItem.h" // Eigen::Array class solver_t; -class LossyCompressor { +class lossy_compressor { public: - LossyCompressor(); - ~LossyCompressor(); + lossy_compressor(); + ~lossy_compressor(); void setSource(const Eigen::ArrayXi &, const TokiColor *[]); bool compress(uint16_t maxHeight, bool allowNaturalCompress = false); const Eigen::ArrayX &getResult() const; diff --git a/SlopeCraftL/OptiChain.cpp b/SlopeCraftL/optimize_chain.cpp similarity index 54% rename from SlopeCraftL/OptiChain.cpp rename to SlopeCraftL/optimize_chain.cpp index 9087a5c0..908d1c4d 100644 --- a/SlopeCraftL/OptiChain.cpp +++ b/SlopeCraftL/optimize_chain.cpp @@ -20,111 +20,99 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "OptiChain.h" +#include "optimize_chain.h" #define NInf -100000 #define MapSize (Base.rows()) -// ArrayXXi OptiChain::Base=MatrixXi::Zero(0,0); -const Eigen::Array3i OptiChain::Both(-1, 2, -1); -const Eigen::Array3i OptiChain::Left(-1, 1, 0); -const Eigen::Array3i OptiChain::Right(0, 1, -1); -// QLabel* OptiChain::SinkIDP=nullptr; +// ArrayXXi optimize_chain::Base=MatrixXi::Zero(0,0); +const Eigen::Array3i optimize_chain::Both(-1, 2, -1); +const Eigen::Array3i optimize_chain::Left(-1, 1, 0); +const Eigen::Array3i optimize_chain::Right(0, 1, -1); +// QLabel* optimize_chain::SinkIDP=nullptr; #ifdef showImg -QLabel *OptiChain::SinkAll = nullptr; -bool OptiChain::AllowSinkHang = false; +QLabel *optimize_chain::SinkAll = nullptr; +bool optimize_chain::AllowSinkHang = false; #else #define AllowSinkHang true #endif -Region::Region(short _Beg, short _End, RegionType _Type) { - Beg = _Beg; - End = _End; - type = _Type; -} -inline bool Region::isHang() const { return (type == Hang); } +inline bool region::isHang() const { return (type == region_type::hanging); } -inline bool Region::isIDP() const { return (type == idp); } +inline bool region::isIDP() const { return (type == region_type::independent); } -inline bool Region::isValid() const { - return (type != Invalid) && (size() >= 1); -} +inline bool region::isValid() const { return (size() >= 1); } -inline int Region::size() const { return (End - Beg + 1); } +inline int region::size() const { return (end - begin + 1); } -inline short Region::indexLocal2Global(short indexLocal) const { - return indexLocal + Beg; +inline int region::indexLocal2Global(int indexLocal) const { + return indexLocal + begin; } -inline short Region::indexGlobal2Local(short indexGlobal) const { - return indexGlobal - Beg; +inline int region::indexGlobal2Local(int indexGlobal) const { + return indexGlobal - begin; } -std::string Region::toString() const { +std::string region::toString() const { if (!isValid()) - return '{' + std::to_string(Beg) + ',' + std::to_string(End) + - '}'; // 无效区间用大括号 + return '{' + std::to_string(begin) + ',' + std::to_string(end) + + '}'; // 无效区间用大括号 if (isHang()) - return '[' + std::to_string(Beg) + ',' + std::to_string(End) + - ']'; // 悬空区间用中括号 + return '[' + std::to_string(begin) + ',' + std::to_string(end) + + ']'; // 悬空区间用中括号 - return '(' + std::to_string(Beg) + ',' + std::to_string(End) + - ')'; // 可沉降区间用括号 + return '(' + std::to_string(begin) + ',' + std::to_string(end) + + ')'; // 可沉降区间用括号 } -OptiChain::OptiChain(int size) { +optimize_chain::optimize_chain(int size) { SubChain.clear(); - if (size < 0) - return; + if (size < 0) return; } -OptiChain::OptiChain(const Eigen::ArrayXi &base, const Eigen::ArrayXi &High, - const Eigen::ArrayXi &Low) { +optimize_chain::optimize_chain(const Eigen::ArrayXi &base, + const Eigen::ArrayXi &High, + const Eigen::ArrayXi &Low) { Base = base; HighLine = High; LowLine = Low; SubChain.clear(); } /* -OptiChain::OptiChain(const HeightLine& src) { +optimize_chain::optimize_chain(const height_line& src) { HighLine=src.HighLine; LowLine=src.LowLine; Base=src.base; SubChain.clear(); }*/ -OptiChain::~OptiChain() { return; } +optimize_chain::~optimize_chain() { return; } -const Eigen::ArrayXi &OptiChain::getHighLine() { return HighLine; } -const Eigen::ArrayXi &OptiChain::getLowLine() { return LowLine; } +const Eigen::ArrayXi &optimize_chain::high_line() { return HighLine; } +const Eigen::ArrayXi &optimize_chain::low_line() { return LowLine; } -int OptiChain::validHeight(int index) const { - if (index < 0 || index >= MapSize) - return NInf; - if (isAir(index)) - return NInf; +int optimize_chain::valid_height(int index) const { + if (index < 0 || index >= MapSize) return NInf; + if (is_air(index)) return NInf; return HighLine(index); } -inline bool OptiChain::isAir(int index) const { - if (index < 0 || index >= MapSize) - return true; +inline bool optimize_chain::is_air(int index) const { + if (index < 0 || index >= MapSize) return true; return (Base(index) == 0); } -inline bool OptiChain::isWater(int index) const { - if (index < 0 || index >= MapSize) - return false; +inline bool optimize_chain::is_water(int index) const { + if (index < 0 || index >= MapSize) return false; return (Base(index) == 12); } -inline bool OptiChain::isSolidBlock(int index) const { - if (index < 0 || index >= MapSize) - return false; +inline bool optimize_chain::is_solid_block(int index) const { + if (index < 0 || index >= MapSize) return false; return (Base(index) != 0 && Base(index) != 12); } -void OptiChain::dispSubChain() const { +void optimize_chain::dispSubChain() const { std::string out = ""; for (auto it = SubChain.cbegin(); it != SubChain.cend(); it++) { out += it->toString(); @@ -136,7 +124,7 @@ void OptiChain::dispSubChain() const { } /* -void HeightLine::segment2Brackets(list&List,short sBeg,short sEnd) +void height_line::segment2Brackets(list&List,short sBeg,short sEnd) { if(sEnd&List,short sBeg,short sEnd) return; } - queuePure; - queue disPure;//极大值区间 - Region Temp; + queuePure; + queue disPure;//极大值区间 + region Temp; bool isReady=false; VectorXi VHL=ValidHighLine(); VectorXi ScanBoth=VHL,ScanLeft=VHL,ScanRight=VHL; @@ -209,7 +197,7 @@ ScanRight=(ScanRight.array()>=0).select(ScanRight,0); #endif } -inline void HeightLine::DealRegion(Region PR, list &List) +inline void height_line::DealRegion(region PR, list &List) { if(PR.Begin<0||PR.End &List) } */ -void OptiChain::divideAndCompress() { +void optimize_chain::divide_and_compress() { divideToChain(); while (!Chain.empty()) { - divideToSubChain(); + divide_into_subchain(); for (auto it = SubChain.begin(); it != SubChain.end(); it++) - if (it->isIDP()) - Sink(*it); + if (it->isIDP()) sink(*it); for (auto it = SubChain.begin(); it != SubChain.end(); it++) - if (AllowSinkHang && it->isHang()) - Sink(*it); + if (AllowSinkHang && it->isHang()) sink(*it); } #ifdef showImg @@ -238,54 +224,53 @@ void OptiChain::divideAndCompress() { #endif } -void OptiChain::divideToChain() { - while (!Chain.empty()) - Chain.pop(); - Region Temp(0, MapSize - 1, idp); +void optimize_chain::divideToChain() { + while (!Chain.empty()) Chain.pop(); + region Temp(0, MapSize - 1, region_type::independent); for (int i = 1; i < MapSize; i++) { - if (isAir(i)) { - Temp.End = i - 1; + if (is_air(i)) { + Temp.end = i - 1; Chain.push(Temp); - Temp.Beg = i; + Temp.begin = i; } - if (isWater(i)) { - Temp.End = i - 1; + if (is_water(i)) { + Temp.end = i - 1; Chain.push(Temp); - Temp.Beg = i; + Temp.begin = i; } - if (isSolidBlock(i) && isAir(i)) { - Temp.End = i - 1; + if (is_solid_block(i) && is_air(i)) { + Temp.end = i - 1; Chain.push(Temp); - Temp.Beg = i; + Temp.begin = i; } } - Temp.End = MapSize - 1; + Temp.end = MapSize - 1; Chain.push(Temp); #ifdef sendInfo - std::cout << "Divided coloum " - << " into " << Chain.size() << "isolated region(s)" << std::endl; + std::cout << "Divided coloum " << " into " << Chain.size() + << "isolated region(s)" << std::endl; #endif } -void OptiChain::divideToSubChain() { +void optimize_chain::divide_into_subchain() { if (!Chain.front().isValid()) { Chain.pop(); return; } SubChain.clear(); - divideToSubChain(Chain.front()); + divide_into_subchain(Chain.front()); Chain.pop(); } -void OptiChain::divideToSubChain(const Region &Cur) { +void optimize_chain::divide_into_subchain(const region &Cur) { #ifdef sendInfo std::cout << "ready to analyse" << Cur.toString() << std::endl; #endif if (Cur.size() <= 3) { - SubChain.push_back(Region(Cur.Beg, Cur.End, idp)); + SubChain.push_back(region(Cur.begin, Cur.end, region_type::independent)); #ifdef sendInfo - std::cout << "Region" << Cur.toString() + std::cout << "region" << Cur.toString() << " in Chain is too thin, sink directly." << std::endl; #endif return; @@ -293,7 +278,7 @@ void OptiChain::divideToSubChain(const Region &Cur) { Eigen::ArrayXi HL; HL.setZero(Cur.size() + 1); - HL.segment(0, Cur.size()) = HighLine.segment(Cur.Beg, Cur.size()); + HL.segment(0, Cur.size()) = HighLine.segment(Cur.begin, Cur.size()); HL(Cur.size()) = NInf; Eigen::ArrayXi ScanBoth, ScanLeft, ScanRight; @@ -301,7 +286,7 @@ void OptiChain::divideToSubChain(const Region &Cur) { ScanLeft.setZero(Cur.size()); ScanRight.setZero(Cur.size()); // qDebug("开始用三个一维算子扫描HighLine和LowLine"); - for (int i = 1; i < Cur.size(); i++) // 用三个算子扫描一个大孤立区间 + for (int i = 1; i < Cur.size(); i++) // 用三个算子扫描一个大孤立区间 { ScanBoth(i) = (HL.segment(i - 1, 3) * Both).sum() > 0; ScanLeft(i) = (HL.segment(i - 1, 3) * Left).sum() > 0; @@ -317,19 +302,19 @@ void OptiChain::divideToSubChain(const Region &Cur) { bool isReady = false; // 表示已经检测出极大值区间的入口,找到出口就装入一个极大值区间 - Region Temp(-1, -1, Hang); // 均写入绝对index而非相对index + region Temp(-1, -1, region_type::hanging); // 均写入绝对index而非相对index for (int i = 0; i < Cur.size(); i++) { if (!isReady && ScanLeft(i)) { isReady = true; - Temp.Beg = Cur.indexLocal2Global(i); - Temp.End = -1; + Temp.begin = Cur.indexLocal2Global(i); + Temp.end = -1; } if (isReady && ScanRight(i)) { isReady = false; - Temp.End = Cur.indexLocal2Global(i); + Temp.end = Cur.indexLocal2Global(i); SubChain.push_back(Temp); - Temp.Beg = -1; - Temp.End = -1; + Temp.begin = -1; + Temp.end = -1; } } // qDebug("已将极大值区间串联成链,即将开始填充孤立区间。此时的SubChain为:"); @@ -337,55 +322,54 @@ void OptiChain::divideToSubChain(const Region &Cur) { auto prev = SubChain.begin(); for (auto it = SubChain.begin(); it != SubChain.end(); prev = it++) { if (it == SubChain.begin()) { - Temp.Beg = Cur.indexLocal2Global(0); - Temp.End = (it->Beg - 1); - Temp.type = idp; - if (Temp.isValid()) - SubChain.insert(it, Temp); + Temp.begin = Cur.indexLocal2Global(0); + Temp.end = (it->begin - 1); + Temp.type = region_type::independent; + if (Temp.isValid()) SubChain.insert(it, Temp); } else { - Temp.Beg = (prev->End + 1); - Temp.End = (it->Beg - 1); - Temp.type = idp; - if (Temp.isValid()) - SubChain.insert(it, Temp); + Temp.begin = (prev->end + 1); + Temp.end = (it->begin - 1); + Temp.type = region_type::independent; + if (Temp.isValid()) SubChain.insert(it, Temp); } } if (SubChain.size() <= 0) { SubChain.push_back(Cur); - } else if (SubChain.back().End < Cur.End) - SubChain.push_back(Region(SubChain.back().End + 1, Cur.End, idp)); + } else if (SubChain.back().end < Cur.end) + SubChain.push_back( + region(SubChain.back().end + 1, Cur.end, region_type::independent)); #ifdef sendInfo std::cout << "SubChain constructed" << std::endl; #endif } -void OptiChain::Sink(const Region &Reg) { +void optimize_chain::sink(const region &Reg) { if (!Reg.isValid()) { - std::cout << "Invalid region: " << Reg.toString() << std::endl; + std::cout << "invalid region: " << Reg.toString() << std::endl; return; } if (Reg.isIDP()) { - HighLine.segment(Reg.Beg, Reg.size()) -= - LowLine.segment(Reg.Beg, Reg.size()).minCoeff(); - LowLine.segment(Reg.Beg, Reg.size()) -= - LowLine.segment(Reg.Beg, Reg.size()).minCoeff(); + HighLine.segment(Reg.begin, Reg.size()) -= + LowLine.segment(Reg.begin, Reg.size()).minCoeff(); + LowLine.segment(Reg.begin, Reg.size()) -= + LowLine.segment(Reg.begin, Reg.size()).minCoeff(); return; } if (AllowSinkHang && Reg.isHang()) { int BegGap; - BegGap = validHeight(Reg.Beg) - validHeight(Reg.Beg - 1); + BegGap = valid_height(Reg.begin) - valid_height(Reg.begin - 1); int EndGap; - if (isSolidBlock(Reg.End + 1)) - EndGap = validHeight(Reg.End) - validHeight(Reg.End + 1); + if (is_solid_block(Reg.end + 1)) + EndGap = valid_height(Reg.end) - valid_height(Reg.end + 1); else - EndGap = validHeight(Reg.End) - NInf; + EndGap = valid_height(Reg.end) - NInf; int offset = std::min(std::max(std::min(BegGap, EndGap) - 1, 0), - LowLine.segment(Reg.Beg, Reg.size()).minCoeff()); - HighLine.segment(Reg.Beg, Reg.size()) -= offset; - LowLine.segment(Reg.Beg, Reg.size()) -= offset; + LowLine.segment(Reg.begin, Reg.size()).minCoeff()); + HighLine.segment(Reg.begin, Reg.size()) -= offset; + LowLine.segment(Reg.begin, Reg.size()) -= offset; } } diff --git a/SlopeCraftL/OptiChain.h b/SlopeCraftL/optimize_chain.h similarity index 62% rename from SlopeCraftL/OptiChain.h rename to SlopeCraftL/optimize_chain.h index 7d866a51..8eacba32 100644 --- a/SlopeCraftL/OptiChain.h +++ b/SlopeCraftL/optimize_chain.h @@ -34,7 +34,7 @@ This file is part of SlopeCraft. // using namespace std; // using namespace Eigen; -enum RegionType { idp, Hang, Invalid }; +enum class region_type { independent, hanging }; #ifndef removeQt extern ARGB isTColor; @@ -43,33 +43,34 @@ extern ARGB WaterColor; extern ARGB greyColor; #endif -class Region { -public: - Region(short = -1, short = -1, RegionType = Invalid); - short Beg; - short End; - RegionType type; +class region { + public: + region() = delete; + region(int b, int e, region_type t) : begin{b}, end{e}, type{t} {} + int begin; + int end; + region_type type; bool isIDP() const; bool isHang() const; bool isValid() const; int size() const; - short indexLocal2Global(short) const; - short indexGlobal2Local(short) const; + int indexLocal2Global(int) const; + int indexGlobal2Local(int) const; std::string toString() const; }; -class OptiChain { -public: +class optimize_chain { + public: // Index一律以Height矩阵中的索引为准。Height(r,c+1)<->Base(r,c) // 高度矩阵一律不含水柱顶的玻璃方块 - OptiChain(int Size = -1); // default Random Constructor - OptiChain(const Eigen::ArrayXi &base, const Eigen::ArrayXi &High, - const Eigen::ArrayXi &Low); - ~OptiChain(); - - void divideAndCompress(); - const Eigen::ArrayXi &getHighLine(); - const Eigen::ArrayXi &getLowLine(); + optimize_chain(int Size = -1); // default Random Constructor + optimize_chain(const Eigen::ArrayXi &base, const Eigen::ArrayXi &High, + const Eigen::ArrayXi &Low); + ~optimize_chain(); + + void divide_and_compress(); + const Eigen::ArrayXi &high_line(); + const Eigen::ArrayXi &low_line(); // ArrayXi toDepth() const; // static ArrayXXi Base; @@ -83,27 +84,27 @@ class OptiChain { static bool AllowSinkHang; #endif -private: + private: // int Col; Eigen::ArrayXi Base; Eigen::ArrayXi HighLine; Eigen::ArrayXi LowLine; - std::queue Chain; // 将一整列按水/空气切分为若干个大的孤立区间 - std::list - SubChain; // 将Chain中每个大的孤立区间切分为若干“最大单孤立区间”和“悬空区间”组成的串 + std::queue Chain; // 将一整列按水/空气切分为若干个大的孤立区间 + std::list + SubChain; // 将Chain中每个大的孤立区间切分为若干“最大单孤立区间”和“悬空区间”组成的串 void divideToChain(); - void divideToSubChain(); + void divide_into_subchain(); - bool isAir(int index) const; - bool isWater(int index) const; - bool isSolidBlock(int index) const; + bool is_air(int index) const; + bool is_water(int index) const; + bool is_solid_block(int index) const; - void Sink(const Region &); - int validHeight(int index) const; + void sink(const region &); + int valid_height(int index) const; void dispSubChain() const; // private: - void divideToSubChain(const Region &); + void divide_into_subchain(const region &); }; -#endif // OPTICHAIN_H +#endif // OPTICHAIN_H diff --git a/SlopeCraftL/PrimGlassBuilder.cpp b/SlopeCraftL/prim_glass_builder.cpp similarity index 91% rename from SlopeCraftL/PrimGlassBuilder.cpp rename to SlopeCraftL/prim_glass_builder.cpp index d35b51cd..11dc3ca8 100644 --- a/SlopeCraftL/PrimGlassBuilder.cpp +++ b/SlopeCraftL/prim_glass_builder.cpp @@ -20,7 +20,7 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "PrimGlassBuilder.h" +#include "prim_glass_builder.h" const ARGB airColor = ARGB32(255, 255, 255); const ARGB targetColor = ARGB32(0, 0, 0); @@ -108,28 +108,28 @@ void pairedEdge::drawEdge(glassMap &map, bool drawHead) const { r = floor(cur(0)); c = floor(cur(1)); if (r >= 0 && r < map.rows() && c >= 0 && c < map.cols()) { - map(r, c) = PrimGlassBuilder::glass; + map(r, c) = prim_glass_builder::glass; continue; } r = ceil(cur(0)); c = ceil(cur(1)); if (r >= 0 && r < map.rows() && c >= 0 && c < map.cols()) - map(r, c) = PrimGlassBuilder::glass; + map(r, c) = prim_glass_builder::glass; } map(first.row, first.col) = - (drawHead ? PrimGlassBuilder::target : PrimGlassBuilder::air); + (drawHead ? prim_glass_builder::target : prim_glass_builder::air); map(second.row, second.col) = - (drawHead ? PrimGlassBuilder::target : PrimGlassBuilder::air); + (drawHead ? prim_glass_builder::target : prim_glass_builder::air); } -PrimGlassBuilder::PrimGlassBuilder() {} -glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, - walkableMap *walkable) { +prim_glass_builder::prim_glass_builder() {} +glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, + walkableMap *walkable) { // clock_t lastTime=std::clock(); const int rowCount = ceil(double(_targetMap.rows()) / unitL); const int colCount = ceil(double(_targetMap.cols()) / unitL); - std::vector> algos(rowCount); + std::vector> algos(rowCount); std::vector> glassMaps(rowCount); std::vector> walkableMaps(rowCount); std::vector> targetMaps(rowCount); @@ -227,8 +227,8 @@ glassMap PrimGlassBuilder::makeBridge(const TokiMap &_targetMap, return result; } -glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, - walkableMap *walkable) { +glassMap prim_glass_builder::make4SingleMap(const TokiMap &_targetMap, + walkableMap *walkable) { if (_targetMap.rows() > unitL || _targetMap.cols() > unitL) { // qDebug("错误!make4SingleMap 不应当收到超过 unitL*unitL 的图"); return glassMap(0, 0); @@ -274,10 +274,10 @@ glassMap PrimGlassBuilder::make4SingleMap(const TokiMap &_targetMap, return result; } -pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, - rc_pos offset1, - const PrimGlassBuilder *map2, - rc_pos offset2) { +pairedEdge prim_glass_builder::connectSingleMaps(const prim_glass_builder *map1, + rc_pos offset1, + const prim_glass_builder *map2, + rc_pos offset2) { if (map1->targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) return pairedEdge(); @@ -307,7 +307,7 @@ pairedEdge PrimGlassBuilder::connectSingleMaps(const PrimGlassBuilder *map1, return min; } -void PrimGlassBuilder::addEdgesToGraph() { +void prim_glass_builder::addEdgesToGraph() { edges.clear(); edge::vertexes = std::addressof(targetPoints); // int taskCount=(targetPoints.size()*(targetPoints.size()-1))/2; @@ -321,7 +321,7 @@ void PrimGlassBuilder::addEdgesToGraph() { } // qDebug("插入了所有的边"); } -void PrimGlassBuilder::runPrim() { +void prim_glass_builder::runPrim() { tree.clear(); tree.reserve(targetPoints.size() - 1); @@ -432,9 +432,9 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, target2.clear(); for (int r = 0; r < map1.rows(); r++) for (int c = 0; c < map1.cols(); c++) { - if (map1(r, c) >= PrimGlassBuilder::target) + if (map1(r, c) >= prim_glass_builder::target) target1.emplace_back(rc_pos{r, c}); - if (map2(r, c) >= PrimGlassBuilder::target) + if (map2(r, c) >= prim_glass_builder::target) target2.emplace_back(rc_pos{r, c}); } std::list linkEdges; @@ -459,14 +459,14 @@ glassMap connectBetweenLayers(const TokiMap &map1, const TokiMap &map2, if (walkable != nullptr) *walkable = result; for (auto t = target1.cbegin(); t != target1.cend(); t++) { - result(t->row, t->col) = PrimGlassBuilder::air; + result(t->row, t->col) = prim_glass_builder::air; if (walkable != nullptr) - walkable->operator()(t->row, t->col) = PrimGlassBuilder::target; + walkable->operator()(t->row, t->col) = prim_glass_builder::target; } for (auto t = target2.cbegin(); t != target2.cend(); t++) { - result(t->row, t->col) = PrimGlassBuilder::air; + result(t->row, t->col) = prim_glass_builder::air; if (walkable != nullptr) - walkable->operator()(t->row, t->col) = PrimGlassBuilder::target; + walkable->operator()(t->row, t->col) = prim_glass_builder::target; } return result; } @@ -478,7 +478,7 @@ TokiMap impl_ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { TokiMap result(raw.dimension(0), raw.dimension(1)); result.setZero(); for (int i = 0; i < raw.size(); i++) - if (raw(i) > 1) result(i) = PrimGlassBuilder::target; + if (raw(i) > 1) result(i) = prim_glass_builder::target; return result; } @@ -502,7 +502,7 @@ TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, for (int x = 0; x < result.rows(); x++) { for (int z = 0; z < result.cols(); z++) { if (xzy(x + start_xzy[0], z + start_xzy[1], start_xzy[2]) > 1) - result(x, z) = PrimGlassBuilder::target; + result(x, z) = prim_glass_builder::target; } } return result; diff --git a/SlopeCraftL/PrimGlassBuilder.h b/SlopeCraftL/prim_glass_builder.h similarity index 92% rename from SlopeCraftL/PrimGlassBuilder.h rename to SlopeCraftL/prim_glass_builder.h index ada32d2b..cd9a8302 100644 --- a/SlopeCraftL/PrimGlassBuilder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -47,6 +47,7 @@ typedef Eigen::Array TokiMap; typedef TokiMap glassMap; typedef TokiMap walkableMap; +#warning "TODO: Remove global variables in this part" class edge { public: edge(); @@ -87,9 +88,9 @@ glassMap connectBetweenLayers(const TokiMap &, const TokiMap &, walkableMap *walkable); // 返回值是架构在相对较高的一层上的,walkable 是各层俯视图叠加 -class PrimGlassBuilder { +class prim_glass_builder { public: - PrimGlassBuilder(); + prim_glass_builder(); template friend class tf::ObjectPool; @@ -112,12 +113,12 @@ class PrimGlassBuilder { void addEdgesToGraph(); void runPrim(); glassMap make4SingleMap(const TokiMap &_targetMap, walkableMap *walkable); - static pairedEdge connectSingleMaps(const PrimGlassBuilder *map1, + static pairedEdge connectSingleMaps(const prim_glass_builder *map1, rc_pos offset1, - const PrimGlassBuilder *map2, + const prim_glass_builder *map2, rc_pos offset2); }; -inline tf::ObjectPool pgb; +inline tf::ObjectPool pgb; EImage TokiMap2EImage(const TokiMap &); From 1230812ba5096643d4e45286ce2a16b83b679f56 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 21:33:12 +0800 Subject: [PATCH 0776/1123] delete duplicated build_options definition Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 56 ++++++++++++++-------------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 4 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index dd7c7669..8a906d5b 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -229,6 +229,22 @@ struct build_options { progress_callbacks main_progressbar; progress_callbacks sub_progressbar; }; +struct litematic_options { + uint64_t caller_api_version{SC_VERSION_U64}; + const char *litename_utf8 = "by SlopeCraft"; + const char *region_name_utf8 = "by SlopeCraft"; +}; +struct vanilla_structure_options { + uint64_t caller_api_version{SC_VERSION_U64}; + bool is_air_structure_void{true}; +}; +struct WE_schem_options { + uint64_t caller_api_version{SC_VERSION_U64}; + int offset[3] = {0, 0, 0}; + int we_offset[3] = {0, 0, 0}; + const char *const *required_mods_name_utf8{nullptr}; + int num_required_mods{0}; +}; struct const_image_reference { const uint32_t *data{nullptr}; @@ -435,18 +451,18 @@ class Kernel { // *dest)const virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, bool expected_col_major) const = 0; - struct build_options { - uint64_t caller_api_version{SC_VERSION_U64}; - uint16_t maxAllowedHeight{256}; - uint16_t bridgeInterval{3}; - compressSettings compressMethod{::SCL_compressSettings::noCompress}; - glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; - bool fire_proof{false}; - bool enderman_proof{false}; - - // added in v5.1.0 - bool connect_mushrooms{false}; - }; + // struct build_options { + // uint64_t caller_api_version{SC_VERSION_U64}; + // uint16_t maxAllowedHeight{256}; + // uint16_t bridgeInterval{3}; + // compressSettings compressMethod{::SCL_compressSettings::noCompress}; + // glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; + // bool fire_proof{false}; + // bool enderman_proof{false}; + // + // // added in v5.1.0 + // bool connect_mushrooms{false}; + // }; virtual bool build(const build_options &option) noexcept = 0; virtual void getCompressedImage(int *row, int *cols, uint32_t *dest, @@ -469,30 +485,14 @@ class Kernel { virtual int getSchemPalette(const char **dest_id, size_t dest_capacity) const noexcept = 0; - struct litematic_options { - uint64_t caller_api_version{SC_VERSION_U64}; - const char *litename_utf8 = "by SlopeCraft"; - const char *region_name_utf8 = "by SlopeCraft"; - }; virtual bool exportAsLitematic( const char *filename_local, const litematic_options &option) const noexcept = 0; - struct vanilla_structure_options { - uint64_t caller_api_version{SC_VERSION_U64}; - bool is_air_structure_void{true}; - }; virtual bool exportAsStructure( const char *filename_local, const vanilla_structure_options &option) const noexcept = 0; - struct WE_schem_options { - uint64_t caller_api_version{SC_VERSION_U64}; - int offset[3] = {0, 0, 0}; - int we_offset[3] = {0, 0, 0}; - const char *const *required_mods_name_utf8{nullptr}; - int num_required_mods{0}; - }; virtual bool exportAsWESchem( const char *filename_local, const WE_schem_options &option) const noexcept = 0; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 37d3ac7a..b8d04cff 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -227,14 +227,14 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, // build hash, dir and cache ------------------------------------ namespace cereal { template -void save(archive &ar, const SlopeCraft::Kernel::build_options &opt) noexcept { +void save(archive &ar, const build_options &opt) noexcept { ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, opt.glassMethod); ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); } template -void load(archive &ar, SlopeCraft::Kernel::build_options &opt) noexcept { +void load(archive &ar, build_options &opt) noexcept { ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, opt.glassMethod); ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); From 0f3de35023314a01ac16d53c0a7db2cd8eb3508c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 21:34:59 +0800 Subject: [PATCH 0777/1123] delete duplicated build_options definition Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 16 ++++++++-------- SlopeCraftL/TokiSlopeCraft_build.cpp | 28 ++++++++++++++-------------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 16 ++++++++-------- SlopeCraftL/color_table.cpp | 24 ++++++++++++------------ SlopeCraftL/height_line.cpp | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 8a906d5b..1dbb9d90 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -215,10 +215,10 @@ struct convert_option { struct build_options { uint64_t caller_api_version{SC_VERSION_U64}; - uint16_t maxAllowedHeight{256}; - uint16_t bridgeInterval{3}; - compressSettings compressMethod{::SCL_compressSettings::noCompress}; - glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; + uint16_t max_allowed_height{256}; + uint16_t bridge_interval{3}; + compressSettings compress_method{::SCL_compressSettings::noCompress}; + glassBridgeSettings glass_method{::SCL_glassBridgeSettings::noBridge}; bool fire_proof{false}; bool enderman_proof{false}; @@ -453,10 +453,10 @@ class Kernel { bool expected_col_major) const = 0; // struct build_options { // uint64_t caller_api_version{SC_VERSION_U64}; - // uint16_t maxAllowedHeight{256}; - // uint16_t bridgeInterval{3}; - // compressSettings compressMethod{::SCL_compressSettings::noCompress}; - // glassBridgeSettings glassMethod{::SCL_glassBridgeSettings::noBridge}; + // uint16_t max_allowed_height{256}; + // uint16_t bridge_interval{3}; + // compressSettings compress_method{::SCL_compressSettings::noCompress}; + // glassBridgeSettings glass_method{::SCL_glassBridgeSettings::noBridge}; // bool fire_proof{false}; // bool enderman_proof{false}; // diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp index a463fbc4..38f196c4 100644 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ b/SlopeCraftL/TokiSlopeCraft_build.cpp @@ -199,8 +199,8 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { cerr << "hasty!" << endl; return false; } - if (option.maxAllowedHeight < 14) { - cerr << "maxAllowedHeight is less than 14!" << endl; + if (option.max_allowed_height < 14) { + cerr << "max_allowed_height is less than 14!" << endl; reportError(wind, errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, "Your maximum allowed height is less than 14, which made lossy " "compressing almost impossible."); @@ -218,11 +218,11 @@ bool TokiSlopeCraft::build(const build_options &option) noexcept { // cerr << "ready to build" << endl; - this->build_opt.compressMethod = option.compressMethod; - this->build_opt.glassMethod = option.glassMethod; + this->build_opt.compress_method = option.compress_method; + this->build_opt.glass_method = option.glass_method; if (isFlat() || !isVanilla()) { - this->build_opt.compressMethod = compressSettings::noCompress; - this->build_opt.glassMethod = glassBridgeSettings::noBridge; + this->build_opt.compress_method = compressSettings::noCompress; + this->build_opt.glass_method = glassBridgeSettings::noBridge; } this->build_opt = option; @@ -273,8 +273,8 @@ void TokiSlopeCraft::makeHeight_new( LowMap.setZero(sizePic(0) + 1, sizePic(1)); WaterList.clear(); bool allowNaturalCompress = - this->build_opt.compressMethod == compressSettings::Both || - this->build_opt.compressMethod == compressSettings::NaturalOnly; + this->build_opt.compress_method == compressSettings::Both || + this->build_opt.compress_method == compressSettings::NaturalOnly; // std::vector src; // cerr << "makeHeight_new\n"; @@ -301,16 +301,16 @@ void TokiSlopeCraft::makeHeight_new( // getTokiColorPtr(c,&src[0]); HL.make(this->mapPic.col(c), allowNaturalCompress); - if (HL.maxHeight() > this->build_opt.maxAllowedHeight && - (this->build_opt.compressMethod == compressSettings::ForcedOnly || - this->build_opt.compressMethod == compressSettings::Both)) { + if (HL.maxHeight() > this->build_opt.max_allowed_height && + (this->build_opt.compress_method == compressSettings::ForcedOnly || + this->build_opt.compress_method == compressSettings::Both)) { std::vector ptr(getImageRows()); this->image_cvter.col_TokiColor_ptrs(c, ptr.data()); // getTokiColorPtr(c, &ptr[0]); Compressor->setSource(HL.getBase(), &ptr[0]); - bool success = Compressor->compress(this->build_opt.maxAllowedHeight, + bool success = Compressor->compress(this->build_opt.max_allowed_height, allowNaturalCompress); if (!success) { std::string msg = "Failed to compress the 3D structure at coloum " + @@ -425,7 +425,7 @@ schem.z_range()}); Build.resize(tempSize3D); void TokiSlopeCraft::makeBridge() { if (this->colorset.map_type != mapTypes::Slope) return; - if (this->build_opt.glassMethod != glassBridgeSettings::withBridge) return; + if (this->build_opt.glass_method != glassBridgeSettings::withBridge) return; int step = sizePic(2) / schem.y_range(); @@ -434,7 +434,7 @@ void TokiSlopeCraft::makeBridge() { for (uint32_t y = 0; y < schem.y_range(); y++) { keepAwake(wind); progressAdd(wind, step); - if (y % (this->build_opt.bridgeInterval + 1) == 0) { + if (y % (this->build_opt.bridge_interval + 1) == 0) { std::array start, extension; // x,z,y start[0] = 0; start[1] = 0; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index b8d04cff..4fa611a7 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -228,15 +228,15 @@ bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, namespace cereal { template void save(archive &ar, const build_options &opt) noexcept { - ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, - opt.glassMethod); + ar(opt.max_allowed_height, opt.bridge_interval, opt.compress_method, + opt.glass_method); ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); } template void load(archive &ar, build_options &opt) noexcept { - ar(opt.maxAllowedHeight, opt.bridgeInterval, opt.compressMethod, - opt.glassMethod); + ar(opt.max_allowed_height, opt.bridge_interval, opt.compress_method, + opt.glass_method); ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); } } // namespace cereal @@ -257,10 +257,10 @@ std::vector TokiSlopeCraft::build_task_hash_of( hash.process_bytes(blkid.data(), blkid.size()); } { - SC_HASH_ADD_DATA(hash, opt.maxAllowedHeight); - SC_HASH_ADD_DATA(hash, opt.bridgeInterval); - SC_HASH_ADD_DATA(hash, opt.compressMethod); - SC_HASH_ADD_DATA(hash, opt.glassMethod); + SC_HASH_ADD_DATA(hash, opt.max_allowed_height); + SC_HASH_ADD_DATA(hash, opt.bridge_interval); + SC_HASH_ADD_DATA(hash, opt.compress_method); + SC_HASH_ADD_DATA(hash, opt.glass_method); SC_HASH_ADD_DATA(hash, opt.fire_proof); SC_HASH_ADD_DATA(hash, opt.enderman_proof); SC_HASH_ADD_DATA(hash, opt.connect_mushrooms); diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 8120a10a..449467b4 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -178,7 +178,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); const bool allow_lossless_compress = - int(option.compressMethod) & int(SCL_compressSettings::NaturalOnly); + int(option.compress_method) & int(SCL_compressSettings::NaturalOnly); if (((map_color - 4 * (map_color / 4)) >= 3).any()) { std::string msg = @@ -208,17 +208,17 @@ converted_image_impl::height_info(const build_options &option) const noexcept { // getTokiColorPtr(c,&src[0]); HL.make(map_color.col(c), allow_lossless_compress); - if (HL.maxHeight() > option.maxAllowedHeight && - (option.compressMethod == compressSettings::ForcedOnly || - option.compressMethod == compressSettings::Both)) { + if (HL.maxHeight() > option.max_allowed_height && + (option.compress_method == compressSettings::ForcedOnly || + option.compress_method == compressSettings::Both)) { std::vector ptr(map_color.rows()); this->converter.col_TokiColor_ptrs(c, ptr.data()); // getTokiColorPtr(c, &ptr[0]); compressor.setSource(HL.getBase(), &ptr[0]); - bool success = - compressor.compress(option.maxAllowedHeight, allow_lossless_compress); + bool success = compressor.compress(option.max_allowed_height, + allow_lossless_compress); if (!success) { option.ui.report_error( SCL_errorFlag::LOSSYCOMPRESS_FAILED, @@ -254,11 +254,11 @@ converted_image_impl::height_info(const build_options &option) const noexcept { std::optional structure_3D_impl::create( const color_table_impl &table, const converted_image_impl &cvted, const build_options &option) noexcept { - if (option.maxAllowedHeight < 14) { + if (option.max_allowed_height < 14) { option.ui.report_error( errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, fmt::format("Max allowed height should be >= 14, but found {}", - option.maxAllowedHeight) + option.max_allowed_height) .c_str()); return std::nullopt; } @@ -274,8 +274,8 @@ std::optional structure_3D_impl::create( build_options fixed_opt = option; if (table.is_flat() || !table.is_vanilla()) { - fixed_opt.compressMethod = compressSettings::noCompress; - fixed_opt.glassMethod = glassBridgeSettings::noBridge; + fixed_opt.compress_method = compressSettings::noCompress; + fixed_opt.glass_method = glassBridgeSettings::noBridge; } option.ui.report_working_status(workStatus::buidingHeighMap); option.main_progressbar.set_range(0, 9 * cvted.size(), 0); @@ -372,7 +372,7 @@ std::optional structure_3D_impl::create( option.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); // build bridges if (table.map_type() == mapTypes::Slope && - fixed_opt.glassMethod == glassBridgeSettings::withBridge) { + fixed_opt.glass_method == glassBridgeSettings::withBridge) { option.ui.report_working_status(workStatus::constructingBridges); option.sub_progressbar.set_range(0, 100, 0); @@ -383,7 +383,7 @@ std::optional structure_3D_impl::create( option.ui.keep_awake(); for (uint32_t y = 0; y < ret.schem.y_range(); y++) { option.sub_progressbar.add(step); - if (y % (fixed_opt.bridgeInterval + 1) == 0) { + if (y % (fixed_opt.bridge_interval + 1) == 0) { std::array start, extension; // x,z,y start[0] = 0; start[1] = 0; diff --git a/SlopeCraftL/height_line.cpp b/SlopeCraftL/height_line.cpp index 5f170555..58c30574 100644 --- a/SlopeCraftL/height_line.cpp +++ b/SlopeCraftL/height_line.cpp @@ -269,7 +269,7 @@ Base.setConstant(sizePic(0)+1,sizePic(1),11); cerr<<"basic sink done"< Date: Wed, 17 Apr 2024 21:49:09 +0800 Subject: [PATCH 0778/1123] split color_table, converted_image and structure_3D Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 10 +- SlopeCraftL/SlopeCraftL.h | 16 ++ SlopeCraftL/color_table.cpp | 284 +------------------------------- SlopeCraftL/color_table.h | 61 +------ SlopeCraftL/converted_image.cpp | 120 ++++++++++++++ SlopeCraftL/converted_image.h | 48 ++++++ SlopeCraftL/structure_3D.cpp | 176 ++++++++++++++++++++ SlopeCraftL/structure_3D.h | 37 +++++ 8 files changed, 406 insertions(+), 346 deletions(-) create mode 100644 SlopeCraftL/converted_image.cpp create mode 100644 SlopeCraftL/converted_image.h create mode 100644 SlopeCraftL/structure_3D.cpp create mode 100644 SlopeCraftL/structure_3D.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index b11a4fca..0adf6e31 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -27,18 +27,19 @@ set(Slope_SCL_internal_headers # AiCvterOpt.h Colors.h height_line.h - optimize_chain.h prim_glass_builder.h SCLDefines.h TokiSlopeCraft.h WaterItem.h lossyCompressor.h - mc_block.h SlopeCraftL_global.h WriteStringDeliver.h Colorset.h + structure_3D.h + color_table.h + converted_image.h ) set(SlopeCraft_SCL_sources @@ -61,11 +62,12 @@ set(SlopeCraft_SCL_sources mc_block.cpp SlopeCraftL.cpp Colorset.cpp + color_table.cpp + structure_3D.cpp + converted_image.cpp #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} - color_table.cpp - color_table.h ) # add this definations to both targets diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 1dbb9d90..36d5c82e 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -233,10 +233,14 @@ struct litematic_options { uint64_t caller_api_version{SC_VERSION_U64}; const char *litename_utf8 = "by SlopeCraft"; const char *region_name_utf8 = "by SlopeCraft"; + ui_callbacks ui; + progress_callbacks progressbar; }; struct vanilla_structure_options { uint64_t caller_api_version{SC_VERSION_U64}; bool is_air_structure_void{true}; + ui_callbacks ui; + progress_callbacks progressbar; }; struct WE_schem_options { uint64_t caller_api_version{SC_VERSION_U64}; @@ -244,6 +248,8 @@ struct WE_schem_options { int we_offset[3] = {0, 0, 0}; const char *const *required_mods_name_utf8{nullptr}; int num_required_mods{0}; + ui_callbacks ui; + progress_callbacks progressbar; }; struct const_image_reference { @@ -281,6 +287,16 @@ class structure_3D { [[nodiscard]] virtual size_t shape_z() const noexcept = 0; [[nodiscard]] virtual size_t palette_length() const noexcept = 0; virtual void get_palette(const char **buffer_block_id) const noexcept = 0; + + // virtual bool export_litematica( + // const char *filename, const litematic_options &option) const noexcept + // = 0; + // virtual bool export_vanilla_structure( + // const char *filename, + // const vanilla_structure_options &option) const noexcept = 0; + // virtual bool export_WE_schem( + // const char *filename, const WE_schem_options &option) const noexcept = + // 0; }; class color_table { diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 449467b4..b1985851 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -2,12 +2,11 @@ // Created by joseph on 4/15/24. // +#include #include "color_table.h" #include "WaterItem.h" #include "height_line.h" -#include "lossyCompressor.h" -#include "prim_glass_builder.h" -#include +#include "structure_3D.h" std::optional color_table_impl::create( const color_table_create_info &args) noexcept { @@ -139,282 +138,3 @@ std::vector color_table_impl::block_id_list() const noexcept { } return dest; } - -converted_image_impl::converted_image_impl(const color_table_impl &table) - : converter{*color_set::basic, table.allowed} {} - -converted_image *color_table_impl::convert_image( - const_image_reference original_img, - const convert_option &option) const noexcept { - converted_image_impl cvted{*this}; - - const auto algo = (option.algo == convertAlgo::gaCvter) - ? convertAlgo::RGB_Better - : option.algo; - cvted.converter.set_raw_image(original_img.data, original_img.rows, - original_img.cols, false); - { - heu::GAOption opt; - opt.crossoverProb = option.ai_cvter_opt.crossoverProb; - opt.mutateProb = option.ai_cvter_opt.mutationProb; - opt.maxGenerations = option.ai_cvter_opt.maxGeneration; - opt.maxFailTimes = option.ai_cvter_opt.maxFailTimes; - opt.populationSize = option.ai_cvter_opt.popSize; - - cvted.converter.convert_image(algo, option.dither, &opt); - } - - option.progress.set_range(0, 4 * cvted.size(), 4 * cvted.size()); - option.ui.report_working_status(workStatus::none); - - return new converted_image_impl{std::move(cvted)}; -} - -std::optional -converted_image_impl::height_info(const build_options &option) const noexcept { - // - // std::unordered_map water_list; - - Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); - - const bool allow_lossless_compress = - int(option.compress_method) & int(SCL_compressSettings::NaturalOnly); - - if (((map_color - 4 * (map_color / 4)) >= 3).any()) { - std::string msg = - "Fatal error : SlopeCraftL found map color with depth 3 in a " - "vanilla map.\n Map contents (map color matrix in col-major) :\n["; - for (int c = 0; c < map_color.cols(); c++) { - for (int r = 0; r < map_color.rows(); r++) { - fmt::format_to(std::back_insert_iterator{msg}, "{},", map_color(r, c)); - } - msg += ";\n"; - } - msg += "];\n"; - option.ui.report_error(errorFlag::DEPTH_3_IN_VANILLA_MAP, msg.c_str()); - return std::nullopt; - } - - Eigen::ArrayXXi base, high_map, low_map; - base.setZero(this->rows(), this->cols()); - high_map.setZero(this->rows(), this->cols()); - low_map.setZero(this->rows(), this->cols()); - std::unordered_map water_list; - - lossy_compressor compressor; - for (int64_t c = 0; c < map_color.cols(); c++) { - // cerr << "Coloumn " << c << '\n'; - height_line HL; - // getTokiColorPtr(c,&src[0]); - HL.make(map_color.col(c), allow_lossless_compress); - - if (HL.maxHeight() > option.max_allowed_height && - (option.compress_method == compressSettings::ForcedOnly || - option.compress_method == compressSettings::Both)) { - std::vector ptr(map_color.rows()); - - this->converter.col_TokiColor_ptrs(c, ptr.data()); - // getTokiColorPtr(c, &ptr[0]); - - compressor.setSource(HL.getBase(), &ptr[0]); - bool success = compressor.compress(option.max_allowed_height, - allow_lossless_compress); - if (!success) { - option.ui.report_error( - SCL_errorFlag::LOSSYCOMPRESS_FAILED, - fmt::format("Failed to compress the 3D structure at column {}.", c) - .data()); - return std::nullopt; - } - Eigen::ArrayXi temp; - HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); - map_color.col(c) = temp; - } - base.col(c) = HL.getBase(); - high_map.col(c) = HL.getHighLine(); - low_map.col(c) = HL.getLowLine(); - - auto hl_water_list = HL.getWaterMap(); - water_list.reserve(water_list.size() + hl_water_list.size()); - for (const auto &[r, water_item] : hl_water_list) { - water_list.emplace( - rc_pos{static_cast(r), static_cast(c)}, water_item); - } - - option.main_progressbar.add(4 * this->size()); - } - - return height_maps{.map_color = map_color, - .base = base, - .high_map = high_map, - .low_map = low_map, - .water_list = water_list}; -} - -std::optional structure_3D_impl::create( - const color_table_impl &table, const converted_image_impl &cvted, - const build_options &option) noexcept { - if (option.max_allowed_height < 14) { - option.ui.report_error( - errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, - fmt::format("Max allowed height should be >= 14, but found {}", - option.max_allowed_height) - .c_str()); - return std::nullopt; - } - structure_3D_impl ret; - // set up basic infos - { - ret.schem.set_MC_major_version_number(table.mc_version_); - ret.schem.set_MC_version_number( - MCDataVersion::suggested_version(table.mc_version_)); - auto id = table.block_id_list(); - ret.schem.set_block_id(id); - } - - build_options fixed_opt = option; - if (table.is_flat() || !table.is_vanilla()) { - fixed_opt.compress_method = compressSettings::noCompress; - fixed_opt.glass_method = glassBridgeSettings::noBridge; - } - option.ui.report_working_status(workStatus::buidingHeighMap); - option.main_progressbar.set_range(0, 9 * cvted.size(), 0); - { - std::unordered_map water_list; - option.main_progressbar.add(cvted.size()); - } - - Eigen::ArrayXi map_color, base_color, high_map, low_map; - std::unordered_map water_list; - { - auto opt = cvted.height_info(fixed_opt); - if (!opt) { - return std::nullopt; - } - map_color = std::move(opt.value().map_color); - base_color = std::move(opt.value().base); - high_map = std::move(opt.value().high_map); - low_map = std::move(opt.value().low_map); - water_list = std::move(opt.value().water_list); - } - - ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, 2 + cvted.rows()); - ret.schem.set_zero(); - // make 3D - { - // base_color(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) - // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 - // 对应空气 - - for (auto it = water_list.begin(); it != water_list.end(); - it++) // 水柱周围的玻璃 - { - const int x = it->first.col + 1; - const int z = it->first.row; - const int y = it->second.high_y; - const int yLow = it->second.low_y; - ret.schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 - for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { - ret.schem(x - 1, yDynamic, z - 0) = 1; - ret.schem(x + 1, yDynamic, z + 0) = 1; - ret.schem(x + 0, yDynamic, z - 1) = 1; - ret.schem(x + 0, yDynamic, z + 1) = 1; - } - if (yLow >= 1) ret.schem(x, yLow - 1, z) = 1; // 柱底玻璃 - } - - option.main_progressbar.add(cvted.size()); - - for (uint32_t r = -1; r < cvted.rows(); r++) // 普通方块 - { - for (uint32_t c = 0; c < cvted.cols(); c++) { - if (base_color(r + 1, c) == 12 || base_color(r + 1, c) == 0) continue; - const int x = c + 1; - const int y = low_map(r + 1, c); - const int z = r + 1; - if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) - ret.schem(x, y - 1, z) = 0 + 1; - if ((option.fire_proof && - table.blocks[base_color(r + 1, c)].burnable) || - (option.enderman_proof && - table.blocks[base_color(r + 1, c)].endermanPickable)) { - if (y >= 1 && ret.schem(x, y - 1, z) == 0) - ret.schem(x, y - 1, z) = 0 + 1; - if (x >= 1 && ret.schem(x - 1, y, z) == 0) - ret.schem(x - 1, y, z) = 0 + 1; - if (z >= 1 && ret.schem(x, y, z - 1) == 0) - ret.schem(x, y, z - 1) = 0 + 1; - if (y + 1 < ret.schem.y_range() && ret.schem(x, y + 1, z) == 0) - ret.schem(x, y + 1, z) = 0 + 1; - if (x + 1 < ret.schem.x_range() && ret.schem(x + 1, y, z) == 0) - ret.schem(x + 1, y, z) = 0 + 1; - if (z + 1 < ret.schem.z_range() && ret.schem(x, y, z + 1) == 0) - ret.schem(x, y, z + 1) = 0 + 1; - } - - ret.schem(x, y, z) = base_color(r + 1, c) + 1; - } - option.main_progressbar.add(cvted.cols()); - } - - option.main_progressbar.add(cvted.size()); - - for (auto it = water_list.cbegin(); it != water_list.cend(); ++it) { - const int x = it->first.col + 1; - const int z = it->first.row; - const int y = it->second.high_y; - const int yLow = it->second.low_y; - for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { - ret.schem(x, yDynamic, z) = 13; - } - } - } - option.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); - // build bridges - if (table.map_type() == mapTypes::Slope && - fixed_opt.glass_method == glassBridgeSettings::withBridge) { - option.ui.report_working_status(workStatus::constructingBridges); - - option.sub_progressbar.set_range(0, 100, 0); - const int step = cvted.size() / ret.schem.y_range(); - -#warning "todo: Use prograss_callback in prim_glass_builder" - prim_glass_builder glass_builder; - option.ui.keep_awake(); - for (uint32_t y = 0; y < ret.schem.y_range(); y++) { - option.sub_progressbar.add(step); - if (y % (fixed_opt.bridge_interval + 1) == 0) { - std::array start, extension; // x,z,y - start[0] = 0; - start[1] = 0; - start[2] = y; - extension[0] = ret.schem.x_range(); - extension[1] = ret.schem.z_range(); - extension[2] = 1; - TokiMap targetMap = - ySlice2TokiMap_u16(ret.schem.tensor(), start, extension); - glassMap glass; - // cerr << "Construct glass bridge at y=" << y << endl; - glass = glass_builder.makeBridge(targetMap); - for (int r = 0; r < glass.rows(); r++) - for (int c = 0; c < glass.cols(); c++) - if (ret.schem(r, y, c) == prim_glass_builder::air && - glass(r, c) == prim_glass_builder::glass) - ret.schem(r, y, c) = prim_glass_builder::glass; - } else { - continue; - } - } - option.ui.keep_awake(); - option.sub_progressbar.set_range(0, 100, 100); - } - - if (fixed_opt.connect_mushrooms) { - ret.schem.process_mushroom_states(); - } - option.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); - option.ui.report_working_status(workStatus::none); - - ret.map_color = std::move(map_color); - return ret; -} \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index a118e9f5..5cca9aec 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -6,12 +6,10 @@ #define SLOPECRAFT_COLOR_TABLE_H #include -#include #include "SlopeCraftL.h" #include "Colorset.h" #include "mc_block.h" -#include "Schem/Schem.h" -#include "WaterItem.h" +#include "converted_image.h" class color_table_impl : public SlopeCraft::color_table { public: @@ -56,61 +54,4 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] std::vector block_id_list() const noexcept; }; -class converted_image_impl : public converted_image { - public: - converted_image_impl(converted_image_impl &&) = default; - explicit converted_image_impl(const color_table_impl &table); - using eimg_row_major = - Eigen::Array; - libMapImageCvt::MapImageCvter converter; - - size_t rows() const noexcept final { return this->converter.rows(); } - size_t cols() const noexcept final { return this->converter.cols(); } - - void get_original_image(uint32_t *buffer) const noexcept final { - Eigen::Map buf{buffer, static_cast(this->rows()), - static_cast(this->cols())}; - buf = this->converter.raw_image(); - } - // void get_dithered_image(uint32_t *buffer) const noexcept final {} - void get_converted_image(uint32_t *buffer) const noexcept final { - this->converter.converted_image(buffer, nullptr, nullptr, false); - } - - struct height_maps { - Eigen::ArrayXXi map_color; - Eigen::ArrayXXi base; - Eigen::ArrayXXi high_map; - Eigen::ArrayXXi low_map; - std::unordered_map water_list; - }; - std::optional height_info( - const build_options &option) const noexcept; -}; - -class structure_3D_impl : public structure_3D { - private: - libSchem::Schem schem; - - Eigen::ArrayXXi map_color; // map color may be modified by lossy - // compression,so we store the modified one - - public: - size_t shape_x() const noexcept final { return this->schem.x_range(); } - size_t shape_y() const noexcept final { return this->schem.y_range(); } - size_t shape_z() const noexcept final { return this->schem.z_range(); } - size_t palette_length() const noexcept final { - return this->schem.palette_size(); - } - void get_palette(const char **buffer_block_id) const noexcept final { - for (size_t i = 0; i < this->palette_length(); i++) { - buffer_block_id[i] = this->schem.palette()[i].c_str(); - } - } - - static std::optional create( - const color_table_impl &, const converted_image_impl &cvted, - const build_options &option) noexcept; -}; - #endif // SLOPECRAFT_COLOR_TABLE_H diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp new file mode 100644 index 00000000..77778dca --- /dev/null +++ b/SlopeCraftL/converted_image.cpp @@ -0,0 +1,120 @@ +// +// Created by joseph on 4/17/24. +// + +#include +#include "converted_image.h" +#include "color_table.h" +#include "height_line.h" +#include "lossyCompressor.h" + +converted_image_impl::converted_image_impl(const color_table_impl &table) + : converter{*color_set::basic, table.allowed} {} + +converted_image *color_table_impl::convert_image( + const_image_reference original_img, + const convert_option &option) const noexcept { + converted_image_impl cvted{*this}; + + const auto algo = (option.algo == convertAlgo::gaCvter) + ? convertAlgo::RGB_Better + : option.algo; + cvted.converter.set_raw_image(original_img.data, original_img.rows, + original_img.cols, false); + { + heu::GAOption opt; + opt.crossoverProb = option.ai_cvter_opt.crossoverProb; + opt.mutateProb = option.ai_cvter_opt.mutationProb; + opt.maxGenerations = option.ai_cvter_opt.maxGeneration; + opt.maxFailTimes = option.ai_cvter_opt.maxFailTimes; + opt.populationSize = option.ai_cvter_opt.popSize; + + cvted.converter.convert_image(algo, option.dither, &opt); + } + + option.progress.set_range(0, 4 * cvted.size(), 4 * cvted.size()); + option.ui.report_working_status(workStatus::none); + + return new converted_image_impl{std::move(cvted)}; +} + +std::optional +converted_image_impl::height_info(const build_options &option) const noexcept { + // + // std::unordered_map water_list; + + Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); + + const bool allow_lossless_compress = + int(option.compress_method) & int(SCL_compressSettings::NaturalOnly); + + if (((map_color - 4 * (map_color / 4)) >= 3).any()) { + std::string msg = + "Fatal error : SlopeCraftL found map color with depth 3 in a " + "vanilla map.\n Map contents (map color matrix in col-major) :\n["; + for (int c = 0; c < map_color.cols(); c++) { + for (int r = 0; r < map_color.rows(); r++) { + fmt::format_to(std::back_insert_iterator{msg}, "{},", map_color(r, c)); + } + msg += ";\n"; + } + msg += "];\n"; + option.ui.report_error(errorFlag::DEPTH_3_IN_VANILLA_MAP, msg.c_str()); + return std::nullopt; + } + + Eigen::ArrayXXi base, high_map, low_map; + base.setZero(this->rows(), this->cols()); + high_map.setZero(this->rows(), this->cols()); + low_map.setZero(this->rows(), this->cols()); + std::unordered_map water_list; + + lossy_compressor compressor; + for (int64_t c = 0; c < map_color.cols(); c++) { + // cerr << "Coloumn " << c << '\n'; + height_line HL; + // getTokiColorPtr(c,&src[0]); + HL.make(map_color.col(c), allow_lossless_compress); + + if (HL.maxHeight() > option.max_allowed_height && + (option.compress_method == compressSettings::ForcedOnly || + option.compress_method == compressSettings::Both)) { + std::vector ptr(map_color.rows()); + + this->converter.col_TokiColor_ptrs(c, ptr.data()); + // getTokiColorPtr(c, &ptr[0]); + + compressor.setSource(HL.getBase(), &ptr[0]); + bool success = compressor.compress(option.max_allowed_height, + allow_lossless_compress); + if (!success) { + option.ui.report_error( + SCL_errorFlag::LOSSYCOMPRESS_FAILED, + fmt::format("Failed to compress the 3D structure at column {}.", c) + .data()); + return std::nullopt; + } + Eigen::ArrayXi temp; + HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); + map_color.col(c) = temp; + } + base.col(c) = HL.getBase(); + high_map.col(c) = HL.getHighLine(); + low_map.col(c) = HL.getLowLine(); + + auto hl_water_list = HL.getWaterMap(); + water_list.reserve(water_list.size() + hl_water_list.size()); + for (const auto &[r, water_item] : hl_water_list) { + water_list.emplace( + rc_pos{static_cast(r), static_cast(c)}, water_item); + } + + option.main_progressbar.add(4 * this->size()); + } + + return height_maps{.map_color = map_color, + .base = base, + .high_map = high_map, + .low_map = low_map, + .water_list = water_list}; +} \ No newline at end of file diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h new file mode 100644 index 00000000..1f77a669 --- /dev/null +++ b/SlopeCraftL/converted_image.h @@ -0,0 +1,48 @@ +// +// Created by joseph on 4/17/24. +// + +#ifndef SLOPECRAFT_CONVERTED_IMAGE_H +#define SLOPECRAFT_CONVERTED_IMAGE_H +#include "SlopeCraftL.h" +#include "Colorset.h" +#include "mc_block.h" +#include "Schem/Schem.h" +#include "WaterItem.h" +#include +#include + +class color_table_impl; + +class converted_image_impl : public converted_image { + public: + converted_image_impl(converted_image_impl &&) = default; + explicit converted_image_impl(const color_table_impl &table); + using eimg_row_major = + Eigen::Array; + libMapImageCvt::MapImageCvter converter; + + size_t rows() const noexcept final { return this->converter.rows(); } + size_t cols() const noexcept final { return this->converter.cols(); } + + void get_original_image(uint32_t *buffer) const noexcept final { + Eigen::Map buf{buffer, static_cast(this->rows()), + static_cast(this->cols())}; + buf = this->converter.raw_image(); + } + // void get_dithered_image(uint32_t *buffer) const noexcept final {} + void get_converted_image(uint32_t *buffer) const noexcept final { + this->converter.converted_image(buffer, nullptr, nullptr, false); + } + + struct height_maps { + Eigen::ArrayXXi map_color; + Eigen::ArrayXXi base; + Eigen::ArrayXXi high_map; + Eigen::ArrayXXi low_map; + std::unordered_map water_list; + }; + std::optional height_info( + const build_options &option) const noexcept; +}; +#endif // SLOPECRAFT_CONVERTED_IMAGE_H diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp new file mode 100644 index 00000000..97adb86b --- /dev/null +++ b/SlopeCraftL/structure_3D.cpp @@ -0,0 +1,176 @@ +// +// Created by joseph on 4/17/24. +// +#include +#include "structure_3D.h" +#include "color_table.h" +#include "lossyCompressor.h" +#include "prim_glass_builder.h" + +std::optional structure_3D_impl::create( + const color_table_impl &table, const converted_image_impl &cvted, + const build_options &option) noexcept { + if (option.max_allowed_height < 14) { + option.ui.report_error( + errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, + fmt::format("Max allowed height should be >= 14, but found {}", + option.max_allowed_height) + .c_str()); + return std::nullopt; + } + structure_3D_impl ret; + // set up basic infos + { + ret.schem.set_MC_major_version_number(table.mc_version_); + ret.schem.set_MC_version_number( + MCDataVersion::suggested_version(table.mc_version_)); + auto id = table.block_id_list(); + ret.schem.set_block_id(id); + } + + build_options fixed_opt = option; + if (table.is_flat() || !table.is_vanilla()) { + fixed_opt.compress_method = compressSettings::noCompress; + fixed_opt.glass_method = glassBridgeSettings::noBridge; + } + option.ui.report_working_status(workStatus::buidingHeighMap); + option.main_progressbar.set_range(0, 9 * cvted.size(), 0); + { + std::unordered_map water_list; + option.main_progressbar.add(cvted.size()); + } + + Eigen::ArrayXi map_color, base_color, high_map, low_map; + std::unordered_map water_list; + { + auto opt = cvted.height_info(fixed_opt); + if (!opt) { + return std::nullopt; + } + map_color = std::move(opt.value().map_color); + base_color = std::move(opt.value().base); + high_map = std::move(opt.value().high_map); + low_map = std::move(opt.value().low_map); + water_list = std::move(opt.value().water_list); + } + + ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, 2 + cvted.rows()); + ret.schem.set_zero(); + // make 3D + { + // base_color(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) + // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 + // 对应空气 + + for (auto it = water_list.begin(); it != water_list.end(); + it++) // 水柱周围的玻璃 + { + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; + ret.schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { + ret.schem(x - 1, yDynamic, z - 0) = 1; + ret.schem(x + 1, yDynamic, z + 0) = 1; + ret.schem(x + 0, yDynamic, z - 1) = 1; + ret.schem(x + 0, yDynamic, z + 1) = 1; + } + if (yLow >= 1) ret.schem(x, yLow - 1, z) = 1; // 柱底玻璃 + } + + option.main_progressbar.add(cvted.size()); + + for (uint32_t r = -1; r < cvted.rows(); r++) // 普通方块 + { + for (uint32_t c = 0; c < cvted.cols(); c++) { + if (base_color(r + 1, c) == 12 || base_color(r + 1, c) == 0) continue; + const int x = c + 1; + const int y = low_map(r + 1, c); + const int z = r + 1; + if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) + ret.schem(x, y - 1, z) = 0 + 1; + if ((option.fire_proof && + table.blocks[base_color(r + 1, c)].burnable) || + (option.enderman_proof && + table.blocks[base_color(r + 1, c)].endermanPickable)) { + if (y >= 1 && ret.schem(x, y - 1, z) == 0) + ret.schem(x, y - 1, z) = 0 + 1; + if (x >= 1 && ret.schem(x - 1, y, z) == 0) + ret.schem(x - 1, y, z) = 0 + 1; + if (z >= 1 && ret.schem(x, y, z - 1) == 0) + ret.schem(x, y, z - 1) = 0 + 1; + if (y + 1 < ret.schem.y_range() && ret.schem(x, y + 1, z) == 0) + ret.schem(x, y + 1, z) = 0 + 1; + if (x + 1 < ret.schem.x_range() && ret.schem(x + 1, y, z) == 0) + ret.schem(x + 1, y, z) = 0 + 1; + if (z + 1 < ret.schem.z_range() && ret.schem(x, y, z + 1) == 0) + ret.schem(x, y, z + 1) = 0 + 1; + } + + ret.schem(x, y, z) = base_color(r + 1, c) + 1; + } + option.main_progressbar.add(cvted.cols()); + } + + option.main_progressbar.add(cvted.size()); + + for (auto it = water_list.cbegin(); it != water_list.cend(); ++it) { + const int x = it->first.col + 1; + const int z = it->first.row; + const int y = it->second.high_y; + const int yLow = it->second.low_y; + for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { + ret.schem(x, yDynamic, z) = 13; + } + } + } + option.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); + // build bridges + if (table.map_type() == mapTypes::Slope && + fixed_opt.glass_method == glassBridgeSettings::withBridge) { + option.ui.report_working_status(workStatus::constructingBridges); + + option.sub_progressbar.set_range(0, 100, 0); + const int step = cvted.size() / ret.schem.y_range(); + +#warning "todo: Use prograss_callback in prim_glass_builder" + prim_glass_builder glass_builder; + option.ui.keep_awake(); + for (uint32_t y = 0; y < ret.schem.y_range(); y++) { + option.sub_progressbar.add(step); + if (y % (fixed_opt.bridge_interval + 1) == 0) { + std::array start, extension; // x,z,y + start[0] = 0; + start[1] = 0; + start[2] = y; + extension[0] = ret.schem.x_range(); + extension[1] = ret.schem.z_range(); + extension[2] = 1; + TokiMap targetMap = + ySlice2TokiMap_u16(ret.schem.tensor(), start, extension); + glassMap glass; + // cerr << "Construct glass bridge at y=" << y << endl; + glass = glass_builder.makeBridge(targetMap); + for (int r = 0; r < glass.rows(); r++) + for (int c = 0; c < glass.cols(); c++) + if (ret.schem(r, y, c) == prim_glass_builder::air && + glass(r, c) == prim_glass_builder::glass) + ret.schem(r, y, c) = prim_glass_builder::glass; + } else { + continue; + } + } + option.ui.keep_awake(); + option.sub_progressbar.set_range(0, 100, 100); + } + + if (fixed_opt.connect_mushrooms) { + ret.schem.process_mushroom_states(); + } + option.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); + option.ui.report_working_status(workStatus::none); + + ret.map_color = std::move(map_color); + return ret; +} \ No newline at end of file diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h new file mode 100644 index 00000000..1d13bc94 --- /dev/null +++ b/SlopeCraftL/structure_3D.h @@ -0,0 +1,37 @@ +// +// Created by joseph on 4/17/24. +// + +#ifndef SLOPECRAFT_STRUCTURE_3D_H +#define SLOPECRAFT_STRUCTURE_3D_H + +#include "converted_image.h" +#include "Schem/Schem.h" +#include "WaterItem.h" + +class structure_3D_impl : public structure_3D { + private: + libSchem::Schem schem; + + Eigen::ArrayXXi map_color; // map color may be modified by lossy + // compression,so we store the modified one + + public: + size_t shape_x() const noexcept final { return this->schem.x_range(); } + size_t shape_y() const noexcept final { return this->schem.y_range(); } + size_t shape_z() const noexcept final { return this->schem.z_range(); } + size_t palette_length() const noexcept final { + return this->schem.palette_size(); + } + void get_palette(const char **buffer_block_id) const noexcept final { + for (size_t i = 0; i < this->palette_length(); i++) { + buffer_block_id[i] = this->schem.palette()[i].c_str(); + } + } + + static std::optional create( + const color_table_impl &, const converted_image_impl &cvted, + const build_options &option) noexcept; +}; + +#endif // SLOPECRAFT_STRUCTURE_3D_H From 7367949d7066368ff3555cbcda8c56f5edd61de4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 22:10:52 +0800 Subject: [PATCH 0779/1123] implement exporting 3D Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 16 ++++---- SlopeCraftL/structure_3D.cpp | 79 ++++++++++++++++++++++++++++++++++++ SlopeCraftL/structure_3D.h | 9 ++++ 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 36d5c82e..c4a8dc4a 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -288,15 +288,13 @@ class structure_3D { [[nodiscard]] virtual size_t palette_length() const noexcept = 0; virtual void get_palette(const char **buffer_block_id) const noexcept = 0; - // virtual bool export_litematica( - // const char *filename, const litematic_options &option) const noexcept - // = 0; - // virtual bool export_vanilla_structure( - // const char *filename, - // const vanilla_structure_options &option) const noexcept = 0; - // virtual bool export_WE_schem( - // const char *filename, const WE_schem_options &option) const noexcept = - // 0; + virtual bool export_litematica( + const char *filename, const litematic_options &option) const noexcept = 0; + virtual bool export_vanilla_structure( + const char *filename, + const vanilla_structure_options &option) const noexcept = 0; + virtual bool export_WE_schem( + const char *filename, const WE_schem_options &option) const noexcept = 0; }; class color_table { diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 97adb86b..2c5d1060 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -173,4 +173,83 @@ std::optional structure_3D_impl::create( ret.map_color = std::move(map_color); return ret; +} + +bool structure_3D_impl::export_litematica( + const char *filename, + const SlopeCraft::litematic_options &option) const noexcept { + option.ui.report_working_status(workStatus::writingMetaInfo); + option.progressbar.set_range(0, 100 + this->schem.size(), 0); + libSchem::litematic_info info{}; + info.litename_utf8 = option.litename_utf8; + info.regionname_utf8 = option.region_name_utf8; + + { + errorFlag flag = errorFlag::NO_ERROR_OCCUR; + std::string error_string; + const bool ok = + this->schem.export_litematic(filename, info, &flag, &error_string); + + if (!ok) { + option.ui.report_error(flag, error_string.c_str()); + return false; + } + } + option.ui.report_working_status(workStatus::none); + option.progressbar.set_range(0, 100, 100); + return true; +} + +bool structure_3D_impl::export_vanilla_structure( + const char *filename, + const SlopeCraft::vanilla_structure_options &option) const noexcept { + option.ui.report_working_status(workStatus::writingMetaInfo); + option.progressbar.set_range(0, 100 + schem.size(), 0); + + errorFlag flag = errorFlag::NO_ERROR_OCCUR; + std::string error_string; + const bool success = schem.export_structure( + filename, option.is_air_structure_void, &flag, &error_string); + + if (!success) { + option.ui.report_error(flag, error_string.c_str()); + return false; + } + + option.progressbar.set_range(0, 100, 100); + option.ui.report_working_status(workStatus::none); + return true; +} + +bool structure_3D_impl::export_WE_schem( + const char *filename, + const SlopeCraft::WE_schem_options &option) const noexcept { + option.progressbar.set_range(0, 100, 0); + + libSchem::WorldEditSchem_info info; + + info.schem_name_utf8 = "GeneratedBySlopeCraftL"; + memcpy(info.offset.data(), option.offset, sizeof(info.offset)); + memcpy(info.WE_offset.data(), option.we_offset, sizeof(info.WE_offset)); + + info.required_mods_utf8.resize(option.num_required_mods); + + for (int idx = 0; idx < option.num_required_mods; idx++) { + info.required_mods_utf8[idx] = option.required_mods_name_utf8[idx]; + } + + option.progressbar.set_range(0, 100, 5); + + errorFlag flag = errorFlag::NO_ERROR_OCCUR; + std::string error_string; + const bool success = + schem.export_WESchem(filename, info, &flag, &error_string); + + if (!success) { + option.ui.report_error(flag, error_string.c_str()); + return false; + } + + option.progressbar.set_range(0, 100, 100); + return true; } \ No newline at end of file diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 1d13bc94..f0497689 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -5,6 +5,7 @@ #ifndef SLOPECRAFT_STRUCTURE_3D_H #define SLOPECRAFT_STRUCTURE_3D_H +#include "SlopeCraftL.h" #include "converted_image.h" #include "Schem/Schem.h" #include "WaterItem.h" @@ -32,6 +33,14 @@ class structure_3D_impl : public structure_3D { static std::optional create( const color_table_impl &, const converted_image_impl &cvted, const build_options &option) noexcept; + + bool export_litematica(const char *filename, + const litematic_options &option) const noexcept final; + bool export_vanilla_structure( + const char *filename, + const vanilla_structure_options &option) const noexcept final; + bool export_WE_schem(const char *filename, + const WE_schem_options &option) const noexcept final; }; #endif // SLOPECRAFT_STRUCTURE_3D_H From 7d9b57e9d2875369d49d25ab4873bda0f80eb83e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 17 Apr 2024 22:26:44 +0800 Subject: [PATCH 0780/1123] add deleter for smart pointers Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.cpp | 4 ++++ SlopeCraftL/SlopeCraftL.h | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 3bb42741..a44fc188 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -391,6 +391,10 @@ SCL_EXPORT color_table *SCL_create_color_table( return nullptr; } +SCL_EXPORT void SCL_destroy_color_table(color_table *c) { delete c; } + +SCL_EXPORT void SCL_destroy_converted_image(converted_image *c) { delete c; } +SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *s) { delete s; } // SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, // size_t capacity) { // return TokiSlopeCraft::getBlockPalette(blkpp, capacity); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index c4a8dc4a..8daf02c7 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -559,6 +559,9 @@ struct color_table_create_info { const color_table_create_info &); SCL_EXPORT void SCL_destroy_color_table(color_table *); +SCL_EXPORT void SCL_destroy_converted_image(converted_image *); +SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *); + [[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); @@ -616,6 +619,22 @@ SCL_EXPORT uint8_t SCL_maxBaseColor(); // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); +class deleter { + public: + void operator()(Kernel *k) const noexcept { SCL_destroyKernel(k); } + void operator()(AbstractBlock *b) const noexcept { SCL_destroyBlock(b); } + void operator()(block_list_interface *b) const noexcept { + SCL_destroyBlockList(b); + } + void operator()(color_table *c) const noexcept { SCL_destroy_color_table(c); } + void operator()(converted_image *c) const noexcept { + SCL_destroy_converted_image(c); + } + void operator()(structure_3D *s) const noexcept { + SCL_destroy_structure_3D(s); + } +}; + } // namespace SlopeCraft } // extern "C" From 8454fbeb445e0142f22ff043de53d6be97a0ab75 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 12:15:08 +0800 Subject: [PATCH 0781/1123] reimplement convert cache loading Signed-off-by: ToKiNoBug --- SlopeCraftL/SCLDefines.h | 4 +- SlopeCraftL/SlopeCraftL.h | 15 ++++- SlopeCraftL/TokiSlopeCraft_cache.cpp | 2 - SlopeCraftL/color_table.cpp | 79 ++++++++++++++++++++++- SlopeCraftL/color_table.h | 57 ++++++++++++++++ SlopeCraftL/converted_image.cpp | 46 +++++++++++++ SlopeCraftL/converted_image.h | 12 ++++ utilities/MapImageCvter/MapImageCvter.cpp | 10 +++ utilities/MapImageCvter/MapImageCvter.h | 4 +- 9 files changed, 223 insertions(+), 6 deletions(-) diff --git a/SlopeCraftL/SCLDefines.h b/SlopeCraftL/SCLDefines.h index 59fcf58e..6def73dc 100644 --- a/SlopeCraftL/SCLDefines.h +++ b/SlopeCraftL/SCLDefines.h @@ -49,10 +49,12 @@ extern const float RGBBasicSource[256 * 3]; } +#define SC_HASH_ADD_DATA(hasher, obj) hasher.process_bytes(&obj, sizeof(obj)); + using ARGB = uint32_t; using EImage = Eigen::Array; using MapList = Eigen::Array; using ColorList = Eigen::Array; using TempVectorXf = Eigen::Array; -#endif // SCLDEFINES_H +#endif // SCLDEFINES_H diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 8daf02c7..82da05be 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -224,7 +224,7 @@ struct build_options { // added in v5.1.0 bool connect_mushrooms{false}; - + // added in v5.3 ui_callbacks ui; progress_callbacks main_progressbar; progress_callbacks sub_progressbar; @@ -320,6 +320,19 @@ class color_table { const_image_reference original_img, const convert_option &option) const noexcept = 0; + [[nodiscard]] virtual bool has_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_dir) const noexcept = 0; + + [[nodiscard]] virtual bool save_convert_cache( + const_image_reference original_img, const convert_option &option, + const converted_image &, const char *cache_dir, + StringDeliver *error) const noexcept = 0; + + [[nodiscard]] virtual converted_image *load_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_dir, StringDeliver *error) const noexcept = 0; + [[nodiscard]] virtual structure_3D *build( const converted_image &, const build_options &) const noexcept = 0; }; diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp index 4fa611a7..96ba693e 100644 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ b/SlopeCraftL/TokiSlopeCraft_cache.cpp @@ -90,8 +90,6 @@ const char *TokiSlopeCraft::cacheDir() const noexcept { const std::string_view hash_suffix{".sha3_512"}; -#define SC_HASH_ADD_DATA(hasher, obj) hasher.process_bytes(&obj, sizeof(obj)); - uint64_t to_short_hash(std::span full_hash) noexcept { assert(full_hash.size() >= 8); return *reinterpret_cast(full_hash.data()); diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index b1985851..94fb6fe6 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -3,9 +3,10 @@ // #include +#include +#include "SCLDefines.h" #include "color_table.h" #include "WaterItem.h" -#include "height_line.h" #include "structure_3D.h" std::optional color_table_impl::create( @@ -138,3 +139,79 @@ std::vector color_table_impl::block_id_list() const noexcept { } return dest; } + +// std::string digest_to_string(std::span hash) noexcept { +// std::string ret; +// ret.reserve(hash.size_bytes() * 2); +// for (uint64_t i : hash) { +// fmt::format_to(std::back_insert_iterator(ret), "{:x}", i); +// } +// return ret; +// } + +uint64_t color_table_impl::hash() const noexcept { + boost::uuids::detail::md5 hash; + SC_HASH_ADD_DATA(hash, this->map_type_) + SC_HASH_ADD_DATA(hash, this->mc_version_) + + this->allowed.hash_add_data(hash); + decltype(hash)::digest_type digest; + hash.get_digest(digest); + std::array result; + memcpy(result.data(), digest, sizeof digest); + static_assert(sizeof(digest) == sizeof(result)); + return result[0] ^ result[1]; +} + +std::filesystem::path color_table_impl::self_cache_dir( + const char *cache_root_dir) const noexcept { + return fmt::format("{}/{:x}", cache_root_dir, this->hash()); +} + +std::filesystem::path color_table_impl::convert_task_cache_filename( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir) const noexcept { + auto self_cache_dir = this->self_cache_dir(cache_root_dir); + self_cache_dir.append(fmt::format( + "{:x}/convert_cache", + converted_image_impl::convert_task_hash(original_img, option))); + return self_cache_dir; +} + +bool color_table_impl::has_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir) const noexcept { + auto path = + this->convert_task_cache_filename(original_img, option, cache_root_dir); + return std::filesystem::is_regular_file(path); +} + +std::string color_table_impl::save_convert_cache( + const_image_reference original_img, const convert_option &option, + const converted_image &cvted, const char *cache_root_dir) const noexcept { + try { + auto filename = + this->convert_task_cache_filename(original_img, option, cache_root_dir); + std::filesystem::create_directories(filename.parent_path()); + + auto err = + dynamic_cast(cvted).save_cache(filename); + if (!err.empty()) { + return fmt::format("Failed to save cache to file \"{}\": {}", + filename.string(), err); + } + } catch (const std::exception &e) { + return fmt::format("Caught exception: {}", e.what()); + } + + return {}; +} + +[[nodiscard]] tl::expected +color_table_impl::load_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir) const noexcept { + return converted_image_impl::load_cache( + *this, + this->convert_task_cache_filename(original_img, option, cache_root_dir)); +} \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 5cca9aec..c0122299 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -6,9 +6,12 @@ #define SLOPECRAFT_COLOR_TABLE_H #include +#include +#include #include "SlopeCraftL.h" #include "Colorset.h" #include "mc_block.h" +#include "WriteStringDeliver.h" #include "converted_image.h" class color_table_impl : public SlopeCraft::color_table { @@ -45,6 +48,57 @@ class color_table_impl : public SlopeCraft::color_table { const_image_reference original_img, const convert_option &option) const noexcept final; + [[nodiscard]] uint64_t hash() const noexcept; + + [[nodiscard]] std::filesystem::path self_cache_dir( + const char *cache_root_dir) const noexcept; + + [[nodiscard]] std::filesystem::path convert_task_cache_filename( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir) const noexcept; + + [[nodiscard]] bool has_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir) const noexcept final; + + [[nodiscard]] bool save_convert_cache( + const_image_reference original_img, const convert_option &option, + const converted_image &cvted, const char *cache_root_dir, + StringDeliver *error) const noexcept final { + auto err = + this->save_convert_cache(original_img, option, cvted, cache_root_dir); + if (error) { + write(*error, err); + } + return err.empty(); + } + + [[nodiscard]] std::string save_convert_cache( + const_image_reference original_img, const convert_option &option, + const converted_image &, const char *cache_root_dir) const noexcept; + + [[nodiscard]] converted_image *load_convert_cache( + const_image_reference original_img, const convert_option &option, + const char *cache_root_dir, StringDeliver *error) const noexcept final { + auto res = this->load_convert_cache(original_img, option, cache_root_dir); + if (!res) { + if (error) { + write(*error, res.error()); + } + return nullptr; + } + + if (error) { + write(*error, ""); + } + return new converted_image_impl{std::move(res.value())}; + } + + [[nodiscard]] tl::expected + load_convert_cache(const_image_reference original_img, + const convert_option &option, + const char *cache_root_dir) const noexcept; + [[nodiscard]] structure_3D *build(const converted_image &, const build_options &) const noexcept final; @@ -54,4 +108,7 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] std::vector block_id_list() const noexcept; }; +//[[nodiscard]] std::string digest_to_string( +// std::span hash) noexcept; + #endif // SLOPECRAFT_COLOR_TABLE_H diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 77778dca..77662f0f 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -3,6 +3,8 @@ // #include +#include +#include "SCLDefines.h" #include "converted_image.h" #include "color_table.h" #include "height_line.h" @@ -117,4 +119,48 @@ converted_image_impl::height_info(const build_options &option) const noexcept { .high_map = high_map, .low_map = low_map, .water_list = water_list}; +} + +uint64_t converted_image_impl::convert_task_hash( + const_image_reference original_img, const convert_option &option) noexcept { + boost::uuids::detail::md5 hash; + + SC_HASH_ADD_DATA(hash, option.algo) + SC_HASH_ADD_DATA(hash, option.dither) + if (option.algo == SCL_convertAlgo::gaCvter) { + SC_HASH_ADD_DATA(hash, option.ai_cvter_opt.popSize) + SC_HASH_ADD_DATA(hash, option.ai_cvter_opt.maxGeneration) + SC_HASH_ADD_DATA(hash, option.ai_cvter_opt.maxFailTimes) + SC_HASH_ADD_DATA(hash, option.ai_cvter_opt.crossoverProb) + SC_HASH_ADD_DATA(hash, option.ai_cvter_opt.mutationProb) + } + + hash.process_bytes(original_img.data, original_img.rows * original_img.cols); + + decltype(hash)::digest_type dig; + hash.get_digest(dig); + std::array temp; + memcpy(temp.data(), dig, sizeof(temp)); + return temp[0] ^ temp[1]; +} + +std::string converted_image_impl::save_cache( + const std::filesystem::path &file) const noexcept { + if (this->converter.save_cache(file.string().c_str())) { + return "Failed to open file."; + } + return {}; +} + +tl::expected +converted_image_impl::load_cache(const color_table_impl &table, + const std::filesystem::path &file) noexcept { + converted_image_impl ret{table}; + if (!std::filesystem::is_regular_file(file)) { + return tl::make_unexpected("No such file"); + } + if (!ret.converter.load_cache(file.string().c_str())) { + return tl::make_unexpected("Failed to load cache, the cache is incorrect"); + } + return ret; } \ No newline at end of file diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index 1f77a669..c031fc5f 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -11,6 +11,8 @@ #include "WaterItem.h" #include #include +#include +#include class color_table_impl; @@ -44,5 +46,15 @@ class converted_image_impl : public converted_image { }; std::optional height_info( const build_options &option) const noexcept; + + [[nodiscard]] static uint64_t convert_task_hash( + const_image_reference original_img, + const convert_option &option) noexcept; + + std::string save_cache(const std::filesystem::path &file) const noexcept; + + [[nodiscard]] static tl::expected + load_cache(const color_table_impl &table, + const std::filesystem::path &file) noexcept; }; #endif // SLOPECRAFT_CONVERTED_IMAGE_H diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index 8caa63f7..e441b0eb 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -129,6 +129,16 @@ bool libMapImageCvt::MapImageCvter::load_cache( this->load_from_itermediate(std::move(temp)); + assert(this->_raw_image.rows() == this->_dithered_image.rows()); + assert(this->_raw_image.cols() == this->_dithered_image.cols()); + return true; +} + +bool libMapImageCvt::MapImageCvter::load_cache(const char *filename) noexcept { + MapImageCvter temp{this->basic_colorset, this->allowed_colorset}; + + this->load_from_itermediate(std::move(temp)); + assert(this->_raw_image.rows() == this->_dithered_image.rows()); assert(this->_raw_image.cols() == this->_dithered_image.cols()); return true; diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index d8615a6d..b72f0673 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -184,7 +184,9 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { bool save_cache(const char *filename) const noexcept; bool examine_cache(const char *filename, uint64_t expected_task_hash, MapImageCvter *itermediate = nullptr) const noexcept; - bool load_cache(const char *filename, uint64_t expected_task_hash) noexcept; + [[nodiscard]] bool load_cache(const char *filename, + uint64_t expected_task_hash) noexcept; + bool load_cache(const char *filename) noexcept; }; } // namespace libMapImageCvt From e40fdeeea23515b99496bb47f40aad25c5f55ed1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 12:36:29 +0800 Subject: [PATCH 0782/1123] rename write to write_to_sd Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.cpp | 4 ++-- SlopeCraftL/TokiSlopeCraft.h | 8 ++++---- SlopeCraftL/WriteStringDeliver.h | 19 +++++++++++-------- SlopeCraftL/color_table.h | 13 ++++--------- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index a44fc188..116aa33e 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -304,9 +304,9 @@ SCL_EXPORT block_list_interface *SCL_createBlockList( const char *zip_filename, const block_list_create_info &option) { auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); - SlopeCraft::write(*option.warnings, warnings); + SlopeCraft::write_to_sd(option.warnings, warnings); if (!res) { - SlopeCraft::write(*option.error, res.error()); + SlopeCraft::write_to_sd(option.error, res.error()); return nullptr; } diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h index 44f03da5..8d94441d 100644 --- a/SlopeCraftL/TokiSlopeCraft.h +++ b/SlopeCraftL/TokiSlopeCraft.h @@ -249,7 +249,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { const flag_diagram_options &option) const noexcept override { std::string err = this->export_flat_diagram(filename_local, option); if (option.err != nullptr) { - write(*option.err, err); + write_to_sd(option.err, err); } return err.empty(); } @@ -354,7 +354,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool saveConvertCache(StringDeliver &_err) const noexcept override { std::string err; this->save_convert_cache(err); - write(_err, err); + write_to_sd(&_err, err); return err.empty(); } @@ -368,7 +368,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { bool saveBuildCache(StringDeliver &_err) const noexcept override { std::string err; this->save_build_cache(err); - write(_err, err); + write_to_sd(&_err, err); return err.empty(); } @@ -380,7 +380,7 @@ class TokiSlopeCraft : public ::SlopeCraft::Kernel { const test_blocklist_options &option) const noexcept override { std::string err = this->impl_make_tests(filename, option); if (option.err != nullptr) { - write(*option.err, err); + write_to_sd(option.err, err); } return err.empty(); } diff --git a/SlopeCraftL/WriteStringDeliver.h b/SlopeCraftL/WriteStringDeliver.h index d696ca2b..2915b3e2 100644 --- a/SlopeCraftL/WriteStringDeliver.h +++ b/SlopeCraftL/WriteStringDeliver.h @@ -4,20 +4,23 @@ #include namespace SlopeCraft { -inline void write(StringDeliver& s, std::string_view sv) noexcept { - if (!s.is_valid()) { +inline void write_to_sd(StringDeliver* s, std::string_view sv) noexcept { + if (s == nullptr) { + return; + } + if (!s->is_valid()) { return; } - const size_t move_bytes = std::min(sv.size(), s.capacity); - memcpy(s.data, sv.data(), move_bytes); - s.is_complete = move_bytes < sv.size(); + const size_t move_bytes = std::min(sv.size(), s->capacity); + memcpy(s->data, sv.data(), move_bytes); + s->is_complete = move_bytes < sv.size(); - if (!s.is_complete) { - s.data[s.capacity - 1] = '\0'; + if (!s->is_complete) { + s->data[s->capacity - 1] = '\0'; } - s.size = move_bytes; + s->size = move_bytes; } }; // namespace SlopeCraft diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index c0122299..a4233c7f 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -67,9 +67,7 @@ class color_table_impl : public SlopeCraft::color_table { StringDeliver *error) const noexcept final { auto err = this->save_convert_cache(original_img, option, cvted, cache_root_dir); - if (error) { - write(*error, err); - } + write_to_sd(error, err); return err.empty(); } @@ -82,15 +80,12 @@ class color_table_impl : public SlopeCraft::color_table { const char *cache_root_dir, StringDeliver *error) const noexcept final { auto res = this->load_convert_cache(original_img, option, cache_root_dir); if (!res) { - if (error) { - write(*error, res.error()); - } + write_to_sd(error, res.error()); return nullptr; } - if (error) { - write(*error, ""); - } + write_to_sd(error, ""); + return new converted_image_impl{std::move(res.value())}; } From 345caab959ce0eea5f5e7e66f8bc0ff0086a5670 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 19:15:01 +0800 Subject: [PATCH 0783/1123] save and load build cache Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 12 +++- SlopeCraftL/color_table.cpp | 71 +++++++++++++++++++++++- SlopeCraftL/color_table.h | 20 ++++++- SlopeCraftL/converted_image.cpp | 6 +- SlopeCraftL/converted_image.h | 2 + SlopeCraftL/structure_3D.cpp | 80 ++++++++++++++++++++++++++- SlopeCraftL/structure_3D.h | 23 +++++++- utilities/ColorManip/imageConvert.hpp | 2 +- 8 files changed, 204 insertions(+), 12 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 82da05be..c09a9541 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -323,18 +323,26 @@ class color_table { [[nodiscard]] virtual bool has_convert_cache( const_image_reference original_img, const convert_option &option, const char *cache_dir) const noexcept = 0; - [[nodiscard]] virtual bool save_convert_cache( const_image_reference original_img, const convert_option &option, const converted_image &, const char *cache_dir, StringDeliver *error) const noexcept = 0; - [[nodiscard]] virtual converted_image *load_convert_cache( const_image_reference original_img, const convert_option &option, const char *cache_dir, StringDeliver *error) const noexcept = 0; [[nodiscard]] virtual structure_3D *build( const converted_image &, const build_options &) const noexcept = 0; + // Once you cache a structure_3D, it can be released to save memory + [[nodiscard]] virtual bool save_build_cache( + const converted_image &, const build_options &, const structure_3D &, + const char *cache_root_dir, StringDeliver *error) const noexcept = 0; + [[nodiscard]] virtual bool has_build_cache( + const converted_image &, const build_options &, + const char *cache_root_dir) const noexcept = 0; + [[nodiscard]] virtual structure_3D *load_build_cache( + const converted_image &, const build_options &, + const char *cache_root_dir, StringDeliver *error) const noexcept = 0; }; class Kernel { diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 94fb6fe6..d4aceb58 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -172,9 +172,9 @@ std::filesystem::path color_table_impl::convert_task_cache_filename( const_image_reference original_img, const convert_option &option, const char *cache_root_dir) const noexcept { auto self_cache_dir = this->self_cache_dir(cache_root_dir); + self_cache_dir.append("convert"); self_cache_dir.append(fmt::format( - "{:x}/convert_cache", - converted_image_impl::convert_task_hash(original_img, option))); + "{:x}", converted_image_impl::convert_task_hash(original_img, option))); return self_cache_dir; } @@ -214,4 +214,71 @@ color_table_impl::load_convert_cache( return converted_image_impl::load_cache( *this, this->convert_task_cache_filename(original_img, option, cache_root_dir)); +} + +std::filesystem::path color_table_impl::build_task_cache_filename( + const converted_image &cvted_, const build_options &opt, + const char *cache_root_dir) const noexcept { + boost::uuids::detail::md5 hash; + SC_HASH_ADD_DATA(hash, opt.max_allowed_height) + SC_HASH_ADD_DATA(hash, opt.bridge_interval) + SC_HASH_ADD_DATA(hash, opt.compress_method) + SC_HASH_ADD_DATA(hash, opt.glass_method) + SC_HASH_ADD_DATA(hash, opt.fire_proof) + SC_HASH_ADD_DATA(hash, opt.enderman_proof) + SC_HASH_ADD_DATA(hash, opt.connect_mushrooms) + + auto &cvted = dynamic_cast(cvted_); + // this can be optimized + auto map_mat = cvted.converter.mapcolor_matrix(); + hash.process_bytes(map_mat.data(), map_mat.size() * sizeof(uint8_t)); + + decltype(hash)::digest_type dig; + hash.get_digest(dig); + std::array dig_u64{0, 0}; + memcpy(dig_u64.data(), dig, sizeof(dig)); + const uint64_t hash_u64 = dig_u64[0] ^ dig_u64[1]; + + auto path = this->self_cache_dir(cache_root_dir); + path.append("build"); + path.append(fmt::format("{:x}", hash_u64)); + return path; +} + +bool color_table_impl::save_build_cache(const converted_image &cvted, + const build_options &option, + const structure_3D &structure, + const char *cache_root_dir, + StringDeliver *error) const noexcept { + const auto filename = + this->build_task_cache_filename(cvted, option, cache_root_dir); + auto err_msg = + dynamic_cast(structure).save_cache(filename); + write_to_sd(error, err_msg); + + return err_msg.empty(); +} + +bool color_table_impl::has_build_cache( + const SlopeCraft::converted_image &cvted, + const SlopeCraft::build_options &option, + const char *cache_root_dir) const noexcept { + const auto filename = + this->build_task_cache_filename(cvted, option, cache_root_dir); + return std::filesystem::is_regular_file(filename); +} + +structure_3D *color_table_impl::load_build_cache( + const SlopeCraft::converted_image &cvted, + const SlopeCraft::build_options &option, const char *cache_root_dir, + SlopeCraft::StringDeliver *error) const noexcept { + const auto filename = + this->build_task_cache_filename(cvted, option, cache_root_dir); + auto res = structure_3D_impl::load_cache(filename); + if (res) { + write_to_sd(error, ""); + return new structure_3D_impl{std::move(res.value())}; + } + write_to_sd(error, res.error()); + return nullptr; } \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index a4233c7f..7fc22955 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -48,6 +48,11 @@ class color_table_impl : public SlopeCraft::color_table { const_image_reference original_img, const convert_option &option) const noexcept final; + [[nodiscard]] static std::optional create( + const color_table_create_info &args) noexcept; + + [[nodiscard]] std::vector block_id_list() const noexcept; + [[nodiscard]] uint64_t hash() const noexcept; [[nodiscard]] std::filesystem::path self_cache_dir( @@ -97,10 +102,19 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] structure_3D *build(const converted_image &, const build_options &) const noexcept final; - [[nodiscard]] static std::optional create( - const color_table_create_info &args) noexcept; + [[nodiscard]] std::filesystem::path build_task_cache_filename( + const converted_image &, const build_options &, + const char *cache_root_dir) const noexcept; - [[nodiscard]] std::vector block_id_list() const noexcept; + [[nodiscard]] bool save_build_cache( + const converted_image &, const build_options &, const structure_3D &, + const char *cache_root_dir, StringDeliver *error) const noexcept final; + [[nodiscard]] bool has_build_cache( + const converted_image &, const build_options &, + const char *cache_root_dir) const noexcept final; + [[nodiscard]] structure_3D *load_build_cache( + const converted_image &, const build_options &, + const char *cache_root_dir, StringDeliver *error) const noexcept final; }; //[[nodiscard]] std::string digest_to_string( diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 77662f0f..d5c0eed8 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -163,4 +163,8 @@ converted_image_impl::load_cache(const color_table_impl &table, return tl::make_unexpected("Failed to load cache, the cache is incorrect"); } return ret; -} \ No newline at end of file +} + +// uint64_t converted_image_impl::hash() const noexcept { +// return this->converter.task_hash(); +// } \ No newline at end of file diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index c031fc5f..1cc810d1 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -24,6 +24,8 @@ class converted_image_impl : public converted_image { Eigen::Array; libMapImageCvt::MapImageCvter converter; + // [[nodiscard]] uint64_t hash() const noexcept; + size_t rows() const noexcept final { return this->converter.rows(); } size_t cols() const noexcept final { return this->converter.cols(); } diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 2c5d1060..edb3435e 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -2,6 +2,13 @@ // Created by joseph on 4/17/24. // #include +#include +#include +#include +#include +#include +#include + #include "structure_3D.h" #include "color_table.h" #include "lossyCompressor.h" @@ -171,7 +178,7 @@ std::optional structure_3D_impl::create( option.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); option.ui.report_working_status(workStatus::none); - ret.map_color = std::move(map_color); + ret.map_color = map_color.cast(); return ret; } @@ -252,4 +259,75 @@ bool structure_3D_impl::export_WE_schem( option.progressbar.set_range(0, 100, 100); return true; +} + +namespace cereal { +template +void save(archive &ar, const Eigen::ArrayXX &mat) { + ar(mat.rows(), mat.cols()); + ar(cereal::binary_data(mat.data(), mat.size())); +} + +template +void load(archive &ar, Eigen::ArrayXX &mat) { + Eigen::Index rows{0}, cols{0}; + ar(rows, cols); + if (rows < 0 || cols < 0) { + throw std::runtime_error{ + fmt::format("Found negative shape when deserializing " + "Eigen::ArrayXX, {} rows and {} cols", + rows, cols)}; + } + mat.resize(rows, cols); + ar(cereal::binary_data(mat.data(), mat.size() * sizeof(uint8_t))); +} +} // namespace cereal + +std::string structure_3D_impl::save_cache( + const std::filesystem::path &filename) const noexcept { + try { + std::filesystem::create_directories(filename.parent_path()); + boost::iostreams::filtering_ostream ofs{}; + ofs.set_auto_close(true); + { + boost::iostreams::zstd_params params; + // ZSTD_defaultCLevel() doesn't exist below zstd 1.5 +#if ZSTD_VERSION_MINOR >= 5 + params.level = uint32_t(ZSTD_defaultCLevel()); +#else + params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); +#endif + ofs.push(boost::iostreams::zstd_compressor{params}); + ofs.push(boost::iostreams::file_sink{filename, std::ios::binary}); + } + + { + cereal::BinaryOutputArchive boa{ofs}; + boa(*this); + } + + } catch (const std::exception &e) { + return fmt::format("Caught exception: {}", e.what()); + } + + return {}; +} + +tl::expected structure_3D_impl::load_cache( + const std::filesystem::path &filename) noexcept { + structure_3D_impl ret; + try { + boost::iostreams::filtering_istream ifs; + ifs.set_auto_close(true); + ifs.push(boost::iostreams::zstd_decompressor{}); + ifs.push(boost::iostreams::file_source{filename, std::ios::binary}); + { + cereal::BinaryInputArchive bia{ifs}; + bia(ret); + } + } catch (const std::exception &e) { + return tl::make_unexpected(fmt::format("Caught exception: {}", e.what())); + } + + return ret; } \ No newline at end of file diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index f0497689..066791d4 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -14,8 +14,9 @@ class structure_3D_impl : public structure_3D { private: libSchem::Schem schem; - Eigen::ArrayXXi map_color; // map color may be modified by lossy - // compression,so we store the modified one + Eigen::ArrayXX + map_color; // map color may be modified by lossy + // compression,so we store the modified one public: size_t shape_x() const noexcept final { return this->schem.x_range(); } @@ -41,6 +42,24 @@ class structure_3D_impl : public structure_3D { const vanilla_structure_options &option) const noexcept final; bool export_WE_schem(const char *filename, const WE_schem_options &option) const noexcept final; + + [[nodiscard]] std::string save_cache( + const std::filesystem::path &file) const noexcept; + + [[nodiscard]] static tl::expected load_cache( + const std::filesystem::path &file) noexcept; + + template + void load(archive &ar) { + ar(this->map_color); + ar(this->schem); + }; + + template + void save(archive &ar) const { + ar(this->map_color); + ar(this->schem); + } }; #endif // SLOPECRAFT_STRUCTURE_3D_H diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index ee5dc68c..e65827a4 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -671,7 +671,7 @@ class ImageCvter : public GPU_wrapper_wrapper { } public: - uint64_t task_hash() const noexcept { + [[deprecated]] uint64_t task_hash() const noexcept { return this->task_hash(this->algo, this->dither); } From fe9cf41a5060ed667d98bd79aac3974cd5cbec2e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 19:38:41 +0800 Subject: [PATCH 0784/1123] remove Kernel and TokiSlopeCraft Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 12 +- SlopeCraftL/Colors.cpp | 2 +- SlopeCraftL/SlopeCraftL.cpp | 17 - SlopeCraftL/SlopeCraftL.h | 440 ++++++------ SlopeCraftL/TokiSlopeCraft.cpp | 558 ---------------- SlopeCraftL/TokiSlopeCraft.h | 465 ------------- SlopeCraftL/TokiSlopeCraft_build.cpp | 737 --------------------- SlopeCraftL/TokiSlopeCraft_cache.cpp | 430 ------------ SlopeCraftL/TokiSlopeCraft_convert.cpp | 280 -------- SlopeCraftL/TokiSlopeCraft_static_funs.cpp | 140 ---- 10 files changed, 231 insertions(+), 2850 deletions(-) delete mode 100644 SlopeCraftL/TokiSlopeCraft.cpp delete mode 100644 SlopeCraftL/TokiSlopeCraft.h delete mode 100644 SlopeCraftL/TokiSlopeCraft_build.cpp delete mode 100644 SlopeCraftL/TokiSlopeCraft_cache.cpp delete mode 100644 SlopeCraftL/TokiSlopeCraft_convert.cpp delete mode 100644 SlopeCraftL/TokiSlopeCraft_static_funs.cpp diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 0adf6e31..646ed913 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -30,7 +30,7 @@ set(Slope_SCL_internal_headers optimize_chain.h prim_glass_builder.h SCLDefines.h - TokiSlopeCraft.h + # to_be_removed/TokiSlopeCraft.h WaterItem.h lossyCompressor.h mc_block.h @@ -52,11 +52,11 @@ set(SlopeCraft_SCL_sources height_line.cpp optimize_chain.cpp prim_glass_builder.cpp - TokiSlopeCraft.cpp - TokiSlopeCraft_static_funs.cpp - TokiSlopeCraft_build.cpp - TokiSlopeCraft_convert.cpp - TokiSlopeCraft_cache.cpp + # to_be_removed/TokiSlopeCraft.cpp + # to_be_removed/TokiSlopeCraft_static_funs.cpp + # to_be_removed/TokiSlopeCraft_build.cpp + # to_be_removed/TokiSlopeCraft_convert.cpp + # to_be_removed/TokiSlopeCraft_cache.cpp imagePreprocess.cpp lossyCompressor.cpp mc_block.cpp diff --git a/SlopeCraftL/Colors.cpp b/SlopeCraftL/Colors.cpp index 5b07ba0e..9df0a1b2 100644 --- a/SlopeCraftL/Colors.cpp +++ b/SlopeCraftL/Colors.cpp @@ -21,7 +21,7 @@ This file is part of SlopeCraft. */ #include "Colors.h" -#include "TokiSlopeCraft.h" +#include "Colorset.h" #include diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 116aa33e..e5d25fc6 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -27,7 +27,6 @@ This file is part of SlopeCraft. #include #include "SlopeCraftL.h" -#include "TokiSlopeCraft.h" #include "mc_block.h" #include "WriteStringDeliver.h" #include "color_table.h" @@ -49,8 +48,6 @@ void AbstractBlock::clear() noexcept { // setWallUseable(false); } -Kernel::Kernel() {} - using namespace SlopeCraft; std::pair parse_block(const nlohmann::json &jo) noexcept( @@ -291,12 +288,6 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { } extern "C" { - -SCL_EXPORT Kernel *SCL_createKernel() { return new TokiSlopeCraft; } -SCL_EXPORT void SCL_destroyKernel(Kernel *k) { - delete static_cast(k); -} - SCL_EXPORT AbstractBlock *SCL_createBlock() { return new mc_block; } SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } @@ -357,14 +348,6 @@ double SCL_EXPORT SCL_getMutationProb(const AiCvterOpt *a) { // TokiSlopeCraft::getColorMapPtrs(rdata, gdata, bdata, mapdata, num); // } -SCL_EXPORT const float *SCL_getBasicColorMapPtrs() { - return TokiSlopeCraft::getBasicColorMapPtrs(); -} - -SCL_EXPORT const char *SCL_getSCLVersion() { - return TokiSlopeCraft::getSCLVersion(); -} - SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { if (basecolor <= 51) { return SCL_gameVersion::ANCIENT; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index c09a9541..b89fb8c6 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -345,219 +345,227 @@ class color_table { const char *cache_root_dir, StringDeliver *error) const noexcept = 0; }; -class Kernel { - public: - Kernel(); - // virtual ~Kernel() {}; - - public: - /// function ptr to window object - virtual void setWindPtr(void *) = 0; - /// a function ptr to show progress of converting and exporting - virtual void setProgressRangeSet(void (*)(void *, int, int, int)) = 0; - /// a function ptr to add progress value - virtual void setProgressAdd(void (*)(void *, int)) = 0; - /// a function ptr to prevent window from being syncoped - virtual void setKeepAwake(void (*)(void *)) = 0; - - /// a function ptr to show progress of compressing and bridge-building - virtual void setAlgoProgressRangeSet(void (*)(void *, int, int, int)) = 0; - /// a function ptr to add progress value of compressing and bridge-building - virtual void setAlgoProgressAdd(void (*)(void *, int)) = 0; - - /// a function ptr to report error when something wrong happens - virtual void setReportError(void (*)(void *, ::SCL_errorFlag, - const char *)) = 0; - /// a function ptr to report working statue especially when busy - virtual void setReportWorkingStatue(void (*)(void *, ::SCL_workStatus)) = 0; - - virtual void setAiCvterOpt(const AiCvterOpt *) = 0; - - virtual const AiCvterOpt *aiCvterOpt() const = 0; - - virtual size_t getBlockPalette(const AbstractBlock **buf, - size_t buf_capacity) const noexcept = 0; - - // can do in nothing: - /// real size of kernel - virtual size_t size() = 0; - /// revert to a previous step - virtual void decreaseStep(::SCL_step) = 0; - - // can do in colorSetReady: - /// get current step - virtual ::SCL_step queryStep() const = 0; - /// set map type and blocklist - virtual bool setType(::SCL_mapTypes, ::SCL_gameVersion, const bool[64], - const AbstractBlock *const *const) = 0; - /// get palette (base colors only) in ARGB32 - virtual void getBaseColorInARGB32(uint32_t *const) const = 0; - - // can do in wait4Image: - /// set original image from ARGB32 matrix (col-major) - [[deprecated]] virtual void setRawImage(const uint32_t *src, int rows, - int cols) = 0; - /// get accessible color count - virtual unsigned short getColorCount() const = 0; - /// get usable colors in ARGB32 - virtual void getAvailableColors(uint32_t *const ARGB32_dest = nullptr, - uint8_t *const map_color_dest = nullptr, - int *const num = nullptr) const = 0; - /// make a structure that includes all accessible blocks - [[deprecated]] virtual bool makeTests(const AbstractBlock **, const uint8_t *, - const char *, char *) = 0; - - // can do in convertionReady: - /// convert original image to map - virtual bool convert(::SCL_convertAlgo = ::SCL_convertAlgo::RGB_Better, - bool dither = false) = 0; - /// get image rows - virtual int getImageRows() const = 0; - /// get image cols - virtual int getImageCols() const = 0; - virtual const uint32_t *getRawImage() const = 0; - /// query if map is buildable in vanilla survival - virtual bool isVanilla() const = 0; - /// query if map is a flat one - virtual bool isFlat() const = 0; - - // can do in converted: - /// construct 3D structure - [[deprecated]] virtual bool build( - ::SCL_compressSettings = ::SCL_compressSettings::noCompress, - uint16_t maxAllowedHeight = 256, - ::SCL_glassBridgeSettings = ::SCL_glassBridgeSettings::noBridge, - uint16_t glassInterval = 3, bool fireProof = false, - bool endermanProof = false) = 0; - - /// get converted image - [[deprecated]] virtual void getConvertedImage(int *rows, int *cols, - uint32_t *dest) const = 0; - /// export as map data files, returns failed files. - virtual void exportAsData(const char *FolderPath, const int indexStart, - int *fileCount, char **dest) const = 0; - /// get converted map(in mapColor array) - virtual void getConvertedMap(int *rows, int *cols, uint8_t *) const = 0; - - // can do in builded: - /// export map into litematica files (*.litematic) - [[deprecated]] virtual void exportAsLitematic( - const char *localEncoding_TargetName, const char *utf8_LiteName, - const char *utf8_RegionName, char *localEncoding_returnVal) const = 0; - - /// export map into Structure files (*.NBT) - [[deprecated]] virtual void exportAsStructure( - const char *localEncoding_TargetName, - char *localEncoding_FileName) const = 0; - [[deprecated]] virtual void exportAsWESchem( - const char *localEncoding_fileName, const int (&offset)[3] = {0, 0, 0}, - const int (&weOffset)[3] = {0, 0, 0}, const char *utf8_Name = "", - const char *const *const utf8_requiredMods = nullptr, - const int requiredModsCount = 0, - char *localEncoding_returnVal = nullptr) const = 0; - - /// get x,y,z size - virtual void get3DSize(int *x, int *y, int *z) const = 0; - - /// get 3d structure's size - virtual int getHeight() const = 0; - /// get 3d structure's size - virtual int getXRange() const = 0; - /// get 3d structure's size - virtual int getZRange() const = 0; - /// get block count in total and in detail - virtual void getBlockCounts(int *total, int detail[64]) const = 0; - /// get sum block count - virtual int64_t getBlockCounts() const = 0; - /// get 3d structure in 3d-matrix (col major) - virtual const uint16_t *getBuild(int *xSize = nullptr, int *ySize = nullptr, - int *zSize = nullptr) const = 0; - - // Virtual functions added after v5.0.0. Define them in the end of vtable to - // matain binary compability - - // introduced in v5.1.0 ----------------------------------------------------- - virtual void setCacheDir(const char *) noexcept = 0; - virtual const char *cacheDir() const noexcept = 0; - // replacement for setRawImage(const uint32_t*,int,int) - virtual void setRawImage(const uint32_t *src, int rows, int cols, - bool is_col_major) = 0; - // replacement for getConvertedImage(int *rows, int *cols, uint32_t - // *dest)const - virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, - bool expected_col_major) const = 0; - // struct build_options { - // uint64_t caller_api_version{SC_VERSION_U64}; - // uint16_t max_allowed_height{256}; - // uint16_t bridge_interval{3}; - // compressSettings compress_method{::SCL_compressSettings::noCompress}; - // glassBridgeSettings glass_method{::SCL_glassBridgeSettings::noBridge}; - // bool fire_proof{false}; - // bool enderman_proof{false}; - // - // // added in v5.1.0 - // bool connect_mushrooms{false}; - // }; - virtual bool build(const build_options &option) noexcept = 0; - - virtual void getCompressedImage(int *row, int *cols, uint32_t *dest, - bool expected_col_major) const noexcept = 0; - // requires step >= wait4image - // virtual bool checkColorsetHash() const noexcept = 0; - // requires step >= converted - virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; - - // requires step >= convertion ready - virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = 0; - - // requires step >= built - virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; - - // requires step >= converted - virtual bool loadBuildCache(const build_options &option) noexcept = 0; - - // requires step >= built - virtual int getSchemPalette(const char **dest_id, - size_t dest_capacity) const noexcept = 0; - - virtual bool exportAsLitematic( - const char *filename_local, - const litematic_options &option) const noexcept = 0; - - virtual bool exportAsStructure( - const char *filename_local, - const vanilla_structure_options &option) const noexcept = 0; - - virtual bool exportAsWESchem( - const char *filename_local, - const WE_schem_options &option) const noexcept = 0; - - struct flag_diagram_options { - uint64_t caller_api_version{SC_VERSION_U64}; - - // 0 or negative number means no split lines - int32_t split_line_row_margin{0}; - // 0 or negative number means no split lines - int32_t split_line_col_margin{0}; - int png_compress_level{9}; - int png_compress_memory_level{8}; - StringDeliver *err{nullptr}; - }; - virtual bool exportAsFlatDiagram( - const char *filename_local, - const flag_diagram_options &option) const noexcept = 0; - - struct test_blocklist_options { - uint64_t caller_api_version{SC_VERSION_U64}; - const AbstractBlock *const *block_ptrs{nullptr}; - const uint8_t *basecolors{nullptr}; - size_t block_count{0}; - StringDeliver *err{nullptr}; - }; - virtual bool makeTests( - const char *filename, - const test_blocklist_options &option) const noexcept = 0; -}; +// class Kernel { +// public: +// Kernel(); +// // virtual ~Kernel() {}; +// +// public: +// /// function ptr to window object +// virtual void setWindPtr(void *) = 0; +// /// a function ptr to show progress of converting and exporting +// virtual void setProgressRangeSet(void (*)(void *, int, int, int)) = 0; +// /// a function ptr to add progress value +// virtual void setProgressAdd(void (*)(void *, int)) = 0; +// /// a function ptr to prevent window from being syncoped +// virtual void setKeepAwake(void (*)(void *)) = 0; +// +// /// a function ptr to show progress of compressing and bridge-building +// virtual void setAlgoProgressRangeSet(void (*)(void *, int, int, int)) = 0; +// /// a function ptr to add progress value of compressing and bridge-building +// virtual void setAlgoProgressAdd(void (*)(void *, int)) = 0; +// +// /// a function ptr to report error when something wrong happens +// virtual void setReportError(void (*)(void *, ::SCL_errorFlag, +// const char *)) = 0; +// /// a function ptr to report working statue especially when busy +// virtual void setReportWorkingStatue(void (*)(void *, ::SCL_workStatus)) = +// 0; +// +// virtual void setAiCvterOpt(const AiCvterOpt *) = 0; +// +// virtual const AiCvterOpt *aiCvterOpt() const = 0; +// +// virtual size_t getBlockPalette(const AbstractBlock **buf, +// size_t buf_capacity) const noexcept = 0; +// +// // can do in nothing: +// /// real size of kernel +// virtual size_t size() = 0; +// /// revert to a previous step +// virtual void decreaseStep(::SCL_step) = 0; +// +// // can do in colorSetReady: +// /// get current step +// virtual ::SCL_step queryStep() const = 0; +// /// set map type and blocklist +// virtual bool setType(::SCL_mapTypes, ::SCL_gameVersion, const bool[64], +// const AbstractBlock *const *const) = 0; +// /// get palette (base colors only) in ARGB32 +// virtual void getBaseColorInARGB32(uint32_t *const) const = 0; +// +// // can do in wait4Image: +// /// set original image from ARGB32 matrix (col-major) +// [[deprecated]] virtual void setRawImage(const uint32_t *src, int rows, +// int cols) = 0; +// /// get accessible color count +// virtual unsigned short getColorCount() const = 0; +// /// get usable colors in ARGB32 +// virtual void getAvailableColors(uint32_t *const ARGB32_dest = nullptr, +// uint8_t *const map_color_dest = nullptr, +// int *const num = nullptr) const = 0; +// /// make a structure that includes all accessible blocks +// [[deprecated]] virtual bool makeTests(const AbstractBlock **, const uint8_t +// *, +// const char *, char *) = 0; +// +// // can do in convertionReady: +// /// convert original image to map +// virtual bool convert(::SCL_convertAlgo = ::SCL_convertAlgo::RGB_Better, +// bool dither = false) = 0; +// /// get image rows +// virtual int getImageRows() const = 0; +// /// get image cols +// virtual int getImageCols() const = 0; +// virtual const uint32_t *getRawImage() const = 0; +// /// query if map is buildable in vanilla survival +// virtual bool isVanilla() const = 0; +// /// query if map is a flat one +// virtual bool isFlat() const = 0; +// +// // can do in converted: +// /// construct 3D structure +// [[deprecated]] virtual bool build( +// ::SCL_compressSettings = ::SCL_compressSettings::noCompress, +// uint16_t maxAllowedHeight = 256, +// ::SCL_glassBridgeSettings = ::SCL_glassBridgeSettings::noBridge, +// uint16_t glassInterval = 3, bool fireProof = false, +// bool endermanProof = false) = 0; +// +// /// get converted image +// [[deprecated]] virtual void getConvertedImage(int *rows, int *cols, +// uint32_t *dest) const = 0; +// /// export as map data files, returns failed files. +// virtual void exportAsData(const char *FolderPath, const int indexStart, +// int *fileCount, char **dest) const = 0; +// /// get converted map(in mapColor array) +// virtual void getConvertedMap(int *rows, int *cols, uint8_t *) const = 0; +// +// // can do in builded: +// /// export map into litematica files (*.litematic) +// [[deprecated]] virtual void exportAsLitematic( +// const char *localEncoding_TargetName, const char *utf8_LiteName, +// const char *utf8_RegionName, char *localEncoding_returnVal) const = 0; +// +// /// export map into Structure files (*.NBT) +// [[deprecated]] virtual void exportAsStructure( +// const char *localEncoding_TargetName, +// char *localEncoding_FileName) const = 0; +// [[deprecated]] virtual void exportAsWESchem( +// const char *localEncoding_fileName, const int (&offset)[3] = {0, 0, 0}, +// const int (&weOffset)[3] = {0, 0, 0}, const char *utf8_Name = "", +// const char *const *const utf8_requiredMods = nullptr, +// const int requiredModsCount = 0, +// char *localEncoding_returnVal = nullptr) const = 0; +// +// /// get x,y,z size +// virtual void get3DSize(int *x, int *y, int *z) const = 0; +// +// /// get 3d structure's size +// virtual int getHeight() const = 0; +// /// get 3d structure's size +// virtual int getXRange() const = 0; +// /// get 3d structure's size +// virtual int getZRange() const = 0; +// /// get block count in total and in detail +// virtual void getBlockCounts(int *total, int detail[64]) const = 0; +// /// get sum block count +// virtual int64_t getBlockCounts() const = 0; +// /// get 3d structure in 3d-matrix (col major) +// virtual const uint16_t *getBuild(int *xSize = nullptr, int *ySize = +// nullptr, +// int *zSize = nullptr) const = 0; +// +// // Virtual functions added after v5.0.0. Define them in the end of vtable +// to +// // matain binary compability +// +// // introduced in v5.1.0 +// ----------------------------------------------------- virtual void +// setCacheDir(const char *) noexcept = 0; virtual const char *cacheDir() +// const noexcept = 0; +// // replacement for setRawImage(const uint32_t*,int,int) +// virtual void setRawImage(const uint32_t *src, int rows, int cols, +// bool is_col_major) = 0; +// // replacement for getConvertedImage(int *rows, int *cols, uint32_t +// // *dest)const +// virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, +// bool expected_col_major) const = 0; +// // struct build_options { +// // uint64_t caller_api_version{SC_VERSION_U64}; +// // uint16_t max_allowed_height{256}; +// // uint16_t bridge_interval{3}; +// // compressSettings compress_method{::SCL_compressSettings::noCompress}; +// // glassBridgeSettings +// glass_method{::SCL_glassBridgeSettings::noBridge}; +// // bool fire_proof{false}; +// // bool enderman_proof{false}; +// // +// // // added in v5.1.0 +// // bool connect_mushrooms{false}; +// // }; +// virtual bool build(const build_options &option) noexcept = 0; +// +// virtual void getCompressedImage(int *row, int *cols, uint32_t *dest, +// bool expected_col_major) const noexcept = +// 0; +// // requires step >= wait4image +// // virtual bool checkColorsetHash() const noexcept = 0; +// // requires step >= converted +// virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; +// +// // requires step >= convertion ready +// virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = +// 0; +// +// // requires step >= built +// virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; +// +// // requires step >= converted +// virtual bool loadBuildCache(const build_options &option) noexcept = 0; +// +// // requires step >= built +// virtual int getSchemPalette(const char **dest_id, +// size_t dest_capacity) const noexcept = 0; +// +// virtual bool exportAsLitematic( +// const char *filename_local, +// const litematic_options &option) const noexcept = 0; +// +// virtual bool exportAsStructure( +// const char *filename_local, +// const vanilla_structure_options &option) const noexcept = 0; +// +// virtual bool exportAsWESchem( +// const char *filename_local, +// const WE_schem_options &option) const noexcept = 0; +// +// struct flag_diagram_options { +// uint64_t caller_api_version{SC_VERSION_U64}; +// +// // 0 or negative number means no split lines +// int32_t split_line_row_margin{0}; +// // 0 or negative number means no split lines +// int32_t split_line_col_margin{0}; +// int png_compress_level{9}; +// int png_compress_memory_level{8}; +// StringDeliver *err{nullptr}; +// }; +// virtual bool exportAsFlatDiagram( +// const char *filename_local, +// const flag_diagram_options &option) const noexcept = 0; +// +// struct test_blocklist_options { +// uint64_t caller_api_version{SC_VERSION_U64}; +// const AbstractBlock *const *block_ptrs{nullptr}; +// const uint8_t *basecolors{nullptr}; +// size_t block_count{0}; +// StringDeliver *err{nullptr}; +// }; +// virtual bool makeTests( +// const char *filename, +// const test_blocklist_options &option) const noexcept = 0; +// }; } // namespace SlopeCraft @@ -565,8 +573,8 @@ class Kernel { extern "C" { namespace SlopeCraft { -[[deprecated]] [[nodiscard]] SCL_EXPORT Kernel *SCL_createKernel(); -SCL_EXPORT void SCL_destroyKernel(Kernel *); +//[[deprecated]] [[nodiscard]] SCL_EXPORT Kernel *SCL_createKernel(); +// SCL_EXPORT void SCL_destroyKernel(Kernel *); struct color_table_create_info { ::SCL_mapTypes map_type; @@ -642,7 +650,7 @@ SCL_EXPORT uint8_t SCL_maxBaseColor(); class deleter { public: - void operator()(Kernel *k) const noexcept { SCL_destroyKernel(k); } + // void operator()(Kernel *k) const noexcept { SCL_destroyKernel(k); } void operator()(AbstractBlock *b) const noexcept { SCL_destroyBlock(b); } void operator()(block_list_interface *b) const noexcept { SCL_destroyBlockList(b); diff --git a/SlopeCraftL/TokiSlopeCraft.cpp b/SlopeCraftL/TokiSlopeCraft.cpp deleted file mode 100644 index a605dcbb..00000000 --- a/SlopeCraftL/TokiSlopeCraft.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TokiSlopeCraft.h" - -#ifdef RGB -#undef RGB -#endif - -// std::unordered_set TokiSlopeCraft::kernel_hash_set; -// -// std::mutex SCL_internal_lock; - -TokiSlopeCraft::TokiSlopeCraft() - : colorset{}, - image_cvter{*color_set::basic, colorset.allowed_colorset}, - glassBuilder{new prim_glass_builder}, - Compressor{new lossy_compressor} { - kernelStep = step::nothing; - this->image_cvter.clear_images(); - this->image_cvter.clear_color_hash(); - // rawImage.setZero(0, 0); - // GAConverter = new GACvter::GAConverter; - this->progressRangeSet = [](void *, int, int, int) {}; - this->progressAdd = [](void *, int) {}; - this->keepAwake = [](void *) {}; - this->reportError = [](void *, errorFlag, const char *) {}; - this->reportWorkingStatue = [](void *, workStatus) {}; - this->algoProgressAdd = [](void *, int) {}; - this->algoProgressRangeSet = [](void *, int, int, int) {}; - - glassBuilder->windPtr = &wind; - glassBuilder->progressAddPtr = &this->algoProgressAdd; - glassBuilder->progressRangeSetPtr = &this->algoProgressRangeSet; - glassBuilder->keepAwakePtr = &this->keepAwake; - - Compressor->windPtr = &wind; - Compressor->progressAddPtr = &this->algoProgressAdd; - Compressor->progressRangeSetPtr = &this->algoProgressRangeSet; - Compressor->keepAwakePtr = &this->keepAwake; -} - -TokiSlopeCraft::~TokiSlopeCraft() {} - -/// function ptr to window object -void TokiSlopeCraft::setWindPtr(void *_w) { - wind = _w; - this->image_cvter.ui._uiPtr = _w; - // GAConverter->setUiPtr(_w); -} -/// a function ptr to show progress of converting and exporting -void TokiSlopeCraft::setProgressRangeSet(void (*prs)(void *, int, int, int)) { - progressRangeSet = prs; - this->image_cvter.ui.progressRangeSet = prs; - // GAConverter->setProgressRangeFun(prs); -} -/// a function ptr to add progress value -void TokiSlopeCraft::setProgressAdd(void (*pa)(void *, int)) { - progressAdd = pa; - this->image_cvter.ui.progressAdd = pa; - // GAConverter->setProgressAddFun(pa); -} -/// a function ptr to prevent window from being syncoped -void TokiSlopeCraft::setKeepAwake(void (*ka)(void *)) { keepAwake = ka; } - -/// a function ptr to show progress of compressing and bridge-building -void TokiSlopeCraft::setAlgoProgressRangeSet(void (*aprs)(void *, int, int, - int)) { - algoProgressRangeSet = aprs; -} -/// a function ptr to add progress value of compressing and bridge-building -void TokiSlopeCraft::setAlgoProgressAdd(void (*apa)(void *, int)) { - algoProgressAdd = apa; -} - -/// a function ptr to report error when something wrong happens -void TokiSlopeCraft::setReportError(void (*re)(void *, errorFlag, - const char *)) { - reportError = re; -} -/// a function ptr to report working statue especially when busy -void TokiSlopeCraft::setReportWorkingStatue(void (*rws)(void *, workStatus)) { - reportWorkingStatue = rws; -} - -void TokiSlopeCraft::decreaseStep(step _step) { - if (kernelStep <= _step) return; - kernelStep = _step; -} - -color_map_ptrs TokiSlopeCraft::getAllowedColorMapPtrs() const noexcept { - const auto &allowed = this->colorset.allowed_colorset; - return {allowed.rgb_data(0), allowed.rgb_data(1), allowed.rgb_data(2), - allowed.map_data(), allowed.color_count()}; -} - -void TokiSlopeCraft::trySkipStep(step s) { - if (this->kernelStep >= s) { - return; - } - - if (this->colorset.allowed_colorset.color_count() != 0 && - this->colorset.palette.size() != 0) { - this->kernelStep = step::wait4Image; - } -} -/* -bool compressFile(const char *inputPath, const char *outputPath) { - const size_t BUFFER_SIZE = 4096; - std::ifstream fin; - fin.open(inputPath, std::ifstream::binary | std::ifstream::in); - if (!fin) - return false; - std::vector buffer(BUFFER_SIZE, 0); - gzFile fout = gzopen(outputPath, "wb"); - while (!fin.eof()) { - fin.read(buffer.data(), buffer.size()); - std::streamsize s = fin.gcount(); - gzwrite(fout, buffer.data(), s); - } - gzclose(fout); - return true; -} - -*/ - -step TokiSlopeCraft::queryStep() const { return kernelStep; } - -void TokiSlopeCraft::setAiCvterOpt(const AiCvterOpt *_a) { AiOpt = *_a; } - -const AiCvterOpt *TokiSlopeCraft::aiCvterOpt() const { return &AiOpt; } - -bool TokiSlopeCraft::setType(mapTypes type, gameVersion ver, - const bool *allowedBaseColor, - const AbstractBlock *const *const palettes) { - /* - if (kernelStep < colorSetReady) - { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You must load colorset before you set the map type."); - return false; - } - */ - - this->colorset.map_type = type; - this->colorset.mc_version = ver; - - this->colorset.allowed_colorset.need_find_side = - (this->colorset.map_type == mapTypes::Slope); - - this->colorset.palette.resize(64); - - // cerr<<__FILE__<<__LINE__<colorset.palette[i].clear(); - continue; - } - palettes[i]->copyTo(&this->colorset.palette[i]); - - if (this->colorset.palette[i].id.find(':') == - this->colorset.palette[i].id.npos) { - this->colorset.palette[i].id = - "minecraft:" + this->colorset.palette[i].id; - } - - if (this->colorset.palette[i].idOld.empty()) { - this->colorset.palette[i].idOld = this->colorset.palette[i].id; - } - - if (this->colorset.palette[i].idOld.size() > 0 && - (this->colorset.palette[i].idOld.find(':') == - this->colorset.palette[i].idOld.npos)) { - this->colorset.palette[i].idOld = - "minecraft:" + this->colorset.palette[i].idOld; - } - } - - // cerr<<__FILE__<<__LINE__<reportWorkingStatue(this->wind, workStatus::collectingColors); - - Eigen::ArrayXi baseColorVer(64); // 基色对应的版本 - baseColorVer.setConstant((int)SCL_gameVersion::FUTURE); - baseColorVer.segment(0, 52).setConstant((int)SCL_gameVersion::ANCIENT); - baseColorVer.segment(52, 7).setConstant((int)SCL_gameVersion::MC16); - baseColorVer.segment(59, 3).setConstant((int)SCL_gameVersion::MC17); - - bool MIndex[256]; - - for (short index = 0; index < 256; index++) { - MIndex[index] = true; // 默认可以使用这种颜色,逐次判断各个不可以使用的条件 - - if (!allowedBaseColor[index2baseColor( - index)]) { // 在 allowedBaseColor 中被禁止 - MIndex[index] = false; - continue; - } - if (index2baseColor(index) == 0) { // 空气禁用 - MIndex[index] = false; - continue; - } - if ((int)this->colorset.mc_version < - baseColorVer(index2baseColor(index))) { // 版本低于基色版本 - MIndex[index] = false; - continue; - } - if (this->colorset.palette[index2baseColor(index)].id.empty()) { // 空 id - MIndex[index] = false; - continue; - } - /* - if ((mapType == mapTypes::Wall) && - !blockPalette[index2baseColor(index)] - .wallUseable) { //墙面像素画且当前方块不适合墙面 - - MIndex[index] = false; - continue; - }*/ - if (this->isVanilla() && - (index2depth(index) >= 3)) { // 可实装的地图画不允许第四种阴影 - MIndex[index] = false; - continue; - } - if (index2baseColor(index) == 12) { // 如果是水且非墙面 - if (this->isFlat() && index2depth(index) != 2) { // 平板且水深不是 1 格 - MIndex[index] = false; - continue; - } - } else { - if (this->isFlat() && index2depth(index) != 1) { // 平板且阴影不为 1 - MIndex[index] = false; - continue; - } - } - } - - if (!this->colorset.allowed_colorset.apply_allowed(*color_set::basic, - MIndex)) { - std::string msg = - "Too few usable color(s) : only " + - std::to_string(this->colorset.allowed_colorset.color_count()) + - " colors\n"; - msg += "Avaliable base color(s) : "; - - for (int idx = 0; idx < this->colorset.allowed_colorset.color_count(); - idx++) { - msg += std::to_string(this->colorset.allowed_colorset.Map(idx)) + ", "; - } - - this->reportError(this->wind, errorFlag::USEABLE_COLOR_TOO_FEW, msg.data()); - return false; - } - - // GACvter::updateMapColor2GrayLUT(); - - this->reportWorkingStatue(this->wind, workStatus::none); - this->image_cvter.on_color_set_changed(); - - this->kernelStep = SCL_step::wait4Image; - - return true; -} - -uint16_t TokiSlopeCraft::getColorCount() const { - if (kernelStep < SCL_step::wait4Image) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only query for avaliable color count after you set " - "the map type and gameversion"); - return 0; - } - return this->colorset.allowed_colorset.color_count(); -} - -void TokiSlopeCraft::getAvailableColors(ARGB *const ARGBDest, - uint8_t *const mapColorDest, - int *const num) const { - if (num != nullptr) { - *num = getColorCount(); - } - - for (int idx = 0; idx < this->colorset.allowed_colorset.color_count(); - idx++) { - if (mapColorDest != nullptr) { - mapColorDest[idx] = this->colorset.allowed_colorset.Map(idx); - } - - if (ARGBDest != nullptr) { - ARGB r, g, b, a; - if (mapColor2baseColor(this->colorset.allowed_colorset.Map(idx)) != 0) - a = 255; - else - a = 0; - - r = ARGB(this->colorset.allowed_colorset.RGB(idx, 0) * 255); - g = ARGB(this->colorset.allowed_colorset.RGB(idx, 1) * 255); - b = ARGB(this->colorset.allowed_colorset.RGB(idx, 2) * 255); - - ARGBDest[idx] = (a << 24) | (r << 16) | (g << 8) | (b); - } - } -} - -void TokiSlopeCraft::setRawImage(const ARGB *src, int rows, int cols, - bool is_col_major) { - if (kernelStep < SCL_step::wait4Image) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only import the raw image count after you set the map " - "type and gameversion"); - return; - } - if (rows <= 0 || cols <= 0) { - reportError(wind, errorFlag::EMPTY_RAW_IMAGE, - "The size of your raw image is 0. You loaded an empty image."); - return; - } - - this->image_cvter.set_raw_image(src, rows, cols, is_col_major); - - kernelStep = SCL_step::convertionReady; - - return; -} - -void TokiSlopeCraft::getBaseColorInARGB32(ARGB *const dest) const { - if (dest == nullptr) return; - - for (uint8_t base = 0; base < 64; base++) - dest[base] = ARGB32(255 * color_set::basic->RGB(128 + base, 0), - 255 * color_set::basic->RGB(128 + base, 1), - 255 * color_set::basic->RGB(128 + base, 2), 255); -} - -int64_t TokiSlopeCraft::sizePic(short dim) const { - if (dim == 0) return this->image_cvter.rows(); - if (dim == 1) return this->image_cvter.cols(); - return this->image_cvter.size(); -} - -TokiSlopeCraft::ColorSpace TokiSlopeCraft::getColorSpace() const { - switch (this->image_cvter.convert_algo()) { - case SCL_convertAlgo::RGB: - return R; - case SCL_convertAlgo::RGB_Better: - return R; - case SCL_convertAlgo::HSV: - return H; - case SCL_convertAlgo::Lab94: - return L; - case convertAlgo::Lab00: - return L; - case SCL_convertAlgo::XYZ: - return X; - case convertAlgo::gaCvter: - return R; - } - return R; -} - -void TokiSlopeCraft::getConvertedImage(int *rows, int *cols, ARGB *dest, - bool expected_col_major) const { - EImage result = this->getConovertedImage(); - if (rows != nullptr) *rows = result.rows(); - if (cols != nullptr) *cols = result.cols(); - if (!expected_col_major) { - result.transposeInPlace(); - } - if (dest != nullptr) { - memcpy(dest, result.data(), sizeof(ARGB) * sizePic(2)); - } -} - -EImage TokiSlopeCraft::getConovertedImage() const { - EImage cvtedImg(sizePic(0), sizePic(1)); - cvtedImg.setZero(); - if (kernelStep < SCL_step::converted) { - reportError( - wind, errorFlag::HASTY_MANIPULATION, - "You can get the converted image only after you converted a map."); - return cvtedImg; - } - - const auto argbLUT = this->LUT_mapcolor_to_argb(); - - for (short r = 0; r < sizePic(0); r++) { - for (short c = 0; c < sizePic(1); c++) { - const auto map_color = this->image_cvter.color_id(r, c); - if (mapColor2baseColor(map_color) == 0) { // if base ==0 - cvtedImg(r, c) = ARGB32(0, 0, 0, 0); - continue; - } - const int Index = mapColor2Index(map_color); - - cvtedImg(r, c) = argbLUT[Index]; - } - } - return cvtedImg; -} - -std::array TokiSlopeCraft::LUT_mapcolor_to_argb() - const noexcept { - std::array argbLUT; - for (int idx = 0; idx < 256; idx++) { - argbLUT[idx] = - RGB2ARGB(color_set::basic->RGB(idx, 0), color_set::basic->RGB(idx, 1), - color_set::basic->RGB(idx, 2)); - } - return argbLUT; -} - -void TokiSlopeCraft::getConvertedMap(int *rows, int *cols, - unsigned char *dst) const { - if (rows != nullptr) { - *rows = this->image_cvter.rows(); - } - if (cols != nullptr) { - *cols = this->image_cvter.cols(); - } - - Eigen::Map> dest( - dst, getImageRows(), getImageCols()); - - dest = this->image_cvter.color_id(); -} - -int TokiSlopeCraft::getImageRows() const { - if (kernelStep < SCL_step::convertionReady) { - reportError( - wind, errorFlag::HASTY_MANIPULATION, - "You can call getImageRows only after you imported the raw image."); - return -1; - } - return this->image_cvter.rows(); -} - -int TokiSlopeCraft::getImageCols() const { - if (kernelStep < SCL_step::convertionReady) { - reportError( - wind, errorFlag::HASTY_MANIPULATION, - "You can call getImageRows only after you imported the raw image."); - return -1; - } - return this->image_cvter.cols(); -} - -void TokiSlopeCraft::get3DSize(int *x, int *y, int *z) const { - if (kernelStep < SCL_step::builded) return; - if (x != nullptr) *x = schem.x_range(); - if (y != nullptr) *y = schem.y_range(); - if (z != nullptr) *z = schem.z_range(); - return; -} - -int TokiSlopeCraft::getHeight() const { - if (kernelStep < SCL_step::builded) return -1; - return schem.y_range(); -} - -void TokiSlopeCraft::getBlockCounts(int *total, int detail[64]) const { - std::vector temp; - if (total != nullptr) *total = getBlockCounts(&temp); - if (detail != nullptr) - for (uint16_t idx = 0; idx < temp.size(); idx++) { - detail[idx] = temp[idx]; - } -} - -int64_t TokiSlopeCraft::getBlockCounts(std::vector *dest) const { - if (kernelStep < SCL_step::builded) return -1; - - const bool is_dest_nonnull = (dest != nullptr); - if (is_dest_nonnull) { - dest->resize(64); - for (int i = 0; i < 64; i++) dest->at(i) = 0; - } - - int64_t total = 0; - - // map ele_t in schem to index in blockPalette(material index) - std::vector map_ele_to_material; - { - map_ele_to_material.resize(this->colorset.palette.size()); - std::fill(map_ele_to_material.begin(), map_ele_to_material.end(), -1); - - for (int ele = 1; ele < this->schem.palette_size(); ele++) { - std::string_view blkid = this->schem.palette()[ele]; - - const mc_block *sbp = TokiSlopeCraft::find_block_for_idx(ele - 1, blkid); - assert(sbp != nullptr); - - int64_t idx = sbp - this->colorset.palette.data(); - assert(idx >= 0); - assert(idx < (int64_t)this->colorset.palette.size()); - - map_ele_to_material[ele] = idx; - } - } - - for (int i = 0; i < schem.size(); i++) { - if (schem(i) == 0) { - continue; - } - - total++; - if (is_dest_nonnull) { - const int mat_idx = map_ele_to_material[schem(i)]; - assert(mat_idx >= 0); - dest->at(mat_idx)++; - } - } - return total; -} - -int64_t TokiSlopeCraft::getBlockCounts() const { - if (kernelStep < SCL_step::builded) return -1; - int totalCount = 0; - for (int i = 0; i < schem.size(); i++) { - if (schem(i)) totalCount++; - } - return totalCount; -} - -const uint16_t *TokiSlopeCraft::getBuild(int *xSize, int *ySize, - int *zSize) const { - if (xSize != nullptr) *xSize = getXRange(); - if (ySize != nullptr) *ySize = getHeight(); - if (zSize != nullptr) *zSize = getZRange(); - return schem.data(); -} - -int TokiSlopeCraft::getXRange() const { - if (kernelStep < SCL_step::builded) return -1; - return schem.x_range(); -} -int TokiSlopeCraft::getZRange() const { - if (kernelStep < SCL_step::builded) return -1; - return schem.x_range(); -} diff --git a/SlopeCraftL/TokiSlopeCraft.h b/SlopeCraftL/TokiSlopeCraft.h deleted file mode 100644 index 8d94441d..00000000 --- a/SlopeCraftL/TokiSlopeCraft.h +++ /dev/null @@ -1,465 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef TOKISLOPECRAFT_H -#define TOKISLOPECRAFT_H -///////////////////////////// - -///////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Colors.h" -#include "SCLDefines.h" -#include "WaterItem.h" -#include "mc_block.h" -#include - -#include "prim_glass_builder.h" -#include "lossyCompressor.h" - -#include - -#include -#include -#include -#include -#include -#include "WriteStringDeliver.h" -#include "Colorset.h" - -#include -#include - -/* -namespace SlopeCraft -{ - void *AllowedRGBList4AiCvters(); - void *AllowedMapList4AiCvters(); - void *BasicalRGBList4AiCvters(); -} -*/ - -using namespace SlopeCraft; -#include - -class prim_glass_builder; -class lossy_compressor; - -namespace NBT { -template -class NBTWriter; -}; - -class TokiSlopeCraft : public ::SlopeCraft::Kernel { - public: - // static const colorset_basic_t Basic; - // static colorset_allowed_t Allowed; - - [[nodiscard]] color_map_ptrs getAllowedColorMapPtrs() const noexcept; - - // void getColorMapPtrs(const float **const rdata, const float **const gdata, - // const float **const bdata, const uint8_t **, int *); - // full palette - static const float *getBasicColorMapPtrs(); - - static const char *getSCLVersion(); - - static uint64_t mcVersion2VersionNumber(::SCL_gameVersion); - - public: - TokiSlopeCraft(); - virtual ~TokiSlopeCraft(); - - // can do in nothing: - void trySkipStep(step); - /// function ptr to window object - void setWindPtr(void *) override; - /// a function ptr to show progress of converting and exporting - void setProgressRangeSet(void (*)(void *, int, int, int)) override; - /// a function ptr to add progress value - void setProgressAdd(void (*)(void *, int)) override; - /// a function ptr to prevent window from being syncoped - void setKeepAwake(void (*)(void *)) override; - - /// a function ptr to show progress of compressing and bridge-building - void setAlgoProgressRangeSet(void (*)(void *, int, int, int)) override; - /// a function ptr to add progress value of compressing and bridge-building - void setAlgoProgressAdd(void (*)(void *, int)) override; - - /// a function ptr to report error when something wrong happens - void setReportError(void (*)(void *, errorFlag, const char *)) override; - /// a function ptr to report working statue especially when busy - void setReportWorkingStatue(void (*)(void *, workStatus)) override; - size_t size() override { return sizeof(TokiSlopeCraft); } - // void destroy() override { delete this; } - void decreaseStep(step) override; - bool makeTests(const AbstractBlock **, const unsigned char *, const char *, - char *) override; - void setAiCvterOpt(const AiCvterOpt *) override; - const AiCvterOpt *aiCvterOpt() const override; - - // can do in colorSetReady: - step queryStep() const override; - - bool setType(mapTypes, gameVersion, const bool[64], - const AbstractBlock *const *const) override; - - private: - bool __impl_setType(mapTypes, gameVersion, const bool[64], - const AbstractBlock *const *const, - const TokiSlopeCraft *reporter) noexcept; - - public: - void getBaseColorInARGB32(unsigned int *const) const override; - // can do in wait4Image: - void setRawImage(const unsigned int *src, int rows, int cols) override { - this->setRawImage(src, rows, cols, true); - } - - void setRawImage(const uint32_t *src, int rows, int cols, - bool is_col_major) override; - - uint16_t getColorCount() const override; - void getAvailableColors(ARGB *const, uint8_t *const, - int *const num = nullptr) const override; - // can do in convertionReady: - bool convert(convertAlgo = SCL_convertAlgo::RGB_Better, - bool dither = false) override; - const uint32_t *getRawImage() const override { - return this->image_cvter.raw_image().data(); - } - int getImageRows() const override; - int getImageCols() const override; - - bool isVanilla() const override { - return this->colorset.map_type != SCL_mapTypes::FileOnly; - } - - bool isFlat() const override { - return this->colorset.map_type == SCL_mapTypes::Flat; - } - - // can do in converted: - // 构建三维结构 - bool build(compressSettings cs = SCL_compressSettings::noCompress, - unsigned short mah = 256, - glassBridgeSettings gbs = SCL_glassBridgeSettings::noBridge, - unsigned short gi = 3, bool fp = false, bool ep = false) override { - return this->build(build_options{SC_VERSION_U64, mah, gi, cs, gbs, fp, ep}); - } - - bool build(const build_options &option) noexcept override; - - void getConvertedImage(int *rows, int *cols, - unsigned int *dest) const override { - this->getConvertedImage(rows, cols, dest, true); - } - void getConvertedImage(int *rows, int *cols, uint32_t *dest, - bool expected_col_major) const override; - EImage getConovertedImage() const; - void getConvertedMap(int *rows, int *cols, unsigned char *) const override; - // void getConvertedMap(Eigen::Arra) const; - void exportAsData(const char *, const int, int *fileCount, - char **) const override; - std::vector exportAsData(std::string, int) const; - // can do in builded: - void exportAsLitematic(const char *TargetName, const char *LiteName, - const char *RegionName, char *FileName) const override; - std::string exportAsLitematic(std::string_view TargetName, // Local - std::string_view LiteName, // Utf8 - std::string_view RegionName // Utf8 - ) const; - bool exportAsLitematic( - const char *filename_local, - const litematic_options &option) const noexcept override { - auto err = this->exportAsLitematic(filename_local, option.litename_utf8, - option.region_name_utf8); - return err.empty(); - } - - bool exportAsStructure( - const char *filename_local, - const vanilla_structure_options &option) const noexcept override { - auto err = - this->exportAsStructure(filename_local, option.is_air_structure_void); - return err.empty(); - } - - bool exportAsWESchem(const char *filename_local, - const WE_schem_options &option) const noexcept override { - const bool have_req = option.num_required_mods > 0 && - option.required_mods_name_utf8 != nullptr; - std::span sp{}; - - if (have_req) { - sp = {option.required_mods_name_utf8, - option.num_required_mods + option.required_mods_name_utf8}; - } - auto err = this->exportAsWESchem(filename_local, option.offset, - option.we_offset, "", sp); - - return err.empty(); - } - - void exportAsStructure(const char *TargetName, char *FileName) const override; - std::string exportAsStructure(std::string_view filename, - bool is_air_structure_void) const; - - void exportAsWESchem(const char *fileName, const int (&offset)[3], - const int (&weOffset)[3], const char *Name, - const char *const *const requiredMods, - const int requiredModsCount, - char *returnVal) const override; - - std::string exportAsWESchem(std::string_view filename, - std::span offset, - std::span weOffset, - std::string_view Name, - std::span requiredMods) const; - - bool exportAsFlatDiagram( - const char *filename_local, - const flag_diagram_options &option) const noexcept override { - std::string err = this->export_flat_diagram(filename_local, option); - if (option.err != nullptr) { - write_to_sd(option.err, err); - } - return err.empty(); - } - - std::string export_flat_diagram( - std::string_view filename, - const flag_diagram_options &option) const noexcept; - - void get3DSize(int *x, int *y, int *z) const override; - int getHeight() const override; - int getXRange() const override; - int getZRange() const override; - - void getBlockCounts(int *total, int detail[64]) const override; - int64_t getBlockCounts(std::vector *) const; - int64_t getBlockCounts() const override; - - const uint16_t *getBuild(int *xSize, int *ySize, int *zSize) const override; - - // const Eigen::Tensor &getBuild() const; - - private: - // friend class TokiColor; - // friend void * allowedRGB(); - // friend void * allowedMap(); - enum ColorSpace { R = 'R', H = 'H', L = 'L', X = 'X' }; - // static const Eigen::Array DitherMapLR, DitherMapRL; - static const uint32_t reportRate = 100; - - void *wind; - void (*progressRangeSet)(void *, int, int, int); - void (*progressAdd)(void *, int); - void (*keepAwake)(void *); - void (*algoProgressRangeSet)(void *, int, int, int); - void (*algoProgressAdd)(void *, int); - void (*reportError)(void *, errorFlag, const char *); - void (*reportWorkingStatue)(void *, workStatus); - - public: - step kernelStep; - color_set colorset; - // convertAlgo ConvertAlgo; - - libMapImageCvt::MapImageCvter image_cvter; - - // std::array size3D; // x,y,z - std::unique_ptr glassBuilder; - std::unique_ptr Compressor; - - // std::shared_ptr GAConverter{nullptr}; - - AiCvterOpt AiOpt; - Eigen::ArrayXXi mapPic; // stores mapColor - /* - Eigen::ArrayXXi Base; - Eigen::ArrayXXi HighMap; - Eigen::ArrayXXi LowMap; - std::unordered_map WaterList; - */ - - build_options build_opt; - libSchem::Schem schem; - - std::optional cache_dir{""}; - // Eigen::Tensor Build; // x,y,z - - // for setType: - - // for setImage: - - // for convert: - ColorSpace getColorSpace() const; - int64_t sizePic(short dim) const; - - // for build - // void makeHeight_old();//构建 HighMap 和 LowMap - void makeHeight_new(Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, - Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList); - // void makeHeightInLine(const uint16_t c); - void buildHeight(bool fireProof, bool endermanProof, - const Eigen::ArrayXXi &Base, const Eigen::ArrayXXi &HighMap, - const Eigen::ArrayXXi &LowMap, - const std::unordered_map - &WaterList); // 构建 Build - void makeBridge(); - // for Litematic - /* - static void writeBlock(const std::string &netBlockId, - const std::vector &Property, - const std::vector &ProVal, - NBT::NBTWriter &); - static void writeTrash(int count, NBT::NBTWriter &); - */ - std::string Noder(const short *src, int size) const; - - Kernel *toBaseClassPtr() { return this; } - - void setCacheDir(const char *) noexcept override; - const char *cacheDir() const noexcept override; - - bool saveConvertCache(StringDeliver &_err) const noexcept override { - std::string err; - this->save_convert_cache(err); - write_to_sd(&_err, err); - return err.empty(); - } - - bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept override { - return this->load_convert_cache(algo, dither); - } - - int getSchemPalette(const char **dest_id, - size_t dest_capacity) const noexcept override; - - bool saveBuildCache(StringDeliver &_err) const noexcept override { - std::string err; - this->save_build_cache(err); - write_to_sd(&_err, err); - return err.empty(); - } - - bool loadBuildCache(const build_options &option) noexcept override { - return this->load_build_cache(option); - } - - bool makeTests(const char *filename, - const test_blocklist_options &option) const noexcept override { - std::string err = this->impl_make_tests(filename, option); - if (option.err != nullptr) { - write_to_sd(option.err, err); - } - return err.empty(); - } - - void getCompressedImage(int *row, int *cols, uint32_t *dest, - bool expected_col_major) const noexcept override; - - std::string impl_make_tests( - std::string_view filename, - const test_blocklist_options &option) const noexcept; - - private: - // determined by mcver, map type and allowed colorest - std::vector type_hash() const noexcept; - std::string type_dir_of(std::string_view root_cache_dir) const noexcept; - inline std::string current_type_dir() const noexcept { - return type_dir_of(this->cache_dir.value()); - } - std::string type_hash_filename() const noexcept; - std::string save_type_hash() const noexcept; - bool check_type_hash() const noexcept; - - // determined by image, convert algo and dither - static std::string convert_dir(std::string_view type_dir, - uint64_t task_hash) noexcept; - std::string convert_dir_of(SCL_convertAlgo algo, bool dither) const noexcept; - std::string current_convert_dir() const noexcept; - static std::string convert_cache_filename_of( - std::string_view convert_dir) noexcept; - std::string current_convert_cache_filename() const noexcept; - void save_convert_cache(std::string &err) const noexcept; - bool load_convert_cache(SCL_convertAlgo algo, bool dither) noexcept; - - // determined by mapPic, palette from type and build_options - static std::vector build_task_hash_of( - const Eigen::ArrayXXi &mapPic, std::span blkids, - const build_options &opt) noexcept; - std::vector current_build_task_hash() const noexcept; - static std::string build_dir_of(std::string_view convert_dir, - uint64_t short_hash) noexcept; - std::string current_build_dir() const noexcept; - static std::string build_cache_filename_of( - std::string_view build_dir) noexcept; - std::string current_build_cache_filename() const noexcept; - void save_build_cache(std::string &err) const noexcept; - struct build_cache_ir { - Eigen::ArrayXXi mapPic; - build_options build_option; - libSchem::Schem schem; - }; - static std::string build_hash_filename_of( - std::string_view build_dir) noexcept; - bool examine_build_cache(const build_options &opt, - std::span expected_sha3_512, - build_cache_ir *ir) const noexcept; - bool load_build_cache(const build_options &opt) noexcept; - - private: - std::vector schem_block_id_list() const noexcept; - - static std::string build_task_dir(std::string_view cvt_task_dir, - uint64_t build_task_hash) noexcept; - std::string build_task_dir() const noexcept; - static std::string build_cache_filename( - std::string_view build_task_dir) noexcept; - - static bool exmaine_build_cache(std::string_view filename, - uint64_t build_task_hash, - build_cache_ir *ir = nullptr) noexcept; - - const mc_block *find_block_for_idx(int idx, - std::string_view blkid) const noexcept; - - std::array LUT_mapcolor_to_argb() const noexcept; - - public: - size_t getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) const noexcept override; -}; - -// bool compressFile(const char *sourcePath, const char *destPath); -#endif // TOKISLOPECRAFT_H diff --git a/SlopeCraftL/TokiSlopeCraft_build.cpp b/SlopeCraftL/TokiSlopeCraft_build.cpp deleted file mode 100644 index 38f196c4..00000000 --- a/SlopeCraftL/TokiSlopeCraft_build.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ -#include -#include "TokiSlopeCraft.h" - -bool TokiSlopeCraft::makeTests(const AbstractBlock **src, - const unsigned char *baseColor, const char *dst, - char *_unFileName) { - if (kernelStep < step::wait4Image) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "Skipping is not allowed.\nYou can only make tests only after " - "you finished the map type and gameversion."); - - if (_unFileName != nullptr) *_unFileName = '\0'; - - return false; - } - size_t blk_count{0}; - for (;; blk_count++) { - if (src[blk_count] == nullptr) { - break; - } - } - test_blocklist_options opt; - opt.block_ptrs = src; - opt.basecolors = baseColor; - opt.block_count = blk_count; - std::string err = this->impl_make_tests(dst, opt); - - if (_unFileName != nullptr) std::strcpy(_unFileName, err.data()); - - return err.empty(); -} - -std::string TokiSlopeCraft::impl_make_tests( - std::string_view filename, - const test_blocklist_options &option) const noexcept { - if (!filename.ends_with(".nbt")) { - return "File name should ends with \".nbt\""; - } - libSchem::Schem test; - test.set_MC_major_version_number(this->colorset.mc_version); - test.set_MC_version_number( - MCDataVersion::suggested_version(this->colorset.mc_version)); - // const mc_block ** realSrc=(const mc_block **)src; - std::vector realSrc; - std::vector realBaseColor; - realSrc.clear(); - realBaseColor.clear(); - for (size_t idx = 0; idx < option.block_count; idx++) { - if (option.block_ptrs[idx]->getVersion() > (int)this->colorset.mc_version) { - continue; - } - realSrc.emplace_back(static_cast(option.block_ptrs[idx])); - realBaseColor.emplace_back(option.basecolors[idx]); - } - - std::vector> blocks; - blocks.resize(64); - - for (uint32_t idx = 0; idx < realSrc.size(); idx++) { - blocks[realBaseColor[idx]].push_back(idx); - } - - { - std::vector ids; - ids.reserve(realSrc.size() + 1); - ids.emplace_back("minecraft:air"); - for (auto i : realSrc) { - ids.emplace_back(i->idForVersion(this->colorset.mc_version)); - } - - test.set_block_id(ids.data(), ids.size()); - } - - int xSize = 0; - constexpr int zSize = 64, ySize = 2; - for (const auto &it : blocks) { - xSize = std::max(size_t(xSize), it.size()); - } - test.resize(xSize + 1, ySize, zSize); - test.set_zero(); - - for (uint8_t base = 0; base < 64; base++) { - for (uint32_t idx = 0; idx < blocks[base].size(); idx++) { - int xPos = idx; - int yPos = 0; - int zPos = base; - - test(xPos, yPos, zPos) = blocks[base][idx] + 1; - } - test(blocks[base].size(), 1, base) = 1; // glass block - } - - SCL_errorFlag err; - std::string detail; - const bool success = test.export_structure(filename, true, &err, &detail); - - if (!success) { - return fmt::format( - "Failed to export structure file {}, error code = {}, detail: {}", - filename, int(err), detail); - } else { - return {}; - } -} - -void TokiSlopeCraft::exportAsLitematic(const char *TargetName, - const char *LiteName, - const char *RegionName, - char *FileName) const { - std::string temp = exportAsLitematic(TargetName, LiteName, RegionName); - - if (FileName != nullptr) std::strcpy(temp.data(), FileName); -} - -std::string TokiSlopeCraft::exportAsLitematic( - std::string_view TargetName, std::string_view LiteName, - std::string_view RegionName) const { - if (kernelStep < SCL_step::builded) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only export a map to litematic after you build the 3D " - "structure."); - return "Too hasty! export litematic after you built!"; - } - reportWorkingStatue(wind, workStatus::writingMetaInfo); - progressRangeSet(wind, 0, 100 + schem.size(), 0); - - libSchem::litematic_info info; - info.litename_utf8 = LiteName; - info.regionname_utf8 = RegionName; - - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool success = - schem.export_litematic(TargetName, info, &flag, &error_string); - - if (!success) { - // this->reportError(this->wind,errorFlag::) - this->reportError(this->wind, flag, error_string.data()); - - return "Failed to export as litematic.\n" + error_string; - } - - progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatus::none); - - return ""; -} - -std::vector TokiSlopeCraft::schem_block_id_list() - const noexcept { - std::vector temp; - temp.reserve(64); - temp.emplace_back("minecraft:air"); - - for (const auto &block : this->colorset.palette) { - std::string_view id_at_curversion = - block.idForVersion(this->colorset.mc_version); - if ("minecraft:air" == id_at_curversion) { - break; - } else { - temp.emplace_back(id_at_curversion); - } - } - return temp; -} - -bool TokiSlopeCraft::build(const build_options &option) noexcept { - /* - bool TokiSlopeCraft::build(compressSettings cS, uint16_t mAH, - glassBridgeSettings gBS, uint16_t bI, bool - fireProof, bool endermanProof){ - */ - - if (kernelStep < SCL_step::converted) { - reportError( - wind, errorFlag::HASTY_MANIPULATION, - "You can build 3D strcuture only after you converted the raw image."); - cerr << "hasty!" << endl; - return false; - } - if (option.max_allowed_height < 14) { - cerr << "max_allowed_height is less than 14!" << endl; - reportError(wind, errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, - "Your maximum allowed height is less than 14, which made lossy " - "compressing almost impossible."); - return false; - } - // cerr << "Setting block palette..." << endl; - { - auto temp = this->schem_block_id_list(); - schem.set_block_id(temp); - } - - schem.set_MC_major_version_number(this->colorset.mc_version); - schem.set_MC_version_number(MCDataVersion::MCDataVersion_t( - TokiSlopeCraft::mcVersion2VersionNumber(this->colorset.mc_version))); - - // cerr << "ready to build" << endl; - - this->build_opt.compress_method = option.compress_method; - this->build_opt.glass_method = option.glass_method; - if (isFlat() || !isVanilla()) { - this->build_opt.compress_method = compressSettings::noCompress; - this->build_opt.glass_method = glassBridgeSettings::noBridge; - } - - this->build_opt = option; - - reportWorkingStatue(wind, workStatus::buidingHeighMap); - - progressRangeSet(wind, 0, 9 * sizePic(2), 0); - // cerr << "start makeHeight" << endl; - { - Eigen::ArrayXXi Base, HighMap, LowMap; - std::unordered_map WaterList; - progressAdd(wind, sizePic(2)); - - makeHeight_new(Base, HighMap, LowMap, WaterList); - // cerr << "makeHeight finished" << endl; - progressRangeSet(wind, 0, 9 * sizePic(2), 5 * sizePic(2)); - - reportWorkingStatue(wind, workStatus::building3D); - // cerr << "start buildHeight" << endl; - buildHeight(this->build_opt.fire_proof, this->build_opt.enderman_proof, - Base, HighMap, LowMap, WaterList); - // cerr << "buildHeight finished" << endl; - progressRangeSet(wind, 0, 9 * sizePic(2), 8 * sizePic(2)); - - reportWorkingStatue(wind, workStatus::constructingBridges); - // cerr << "start makeBridge" << endl; - makeBridge(); - } - - if (option.connect_mushrooms) { - this->schem.process_mushroom_states_fast(); - } - // cerr << "makeBridge finished" << endl; - progressRangeSet(wind, 0, 9 * sizePic(2), 9 * sizePic(2)); - - reportWorkingStatue(wind, workStatus::none); - - kernelStep = SCL_step::builded; - - return true; -} - -void TokiSlopeCraft::makeHeight_new( - Eigen::ArrayXXi &Base, Eigen::ArrayXXi &HighMap, Eigen::ArrayXXi &LowMap, - std::unordered_map &WaterList) { - Base.setZero(sizePic(0) + 1, sizePic(1)); - HighMap.setZero(sizePic(0) + 1, sizePic(1)); - LowMap.setZero(sizePic(0) + 1, sizePic(1)); - WaterList.clear(); - bool allowNaturalCompress = - this->build_opt.compress_method == compressSettings::Both || - this->build_opt.compress_method == compressSettings::NaturalOnly; - // std::vector src; - // cerr << "makeHeight_new\n"; - - if ((this->mapPic - 4 * (this->mapPic / 4) >= 3).any()) { - std::string msg = - "Fatal error : SlopeCraftL found map color with depth 3 in a " - "vanilla map.\n Map contents (map color matrix in col-major) :\n["; - - for (int c = 0; c < this->mapPic.cols(); c++) { - for (int r = 0; r < this->mapPic.rows(); r++) { - msg += std::to_string(this->mapPic(r, c)) + ','; - } - msg += ";\n"; - } - msg += "];\n"; - - reportError(wind, errorFlag::DEPTH_3_IN_VANILLA_MAP, msg.data()); - return; - } - - for (uint16_t c = 0; c < sizePic(1); c++) { - // cerr << "Coloumn " << c << '\n'; - height_line HL; - // getTokiColorPtr(c,&src[0]); - HL.make(this->mapPic.col(c), allowNaturalCompress); - - if (HL.maxHeight() > this->build_opt.max_allowed_height && - (this->build_opt.compress_method == compressSettings::ForcedOnly || - this->build_opt.compress_method == compressSettings::Both)) { - std::vector ptr(getImageRows()); - - this->image_cvter.col_TokiColor_ptrs(c, ptr.data()); - // getTokiColorPtr(c, &ptr[0]); - - Compressor->setSource(HL.getBase(), &ptr[0]); - bool success = Compressor->compress(this->build_opt.max_allowed_height, - allowNaturalCompress); - if (!success) { - std::string msg = "Failed to compress the 3D structure at coloum " + - std::to_string(c); - reportError(wind, SCL_errorFlag::LOSSYCOMPRESS_FAILED, msg.data()); - return; - } - Eigen::ArrayXi temp; - HL.make(&ptr[0], Compressor->getResult(), allowNaturalCompress, &temp); - this->mapPic.col(c) = temp; - } - - Base.col(c) = HL.getBase(); - HighMap.col(c) = HL.getHighLine(); - LowMap.col(c) = HL.getLowLine(); - auto HLM = &HL.getWaterMap(); - - for (auto it = HLM->cbegin(); it != HLM->cend(); it++) { - WaterList[rc_pos{static_cast(it->first), c}] = it->second; - } - - progressAdd(wind, 4 * sizePic(0)); - } - // cerr << "makeHeight_new finished\n"; - schem.resize(2 + sizePic(1), HighMap.maxCoeff() + 1, 2 + sizePic(0)); - schem.set_zero(); - // schem.z_range() = 2 + sizePic(0); // z - // schem.x_range() = 2 + sizePic(1); // x - // schem.y_range() = HighMap.maxCoeff() + 1; // y -} - -void TokiSlopeCraft::buildHeight( - bool fireProof, bool endermanProof, const Eigen::ArrayXXi &Base, - const Eigen::ArrayXXi &, const Eigen::ArrayXXi &LowMap, - const std::unordered_map &WaterList) { - /* -{ - std::array tempSize3D({schem.x_range(), schem.y_range(), -schem.z_range()}); Build.resize(tempSize3D); -} -*/ - schem.set_zero(); - // Base(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) - // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 - // 对应空气 - // int x = 0, y = 0, z = 0; - // int yLow = 0; - - // cerr << WaterList.size() << " water columns in map\n"; - for (auto it = WaterList.begin(); it != WaterList.end(); - it++) // 水柱周围的玻璃 - { - const int x = it->first.col + 1; - const int z = it->first.row; - const int y = it->second.high_y; - const int yLow = it->second.low_y; - schem(x, y + 1, z) = 0 + 1; // 柱顶玻璃 - for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { - schem(x - 1, yDynamic, z - 0) = 1; - schem(x + 1, yDynamic, z + 0) = 1; - schem(x + 0, yDynamic, z - 1) = 1; - schem(x + 0, yDynamic, z + 1) = 1; - } - if (yLow >= 1) schem(x, yLow - 1, z) = 1; // 柱底玻璃 - } - - progressAdd(wind, sizePic(2)); - - for (short r = -1; r < sizePic(0); r++) // 普通方块 - { - for (short c = 0; c < sizePic(1); c++) { - if (Base(r + 1, c) == 12 || Base(r + 1, c) == 0) continue; - const int x = c + 1; - const int y = LowMap(r + 1, c); - const int z = r + 1; - if (y >= 1 && this->colorset.palette[Base(r + 1, c)].needGlass) - schem(x, y - 1, z) = 0 + 1; - if ((fireProof && this->colorset.palette[Base(r + 1, c)].burnable) || - (endermanProof && - this->colorset.palette[Base(r + 1, c)].endermanPickable)) { - if (y >= 1 && schem(x, y - 1, z) == 0) schem(x, y - 1, z) = 0 + 1; - if (x >= 1 && schem(x - 1, y, z) == 0) schem(x - 1, y, z) = 0 + 1; - if (z >= 1 && schem(x, y, z - 1) == 0) schem(x, y, z - 1) = 0 + 1; - if (y + 1 < schem.y_range() && schem(x, y + 1, z) == 0) - schem(x, y + 1, z) = 0 + 1; - if (x + 1 < schem.x_range() && schem(x + 1, y, z) == 0) - schem(x + 1, y, z) = 0 + 1; - if (z + 1 < schem.z_range() && schem(x, y, z + 1) == 0) - schem(x, y, z + 1) = 0 + 1; - } - - schem(x, y, z) = Base(r + 1, c) + 1; - } - progressAdd(wind, sizePic(1)); - } - - progressAdd(wind, sizePic(2)); - - for (auto it = WaterList.cbegin(); it != WaterList.cend(); ++it) { - const int x = it->first.col + 1; - const int z = it->first.row; - const int y = it->second.high_y; - const int yLow = it->second.low_y; - for (int yDynamic = yLow; yDynamic <= y; yDynamic++) { - schem(x, yDynamic, z) = 13; - } - } - /* - for(short c=0;ccolorset.map_type != mapTypes::Slope) return; - if (this->build_opt.glass_method != glassBridgeSettings::withBridge) return; - - int step = sizePic(2) / schem.y_range(); - - algoProgressRangeSet(wind, 0, 100, 0); - - for (uint32_t y = 0; y < schem.y_range(); y++) { - keepAwake(wind); - progressAdd(wind, step); - if (y % (this->build_opt.bridge_interval + 1) == 0) { - std::array start, extension; // x,z,y - start[0] = 0; - start[1] = 0; - start[2] = y; - extension[0] = schem.x_range(); - extension[1] = schem.z_range(); - extension[2] = 1; - TokiMap targetMap = ySlice2TokiMap_u16(schem.tensor(), start, extension); - glassMap glass; - // cerr << "Construct glass bridge at y=" << y << endl; - glass = glassBuilder->makeBridge(targetMap); - for (int r = 0; r < glass.rows(); r++) - for (int c = 0; c < glass.cols(); c++) - if (schem(r, y, c) == prim_glass_builder::air && - glass(r, c) == prim_glass_builder::glass) - schem(r, y, c) = prim_glass_builder::glass; - } else { - continue; - } - } - algoProgressRangeSet(wind, 0, 100, 100); - cerr << "makeBridge finished\n"; -} - -void TokiSlopeCraft::exportAsStructure(const char *TargetName, - char *FileName) const { - std::string temp = exportAsStructure(TargetName, true); - - if (FileName != nullptr) std::strcpy(temp.data(), FileName); -} - -std::string TokiSlopeCraft::exportAsStructure( - std::string_view filename, bool is_air_structure_void) const { - if (kernelStep < SCL_step::builded) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only export a map to structure after you build the 3D " - "structure."); - return "Too hasty! export structure after you built!"; - } - - reportWorkingStatue(wind, workStatus::writingMetaInfo); - progressRangeSet(wind, 0, 100 + schem.size(), 0); - - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool success = schem.export_structure(filename, is_air_structure_void, - &flag, &error_string); - - if (!success) { - this->reportError(this->wind, flag, error_string.data()); - return "Failed to export structure.\n" + error_string; - } - - progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatus::none); - - return ""; -} - -void TokiSlopeCraft::exportAsWESchem(const char *fileName, - const int (&offset)[3], - const int (&weOffset)[3], const char *Name, - const char *const *const requiredMods, - const int requiredModsCount, - char *returnVal) const { - if (fileName == nullptr || strlen(fileName) == 0) { - return; - } - - const std::array _offset({offset[0], offset[1], offset[2]}); - const std::array _weOffset({weOffset[0], weOffset[1], weOffset[2]}); - - std::vector _reqMods; - _reqMods.reserve(requiredModsCount); - if (requiredMods != nullptr) - for (int idx = 0; idx < requiredModsCount; idx++) { - if (requiredMods[idx] == nullptr) continue; - _reqMods.emplace_back(requiredMods[idx]); - } - - const std::string retVal = - this->exportAsWESchem(fileName, _offset, _weOffset, Name, _reqMods); - if (returnVal != nullptr) { - strcpy(returnVal, retVal.data()); - } - return; -} - -std::string TokiSlopeCraft::exportAsWESchem( - std::string_view filename, std::span offset, - std::span weOffset, std::string_view Name, - std::span requiredMods) const { - if (kernelStep < SCL_step::builded) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only export a map to structure after you build the 3D " - "structure."); - return "Too hasty! export structure after you built!"; - } - - // progress bar value : 10(open+others) + 64(palette) + Build + 10 - // (others+compress+remove) - - progressRangeSet(wind, 0, 100, 0); - - libSchem::WorldEditSchem_info info; - - info.schem_name_utf8 = Name; - memcpy(info.offset.data(), offset.data(), sizeof(info.offset)); - memcpy(info.WE_offset.data(), weOffset.data(), sizeof(info.WE_offset)); - - info.required_mods_utf8.resize(requiredMods.size()); - - for (int idx = 0; idx < int(requiredMods.size()); idx++) { - info.required_mods_utf8[idx] = requiredMods[idx]; - } - - progressRangeSet(wind, 0, 100, 5); - - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool success = - schem.export_WESchem(filename, info, &flag, &error_string); - - if (!success) { - this->reportError(this->wind, flag, error_string.data()); - return "Failed to export as WE schem files.\n" + error_string; - } - - progressRangeSet(wind, 0, 100, 100); - - return ""; -} - -int TokiSlopeCraft::getSchemPalette(const char **dest_id, - size_t dest_capacity) const noexcept { - if (kernelStep < SCL_step::builded) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only export a map to structure after you build the 3D " - "structure."); - return -1; - } - - const int ret = this->schem.palette_size(); - - if (dest_id == nullptr || dest_capacity <= 0) { - return ret; - } - - size_t write_counter = 0; - for (const auto &id : this->schem.palette()) { - if (write_counter < dest_capacity) { - dest_id[write_counter] = id.c_str(); - write_counter++; - } - } - - return ret; -} - -#include - -std::string TokiSlopeCraft::export_flat_diagram( - std::string_view filename, - const flag_diagram_options &option) const noexcept { - if (kernelStep < SCL_step::builded) { - return "You can only export a flat diagram after you build the 3D " - "structure."; - } - - if (this->colorset.map_type != SCL_mapTypes::Flat) { - return "Only flat maps can be exported to flat diagram."; - } - - libFlatDiagram::fd_option fdopt; - // set up fdopt - { - fdopt.row_start = 0; - fdopt.row_end = this->schem.z_range(); - fdopt.cols = this->schem.x_range(); - fdopt.split_line_row_margin = option.split_line_row_margin; - fdopt.split_line_col_margin = option.split_line_col_margin; - fdopt.png_compress_level = option.png_compress_level; - fdopt.png_compress_memory_level = option.png_compress_memory_level; - } - - std::vector> img_list_rmj; - img_list_rmj.reserve(this->schem.palette_size()); - - for (int pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { - if (pblkid == 0) { - img_list_rmj.emplace_back(); - img_list_rmj[0].setZero(); - continue; - } - std::string_view id = this->schem.palette()[pblkid]; - const mc_block *blkp = TokiSlopeCraft::find_block_for_idx(pblkid - 1, id); - if (blkp == nullptr) { - std::string blkid_full; - blkid_full.reserve(64 * 2048); - for (const auto &blk : this->colorset.palette) { - blkid_full += blk.id; - blkid_full.push_back('\n'); - } - - return fmt::format( - "SlopeCraftL internal error. Failed to find block image for \"{}\". " - "In the 3d structure, the corresponding block idx is {}.\nThe whole " - "block palette is as below: {}", - id, pblkid, blkid_full); - } - - img_list_rmj.emplace_back(blkp->image.transpose()); - } - - auto block_at_callback = [this, &img_list_rmj]( - int64_t r, - int64_t c) -> libFlatDiagram::block_img_ref_t { - if (r < 0 || c < 0 || r >= this->schem.z_range() || - c >= this->schem.x_range()) { - return libFlatDiagram::block_img_ref_t{img_list_rmj.at(0).data()}; - } - - const int ele = this->schem(c, 0, r); - assert(ele >= 0 && ele < this->schem.palette_size()); - - return libFlatDiagram::block_img_ref_t{img_list_rmj.at(ele).data()}; - }; - - std::array, 4> txt{ - std::make_pair( - "Title", "Flat diagram generated by SlopeCraftL."), - std::make_pair("Software", "SlopeCraftL"), - std::make_pair( - "Description", - "This image is a flat diagram created by SlopeCraftL, which is is " - "a subproject of SlopeCraft, developed by TokiNoBug."), - std::make_pair( - "Comment", - "SlopeCraft is a free software published " - "under GPLv3 license. You can find " - "its repository at https://github.com/SlopeCraft/SlopeCraft")}; - - auto err = libFlatDiagram::export_flat_diagram(filename, fdopt, - block_at_callback, txt); - - if (err.empty()) { - return {}; - } - - return fmt::format("Failed to export flat diagram. Details: {}", err); -} - -void TokiSlopeCraft::getCompressedImage( - int *rows, int *cols, uint32_t *dest_ptr, - bool expected_col_major) const noexcept { - if (kernelStep < SCL_step::builded) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can only export a map to structure after you build the 3D " - "structure."); - return; - } - - if (rows != nullptr) { - *rows = this->image_cvter.rows(); - } - if (cols != nullptr) { - *cols = this->image_cvter.cols(); - } - - if (dest_ptr == nullptr) { - return; - } - - const auto LUT = this->LUT_mapcolor_to_argb(); - - auto fun = [this, &LUT](auto &dst) { - for (int r = 0; r < this->image_cvter.rows(); r++) { - for (int c = 0; c < this->image_cvter.cols(); c++) { - const auto map_color = this->mapPic(r, c); - if (mapColor2baseColor(map_color) == 0) { // if base ==0 - dst(r, c) = ARGB32(0, 0, 0, 0); - continue; - } - const int index = mapColor2Index(map_color); - dst(r, c) = LUT[index]; - } - } - }; - - if (expected_col_major) { - Eigen::Map dest{dest_ptr, this->image_cvter.rows(), - this->image_cvter.cols()}; - fun(dest); - } else { - Eigen::Map< - Eigen::Array> - dest{dest_ptr, this->image_cvter.rows(), this->image_cvter.cols()}; - fun(dest); - } -} \ No newline at end of file diff --git a/SlopeCraftL/TokiSlopeCraft_cache.cpp b/SlopeCraftL/TokiSlopeCraft_cache.cpp deleted file mode 100644 index 96ba693e..00000000 --- a/SlopeCraftL/TokiSlopeCraft_cache.cpp +++ /dev/null @@ -1,430 +0,0 @@ -#include "TokiSlopeCraft.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -namespace stdfs = std::filesystem; -// common utilities ------------------------------------ -std::string write_hash(std::string_view filename, - std::span hash) noexcept { - std::ofstream ofs{filename.data(), std::ios::binary}; - - if (!ofs) { - return fmt::format("ofstream failed to open hash file: {}", filename); - } - - ofs.write((const char *)hash.data(), sizeof(uint8_t) * hash.size()); - ofs.close(); - return {}; -} - -bool examine_hash_file(std::string_view filename, - std::span expected) noexcept { - if (!stdfs::is_regular_file(filename)) { - return false; - } - const uint64_t filesize = stdfs::file_size(filename); - if (filesize != expected.size()) { - return false; - } - { - std::ifstream ifs{filename.data(), std::ios::binary}; - if (!ifs) { - return false; - } - - for (uint8_t exp_val : expected) { - uint8_t val{0}; - ifs.read((char *)&val, sizeof(val)); - if (val != exp_val) { - return false; - } - } - ifs.close(); - } - - return true; -} - -bool create_dir_r_if_not_exist(std::string_view dir, - std::string &err) noexcept { - err.clear(); - if (stdfs::is_directory(dir)) { - return true; - } - std::error_code ec; - if (stdfs::create_directories(dir, ec)) { - return true; - } - - err = fmt::format( - "Cache directory \"{}\" does not exists, and std::filesystem failed to " - "create this dir. Error code = {}, message = {}.", - dir, ec.value(), ec.message()); - return false; -} - -void TokiSlopeCraft::setCacheDir(const char *d) noexcept { - this->cache_dir = d; - - std::filesystem::create_directories(d); -} -const char *TokiSlopeCraft::cacheDir() const noexcept { - if (this->cache_dir.has_value()) { - return this->cache_dir.value().c_str(); - } - - return nullptr; -} - -const std::string_view hash_suffix{".sha3_512"}; - -uint64_t to_short_hash(std::span full_hash) noexcept { - assert(full_hash.size() >= 8); - return *reinterpret_cast(full_hash.data()); - /* - uint64_t ret = 0; - std::span hash_u64{(const uint64_t *)full_hash.data(), - full_hash.size() / sizeof(uint64_t)}; - for (uint64_t val : hash_u64) { - ret = ret ^ val; - } - return ret; - */ -} -// type hash and dir ------------------------------------ -std::vector TokiSlopeCraft::type_hash() const noexcept { - // Chocobo1::SHA3_512 hash; - boost::uuids::detail::sha1 hash; - SC_HASH_ADD_DATA(hash, this->colorset.map_type); - SC_HASH_ADD_DATA(hash, this->colorset.mc_version); - - this->colorset.allowed_colorset.hash_add_data(hash); - - boost::uuids::detail::sha1::digest_type digest; - hash.get_digest(digest); - std::span dig{reinterpret_cast(digest), - sizeof(digest)}; - - return {dig.begin(), dig.end()}; -} - -std::string TokiSlopeCraft::type_dir_of( - std::string_view cache_dir) const noexcept { - return fmt::format("{}/{:x}", cache_dir, to_short_hash(this->type_hash())); -} - -std::string TokiSlopeCraft::type_hash_filename() const noexcept { - assert(this->kernelStep >= SCL_step::wait4Image); - return fmt::format("{}/{}{}", this->current_type_dir(), "type", hash_suffix); -} - -std::string TokiSlopeCraft::save_type_hash() const noexcept { - if (this->kernelStep < SCL_step::wait4Image) { - return "Set map type before you export type hash."; - } - std::string err; - if (!create_dir_r_if_not_exist(this->current_type_dir(), err)) { - return err; - } - - err = write_hash(this->type_hash_filename(), this->type_hash()); - return err; -} - -bool TokiSlopeCraft::check_type_hash() const noexcept { - return examine_hash_file(this->type_hash_filename(), this->type_hash()); -} - -// convert hash, dir and cache ------------------------------------ -std::string TokiSlopeCraft::convert_dir(std::string_view type_dir, - uint64_t short_hash) noexcept { - return fmt::format("{}/{:x}", type_dir, short_hash); -} - -std::string TokiSlopeCraft::convert_dir_of(SCL_convertAlgo algo, - bool dither) const noexcept { - assert(this->kernelStep >= SCL_step::convertionReady); - return convert_dir(this->current_type_dir(), - this->image_cvter.task_hash(algo, dither)); -} - -std::string TokiSlopeCraft::current_convert_dir() const noexcept { - assert(this->kernelStep >= SCL_step::converted); - return this->convert_dir_of(this->image_cvter.convert_algo(), - this->image_cvter.is_dither()); -} - -std::string TokiSlopeCraft::convert_cache_filename_of( - std::string_view convert_dir) noexcept { - return fmt::format("{}/convert", convert_dir); -} - -std::string TokiSlopeCraft::current_convert_cache_filename() const noexcept { - assert(this->kernelStep >= SCL_step::converted); - return convert_cache_filename_of(this->current_convert_dir()); -} - -void TokiSlopeCraft::save_convert_cache(std::string &err) const noexcept { - err.clear(); - if (this->kernelStep < SlopeCraft::step::converted) { - err = "Can not save cache before the image is converted."; - return; - } - this->save_type_hash(); - const std::string convert_dir = this->current_convert_dir(); - if (!create_dir_r_if_not_exist(convert_dir, err)) { - return; - } - - std::string filename = convert_cache_filename_of(convert_dir); - if (!this->image_cvter.save_cache(filename.c_str())) { - err = fmt::format("this->image_cvter.save_cache failed to create {}", - filename); - return; - } - return; -} - -bool TokiSlopeCraft::load_convert_cache(SCL_convertAlgo algo, - bool dither) noexcept { - if (this->kernelStep < SlopeCraft::step::convertionReady) { - // "Can not save cache before the image is converted."; - return false; - } - - if (!this->check_type_hash()) { // type hash mismatch - return false; - } - - libMapImageCvt::MapImageCvter temp{*color_set::basic, - this->colorset.allowed_colorset}; - const uint64_t expected_hash = this->image_cvter.task_hash(algo, dither); - const std::string filename = this->convert_cache_filename_of( - convert_dir(this->current_type_dir(), expected_hash)); - if (!this->image_cvter.load_cache(filename.c_str(), expected_hash)) { - return false; - } - - this->mapPic = this->image_cvter.mapcolor_matrix().cast(); - this->kernelStep = SCL_step::converted; - return true; -} - -// build hash, dir and cache ------------------------------------ -namespace cereal { -template -void save(archive &ar, const build_options &opt) noexcept { - ar(opt.max_allowed_height, opt.bridge_interval, opt.compress_method, - opt.glass_method); - ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); -} - -template -void load(archive &ar, build_options &opt) noexcept { - ar(opt.max_allowed_height, opt.bridge_interval, opt.compress_method, - opt.glass_method); - ar(opt.fire_proof, opt.enderman_proof, opt.connect_mushrooms); -} -} // namespace cereal -std::vector TokiSlopeCraft::build_task_hash_of( - const Eigen::ArrayXXi &mapPic, std::span blkids, - const build_options &opt) noexcept { - boost::uuids::detail::sha1 hash; - // Chocobo1::SHA3_512 hash; - { - const int64_t rows{mapPic.rows()}; - const int64_t cols{mapPic.cols()}; - SC_HASH_ADD_DATA(hash, rows); - SC_HASH_ADD_DATA(hash, cols); - hash.process_bytes(mapPic.data(), mapPic.size() * sizeof(uint32_t)); - } - - for (auto blkid : blkids) { - hash.process_bytes(blkid.data(), blkid.size()); - } - { - SC_HASH_ADD_DATA(hash, opt.max_allowed_height); - SC_HASH_ADD_DATA(hash, opt.bridge_interval); - SC_HASH_ADD_DATA(hash, opt.compress_method); - SC_HASH_ADD_DATA(hash, opt.glass_method); - SC_HASH_ADD_DATA(hash, opt.fire_proof); - SC_HASH_ADD_DATA(hash, opt.enderman_proof); - SC_HASH_ADD_DATA(hash, opt.connect_mushrooms); - } - boost::uuids::detail::sha1::digest_type digest; - hash.get_digest(digest); - std::span dig{reinterpret_cast(digest), - sizeof(digest)}; - - return {dig.begin(), dig.end()}; -} - -std::vector TokiSlopeCraft::current_build_task_hash() const noexcept { - assert(this->kernelStep >= SCL_step::converted); - auto abil = this->schem_block_id_list(); - return build_task_hash_of(this->mapPic, abil, this->build_opt); -} - -std::string TokiSlopeCraft::build_dir_of(std::string_view convert_dir, - uint64_t short_hash) noexcept { - return fmt::format("{}/{}", convert_dir, short_hash); -} - -std::string TokiSlopeCraft::current_build_dir() const noexcept { - assert(this->kernelStep >= SCL_step::converted); - return build_dir_of(this->current_convert_dir(), - to_short_hash(this->current_build_task_hash())); -} - -std::string TokiSlopeCraft::build_cache_filename_of( - std::string_view build_dir) noexcept { - return fmt::format("{}/build.zst", build_dir); -} - -std::string TokiSlopeCraft::current_build_cache_filename() const noexcept { - assert(this->kernelStep >= SCL_step::builded); - return build_cache_filename_of(this->current_build_dir()); -} - -std::string TokiSlopeCraft::build_hash_filename_of( - std::string_view build_dir) noexcept { - return fmt::format("{}/build_task_hash{}", build_dir, hash_suffix); -} - -void TokiSlopeCraft::save_build_cache(std::string &err) const noexcept { - err.clear(); - - if (this->kernelStep < SCL_step::builded) { - err = "Can not save cache before 3d is built."; - return; - } - - const std::string build_dir = this->current_build_dir(); - if (!create_dir_r_if_not_exist(build_dir, err)) { - return; - } - - const std::string filename = build_cache_filename_of(build_dir); - { - // std::ofstream ofs{build_cache_file, std::ios::binary}; - boost::iostreams::filtering_ostream ofs{}; - ofs.set_auto_close(true); - { - boost::iostreams::zstd_params params; - // ZSTD_defaultCLevel() doesn't exist below zstd 1.5 -#if ZSTD_VERSION_MINOR >= 5 - params.level = uint32_t(ZSTD_defaultCLevel()); -#else - params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); -#endif - ofs.push(boost::iostreams::zstd_compressor{params}); - ofs.push(boost::iostreams::file_sink{filename, std::ios::binary}); - } - - // zstr::ofstream ofs{filename, std::ios::binary, Z_DEFAULT_COMPRESSION}; - if (!ofs) { - err = fmt::format("ofstream failed to open cache file {}", filename); - return; - } - - { - cereal::BinaryOutputArchive boa{ofs}; - boa(this->mapPic); - boa(this->build_opt); - boa(this->schem); - } - // ofs.close(); - } - - auto sha3_512 = this->current_build_task_hash(); - err += write_hash(build_hash_filename_of(build_dir), sha3_512); - return; -} - -bool TokiSlopeCraft::examine_build_cache( - [[maybe_unused]] const build_options &opt, - std::span expected_sha3_512, - build_cache_ir *ir) const noexcept { - assert(this->kernelStep >= SCL_step::converted); - - // this->build_task_hash_of(this->mapPic,this->schem_block_id_list(),opt); - - const std::string build_dir = build_dir_of(this->current_convert_dir(), - to_short_hash(expected_sha3_512)); - - if (!examine_hash_file(this->build_hash_filename_of(build_dir), - expected_sha3_512)) { - return false; - } - - build_cache_ir temp; - try { - auto filename = this->build_cache_filename_of(build_dir); - // zstr::ifstream ifs{filename, std::ios::binary}; - boost::iostreams::filtering_istream ifs; - ifs.set_auto_close(true); - { - boost::iostreams::zstd_params params; -#if ZSTD_VERSION_MINOR >= 5 - params.level = uint32_t(ZSTD_defaultCLevel()); -#else - params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); -#endif - ifs.push(boost::iostreams::zstd_decompressor{}); - ifs.push(boost::iostreams::file_source{filename, std::ios::binary}); - } - if (!ifs) { - return false; - } - - { - cereal::BinaryInputArchive bia{ifs}; - bia(temp.mapPic); - bia(temp.build_option); - bia(temp.schem); - } - // ifs.close(); - } catch (...) { - return false; - } - - if (ir != nullptr) { - *ir = std::move(temp); - } - - return true; -} - -bool TokiSlopeCraft::load_build_cache(const build_options &opt) noexcept { - if (this->kernelStep < SCL_step::converted) { - return false; - } - - auto sbil = this->schem_block_id_list(); - auto expected_hash = this->build_task_hash_of(this->mapPic, sbil, opt); - - build_cache_ir ir; - - if (!this->examine_build_cache(opt, expected_hash, &ir)) { - return false; - } - - this->mapPic = std::move(ir.mapPic); - this->build_opt = opt; - this->schem = std::move(ir.schem); - - this->kernelStep = SCL_step::builded; - return true; -} diff --git a/SlopeCraftL/TokiSlopeCraft_convert.cpp b/SlopeCraftL/TokiSlopeCraft_convert.cpp deleted file mode 100644 index d56aff43..00000000 --- a/SlopeCraftL/TokiSlopeCraft_convert.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TokiSlopeCraft.h" -#include - -bool TokiSlopeCraft::convert(convertAlgo algo, bool dither) { - if (kernelStep < SCL_step::convertionReady) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can call convert only after you imported the raw image"); - return false; - } - - if (algo == convertAlgo::gaCvter) { - algo = convertAlgo::RGB_Better; - } - - // this->ConvertAlgo = algo; - - // TokiColor::convertAlgo() = algo; - progressRangeSet(wind, 0, 100, 100); - reportWorkingStatue(wind, workStatus::converting); - - { - heu::GAOption opt; - opt.crossoverProb = AiOpt.crossoverProb; - opt.mutateProb = AiOpt.mutationProb; - opt.maxGenerations = AiOpt.maxGeneration; - opt.maxFailTimes = AiOpt.maxFailTimes; - opt.populationSize = AiOpt.popSize; - // here opt is passed as a const ptr, it won't be changed in this function - // call - this->image_cvter.convert_image(algo, dither, &opt); - } - - /* - if (algo == convertAlgo::gaCvter) { - - convertAlgo algos[6] = {RGB, RGB_Better, HSV, Lab94, Lab00, XYZ}; - Eigen::ArrayXX CvtedMap[6]; - std::vector *> seeds(6); - for (int a = 0; a < 6; a++) { - this->convert(algos[a]); - CvtedMap[a].resize(getImageRows(), getImageCols()); - this->getConvertedMap(nullptr, nullptr, CvtedMap[a].data()); - seeds[a] = &CvtedMap[a]; - } - - { - heu::GAOption opt; - opt.crossoverProb = AiOpt.crossoverProb; - opt.mutateProb = AiOpt.mutationProb; - opt.maxGenerations = AiOpt.maxGeneration; - opt.maxFailTimes = AiOpt.maxFailTimes; - opt.populationSize = AiOpt.popSize; - GAConverter->setOption(opt); - } - - GAConverter->setSeeds(seeds); - - GAConverter->run(); - - // replace raw image with ai result - GAConverter->resultImage(&rawImage); - - algo = convertAlgo::RGB_Better; - } - - ConvertAlgo = algo; - colorHash.clear(); - - progressRangeSet(wind, 0, 4 * sizePic(2), 0); - - reportWorkingStatue(wind, workStatus::collectingColors); - pushToHash(); - - keepAwake(wind); - progressRangeSet(wind, 0, 4 * sizePic(2), 1 * sizePic(2)); - - reportWorkingStatue(wind, workStatus::converting); - applyTokiColor(); - - keepAwake(wind); - progressRangeSet(wind, 0, 4 * sizePic(2), 2 * sizePic(2)); - - fillMapMat(); - keepAwake(wind); - progressRangeSet(wind, 0, 4 * sizePic(2), 3 * sizePic(2)); - - ditheredImage = this->rawImage; - - if (dither) { - reportWorkingStatue(wind, workStatus::dithering); - Dither(); - } - */ - this->mapPic = this->image_cvter.mapcolor_matrix().cast(); - progressRangeSet(wind, 0, 4 * sizePic(2), 4 * sizePic(2)); - keepAwake(wind); - - reportWorkingStatue(wind, workStatus::none); - - kernelStep = SCL_step::converted; - return true; -} - -void TokiSlopeCraft::exportAsData(const char *FolderPath, const int indexStart, - int *fileCount, char **dest) const { - std::vector uFL = exportAsData(FolderPath, indexStart); - if (fileCount != nullptr) *fileCount = uFL.size(); - if (dest != nullptr) - for (uint16_t i = 0; i < uFL.size(); i++) { - if (dest[i] != nullptr) std::strcpy(dest[i], uFL[i].data()); - } -} - -std::vector TokiSlopeCraft::exportAsData(std::string FolderPath, - int indexStart) const { - std::vector failed_file_list; - - if (kernelStep < SCL_step::converted) { - reportError(wind, errorFlag::HASTY_MANIPULATION, - "You can export the map as map data files only after the image " - "isSCL_step::converted."); - failed_file_list.push_back( - "Too hasty! export after youSCL_step::converted the map!"); - return failed_file_list; - } - - if (FolderPath.back() == '/') { - FolderPath.pop_back(); - } - const int rows = ceil(mapPic.rows() / 128.0f); - const int cols = ceil(mapPic.cols() / 128.0f); - // const int maxrr=rows*128; - // const int maxcc=cols*128; - progressRangeSet(wind, 0, 128 * rows * cols, 0); - - int offset[2] = {0, 0}; // r,c - int currentIndex = indexStart; - - reportWorkingStatue(wind, workStatus::writingMapDataFiles); - - for (int c = 0; c < cols; c++) { - for (int r = 0; r < rows; r++) { - offset[0] = r * 128; - offset[1] = c * 128; - std::string current_filename = - FolderPath + "/map_" + std::to_string(currentIndex) + ".dat"; - // string - // currentFile=FolderPath+"/map_"+std::to_string(currentIndex)+".dat"; - - // cerr << "Export map of (" << r << "," << c << ")" << current_filename - // << endl; - - NBT::NBTWriter MapFile; - - if (!MapFile.open(current_filename.data())) { - cerr << "Failed to create nbt file " << current_filename << endl; - failed_file_list.emplace_back(current_filename); - continue; - } - - switch (this->colorset.mc_version) { - case SCL_gameVersion::MC12: - case SCL_gameVersion::MC13: - break; - case SCL_gameVersion::MC14: - case SCL_gameVersion::MC15: - case SCL_gameVersion::MC16: - case SCL_gameVersion::MC17: - case SCL_gameVersion::MC18: - case SCL_gameVersion::MC19: - case SCL_gameVersion::MC20: - MapFile.writeInt("DataVersion", - mcVersion2VersionNumber(this->colorset.mc_version)); - break; - default: - cerr << "Wrong game version!\n"; - break; - } - static const std::string ExportedBy = - "Exported by SlopeCraft " + - std::string(TokiSlopeCraft::getSCLVersion()) + - ", developed by TokiNoBug"; - MapFile.writeString("ExportedBy", ExportedBy.data()); - MapFile.writeCompound("data"); - { - MapFile.writeByte("scale", 0); - MapFile.writeByte("trackingPosition", 0); - MapFile.writeByte("unlimitedTracking", 0); - MapFile.writeInt("xCenter", 0); - MapFile.writeInt("zCenter", 0); - switch (this->colorset.mc_version) { - case SCL_gameVersion::MC12: - MapFile.writeByte("dimension", 114); - MapFile.writeShort("height", 128); - MapFile.writeShort("width", 128); - break; - case SCL_gameVersion::MC13: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 889464); - break; - case SCL_gameVersion::MC14: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 0); - MapFile.writeByte("locked", 1); - break; - case SCL_gameVersion::MC15: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeInt("dimension", 0); - MapFile.writeByte("locked", 1); - break; - case SCL_gameVersion::MC16: - case SCL_gameVersion::MC17: - case SCL_gameVersion::MC18: - case SCL_gameVersion::MC19: - case SCL_gameVersion::MC20: - MapFile.writeListHead("banners", NBT::Compound, 0); - MapFile.writeListHead("frames", NBT::Compound, 0); - MapFile.writeString("dimension", "minecraft:overworld"); - MapFile.writeByte("locked", 1); - break; - default: - cerr << "Wrong game version!\n"; - this->reportError(this->wind, errorFlag::UNKNOWN_MAJOR_GAME_VERSION, - "Unknown major game version!"); - failed_file_list.emplace_back(current_filename); - continue; - } - - MapFile.writeByteArrayHead("colors", 16384); - { - for (short rr = 0; rr < 128; rr++) { - for (short cc = 0; cc < 128; cc++) { - uint8_t ColorCur; - if (rr + offset[0] < mapPic.rows() && - cc + offset[1] < mapPic.cols()) - ColorCur = mapPic(rr + offset[0], cc + offset[1]); - else - ColorCur = 0; - MapFile.writeByte("this should never be seen", ColorCur); - } - progressAdd(wind, 1); - } - } - } - MapFile.endCompound(); - MapFile.close(); - - currentIndex++; - } - } - - reportWorkingStatue(wind, workStatus::none); - - return failed_file_list; -} diff --git a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp b/SlopeCraftL/TokiSlopeCraft_static_funs.cpp deleted file mode 100644 index c28799aa..00000000 --- a/SlopeCraftL/TokiSlopeCraft_static_funs.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "TokiSlopeCraft.h" -#include - -const char *TokiSlopeCraft::getSCLVersion() { return SC_VERSION_STR; } - -// void TokiSlopeCraft::getColorMapPtrs(const float **const r, -// const float **const g, -// const float **const b, -// const unsigned char **m, int *rows) { -// if (r != nullptr) *r = TokiSlopeCraft::Allowed.rgb_data(0); -// if (g != nullptr) *g = TokiSlopeCraft::Allowed.rgb_data(1); -// if (b != nullptr) *b = TokiSlopeCraft::Allowed.rgb_data(2); -// -// if (m != nullptr) *m = TokiSlopeCraft::Allowed.map_data(); -// if (rows != nullptr) *rows = TokiSlopeCraft::Allowed.color_count(); -// } - -const float *TokiSlopeCraft::getBasicColorMapPtrs() { - return color_set::basic->RGB_mat().data(); -} - -uint64_t TokiSlopeCraft::mcVersion2VersionNumber(SCL_gameVersion g) { - switch (g) { - case SCL_gameVersion::ANCIENT: - return 114514; - case SCL_gameVersion::MC12: - case SCL_gameVersion::MC13: - case SCL_gameVersion::MC14: - case SCL_gameVersion::MC15: - case SCL_gameVersion::MC16: - case SCL_gameVersion::MC17: - case SCL_gameVersion::MC18: - case SCL_gameVersion::MC19: - case SCL_gameVersion::MC20: - return uint64_t(MCDataVersion::suggested_version(g)); - default: - return 1919810; - } -} - -#include -#include - -const mc_block *TokiSlopeCraft::find_block_for_idx( - int idx, std::string_view blkid) const noexcept { - if (idx < 0) { - return nullptr; - } - - if (idx < (int)this->colorset.palette.size()) { - return &this->colorset.palette[idx]; - } - - // the block must be mushroom - namespace lsi = libSchem::internal; - using lsi::mushroom_type; - - blkid::char_range pure_id_range; - // invalid block id - if (!blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { - return nullptr; - } - - std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; - - auto mush_type_opt = lsi::pureid_to_type(pure_id); - if (!mush_type_opt.has_value()) { - return nullptr; - } - - uint8_t expected_basecolor = 0; - switch (mush_type_opt.value()) { - case mushroom_type::red: - expected_basecolor = 28; - break; - case mushroom_type::brown: - expected_basecolor = 10; - break; - case mushroom_type::stem: - expected_basecolor = 3; - break; - } - - const mc_block *blkp = find_block_for_idx(expected_basecolor, {}); - - if (blkp == nullptr) { - return nullptr; - } - - if (lsi::pureid_to_type(blkp->id) != mush_type_opt) { - return nullptr; - } - - return blkp; -} - -size_t TokiSlopeCraft::getBlockPalette(const AbstractBlock **blkpp, - size_t capacity) const noexcept { - const size_t palette_size = - std::min(SCL_maxBaseColor() + 1, this->colorset.palette.size()); - if (blkpp == nullptr || capacity <= 0) { - return palette_size; - } - - for (size_t idx = 0; idx < palette_size; idx++) { - if (capacity <= idx) { - break; - } - - blkpp[idx] = &this->colorset.palette[idx]; - } - - for (size_t idx = palette_size; idx < capacity; idx++) { - blkpp[idx] = nullptr; - } - - return palette_size; -} \ No newline at end of file From 5f92bd251dd234ca37e4783947e4e654caa8cdb7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 19:53:57 +0800 Subject: [PATCH 0785/1123] remove redundant colorset files and types Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 4 - SlopeCraftL/ColorSource.cpp | 7 +- SlopeCraftL/Colors.cpp | 73 ------------------- SlopeCraftL/Colors.h | 38 ---------- SlopeCraftL/Colorset.cpp | 9 --- SlopeCraftL/Colorset.h | 36 --------- SlopeCraftL/SCLDefines.h | 17 ++++- SlopeCraftL/SlopeCraftL.cpp | 7 ++ SlopeCraftL/color_table.cpp | 2 +- SlopeCraftL/color_table.h | 2 +- SlopeCraftL/converted_image.cpp | 3 +- SlopeCraftL/converted_image.h | 10 +-- SlopeCraftL/height_line.h | 7 +- SlopeCraftL/lossyCompressor.h | 1 - SlopeCraftL/prim_glass_builder.h | 10 +-- .../GAConverter/GAConverter.cpp | 1 + .../GAConverter/sortColor.cpp | 2 +- .../GAConverter/sortColor.h | 2 +- utilities/MapImageCvter/MapImageCvter.h | 8 +- 19 files changed, 53 insertions(+), 186 deletions(-) delete mode 100644 SlopeCraftL/Colors.cpp delete mode 100644 SlopeCraftL/Colors.h delete mode 100644 SlopeCraftL/Colorset.cpp delete mode 100644 SlopeCraftL/Colorset.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 646ed913..98e160da 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -25,7 +25,6 @@ set(Slope_SCL_internal_headers ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h # AiCvterOpt.h - Colors.h height_line.h optimize_chain.h prim_glass_builder.h @@ -36,7 +35,6 @@ set(Slope_SCL_internal_headers mc_block.h SlopeCraftL_global.h WriteStringDeliver.h - Colorset.h structure_3D.h color_table.h converted_image.h @@ -47,7 +45,6 @@ set(SlopeCraft_SCL_sources SlopeCraftL.h # AiCvterOpt.cpp - Colors.cpp ColorSource.cpp height_line.cpp optimize_chain.cpp @@ -61,7 +58,6 @@ set(SlopeCraft_SCL_sources lossyCompressor.cpp mc_block.cpp SlopeCraftL.cpp - Colorset.cpp color_table.cpp structure_3D.cpp converted_image.cpp diff --git a/SlopeCraftL/ColorSource.cpp b/SlopeCraftL/ColorSource.cpp index 10b34e84..719842b7 100644 --- a/SlopeCraftL/ColorSource.cpp +++ b/SlopeCraftL/ColorSource.cpp @@ -20,10 +20,13 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -// #include "SCLDefines.h" +#include "SCLDefines.h" namespace SlopeCraft { extern const float RGBBasicSource[256 * 3]; +const std::unique_ptr basic{ + new colorset_basic_t{RGBBasicSource}}; + const float RGBBasicSource[256 * 3] = { 0 / 255.0f, 90 / 255.0f, 174 / 255.0f, 140 / 255.0f, 180 / 255.0f, 113 / 255.0f, 118 / 255.0f, 0 / 255.0f, 180 / 255.0f, 116 / 255.0f, @@ -181,4 +184,4 @@ const float RGBBasicSource[256 * 3] = { 79 / 255.0f, 0 / 255.0f, 0 / 255.0f, }; -} // namespace SlopeCraft +} // namespace SlopeCraft diff --git a/SlopeCraftL/Colors.cpp b/SlopeCraftL/Colors.cpp deleted file mode 100644 index 9df0a1b2..00000000 --- a/SlopeCraftL/Colors.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "Colors.h" -#include "Colorset.h" - -#include - -// template <> -// const colorset_allowed_t *const TokiColor::Allowed = -// &TokiSlopeCraft::Allowed; template <> const colorset_basic_t *const -// TokiColor::Basic = &TokiSlopeCraft::Basic; - -namespace SlopeCraft { -// int colorCount4External() { return TokiSlopeCraft::Allowed.color_count(); } - -extern Eigen::Map BasicRGB4External(int channel) { - return Eigen::Map( - &color_set::basic->RGB_mat()(0, channel), - color_set::basic->color_count()); -} - -// Eigen::Map AllowedRGB4External(int channel) { -// return Eigen::Map( -// TokiSlopeCraft::Allowed.rgb_data(channel), colorCount4External()); -// } -// -// extern Eigen::Map> -// AllowedMapList4External() { -// return Eigen::Map>( -// TokiSlopeCraft::Allowed.map_data(), colorCount4External()); -// } - -} // end namespace SlopeCraft - -void SCL_testHSV() { - const float rgb[][3] = {{0, 0, 0}, {1, 1, 1}, {0.99, 0, 0}, {0, 1, 0}, - {0, 0, 1}, {1, 1, 0}, {1, 0, 1}, {0, 1, 1}}; - - const int N = sizeof(rgb) / sizeof(float[3]); - - float hsv[N][3], irgb[N][3]; - - for (int r = 0; r < N; r++) { - RGB2HSV(rgb[r][0], rgb[r][1], rgb[r][2], hsv[r][0], hsv[r][1], hsv[r][2]); - - HSV2RGB(hsv[r][0], hsv[r][1], hsv[r][2], irgb[r][0], irgb[r][1], - irgb[r][2]); - - printf("RGB = [%f, %f, %f] , ", rgb[r][0], rgb[r][1], rgb[r][2]); - printf("HSV = [%f, %f, %f] , ", hsv[r][0], hsv[r][1], hsv[r][2]); - printf("iRGB = [%f, %f, %f]\n", irgb[r][0], irgb[r][1], irgb[r][2]); - } -} \ No newline at end of file diff --git a/SlopeCraftL/Colors.h b/SlopeCraftL/Colors.h deleted file mode 100644 index df621fb3..00000000 --- a/SlopeCraftL/Colors.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef SCL_COLORS_H -#define SCL_COLORS_H -#include -#include - -#include "SCLDefines.h" -#include - -#include "SCLDefines.h" - -using colorset_allowed_t = colorset_new; -using colorset_basic_t = colorset_new; - -using TokiColor = newTokiColor; - -#endif // SCL_COLORS_H diff --git a/SlopeCraftL/Colorset.cpp b/SlopeCraftL/Colorset.cpp deleted file mode 100644 index ccfcf1cd..00000000 --- a/SlopeCraftL/Colorset.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by joseph on 4/12/24. -// - -#include "Colorset.h" -#include "SCLDefines.h" - -const std::unique_ptr color_set::basic{ - new colorset_basic_t{RGBBasicSource}}; \ No newline at end of file diff --git a/SlopeCraftL/Colorset.h b/SlopeCraftL/Colorset.h deleted file mode 100644 index dcbd8bcc..00000000 --- a/SlopeCraftL/Colorset.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Created by joseph on 4/12/24. -// - -#ifndef SLOPECRAFT_COLORSET_H -#define SLOPECRAFT_COLORSET_H - -#include -#include -#include -#include -#include -#include -#include "mc_block.h" -#include "Colors.h" -#include "SlopeCraftL.h" - -#define mapColor2Index(mapColor) (64 * ((mapColor) % 4) + ((mapColor) / 4)) -#define index2mapColor(index) (4 * ((index) % 64) + ((index) / 64)) -#define mapColor2baseColor(mapColor) ((mapColor) >> 2) -#define index2baseColor(index) (mapColor2baseColor(index2mapColor(index))) -#define mapColor2depth(mapColor) ((mapColor) % 4) -#define index2depth(index) (mapColor2depth(index2mapColor(index))) - -#warning "TODO: Remove this struct" -struct color_set { - static const std::unique_ptr basic; - - colorset_allowed_t allowed_colorset; - - SlopeCraft::gameVersion mc_version{SCL_gameVersion::MC17}; - SlopeCraft::mapTypes map_type{SCL_mapTypes::Slope}; - std::vector palette{}; -}; - -#endif // SLOPECRAFT_COLORSET_H diff --git a/SlopeCraftL/SCLDefines.h b/SlopeCraftL/SCLDefines.h index 6def73dc..39a39df0 100644 --- a/SlopeCraftL/SCLDefines.h +++ b/SlopeCraftL/SCLDefines.h @@ -34,20 +34,35 @@ This file is part of SlopeCraft. #include #include "SlopeCraftL.h" +#include +#include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif +#define mapColor2Index(mapColor) (64 * ((mapColor) % 4) + ((mapColor) / 4)) +#define index2mapColor(index) (4 * ((index) % 64) + ((index) / 64)) +#define mapColor2baseColor(mapColor) ((mapColor) >> 2) +#define index2baseColor(index) (mapColor2baseColor(index2mapColor(index))) +#define mapColor2depth(mapColor) ((mapColor) % 4) +#define index2depth(index) (mapColor2depth(index2mapColor(index))) + using std::cout, std::cerr, std::endl; using Eigen::Dynamic; +using colorset_allowed_t = colorset_new; +using colorset_basic_t = colorset_new; + +using TokiColor = newTokiColor; + namespace SlopeCraft { extern const float RGBBasicSource[256 * 3]; +extern const std::unique_ptr basic_colorset; -} +} // namespace SlopeCraft #define SC_HASH_ADD_DATA(hasher, obj) hasher.process_bytes(&obj, sizeof(obj)); diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index e5d25fc6..1514af36 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -383,3 +383,10 @@ SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *s) { delete s; } // return TokiSlopeCraft::getBlockPalette(blkpp, capacity); // } } + +#include +extern Eigen::Map BasicRGB4External(int channel) { + return Eigen::Map( + &SlopeCraft::basic_colorset->RGB_mat()(0, channel), + SlopeCraft::basic_colorset->color_count()); +} \ No newline at end of file diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index d4aceb58..e038bbcb 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -103,7 +103,7 @@ std::optional color_table_impl::create( } } - if (!result.allowed.apply_allowed(*color_set::basic, m_index)) { + if (!result.allowed.apply_allowed(*SlopeCraft::basic_colorset, m_index)) { std::string msg = fmt::format( "Too few usable color(s) : only {} colors\nAvaliable base color(s) : ", result.allowed.color_count()); diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 7fc22955..0e6a23bd 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -9,7 +9,7 @@ #include #include #include "SlopeCraftL.h" -#include "Colorset.h" +#include "SCLDefines.h" #include "mc_block.h" #include "WriteStringDeliver.h" #include "converted_image.h" diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index d5c0eed8..8cb8ff28 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "SCLDefines.h" #include "converted_image.h" #include "color_table.h" @@ -11,7 +12,7 @@ #include "lossyCompressor.h" converted_image_impl::converted_image_impl(const color_table_impl &table) - : converter{*color_set::basic, table.allowed} {} + : converter{*SlopeCraft::basic_colorset, table.allowed} {} converted_image *color_table_impl::convert_image( const_image_reference original_img, diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index 1cc810d1..e72ff02c 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -4,15 +4,15 @@ #ifndef SLOPECRAFT_CONVERTED_IMAGE_H #define SLOPECRAFT_CONVERTED_IMAGE_H -#include "SlopeCraftL.h" -#include "Colorset.h" -#include "mc_block.h" -#include "Schem/Schem.h" -#include "WaterItem.h" #include #include #include #include +#include "SlopeCraftL.h" +#include "SCLDefines.h" +#include "mc_block.h" +#include "Schem/Schem.h" +#include "WaterItem.h" class color_table_impl; diff --git a/SlopeCraftL/height_line.h b/SlopeCraftL/height_line.h index 68e0d4ec..1e32e1d1 100644 --- a/SlopeCraftL/height_line.h +++ b/SlopeCraftL/height_line.h @@ -23,13 +23,12 @@ This file is part of SlopeCraft. #ifndef HEIGHTLINE_H #define HEIGHTLINE_H -#include "Colors.h" -#include "optimize_chain.h" -#include "SCLDefines.h" -#include "WaterItem.h" #include #include #include +#include "optimize_chain.h" +#include "SCLDefines.h" +#include "WaterItem.h" class height_line { public: diff --git a/SlopeCraftL/lossyCompressor.h b/SlopeCraftL/lossyCompressor.h index e4389e3a..917ad136 100644 --- a/SlopeCraftL/lossyCompressor.h +++ b/SlopeCraftL/lossyCompressor.h @@ -32,7 +32,6 @@ This file is part of SlopeCraft. #include #include -#include "Colors.h" #include "height_line.h" #include "SCLDefines.h" #include "WaterItem.h" diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index cd9a8302..ad4d1c0b 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -22,12 +22,6 @@ This file is part of SlopeCraft. #ifndef PRIMGLASSBUILDER_H #define PRIMGLASSBUILDER_H -#include "object_pool.hpp" - -#include "SCLDefines.h" - -#include "Colors.h" -#include "WaterItem.h" #include #include #include @@ -37,6 +31,10 @@ This file is part of SlopeCraft. #include #include +#include "object_pool.hpp" +#include "SCLDefines.h" +#include "WaterItem.h" + // using namespace Eigen; extern const ARGB airColor; diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.cpp b/utilities/ExternalConverters/GAConverter/GAConverter.cpp index 676119f1..f1ad91a3 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.cpp +++ b/utilities/ExternalConverters/GAConverter/GAConverter.cpp @@ -32,6 +32,7 @@ using namespace GACvter; namespace GACvter { +void delete_GA_converter(GAConverter *g) noexcept { delete g; } // #error "Fix singleton here" // mapColor2Gray_LUT_t mapColor2Gray; diff --git a/utilities/ExternalConverters/GAConverter/sortColor.cpp b/utilities/ExternalConverters/GAConverter/sortColor.cpp index 9e98e9f4..cfc11dc8 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.cpp +++ b/utilities/ExternalConverters/GAConverter/sortColor.cpp @@ -21,7 +21,7 @@ This file is part of SlopeCraft. */ #include "sortColor.h" -#include "../../../SlopeCraftL/Colors.h" +#include "../../../SlopeCraftL/SCLDefines.h" using namespace GACvter; using namespace SlopeCraft; diff --git a/utilities/ExternalConverters/GAConverter/sortColor.h b/utilities/ExternalConverters/GAConverter/sortColor.h index 6572d6e0..4bd8bd3e 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.h +++ b/utilities/ExternalConverters/GAConverter/sortColor.h @@ -24,7 +24,7 @@ This file is part of SlopeCraft. #define SORTCOLOR_H #include "GACvterDefines.hpp" -#include "../../SlopeCraftL/Colors.h" +#include "../../SlopeCraftL/SCLDefines.h" namespace GACvter { diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index b72f0673..6e2b875a 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -33,7 +33,8 @@ This file is part of SlopeCraft. namespace GACvter { class GAConverter; -} +void delete_GA_converter(GAConverter *) noexcept; +} // namespace GACvter namespace heu { struct GAOption; @@ -43,7 +44,10 @@ namespace libMapImageCvt { class MapImageCvter : public ::libImageCvt::ImageCvter { private: - std::unique_ptr gacvter; + using deleter_t = decltype([](GACvter::GAConverter *g) { + GACvter::delete_GA_converter(g); + }); + std::unique_ptr gacvter; public: using Base_t = ::libImageCvt::ImageCvter; From f68ba4afd7d66b17b4a833a90a4d90db42cc8934 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:08:14 +0800 Subject: [PATCH 0786/1123] replace SlopeCraftL_global.h with generated export headers Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 7 +- SlopeCraftL/SlopeCraftL.h | 10 ++- SlopeCraftL/SlopeCraftL_global.h | 65 ------------------- SlopeCraftL/install.cmake | 4 +- .../GAConverter/CMakeLists.txt | 4 +- utilities/MapImageCvter/CMakeLists.txt | 3 +- 6 files changed, 19 insertions(+), 74 deletions(-) delete mode 100644 SlopeCraftL/SlopeCraftL_global.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 98e160da..ecb1b35a 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -33,7 +33,6 @@ set(Slope_SCL_internal_headers WaterItem.h lossyCompressor.h mc_block.h - SlopeCraftL_global.h WriteStringDeliver.h structure_3D.h color_table.h @@ -71,11 +70,15 @@ add_definitions(-DSLOPECRAFTL_LIBRARY) add_library(SlopeCraftL SHARED ${SlopeCraft_SCL_sources}) +include(GenerateExportHeader) +generate_export_header(SlopeCraftL BASE_NAME SCL EXPORT_FILE_NAME SlopeCraftL_global.h) + # add_library(SlopeCraftL_C SHARED ${SlopeCraft_SCL_sources}) target_compile_features(SlopeCraftL PRIVATE cxx_std_23) target_precompile_headers(SlopeCraftL PRIVATE ${SlopeCraft_SCL_internal_headers}) -target_include_directories(SlopeCraftL INTERFACE +target_include_directories(SlopeCraftL PUBLIC $ + $ $) target_include_directories(SlopeCraftL PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index b89fb8c6..e597349e 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -22,11 +22,17 @@ This file is part of SlopeCraft. #ifndef KERNEL_H #define KERNEL_H -#include -#include +#include +#include #include "SlopeCraftL_global.h" +#ifdef SLOPECRAFTL_NOT_INSTALLED +#include +#else +#include "SC_version_buildtime.h" +#endif // SLOPECRAFTL_NOT_INSTALLED + // define enumerations first #ifdef SCL_FIND_GlobalEnums_BY_PATH #include "../utilities/SC_GlobalEnums.h" diff --git a/SlopeCraftL/SlopeCraftL_global.h b/SlopeCraftL/SlopeCraftL_global.h deleted file mode 100644 index 5645ec94..00000000 --- a/SlopeCraftL/SlopeCraftL_global.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef SLOPECRAFTL_GLOBAL_H -#define SLOPECRAFTL_GLOBAL_H - -#ifdef Q_DECL_EXPORT -#undef Q_DECL_EXPORT -#endif -#ifdef Q_DECL_IMPORT -#undef Q_DECL_IMPORT -#endif - -#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || \ - defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || \ - defined(__WIN32__) || defined(__NT__) -#define Q_DECL_EXPORT __declspec(dllexport) -#define Q_DECL_IMPORT __declspec(dllimport) -#else -#define Q_DECL_EXPORT __attribute__((visibility("default"))) -#define Q_DECL_IMPORT __attribute__((visibility("default"))) -#endif - -#if defined(SLOPECRAFTL_LIBRARY) -#define SLOPECRAFTL_EXPORT Q_DECL_EXPORT -#else -#define SLOPECRAFTL_EXPORT Q_DECL_IMPORT -#endif - -#define SCL_EXPORT SLOPECRAFTL_EXPORT - -#ifndef SCL_external_class -#ifdef SCL_CAPI -#define SCL_external_class struct -#else -#define SCL_external_class class SCL_EXPORT -#endif -#endif - -#ifdef SLOPECRAFTL_NOT_INSTALLED -#include -#else -#include "SC_version_buildtime.h" -#endif // SLOPECRAFTL_NOT_INSTALLED - -#endif // SLOPECRAFTL_GLOBAL_H diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index 0f2151ad..ae0f848c 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -10,8 +10,8 @@ set(SlopeCraft_SCL_Cpp_include_files ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h - SlopeCraftL.h - SlopeCraftL_global.h + ${CMAKE_CURRENT_SOURCE_DIR}/SlopeCraftL.h + ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraftL_global.h ) install(FILES ${SlopeCraft_SCL_Cpp_include_files} DESTINATION include/SlopeCraft) diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index 97e4753e..dd466a25 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -18,7 +18,7 @@ set(SlopeCraft_GAConverter_sources ) add_library(GAConverter STATIC ${SlopeCraft_GAConverter_sources}) - +target_include_directories(GAConverter PRIVATE "${CMAKE_BINARY_DIR}/SlopeCraftL") target_link_libraries(GAConverter PUBLIC ColorManip) #target_include_directories(GAConverter PUBLIC # ../../ColorManip @@ -27,7 +27,7 @@ target_link_libraries(GAConverter PUBLIC ColorManip) find_package(Eigen3 REQUIRED) target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen Heu::Genetic) -target_compile_features(GAConverter PRIVATE cxx_std_20) +target_compile_features(GAConverter PRIVATE cxx_std_23) if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(GAConverter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index 223bb027..a6e53aa8 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -19,9 +19,10 @@ target_link_libraries(MapImageCvter PUBLIC OpenMP::OpenMP_CXX cereal::cereal) +target_include_directories(MapImageCvter PRIVATE "${CMAKE_BINARY_DIR}/SlopeCraftL") target_compile_options(MapImageCvter PRIVATE ${SlopeCraft_vectorize_flags}) -target_compile_features(MapImageCvter PUBLIC cxx_std_20) +target_compile_features(MapImageCvter PUBLIC cxx_std_23) if (CMAKE_SYSTEM_NAME MATCHES "Linux") set_target_properties(MapImageCvter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) From a46a555058bb1788461df98a4c5ec19cedb4055e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:14:18 +0800 Subject: [PATCH 0787/1123] replace SlopeCraftL_global.h with generated export headers Signed-off-by: ToKiNoBug --- MapViewer/CMakeLists.txt | 6 +-- SlopeCraft/SCWind.cpp | 4 +- SlopeCraft/SCWind_slots.cpp | 2 +- SlopeCraftL/CMakeLists.txt | 14 +++---- SlopeCraftL/SlopeCraftL.cpp | 2 +- SlopeCraftL/SlopeCraftL.h | 38 +++++++++---------- .../{ColorSource.cpp => color_source.cpp} | 0 SlopeCraftL/color_table.cpp | 6 +-- SlopeCraftL/color_table.h | 10 ++--- SlopeCraftL/converted_image.cpp | 2 +- SlopeCraftL/converted_image.h | 2 +- SlopeCraftL/height_line.h | 2 +- ...agePreprocess.cpp => image_preprocess.cpp} | 0 ...ssyCompressor.cpp => lossy_compressor.cpp} | 2 +- .../{lossyCompressor.h => lossy_compressor.h} | 2 +- SlopeCraftL/prim_glass_builder.h | 2 +- ...{WriteStringDeliver.h => string_deliver.h} | 2 +- SlopeCraftL/structure_3D.cpp | 2 +- SlopeCraftL/structure_3D.h | 2 +- SlopeCraftL/tests/load_scl_blocklist.cpp | 4 +- SlopeCraftL/{WaterItem.h => water_item.h} | 0 .../BlockListManager/BlockListManager.cpp | 4 +- 22 files changed, 54 insertions(+), 54 deletions(-) rename SlopeCraftL/{ColorSource.cpp => color_source.cpp} (100%) rename SlopeCraftL/{imagePreprocess.cpp => image_preprocess.cpp} (100%) rename SlopeCraftL/{lossyCompressor.cpp => lossy_compressor.cpp} (99%) rename SlopeCraftL/{lossyCompressor.h => lossy_compressor.h} (98%) rename SlopeCraftL/{WriteStringDeliver.h => string_deliver.h} (88%) rename SlopeCraftL/{WaterItem.h => water_item.h} (100%) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index a4509c20..23c3b294 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -21,7 +21,7 @@ set(MapViewer_header_files set(MapViewer_source_files main.cpp - ../SlopeCraftL/ColorSource.cpp + ../SlopeCraftL/color_source.cpp processMapFiles.cpp MapViewerWind.cpp resource_manually.cpp @@ -29,11 +29,11 @@ set(MapViewer_source_files set(MapViewer_windows_rc_files) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") message("Configuring on Windows. Adding rc file to " ${PROJECT_NAME}) configure_file(others/MapViewer.rc.in others/MapViewer.rc) set(MapViewer_windows_rc_files ${CMAKE_CURRENT_BINARY_DIR}/others/MapViewer.rc) -endif() +endif () set(MapViewer_ts_files MapViewer_en_US.ts) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 8d446caa..c9ee624a 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -612,7 +612,7 @@ void SCWind::kernel_convert_image() noexcept { void SCWind::kernel_make_cvt_cache() noexcept { std::string err; err.resize(4096); - SlopeCraft::StringDeliver sd{err.data(), err.size()}; + SlopeCraft::string_deliver sd{err.data(), err.size()}; if (!this->kernel->saveConvertCache(sd)) { QString qerr = QString::fromUtf8(sd.data); @@ -787,7 +787,7 @@ void SCWind::when_export_pool_selectionChanged() noexcept { void SCWind::kernel_make_build_cache() noexcept { std::string err; err.resize(4096); - SlopeCraft::StringDeliver sd{err.data(), err.size()}; + SlopeCraft::string_deliver sd{err.data(), err.size()}; if (!this->kernel->saveBuildCache(sd)) { QString qerr = QString::fromUtf8(sd.data); diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index b421e05c..3e6a390a 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -982,7 +982,7 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { std::string err; err.resize(4096); - SlopeCraft::StringDeliver sd{err.data(), err.size()}; + SlopeCraft::string_deliver sd{err.data(), err.size()}; SlopeCraft::Kernel::test_blocklist_options opt; opt.block_count = blks.size(); diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ecb1b35a..6f7bcc38 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -30,10 +30,10 @@ set(Slope_SCL_internal_headers prim_glass_builder.h SCLDefines.h # to_be_removed/TokiSlopeCraft.h - WaterItem.h - lossyCompressor.h + water_item.h + lossy_compressor.h mc_block.h - WriteStringDeliver.h + string_deliver.h structure_3D.h color_table.h converted_image.h @@ -44,7 +44,7 @@ set(SlopeCraft_SCL_sources SlopeCraftL.h # AiCvterOpt.cpp - ColorSource.cpp + color_source.cpp height_line.cpp optimize_chain.cpp prim_glass_builder.cpp @@ -53,8 +53,8 @@ set(SlopeCraft_SCL_sources # to_be_removed/TokiSlopeCraft_build.cpp # to_be_removed/TokiSlopeCraft_convert.cpp # to_be_removed/TokiSlopeCraft_cache.cpp - imagePreprocess.cpp - lossyCompressor.cpp + image_preprocess.cpp + lossy_compressor.cpp mc_block.cpp SlopeCraftL.cpp color_table.cpp @@ -71,7 +71,7 @@ add_definitions(-DSLOPECRAFTL_LIBRARY) add_library(SlopeCraftL SHARED ${SlopeCraft_SCL_sources}) include(GenerateExportHeader) -generate_export_header(SlopeCraftL BASE_NAME SCL EXPORT_FILE_NAME SlopeCraftL_global.h) +generate_export_header(SlopeCraftL BASE_NAME SCL EXPORT_FILE_NAME SlopeCraftL_export.h) # add_library(SlopeCraftL_C SHARED ${SlopeCraft_SCL_sources}) target_compile_features(SlopeCraftL PRIVATE cxx_std_23) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 1514af36..a109cbb0 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -28,7 +28,7 @@ This file is part of SlopeCraft. #include "SlopeCraftL.h" #include "mc_block.h" -#include "WriteStringDeliver.h" +#include "string_deliver.h" #include "color_table.h" using namespace SlopeCraft; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index e597349e..9b86f4c3 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -25,7 +25,7 @@ This file is part of SlopeCraft. #include #include -#include "SlopeCraftL_global.h" +#include "SlopeCraftL_export.h" #ifdef SLOPECRAFTL_NOT_INSTALLED #include @@ -70,9 +70,9 @@ struct AiCvterOpt { double mutationProb{0.01}; }; -struct StringDeliver { - StringDeliver() = default; - StringDeliver(char *p, size_t cap) : data(p), capacity(cap) {} +struct string_deliver { + string_deliver() = default; + string_deliver(char *p, size_t cap) : data(p), capacity(cap) {} char *const data{nullptr}; const size_t capacity{0}; size_t size{0}; @@ -83,8 +83,8 @@ struct StringDeliver { } template - [[nodiscard]] static StringDeliver from_string(string_t &s) noexcept { - return StringDeliver{s.data(), s.size()}; + [[nodiscard]] static string_deliver from_string(string_t &s) noexcept { + return string_deliver{s.data(), s.size()}; } }; @@ -332,23 +332,23 @@ class color_table { [[nodiscard]] virtual bool save_convert_cache( const_image_reference original_img, const convert_option &option, const converted_image &, const char *cache_dir, - StringDeliver *error) const noexcept = 0; + string_deliver *error) const noexcept = 0; [[nodiscard]] virtual converted_image *load_convert_cache( const_image_reference original_img, const convert_option &option, - const char *cache_dir, StringDeliver *error) const noexcept = 0; + const char *cache_dir, string_deliver *error) const noexcept = 0; [[nodiscard]] virtual structure_3D *build( const converted_image &, const build_options &) const noexcept = 0; // Once you cache a structure_3D, it can be released to save memory [[nodiscard]] virtual bool save_build_cache( const converted_image &, const build_options &, const structure_3D &, - const char *cache_root_dir, StringDeliver *error) const noexcept = 0; + const char *cache_root_dir, string_deliver *error) const noexcept = 0; [[nodiscard]] virtual bool has_build_cache( const converted_image &, const build_options &, const char *cache_root_dir) const noexcept = 0; [[nodiscard]] virtual structure_3D *load_build_cache( const converted_image &, const build_options &, - const char *cache_root_dir, StringDeliver *error) const noexcept = 0; + const char *cache_root_dir, string_deliver *error) const noexcept = 0; }; // class Kernel { @@ -518,14 +518,14 @@ class color_table { // // requires step >= wait4image // // virtual bool checkColorsetHash() const noexcept = 0; // // requires step >= converted -// virtual bool saveConvertCache(StringDeliver &err) const noexcept = 0; +// virtual bool saveConvertCache(string_deliver &err) const noexcept = 0; // // // requires step >= convertion ready // virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = // 0; // // // requires step >= built -// virtual bool saveBuildCache(StringDeliver &err) const noexcept = 0; +// virtual bool saveBuildCache(string_deliver &err) const noexcept = 0; // // // requires step >= converted // virtual bool loadBuildCache(const build_options &option) noexcept = 0; @@ -555,7 +555,7 @@ class color_table { // int32_t split_line_col_margin{0}; // int png_compress_level{9}; // int png_compress_memory_level{8}; -// StringDeliver *err{nullptr}; +// string_deliver *err{nullptr}; // }; // virtual bool exportAsFlatDiagram( // const char *filename_local, @@ -566,7 +566,7 @@ class color_table { // const AbstractBlock *const *block_ptrs{nullptr}; // const uint8_t *basecolors{nullptr}; // size_t block_count{0}; -// StringDeliver *err{nullptr}; +// string_deliver *err{nullptr}; // }; // virtual bool makeTests( // const char *filename, @@ -597,13 +597,13 @@ SCL_EXPORT void SCL_destroy_color_table(color_table *); SCL_EXPORT void SCL_destroy_converted_image(converted_image *); SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *); -[[nodiscard]] SCL_EXPORT AbstractBlock *SCL_createBlock(); -SCL_EXPORT void SCL_destroyBlock(AbstractBlock *); +[[nodiscard]] SCL_EXPORT AbstractBlock *SCL_create_block(); +SCL_EXPORT void SCL_destroy_block(AbstractBlock *); struct block_list_create_info { uint64_t caller_api_version{SC_VERSION_U64}; - StringDeliver *warnings{nullptr}; - StringDeliver *error{nullptr}; + string_deliver *warnings{nullptr}; + string_deliver *error{nullptr}; }; [[nodiscard]] SCL_EXPORT block_list_interface *SCL_createBlockList( @@ -657,7 +657,7 @@ SCL_EXPORT uint8_t SCL_maxBaseColor(); class deleter { public: // void operator()(Kernel *k) const noexcept { SCL_destroyKernel(k); } - void operator()(AbstractBlock *b) const noexcept { SCL_destroyBlock(b); } + void operator()(AbstractBlock *b) const noexcept { SCL_destroy_block(b); } void operator()(block_list_interface *b) const noexcept { SCL_destroyBlockList(b); } diff --git a/SlopeCraftL/ColorSource.cpp b/SlopeCraftL/color_source.cpp similarity index 100% rename from SlopeCraftL/ColorSource.cpp rename to SlopeCraftL/color_source.cpp diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index e038bbcb..a6407551 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -6,7 +6,7 @@ #include #include "SCLDefines.h" #include "color_table.h" -#include "WaterItem.h" +#include "water_item.h" #include "structure_3D.h" std::optional color_table_impl::create( @@ -249,7 +249,7 @@ bool color_table_impl::save_build_cache(const converted_image &cvted, const build_options &option, const structure_3D &structure, const char *cache_root_dir, - StringDeliver *error) const noexcept { + string_deliver *error) const noexcept { const auto filename = this->build_task_cache_filename(cvted, option, cache_root_dir); auto err_msg = @@ -271,7 +271,7 @@ bool color_table_impl::has_build_cache( structure_3D *color_table_impl::load_build_cache( const SlopeCraft::converted_image &cvted, const SlopeCraft::build_options &option, const char *cache_root_dir, - SlopeCraft::StringDeliver *error) const noexcept { + SlopeCraft::string_deliver *error) const noexcept { const auto filename = this->build_task_cache_filename(cvted, option, cache_root_dir); auto res = structure_3D_impl::load_cache(filename); diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 0e6a23bd..31103c4c 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -11,7 +11,7 @@ #include "SlopeCraftL.h" #include "SCLDefines.h" #include "mc_block.h" -#include "WriteStringDeliver.h" +#include "string_deliver.h" #include "converted_image.h" class color_table_impl : public SlopeCraft::color_table { @@ -69,7 +69,7 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] bool save_convert_cache( const_image_reference original_img, const convert_option &option, const converted_image &cvted, const char *cache_root_dir, - StringDeliver *error) const noexcept final { + string_deliver *error) const noexcept final { auto err = this->save_convert_cache(original_img, option, cvted, cache_root_dir); write_to_sd(error, err); @@ -82,7 +82,7 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] converted_image *load_convert_cache( const_image_reference original_img, const convert_option &option, - const char *cache_root_dir, StringDeliver *error) const noexcept final { + const char *cache_root_dir, string_deliver *error) const noexcept final { auto res = this->load_convert_cache(original_img, option, cache_root_dir); if (!res) { write_to_sd(error, res.error()); @@ -108,13 +108,13 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] bool save_build_cache( const converted_image &, const build_options &, const structure_3D &, - const char *cache_root_dir, StringDeliver *error) const noexcept final; + const char *cache_root_dir, string_deliver *error) const noexcept final; [[nodiscard]] bool has_build_cache( const converted_image &, const build_options &, const char *cache_root_dir) const noexcept final; [[nodiscard]] structure_3D *load_build_cache( const converted_image &, const build_options &, - const char *cache_root_dir, StringDeliver *error) const noexcept final; + const char *cache_root_dir, string_deliver *error) const noexcept final; }; //[[nodiscard]] std::string digest_to_string( diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 8cb8ff28..5a50efd6 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -9,7 +9,7 @@ #include "converted_image.h" #include "color_table.h" #include "height_line.h" -#include "lossyCompressor.h" +#include "lossy_compressor.h" converted_image_impl::converted_image_impl(const color_table_impl &table) : converter{*SlopeCraft::basic_colorset, table.allowed} {} diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index e72ff02c..97732405 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -12,7 +12,7 @@ #include "SCLDefines.h" #include "mc_block.h" #include "Schem/Schem.h" -#include "WaterItem.h" +#include "water_item.h" class color_table_impl; diff --git a/SlopeCraftL/height_line.h b/SlopeCraftL/height_line.h index 1e32e1d1..0976b588 100644 --- a/SlopeCraftL/height_line.h +++ b/SlopeCraftL/height_line.h @@ -28,7 +28,7 @@ This file is part of SlopeCraft. #include #include "optimize_chain.h" #include "SCLDefines.h" -#include "WaterItem.h" +#include "water_item.h" class height_line { public: diff --git a/SlopeCraftL/imagePreprocess.cpp b/SlopeCraftL/image_preprocess.cpp similarity index 100% rename from SlopeCraftL/imagePreprocess.cpp rename to SlopeCraftL/image_preprocess.cpp diff --git a/SlopeCraftL/lossyCompressor.cpp b/SlopeCraftL/lossy_compressor.cpp similarity index 99% rename from SlopeCraftL/lossyCompressor.cpp rename to SlopeCraftL/lossy_compressor.cpp index 4451648f..b2d44bc5 100644 --- a/SlopeCraftL/lossyCompressor.cpp +++ b/SlopeCraftL/lossy_compressor.cpp @@ -20,7 +20,7 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "lossyCompressor.h" +#include "lossy_compressor.h" #define heu_NO_OUTPUT #define heu_USE_THREADS diff --git a/SlopeCraftL/lossyCompressor.h b/SlopeCraftL/lossy_compressor.h similarity index 98% rename from SlopeCraftL/lossyCompressor.h rename to SlopeCraftL/lossy_compressor.h index 917ad136..75b4225b 100644 --- a/SlopeCraftL/lossyCompressor.h +++ b/SlopeCraftL/lossy_compressor.h @@ -34,7 +34,7 @@ This file is part of SlopeCraft. #include "height_line.h" #include "SCLDefines.h" -#include "WaterItem.h" +#include "water_item.h" // Eigen::Array class solver_t; diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index ad4d1c0b..48691af5 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -33,7 +33,7 @@ This file is part of SlopeCraft. #include "object_pool.hpp" #include "SCLDefines.h" -#include "WaterItem.h" +#include "water_item.h" // using namespace Eigen; diff --git a/SlopeCraftL/WriteStringDeliver.h b/SlopeCraftL/string_deliver.h similarity index 88% rename from SlopeCraftL/WriteStringDeliver.h rename to SlopeCraftL/string_deliver.h index 2915b3e2..71047837 100644 --- a/SlopeCraftL/WriteStringDeliver.h +++ b/SlopeCraftL/string_deliver.h @@ -4,7 +4,7 @@ #include namespace SlopeCraft { -inline void write_to_sd(StringDeliver* s, std::string_view sv) noexcept { +inline void write_to_sd(string_deliver* s, std::string_view sv) noexcept { if (s == nullptr) { return; } diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index edb3435e..f25d0d57 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -11,7 +11,7 @@ #include "structure_3D.h" #include "color_table.h" -#include "lossyCompressor.h" +#include "lossy_compressor.h" #include "prim_glass_builder.h" std::optional structure_3D_impl::create( diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 066791d4..3acf6ec2 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -8,7 +8,7 @@ #include "SlopeCraftL.h" #include "converted_image.h" #include "Schem/Schem.h" -#include "WaterItem.h" +#include "water_item.h" class structure_3D_impl : public structure_3D { private: diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp index eb403f53..44dea2c0 100644 --- a/SlopeCraftL/tests/load_scl_blocklist.cpp +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -14,11 +14,11 @@ int main(int argc, char** argv) { { std::string errmsg; errmsg.resize(8192); - SlopeCraft::StringDeliver err_sd{errmsg.data(), errmsg.size()}; + SlopeCraft::string_deliver err_sd{errmsg.data(), errmsg.size()}; std::string warnings; warnings.resize(8192); - SlopeCraft::StringDeliver warn_sd{warnings.data(), warnings.size()}; + SlopeCraft::string_deliver warn_sd{warnings.data(), warnings.size()}; SlopeCraft::block_list_create_info option{ SC_VERSION_U64, &warn_sd, diff --git a/SlopeCraftL/WaterItem.h b/SlopeCraftL/water_item.h similarity index 100% rename from SlopeCraftL/WaterItem.h rename to SlopeCraftL/water_item.h diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index dd22e73b..98de3996 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -48,10 +48,10 @@ std::unique_ptr BlockListManager::impl_addblocklist(const QString &filename) noexcept { std::string errmsg; errmsg.resize(8192); - auto sd_err = SlopeCraft::StringDeliver::from_string(errmsg); + auto sd_err = SlopeCraft::string_deliver::from_string(errmsg); std::string warning; warning.resize(8192); - auto sd_warn = SlopeCraft::StringDeliver::from_string(warning); + auto sd_warn = SlopeCraft::string_deliver::from_string(warning); SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::block_list_interface *bli = From d647288e4dac79e0e2af4b8a76877fb58323089b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:21:26 +0800 Subject: [PATCH 0788/1123] rename AbstractBlock and BlockListInterface Signed-off-by: ToKiNoBug --- SlopeCraft/AiCvterParameterDialog.cpp | 7 +- SlopeCraft/AiCvterParameterDialog.h | 2 +- SlopeCraft/PreviewWind.cpp | 2 +- SlopeCraft/PreviewWind.h | 2 +- SlopeCraft/SCWind.cpp | 2 +- SlopeCraft/SCWind_slots.cpp | 34 +- SlopeCraftL/CMakeLists.txt | 4 +- SlopeCraftL/SlopeCraftL.cpp | 36 +- SlopeCraftL/SlopeCraftL.h | 376 +++--------------- SlopeCraftL/color_table.h | 4 +- SlopeCraftL/mc_block.cpp | 5 +- SlopeCraftL/mc_block.h | 10 +- SlopeCraftL/tests/load_scl_blocklist.cpp | 4 +- utilities/BlockListManager/BaseColor.cpp | 4 +- utilities/BlockListManager/BaseColor.h | 6 +- utilities/BlockListManager/Block.cpp | 2 +- utilities/BlockListManager/Block.h | 4 +- .../BlockListManager/BlockListManager.cpp | 7 +- utilities/BlockListManager/BlockListManager.h | 6 +- 19 files changed, 133 insertions(+), 384 deletions(-) diff --git a/SlopeCraft/AiCvterParameterDialog.cpp b/SlopeCraft/AiCvterParameterDialog.cpp index 975582ae..6241192b 100644 --- a/SlopeCraft/AiCvterParameterDialog.cpp +++ b/SlopeCraft/AiCvterParameterDialog.cpp @@ -31,7 +31,7 @@ AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent, : QDialog(parent), ui(new Ui::AiCvterParameterDialog), kernel(kernelp) { this->ui->setupUi(this); - SlopeCraft::AiCvterOpt opt = *this->kernel->aiCvterOpt(); + SlopeCraft::GA_converter_option opt = *this->kernel->aiCvterOpt(); opt.version = SC_VERSION_U64; this->ui->sb_pop_size->setValue(opt.popSize); @@ -43,8 +43,9 @@ AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent, AiCvterParameterDialog::~AiCvterParameterDialog() { delete this->ui; } -SlopeCraft::AiCvterOpt AiCvterParameterDialog::current_option() const noexcept { - SlopeCraft::AiCvterOpt ret; +SlopeCraft::GA_converter_option AiCvterParameterDialog::current_option() + const noexcept { + SlopeCraft::GA_converter_option ret; ret.crossoverProb = this->ui->dsb_crossover_prob->value(); ret.mutationProb = this->ui->dsb_mutate_prob->value(); ret.maxFailTimes = this->ui->sb_max_early_stop->value(); diff --git a/SlopeCraft/AiCvterParameterDialog.h b/SlopeCraft/AiCvterParameterDialog.h index 9fd435af..f9ea710c 100644 --- a/SlopeCraft/AiCvterParameterDialog.h +++ b/SlopeCraft/AiCvterParameterDialog.h @@ -42,7 +42,7 @@ class AiCvterParameterDialog : public QDialog { explicit AiCvterParameterDialog(SCWind *parent, SlopeCraft::Kernel *kernelp); ~AiCvterParameterDialog(); - SlopeCraft::AiCvterOpt current_option() const noexcept; + SlopeCraft::GA_converter_option current_option() const noexcept; private slots: // void updateMaxFailTimes(); diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 980bc974..6eb5b312 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -53,7 +53,7 @@ void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { kernel->getBlockCounts(&total_blks, count_list.data()); this->set_total_count(total_blks); } - std::vector blkp_arr; + std::vector blkp_arr; { const size_t num = kernel->getBlockPalette(nullptr, 0); blkp_arr.resize(num); diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h index c466e1bb..537095d3 100644 --- a/SlopeCraft/PreviewWind.h +++ b/SlopeCraft/PreviewWind.h @@ -15,7 +15,7 @@ class PreviewWind; } struct material_item { - const SlopeCraft::AbstractBlock* blk{nullptr}; + const SlopeCraft::mc_block_interface* blk{nullptr}; int count{0}; }; diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index c9ee624a..d6b88765 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -438,7 +438,7 @@ void SCWind::when_blocklist_changed() noexcept { void SCWind::kernel_set_type() noexcept { std::vector a; - std::vector b; + std::vector b; this->ui->blm->get_blocklist(a, b); diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 3e6a390a..9ca85b3f 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -191,7 +191,7 @@ void SCWind::on_pb_save_preset_clicked() noexcept { } inline int impl_select_blk_by_id( - const std::vector &blks, + const std::vector &blks, std::string_view keyword) noexcept { int result = -1; for (int idx = 0; idx < int(blks.size()); idx++) { @@ -209,44 +209,38 @@ inline int impl_select_blk_by_id( void SCWind::on_pb_prefer_concrete_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "concrete"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "concrete"); }); } void SCWind::on_pb_prefer_wool_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "wool"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "wool"); }); } void SCWind::on_pb_prefer_glass_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "stained_glass"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "stained_glass"); }); } void SCWind::on_pb_prefer_planks_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "planks"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "planks"); }); } void SCWind::on_pb_prefer_logs_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "log"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "log"); }); } void SCWind::on_pb_prefer_slabs_clicked() noexcept { this->ui->blm->select_block_by_callback( - [](const std::vector &blks) -> int { - return impl_select_blk_by_id(blks, "_slab"); - }); + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "_slab"); }); } void SCWind::on_pb_cvt_current_clicked() noexcept { @@ -967,7 +961,7 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { } prev_dir = QFileInfo{filename}.dir().path(); - std::vector blks; + std::vector blks; std::vector basecolors; for (uint8_t basecolor = 0; basecolor <= SlopeCraft::SCL_maxBaseColor(); basecolor++) { diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 6f7bcc38..677a01e6 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -24,7 +24,7 @@ endif () set(Slope_SCL_internal_headers ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h - # AiCvterOpt.h + # GA_converter_option.h height_line.h optimize_chain.h prim_glass_builder.h @@ -43,7 +43,7 @@ set(SlopeCraft_SCL_sources SlopeCraftL.h - # AiCvterOpt.cpp + # GA_converter_option.cpp color_source.cpp height_line.cpp optimize_chain.cpp diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index a109cbb0..ca0eb671 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -33,9 +33,9 @@ This file is part of SlopeCraft. using namespace SlopeCraft; -// AbstractBlock *AbstractBlock::create() { return new mc_block; } +// mc_block_interface *mc_block_interface::create() { return new mc_block; } -void AbstractBlock::clear() noexcept { +void mc_block_interface::clear() noexcept { setBurnable(false); setDoGlow(false); setEndermanPickable(false); @@ -288,8 +288,8 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { } extern "C" { -SCL_EXPORT AbstractBlock *SCL_createBlock() { return new mc_block; } -SCL_EXPORT void SCL_destroyBlock(AbstractBlock *b) { delete b; } +SCL_EXPORT mc_block_interface *SCL_createBlock() { return new mc_block; } +SCL_EXPORT void SCL_destroyBlock(mc_block_interface *b) { delete b; } SCL_EXPORT block_list_interface *SCL_createBlockList( const char *zip_filename, const block_list_create_info &option) { @@ -306,38 +306,40 @@ SCL_EXPORT block_list_interface *SCL_createBlockList( SCL_EXPORT void SCL_destroyBlockList(block_list_interface *) {} -SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt() { return new AiCvterOpt; } -void SCL_EXPORT SCL_destroyAiCvterOpt(AiCvterOpt *a) { delete a; } +SCL_EXPORT GA_converter_option *SCL_createAiCvterOpt() { + return new GA_converter_option; +} +void SCL_EXPORT SCL_destroyAiCvterOpt(GA_converter_option *a) { delete a; } -void SCL_EXPORT SCL_setPopSize(AiCvterOpt *a, unsigned int p) { +void SCL_EXPORT SCL_setPopSize(GA_converter_option *a, unsigned int p) { a->popSize = p; } -void SCL_EXPORT SCL_setMaxGeneration(AiCvterOpt *a, unsigned int p) { +void SCL_EXPORT SCL_setMaxGeneration(GA_converter_option *a, unsigned int p) { a->maxGeneration = p; } -void SCL_EXPORT SCL_setMaxFailTimes(AiCvterOpt *a, unsigned int p) { +void SCL_EXPORT SCL_setMaxFailTimes(GA_converter_option *a, unsigned int p) { a->maxFailTimes = p; } -void SCL_EXPORT SCL_setCrossoverProb(AiCvterOpt *a, double p) { +void SCL_EXPORT SCL_setCrossoverProb(GA_converter_option *a, double p) { a->crossoverProb = p; } -void SCL_EXPORT SCL_setMutationProb(AiCvterOpt *a, double p) { +void SCL_EXPORT SCL_setMutationProb(GA_converter_option *a, double p) { a->mutationProb = p; } -unsigned int SCL_EXPORT SCL_getPopSize(const AiCvterOpt *a) { +unsigned int SCL_EXPORT SCL_getPopSize(const GA_converter_option *a) { return a->popSize; } -unsigned int SCL_EXPORT SCL_getMaxGeneration(const AiCvterOpt *a) { +unsigned int SCL_EXPORT SCL_getMaxGeneration(const GA_converter_option *a) { return a->maxGeneration; } -unsigned int SCL_EXPORT SCL_getMaxFailTimes(const AiCvterOpt *a) { +unsigned int SCL_EXPORT SCL_getMaxFailTimes(const GA_converter_option *a) { return a->maxFailTimes; } -double SCL_EXPORT SCL_getCrossoverProb(const AiCvterOpt *a) { +double SCL_EXPORT SCL_getCrossoverProb(const GA_converter_option *a) { return a->crossoverProb; } -double SCL_EXPORT SCL_getMutationProb(const AiCvterOpt *a) { +double SCL_EXPORT SCL_getMutationProb(const GA_converter_option *a) { return a->mutationProb; } @@ -378,7 +380,7 @@ SCL_EXPORT void SCL_destroy_color_table(color_table *c) { delete c; } SCL_EXPORT void SCL_destroy_converted_image(converted_image *c) { delete c; } SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *s) { delete s; } -// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, +// SCL_EXPORT int SCL_getBlockPalette(const mc_block_interface **blkpp, // size_t capacity) { // return TokiSlopeCraft::getBlockPalette(blkpp, capacity); // } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 9b86f4c3..14ed0a1c 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -40,14 +40,8 @@ This file is part of SlopeCraft. #include "SC_GlobalEnums.h" #endif -// declare classes namespace SlopeCraft { -class AbstractBlock; -class Kernel; -struct AiCvterOpt; -} // namespace SlopeCraft -namespace SlopeCraft { using step = ::SCL_step; using mapTypes = ::SCL_mapTypes; using compressSettings = ::SCL_compressSettings; @@ -57,11 +51,7 @@ using gameVersion = ::SCL_gameVersion; using workStatus = ::SCL_workStatus; using errorFlag = ::SCL_errorFlag; -} // namespace SlopeCraft - -namespace SlopeCraft { - -struct AiCvterOpt { +struct GA_converter_option { uint64_t caller_api_version{SC_VERSION_U64}; size_t popSize{50}; size_t maxGeneration{200}; @@ -70,6 +60,7 @@ struct AiCvterOpt { double mutationProb{0.01}; }; +/// struct to deliver string via ABI struct string_deliver { string_deliver() = default; string_deliver(char *p, size_t cap) : data(p), capacity(cap) {} @@ -88,10 +79,10 @@ struct string_deliver { } }; -class AbstractBlock { +class mc_block_interface { public: - AbstractBlock() = default; - virtual ~AbstractBlock() = default; + mc_block_interface() = default; + virtual ~mc_block_interface() = default; /// id of this block virtual const char *getId() const noexcept = 0; @@ -139,7 +130,7 @@ class AbstractBlock { virtual void setImage(const uint32_t *src, bool is_row_major) noexcept = 0; /// let *b equal to *this - virtual void copyTo(AbstractBlock *b) const noexcept = 0; + virtual void copyTo(mc_block_interface *b) const noexcept = 0; /// set this block to air virtual void clear() noexcept; @@ -152,13 +143,15 @@ class block_list_interface { virtual ~block_list_interface() = default; [[nodiscard]] virtual size_t size() const noexcept = 0; [[nodiscard]] virtual size_t get_blocks( - AbstractBlock **, uint8_t *, size_t capacity_in_elements) noexcept = 0; + mc_block_interface **, uint8_t *, + size_t capacity_in_elements) noexcept = 0; [[nodiscard]] virtual size_t get_blocks( - const AbstractBlock **, uint8_t *, + const mc_block_interface **, uint8_t *, size_t capacity_in_elements) const noexcept = 0; - [[nodiscard]] virtual bool contains(const AbstractBlock *) const noexcept = 0; + [[nodiscard]] virtual bool contains( + const mc_block_interface *) const noexcept = 0; }; struct color_map_ptrs { @@ -214,7 +207,7 @@ struct convert_option { uint64_t caller_api_version{SC_VERSION_U64}; SCL_convertAlgo algo{SCL_convertAlgo::RGB_Better}; bool dither{false}; - AiCvterOpt ai_cvter_opt{}; + GA_converter_option ai_cvter_opt{}; progress_callbacks progress{}; ui_callbacks ui{}; }; @@ -264,44 +257,9 @@ struct const_image_reference { size_t cols{0}; }; +class color_table; +class converted_image; class structure_3D; -class converted_image { - public: - virtual ~converted_image() = default; - [[nodiscard]] virtual size_t rows() const noexcept = 0; - [[nodiscard]] virtual size_t cols() const noexcept = 0; - [[nodiscard]] inline size_t height() const noexcept { return this->rows(); } - [[nodiscard]] inline size_t width() const noexcept { return this->cols(); } - [[nodiscard]] inline size_t size() const noexcept { - return this->rows() * this->cols(); - } - - [[nodiscard]] inline size_t size_in_bytes() const noexcept { - return sizeof(uint32_t) * this->rows() * this->cols(); - } - - virtual void get_original_image(uint32_t *buffer) const noexcept = 0; - // virtual void get_dithered_image(uint32_t *buffer) const noexcept = 0; - virtual void get_converted_image(uint32_t *buffer) const noexcept = 0; -}; - -class structure_3D { - public: - virtual ~structure_3D() = default; - [[nodiscard]] virtual size_t shape_x() const noexcept = 0; - [[nodiscard]] virtual size_t shape_y() const noexcept = 0; - [[nodiscard]] virtual size_t shape_z() const noexcept = 0; - [[nodiscard]] virtual size_t palette_length() const noexcept = 0; - virtual void get_palette(const char **buffer_block_id) const noexcept = 0; - - virtual bool export_litematica( - const char *filename, const litematic_options &option) const noexcept = 0; - virtual bool export_vanilla_structure( - const char *filename, - const vanilla_structure_options &option) const noexcept = 0; - virtual bool export_WE_schem( - const char *filename, const WE_schem_options &option) const noexcept = 0; -}; class color_table { public: @@ -319,7 +277,8 @@ class color_table { [[nodiscard]] virtual ::SCL_gameVersion mc_version() const noexcept = 0; [[nodiscard]] virtual size_t num_blocks() const noexcept = 0; - virtual void visit_blocks(void (*)(const AbstractBlock *, void *custom_data), + virtual void visit_blocks(void (*)(const mc_block_interface *, + void *custom_data), void *custom_data) const = 0; [[nodiscard]] virtual converted_image *convert_image( @@ -351,227 +310,43 @@ class color_table { const char *cache_root_dir, string_deliver *error) const noexcept = 0; }; -// class Kernel { -// public: -// Kernel(); -// // virtual ~Kernel() {}; -// -// public: -// /// function ptr to window object -// virtual void setWindPtr(void *) = 0; -// /// a function ptr to show progress of converting and exporting -// virtual void setProgressRangeSet(void (*)(void *, int, int, int)) = 0; -// /// a function ptr to add progress value -// virtual void setProgressAdd(void (*)(void *, int)) = 0; -// /// a function ptr to prevent window from being syncoped -// virtual void setKeepAwake(void (*)(void *)) = 0; -// -// /// a function ptr to show progress of compressing and bridge-building -// virtual void setAlgoProgressRangeSet(void (*)(void *, int, int, int)) = 0; -// /// a function ptr to add progress value of compressing and bridge-building -// virtual void setAlgoProgressAdd(void (*)(void *, int)) = 0; -// -// /// a function ptr to report error when something wrong happens -// virtual void setReportError(void (*)(void *, ::SCL_errorFlag, -// const char *)) = 0; -// /// a function ptr to report working statue especially when busy -// virtual void setReportWorkingStatue(void (*)(void *, ::SCL_workStatus)) = -// 0; -// -// virtual void setAiCvterOpt(const AiCvterOpt *) = 0; -// -// virtual const AiCvterOpt *aiCvterOpt() const = 0; -// -// virtual size_t getBlockPalette(const AbstractBlock **buf, -// size_t buf_capacity) const noexcept = 0; -// -// // can do in nothing: -// /// real size of kernel -// virtual size_t size() = 0; -// /// revert to a previous step -// virtual void decreaseStep(::SCL_step) = 0; -// -// // can do in colorSetReady: -// /// get current step -// virtual ::SCL_step queryStep() const = 0; -// /// set map type and blocklist -// virtual bool setType(::SCL_mapTypes, ::SCL_gameVersion, const bool[64], -// const AbstractBlock *const *const) = 0; -// /// get palette (base colors only) in ARGB32 -// virtual void getBaseColorInARGB32(uint32_t *const) const = 0; -// -// // can do in wait4Image: -// /// set original image from ARGB32 matrix (col-major) -// [[deprecated]] virtual void setRawImage(const uint32_t *src, int rows, -// int cols) = 0; -// /// get accessible color count -// virtual unsigned short getColorCount() const = 0; -// /// get usable colors in ARGB32 -// virtual void getAvailableColors(uint32_t *const ARGB32_dest = nullptr, -// uint8_t *const map_color_dest = nullptr, -// int *const num = nullptr) const = 0; -// /// make a structure that includes all accessible blocks -// [[deprecated]] virtual bool makeTests(const AbstractBlock **, const uint8_t -// *, -// const char *, char *) = 0; -// -// // can do in convertionReady: -// /// convert original image to map -// virtual bool convert(::SCL_convertAlgo = ::SCL_convertAlgo::RGB_Better, -// bool dither = false) = 0; -// /// get image rows -// virtual int getImageRows() const = 0; -// /// get image cols -// virtual int getImageCols() const = 0; -// virtual const uint32_t *getRawImage() const = 0; -// /// query if map is buildable in vanilla survival -// virtual bool isVanilla() const = 0; -// /// query if map is a flat one -// virtual bool isFlat() const = 0; -// -// // can do in converted: -// /// construct 3D structure -// [[deprecated]] virtual bool build( -// ::SCL_compressSettings = ::SCL_compressSettings::noCompress, -// uint16_t maxAllowedHeight = 256, -// ::SCL_glassBridgeSettings = ::SCL_glassBridgeSettings::noBridge, -// uint16_t glassInterval = 3, bool fireProof = false, -// bool endermanProof = false) = 0; -// -// /// get converted image -// [[deprecated]] virtual void getConvertedImage(int *rows, int *cols, -// uint32_t *dest) const = 0; -// /// export as map data files, returns failed files. -// virtual void exportAsData(const char *FolderPath, const int indexStart, -// int *fileCount, char **dest) const = 0; -// /// get converted map(in mapColor array) -// virtual void getConvertedMap(int *rows, int *cols, uint8_t *) const = 0; -// -// // can do in builded: -// /// export map into litematica files (*.litematic) -// [[deprecated]] virtual void exportAsLitematic( -// const char *localEncoding_TargetName, const char *utf8_LiteName, -// const char *utf8_RegionName, char *localEncoding_returnVal) const = 0; -// -// /// export map into Structure files (*.NBT) -// [[deprecated]] virtual void exportAsStructure( -// const char *localEncoding_TargetName, -// char *localEncoding_FileName) const = 0; -// [[deprecated]] virtual void exportAsWESchem( -// const char *localEncoding_fileName, const int (&offset)[3] = {0, 0, 0}, -// const int (&weOffset)[3] = {0, 0, 0}, const char *utf8_Name = "", -// const char *const *const utf8_requiredMods = nullptr, -// const int requiredModsCount = 0, -// char *localEncoding_returnVal = nullptr) const = 0; -// -// /// get x,y,z size -// virtual void get3DSize(int *x, int *y, int *z) const = 0; -// -// /// get 3d structure's size -// virtual int getHeight() const = 0; -// /// get 3d structure's size -// virtual int getXRange() const = 0; -// /// get 3d structure's size -// virtual int getZRange() const = 0; -// /// get block count in total and in detail -// virtual void getBlockCounts(int *total, int detail[64]) const = 0; -// /// get sum block count -// virtual int64_t getBlockCounts() const = 0; -// /// get 3d structure in 3d-matrix (col major) -// virtual const uint16_t *getBuild(int *xSize = nullptr, int *ySize = -// nullptr, -// int *zSize = nullptr) const = 0; -// -// // Virtual functions added after v5.0.0. Define them in the end of vtable -// to -// // matain binary compability -// -// // introduced in v5.1.0 -// ----------------------------------------------------- virtual void -// setCacheDir(const char *) noexcept = 0; virtual const char *cacheDir() -// const noexcept = 0; -// // replacement for setRawImage(const uint32_t*,int,int) -// virtual void setRawImage(const uint32_t *src, int rows, int cols, -// bool is_col_major) = 0; -// // replacement for getConvertedImage(int *rows, int *cols, uint32_t -// // *dest)const -// virtual void getConvertedImage(int *rows, int *cols, uint32_t *dest, -// bool expected_col_major) const = 0; -// // struct build_options { -// // uint64_t caller_api_version{SC_VERSION_U64}; -// // uint16_t max_allowed_height{256}; -// // uint16_t bridge_interval{3}; -// // compressSettings compress_method{::SCL_compressSettings::noCompress}; -// // glassBridgeSettings -// glass_method{::SCL_glassBridgeSettings::noBridge}; -// // bool fire_proof{false}; -// // bool enderman_proof{false}; -// // -// // // added in v5.1.0 -// // bool connect_mushrooms{false}; -// // }; -// virtual bool build(const build_options &option) noexcept = 0; -// -// virtual void getCompressedImage(int *row, int *cols, uint32_t *dest, -// bool expected_col_major) const noexcept = -// 0; -// // requires step >= wait4image -// // virtual bool checkColorsetHash() const noexcept = 0; -// // requires step >= converted -// virtual bool saveConvertCache(string_deliver &err) const noexcept = 0; -// -// // requires step >= convertion ready -// virtual bool loadConvertCache(SCL_convertAlgo algo, bool dither) noexcept = -// 0; -// -// // requires step >= built -// virtual bool saveBuildCache(string_deliver &err) const noexcept = 0; -// -// // requires step >= converted -// virtual bool loadBuildCache(const build_options &option) noexcept = 0; -// -// // requires step >= built -// virtual int getSchemPalette(const char **dest_id, -// size_t dest_capacity) const noexcept = 0; -// -// virtual bool exportAsLitematic( -// const char *filename_local, -// const litematic_options &option) const noexcept = 0; -// -// virtual bool exportAsStructure( -// const char *filename_local, -// const vanilla_structure_options &option) const noexcept = 0; -// -// virtual bool exportAsWESchem( -// const char *filename_local, -// const WE_schem_options &option) const noexcept = 0; -// -// struct flag_diagram_options { -// uint64_t caller_api_version{SC_VERSION_U64}; -// -// // 0 or negative number means no split lines -// int32_t split_line_row_margin{0}; -// // 0 or negative number means no split lines -// int32_t split_line_col_margin{0}; -// int png_compress_level{9}; -// int png_compress_memory_level{8}; -// string_deliver *err{nullptr}; -// }; -// virtual bool exportAsFlatDiagram( -// const char *filename_local, -// const flag_diagram_options &option) const noexcept = 0; -// -// struct test_blocklist_options { -// uint64_t caller_api_version{SC_VERSION_U64}; -// const AbstractBlock *const *block_ptrs{nullptr}; -// const uint8_t *basecolors{nullptr}; -// size_t block_count{0}; -// string_deliver *err{nullptr}; -// }; -// virtual bool makeTests( -// const char *filename, -// const test_blocklist_options &option) const noexcept = 0; -// }; +class converted_image { + public: + virtual ~converted_image() = default; + [[nodiscard]] virtual size_t rows() const noexcept = 0; + [[nodiscard]] virtual size_t cols() const noexcept = 0; + [[nodiscard]] inline size_t height() const noexcept { return this->rows(); } + [[nodiscard]] inline size_t width() const noexcept { return this->cols(); } + [[nodiscard]] inline size_t size() const noexcept { + return this->rows() * this->cols(); + } + + [[nodiscard]] inline size_t size_in_bytes() const noexcept { + return sizeof(uint32_t) * this->rows() * this->cols(); + } + + virtual void get_original_image(uint32_t *buffer) const noexcept = 0; + // virtual void get_dithered_image(uint32_t *buffer) const noexcept = 0; + virtual void get_converted_image(uint32_t *buffer) const noexcept = 0; +}; + +class structure_3D { + public: + virtual ~structure_3D() = default; + [[nodiscard]] virtual size_t shape_x() const noexcept = 0; + [[nodiscard]] virtual size_t shape_y() const noexcept = 0; + [[nodiscard]] virtual size_t shape_z() const noexcept = 0; + [[nodiscard]] virtual size_t palette_length() const noexcept = 0; + virtual void get_palette(const char **buffer_block_id) const noexcept = 0; + + virtual bool export_litematica( + const char *filename, const litematic_options &option) const noexcept = 0; + virtual bool export_vanilla_structure( + const char *filename, + const vanilla_structure_options &option) const noexcept = 0; + virtual bool export_WE_schem( + const char *filename, const WE_schem_options &option) const noexcept = 0; +}; } // namespace SlopeCraft @@ -579,14 +354,14 @@ class color_table { extern "C" { namespace SlopeCraft { -//[[deprecated]] [[nodiscard]] SCL_EXPORT Kernel *SCL_createKernel(); -// SCL_EXPORT void SCL_destroyKernel(Kernel *); +[[nodiscard]] SCL_EXPORT mc_block_interface *SCL_create_block(); +SCL_EXPORT void SCL_destroy_block(mc_block_interface *); struct color_table_create_info { ::SCL_mapTypes map_type; ::SCL_gameVersion mc_version; bool basecolor_allow_LUT[64]; - const AbstractBlock *blocks[64]; + const mc_block_interface *blocks[64]; ui_callbacks ui; }; @@ -597,34 +372,15 @@ SCL_EXPORT void SCL_destroy_color_table(color_table *); SCL_EXPORT void SCL_destroy_converted_image(converted_image *); SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *); -[[nodiscard]] SCL_EXPORT AbstractBlock *SCL_create_block(); -SCL_EXPORT void SCL_destroy_block(AbstractBlock *); - struct block_list_create_info { uint64_t caller_api_version{SC_VERSION_U64}; string_deliver *warnings{nullptr}; string_deliver *error{nullptr}; }; -[[nodiscard]] SCL_EXPORT block_list_interface *SCL_createBlockList( +[[nodiscard]] SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option); - -SCL_EXPORT void SCL_destroyBlockList(block_list_interface *); - -//[[deprecated]] [[nodiscard]] SCL_EXPORT AiCvterOpt *SCL_createAiCvterOpt(); -//[[deprecated]] SCL_EXPORT void SCL_destroyAiCvterOpt(AiCvterOpt *); -// -//[[deprecated]] SCL_EXPORT void SCL_setPopSize(AiCvterOpt *, uint32_t p); -//[[deprecated]] SCL_EXPORT void SCL_setMaxGeneration(AiCvterOpt *, uint32_t p); -//[[deprecated]] SCL_EXPORT void SCL_setMaxFailTimes(AiCvterOpt *, uint32_t p); -//[[deprecated]] SCL_EXPORT void SCL_setCrossoverProb(AiCvterOpt *, double p); -//[[deprecated]] SCL_EXPORT void SCL_setMutationProb(AiCvterOpt *, double p); -// -//[[deprecated]] SCL_EXPORT uint32_t SCL_getPopSize(const AiCvterOpt *); -//[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxGeneration(const AiCvterOpt *); -//[[deprecated]] SCL_EXPORT uint32_t SCL_getMaxFailTimes(const AiCvterOpt *); -//[[deprecated]] SCL_EXPORT double SCL_getCrossoverProb(const AiCvterOpt *); -//[[deprecated]] SCL_EXPORT double SCL_getMutationProb(const AiCvterOpt *); +SCL_EXPORT void SCL_destroy_block_list(block_list_interface *); SCL_EXPORT void SCL_preprocessImage( uint32_t *ARGB32ptr, const uint64_t imageSize, @@ -639,27 +395,21 @@ SCL_EXPORT SCL_gameVersion SCL_maxAvailableVersion(); SCL_EXPORT const char *SCL_getSCLVersion(); -// SCL_EXPORT void SCL_getColorMapPtrs(const float **const rdata, -// const float **const gdata, -// const float **const bdata, const uint8_t -// **, int *); -// full palette SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); +SCL_EXPORT uint8_t SCL_maxBaseColor(); // SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); -SCL_EXPORT uint8_t SCL_maxBaseColor(); -// SCL_EXPORT int SCL_getBlockPalette(const AbstractBlock **blkpp, -// size_t capacity_in_elements); - // SCL_EXPORT uint64_t SCL_mcVersion2VersionNumber(::SCL_gameVersion); class deleter { public: // void operator()(Kernel *k) const noexcept { SCL_destroyKernel(k); } - void operator()(AbstractBlock *b) const noexcept { SCL_destroy_block(b); } + void operator()(mc_block_interface *b) const noexcept { + SCL_destroy_block(b); + } void operator()(block_list_interface *b) const noexcept { - SCL_destroyBlockList(b); + SCL_destroy_block_list(b); } void operator()(color_table *c) const noexcept { SCL_destroy_color_table(c); } void operator()(converted_image *c) const noexcept { diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 31103c4c..1966c1c0 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -37,10 +37,10 @@ class color_table_impl : public SlopeCraft::color_table { size_t num_blocks() const noexcept final { return this->blocks.size(); } - void visit_blocks(void (*fun)(const AbstractBlock *, void *custom_data), + void visit_blocks(void (*fun)(const mc_block_interface *, void *custom_data), void *custom_data) const final { for (auto &blk : this->blocks) { - fun(static_cast(&blk), custom_data); + fun(static_cast(&blk), custom_data); } } diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index a86ee38c..6dcbe046 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -35,7 +35,7 @@ mc_block::mc_block() { // wallUseable=true; } -size_t block_list::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, +size_t block_list::get_blocks(mc_block_interface **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) noexcept { if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { return 0; @@ -53,7 +53,8 @@ size_t block_list::get_blocks(AbstractBlock **dst, uint8_t *dst_basecolor, return counter; } -size_t block_list::get_blocks(const AbstractBlock **dst, uint8_t *dst_basecolor, +size_t block_list::get_blocks(const mc_block_interface **dst, + uint8_t *dst_basecolor, size_t capacity_in_elements) const noexcept { if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { return 0; diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index b20a097f..389fb0e2 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -34,7 +34,7 @@ using namespace SlopeCraft; typedef std::vector stringList; -class mc_block : public ::SlopeCraft::AbstractBlock { +class mc_block : public ::SlopeCraft::mc_block_interface { public: mc_block(); ~mc_block(){}; @@ -103,7 +103,7 @@ class mc_block : public ::SlopeCraft::AbstractBlock { this->imageFilename = _ifn; } - void copyTo(AbstractBlock *dst) const noexcept override { + void copyTo(mc_block_interface *dst) const noexcept override { *static_cast(dst) = *this; } @@ -134,13 +134,13 @@ class block_list : public ::SlopeCraft::block_list_interface { public: size_t size() const noexcept override { return m_blocks.size(); } - size_t get_blocks(AbstractBlock **dst, uint8_t *, + size_t get_blocks(mc_block_interface **dst, uint8_t *, size_t capacity_in_elements) noexcept override; - size_t get_blocks(const AbstractBlock **dst, uint8_t *, + size_t get_blocks(const mc_block_interface **dst, uint8_t *, size_t capacity_in_elements) const noexcept override; - bool contains(const AbstractBlock *cp) const noexcept override { + bool contains(const mc_block_interface *cp) const noexcept override { const mc_block *ptr = dynamic_cast(cp); return this->m_blocks.contains( reinterpret_cast &>(ptr)); diff --git a/SlopeCraftL/tests/load_scl_blocklist.cpp b/SlopeCraftL/tests/load_scl_blocklist.cpp index 44dea2c0..7f5f1bd2 100644 --- a/SlopeCraftL/tests/load_scl_blocklist.cpp +++ b/SlopeCraftL/tests/load_scl_blocklist.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) { &warn_sd, &err_sd, }; - blocklist = SlopeCraft::SCL_createBlockList(archive_path, option); + blocklist = SlopeCraft::SCL_create_block_list(archive_path, option); errmsg.resize(err_sd.size); warnings.resize(warn_sd.size); @@ -39,7 +39,7 @@ int main(int argc, char** argv) { } printf("%s loaded successfully\n", archive_path); - SlopeCraft::SCL_destroyBlockList(blocklist); + SlopeCraft::SCL_destroy_block_list(blocklist); return 0; // if (archive.getE) return 0; diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index 8ac2d6e0..bca3f65e 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -28,7 +28,7 @@ void BaseColorWidget::set_color(uint32_t color) noexcept { constexpr int basecolor_cols = 3; static_assert(basecolor_cols >= 1); -void BaseColorWidget::add_block(SlopeCraft::AbstractBlock* ab) noexcept { +void BaseColorWidget::add_block(SlopeCraft::mc_block_interface* ab) noexcept { BlockWidget* bw = new BlockWidget(this, ab); const int idx = this->blocks.size(); @@ -196,7 +196,7 @@ void BaseColorWidget::set_enabled(bool enabled) noexcept { } void BaseColorWidget::select_by_callback(const select_callback_t& fun) { - std::vector blks; + std::vector blks; blks.reserve(this->blocks.size()); for (auto bw : this->blocks) { blks.emplace_back(bw->attachted_block()); diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index e02c09b4..20e4321e 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -12,7 +12,7 @@ class BaseColorWidget; } using select_callback_t = std::function& blks)>; + const std::vector& blks)>; class BaseColorWidget : public QGroupBox { Q_OBJECT @@ -27,7 +27,7 @@ class BaseColorWidget : public QGroupBox { void set_color(uint32_t argb32) noexcept; - void add_block(SlopeCraft::AbstractBlock* ab) noexcept; + void add_block(SlopeCraft::mc_block_interface* ab) noexcept; void finish_blocks() noexcept; @@ -39,7 +39,7 @@ class BaseColorWidget : public QGroupBox { bool is_enabled() const noexcept; - const SlopeCraft::AbstractBlock* selected_block() const noexcept { + const SlopeCraft::mc_block_interface* selected_block() const noexcept { return this->blocks[this->selected_idx()]->attachted_block(); } diff --git a/utilities/BlockListManager/Block.cpp b/utilities/BlockListManager/Block.cpp index 6b1b5911..d30adbc1 100644 --- a/utilities/BlockListManager/Block.cpp +++ b/utilities/BlockListManager/Block.cpp @@ -1,6 +1,6 @@ #include "Block.h" -BlockWidget::BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk) +BlockWidget::BlockWidget(QWidget* parent, SlopeCraft::mc_block_interface* _blk) : QRadioButton(parent), block(_blk) { this->setText(this->block->getNameZH()); QImage img{this->block->imageCols(), this->block->imageRows(), diff --git a/utilities/BlockListManager/Block.h b/utilities/BlockListManager/Block.h index 3935d4d6..189de5d5 100644 --- a/utilities/BlockListManager/Block.h +++ b/utilities/BlockListManager/Block.h @@ -9,10 +9,10 @@ class BlockWidget : public QRadioButton { Q_OBJECT private: - SlopeCraft::AbstractBlock* const block; + SlopeCraft::mc_block_interface* const block; public: - explicit BlockWidget(QWidget* parent, SlopeCraft::AbstractBlock* _blk); + explicit BlockWidget(QWidget* parent, SlopeCraft::mc_block_interface* _blk); ~BlockWidget() = default; auto attachted_block() const noexcept { return this->block; } diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 98de3996..3cde233a 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -55,7 +55,7 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::block_list_interface *bli = - SlopeCraft::SCL_createBlockList(filename.toLocal8Bit().data(), option); + SlopeCraft::SCL_create_block_list(filename.toLocal8Bit().data(), option); errmsg.resize(sd_err.size); warning.resize(sd_warn.size); @@ -76,7 +76,7 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { } } - std::vector blockps; + std::vector blockps; std::vector base_colors; base_colors.resize(bli->size()); blockps.resize(bli->size()); @@ -118,7 +118,8 @@ void BlockListManager::when_version_updated() noexcept { void BlockListManager::get_blocklist( std::vector &enable_list, - std::vector &block_list) const noexcept { + std::vector &block_list) + const noexcept { enable_list.resize(64); block_list.resize(64); diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index ad1dd2dd..8599498e 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -25,7 +25,7 @@ QString serialize_preset(const blockListPreset &preset) noexcept; class BlockListDeleter { public: void operator()(SlopeCraft::block_list_interface *ptr) noexcept { - SlopeCraft::SCL_destroyBlockList(ptr); + SlopeCraft::SCL_destroy_block_list(ptr); } }; @@ -72,8 +72,8 @@ class BlockListManager : public QWidget { } void get_blocklist(std::vector &enable_list, - std::vector &block_list) - const noexcept; + std::vector + &block_list) const noexcept; bool loadPreset(const blockListPreset &preset) noexcept; From 2a07d08d074932be2f9bf5a654b2118290d44ee4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:39:12 +0800 Subject: [PATCH 0789/1123] remove singleton in prim glass builder Signed-off-by: ToKiNoBug --- SlopeCraftL/prim_glass_builder.cpp | 76 +++++++++++++++--------------- SlopeCraftL/prim_glass_builder.h | 34 +++++++------ 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/SlopeCraftL/prim_glass_builder.cpp b/SlopeCraftL/prim_glass_builder.cpp index 11dc3ca8..68c151c0 100644 --- a/SlopeCraftL/prim_glass_builder.cpp +++ b/SlopeCraftL/prim_glass_builder.cpp @@ -26,37 +26,35 @@ const ARGB airColor = ARGB32(255, 255, 255); const ARGB targetColor = ARGB32(0, 0, 0); const ARGB glassColor = ARGB32(192, 192, 192); -const std::vector *edge::vertexes = nullptr; - -edge::edge() { - // beg=TokiRC(0,0); - // end=TokiRC(0,0); - begIdx = 0; - endIdx = 0; - lengthSquare = 0; +// const std::vector *edge::vertexes = nullptr; + +// edge::edge() { +// // beg=TokiRC(0,0); +// // end=TokiRC(0,0); +// begIdx = 0; +// endIdx = 0; +// lengthSquare = 0; +// } + +edge::edge(uint32_t b, uint32_t e, std::span v) + : begIdx{b}, endIdx{e}, lengthSquare{[b, e, v]() { + const auto beg = v[b]; + const auto end = v[e]; + const int rowSpan = beg.row - end.row; + const int colSpan = beg.col - end.col; + return (rowSpan * rowSpan + colSpan * colSpan); + }()} {} + +rc_pos edge::beg(std::span vertices) const { + return vertices[begIdx]; } -edge::edge(uint32_t _begIdx, uint32_t _endIdx) { - begIdx = _begIdx; - endIdx = _endIdx; - // const int r1 =beg().row,c1=; TokiRow(beg()), c1 = TokiCol(beg()); - // int r2 = TokiRow(end()), c2 = TokiCol(end()); - - const int rowSpan = beg().row - end().row; - const int colSpan = beg().col - end().col; - lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); +rc_pos edge::end(std::span vertices) const { + return vertices[endIdx]; } -rc_pos edge::beg() const { return vertexes->at(begIdx); } - -rc_pos edge::end() const { return vertexes->at(endIdx); } - pairedEdge::pairedEdge() - : std::pair{{0, 0}, {0, 0}}, lengthSquare{0} { - // first = TokiRC(0, 0); - // second = TokiRC(0, 0); - // lengthSquare = 0; -} + : std::pair{{0, 0}, {0, 0}}, lengthSquare{0} {} pairedEdge::pairedEdge(rc_pos A, rc_pos B) { int r1 = A.row, c1 = A.col; int r2 = B.row, c2 = B.col; @@ -75,9 +73,9 @@ pairedEdge::pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2) { lengthSquare = (rowSpan * rowSpan + colSpan * colSpan); } -pairedEdge::pairedEdge(const edge &src) { - first = src.beg(); - second = src.end(); +pairedEdge::pairedEdge(const edge &src, std::span v) { + first = src.beg(v); + second = src.end(v); lengthSquare = src.lengthSquare; } /* @@ -309,12 +307,12 @@ pairedEdge prim_glass_builder::connectSingleMaps(const prim_glass_builder *map1, void prim_glass_builder::addEdgesToGraph() { edges.clear(); - edge::vertexes = std::addressof(targetPoints); + // edge::vertexes = std::addressof(targetPoints); // int taskCount=(targetPoints.size()*(targetPoints.size()-1))/2; // progressRangeSet(*windPtr,0,taskCount,0); for (uint32_t i = 0; i < targetPoints.size(); i++) { for (uint32_t j = i + 1; j < targetPoints.size(); j++) { - edges.emplace_back(edge(i, j)); + edges.emplace_back(edge(i, j, this->targetPoints)); } // emit keepAwake(); // emit progressAdd(targetPoints.size()-i); @@ -404,7 +402,7 @@ void prim_glass_builder::runPrim() { // found.emplace(y); // unsearched.erase(x); // unsearched.erase(y); - tree.emplace_back(*selectedEdge); + tree.emplace_back(*selectedEdge, this->targetPoints); } // if(foundCount%reportRate==0) { // //progressRangeSet(*windPtr,0,targetPoints.size(),foundCount); @@ -482,13 +480,13 @@ TokiMap impl_ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { return result; } -TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { - return impl_ySlice2TokiMap(raw); -} - -TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { - return impl_ySlice2TokiMap(raw); -} +// TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { +// return impl_ySlice2TokiMap(raw); +// } +// +// TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { +// return impl_ySlice2TokiMap(raw); +// } TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, std::span start_xzy, diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index 48691af5..89e46441 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -45,21 +45,18 @@ typedef Eigen::Array TokiMap; typedef TokiMap glassMap; typedef TokiMap walkableMap; -#warning "TODO: Remove global variables in this part" class edge { public: - edge(); - edge(uint32_t begIdx, uint32_t endIdx); - uint32_t begIdx; - uint32_t endIdx; - int lengthSquare; - - static const std::vector *vertexes; - - rc_pos beg() const; - rc_pos end() const; - bool connectWith(rc_pos) const; - void drawEdge(glassMap &, bool drawHead = false) const; + explicit edge() = delete; + edge(uint32_t begIdx, uint32_t endIdx, std::span vertices); + const uint32_t begIdx; + const uint32_t endIdx; + const int lengthSquare; + + rc_pos beg(std::span vertices) const; + rc_pos end(std::span vertices) const; + // bool connectWith(rc_pos) const; + // void drawEdge(glassMap &, bool drawHead = false) const; }; class pairedEdge : public std::pair { @@ -67,17 +64,18 @@ class pairedEdge : public std::pair { pairedEdge(); pairedEdge(rc_pos, rc_pos); pairedEdge(uint32_t r1, uint32_t c1, uint32_t r2, uint32_t c2); - pairedEdge(const edge &); + pairedEdge(const edge &, std::span vertices); + int lengthSquare; bool connectWith(rc_pos) const; void drawEdge(glassMap &, bool drawHead = false) const; }; -[[deprecated]] TokiMap ySlice2TokiMap( - const Eigen::Tensor &) noexcept; -[[deprecated]] TokiMap ySlice2TokiMap_u16( - const Eigen::Tensor &) noexcept; +//[[deprecated]] TokiMap ySlice2TokiMap( +// const Eigen::Tensor &) noexcept; +//[[deprecated]] TokiMap ySlice2TokiMap_u16( +// const Eigen::Tensor &) noexcept; TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, std::span start_xzy, std::span extension_xzy) noexcept; From 3315cd246ef99f08e641002ccf37c866ca4ffeae Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:47:03 +0800 Subject: [PATCH 0790/1123] remove object_pool from prim glass builder Signed-off-by: ToKiNoBug --- SlopeCraftL/object_pool.hpp | 778 ----------------------------- SlopeCraftL/prim_glass_builder.cpp | 22 +- SlopeCraftL/prim_glass_builder.h | 10 +- 3 files changed, 13 insertions(+), 797 deletions(-) delete mode 100644 SlopeCraftL/object_pool.hpp diff --git a/SlopeCraftL/object_pool.hpp b/SlopeCraftL/object_pool.hpp deleted file mode 100644 index abee2d99..00000000 --- a/SlopeCraftL/object_pool.hpp +++ /dev/null @@ -1,778 +0,0 @@ -// 2020/03/13 - modified by Tsung-Wei Huang -// - fixed bug in aligning memory -// -// 2020/02/02 - modified by Tsung-Wei Huang -// - new implementation motivated by Hoard -// -// 2019/07/10 - modified by Tsung-Wei Huang -// - replace raw pointer with smart pointer -// -// 2019/06/13 - created by Tsung-Wei Huang -// - implemented an object pool class - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace tf { - -#define TF_ENABLE_POOLABLE_ON_THIS \ - template friend class ObjectPool; \ - void* _object_pool_block - -// Class: ObjectPool -// -// The class implements an efficient thread-safe object pool motivated -// by the Hoard memory allocator algorithm. -// Different from the normal memory allocator, object pool allocates -// only one object at a time. -// -// Internall, we use the following variables to maintain blocks and heaps: -// X: size in byte of a item slot -// M: number of items per block -// F: emptiness threshold -// B: number of bins per local heap (bin[B-1] is the full list) -// W: number of items per bin -// K: shrinkness constant -// -// Example scenario 1: -// M = 30 -// F = 4 -// W = (30+4-1)/4 = 8 -// -// b0: 0, 1, 2, 3, 4, 5, 6, 7 -// b1: 8, 9, 10, 11, 12, 13, 14, 15 -// b2: 16, 17, 18, 19, 20, 21, 22, 23 -// b3: 24, 25, 26, 27, 28, 29 -// b4: 30 (anything equal to M) -// -// Example scenario 2: -// M = 32 -// F = 4 -// W = (32+4-1)/4 = 8 -// b0: 0, 1, 2, 3, 4, 5, 6, 7 -// b1: 8, 9, 10, 11, 12, 13, 14, 15 -// b2: 16, 17, 18, 19, 20, 21, 22, 23 -// b3: 24, 25, 26, 27, 28, 29, 30, 31 -// b4: 32 (anything equal to M) -// -template -class ObjectPool { - - // the data column must be sufficient to hold the pointer in freelist - constexpr static size_t X = (std::max)(sizeof(T*), sizeof(T)); - //constexpr static size_t X = sizeof(long double) + std::max(sizeof(T*), sizeof(T)); - //constexpr static size_t M = (S - offsetof(Block, data)) / X; - constexpr static size_t M = S / X; - constexpr static size_t F = 4; - constexpr static size_t B = F + 1; - constexpr static size_t W = (M + F - 1) / F; - constexpr static size_t K = 4; - - static_assert( - S && (!(S & (S-1))), "block size S must be a power of two" - ); - - static_assert( - M >= 128, "block size S must be larger enough to pool at least 128 objects" - ); - - struct Blocklist { - Blocklist* prev; - Blocklist* next; - }; - - struct GlobalHeap { - std::mutex mutex; - Blocklist list; - }; - - struct LocalHeap { - std::mutex mutex; - Blocklist lists[B]; - size_t u {0}; - size_t a {0}; - }; - - struct Block { - std::atomic heap; - Blocklist list_node; - size_t i; - size_t u; - T* top; - // long double padding; - char data[S]; - }; - - public: - - /** - @brief constructs an object pool from a number of anticipated threads - */ - explicit ObjectPool(unsigned = std::thread::hardware_concurrency()); - - /** - @brief destructs the object pool - */ - ~ObjectPool(); - - /** - @brief acquires a pointer to a object constructed from a given argument list - */ - template - T* animate(ArgsT&&... args); - - /** - @brief recycles a object pointed by @c ptr and destroys it - */ - void recycle(T* ptr); - - size_t num_bins_per_local_heap() const; - size_t num_objects_per_bin() const; - size_t num_objects_per_block() const; - size_t num_available_objects() const; - size_t num_allocated_objects() const; - size_t capacity() const; - size_t num_local_heaps() const; - size_t num_global_heaps() const; - size_t num_heaps() const; - - float emptiness_threshold() const; - - private: - - const size_t _lheap_mask; - - GlobalHeap _gheap; - - std::vector _lheaps; - - LocalHeap& _this_heap(); - - constexpr unsigned _next_pow2(unsigned n) const; - - template - constexpr size_t _offset_in_class(const Q P::*member) const; - - template - constexpr P* _parent_class_of(Q*, const Q P::*member); - - template - constexpr P* _parent_class_of(const Q*, const Q P::*member) const; - - constexpr Block* _block_of(Blocklist*); - constexpr Block* _block_of(const Blocklist*) const; - - size_t _bin(size_t) const; - - T* _allocate(Block*); - - void _deallocate(Block*, T*); - void _blocklist_init_head(Blocklist*); - void _blocklist_add_impl(Blocklist*, Blocklist*, Blocklist*); - void _blocklist_push_front(Blocklist*, Blocklist*); - void _blocklist_push_back(Blocklist*, Blocklist*); - void _blocklist_del_impl(Blocklist*, Blocklist*); - void _blocklist_del(Blocklist*); - void _blocklist_replace(Blocklist*, Blocklist*); - void _blocklist_move_front(Blocklist*, Blocklist*); - void _blocklist_move_back(Blocklist*, Blocklist*); - bool _blocklist_is_first(const Blocklist*, const Blocklist*); - bool _blocklist_is_last(const Blocklist*, const Blocklist*); - bool _blocklist_is_empty(const Blocklist*); - bool _blocklist_is_singular(const Blocklist*); - - template - void _for_each_block_safe(Blocklist*, C&&); - - template - void _for_each_block(Blocklist*, C&&); - -}; - -// ---------------------------------------------------------------------------- -// ObjectPool definition -// ---------------------------------------------------------------------------- - -// Constructor -template -ObjectPool::ObjectPool(unsigned t) : - //_heap_mask {(_next_pow2(t) << 1) - 1u}, - //_heap_mask { _next_pow2(t<<1) - 1u }, - //_heap_mask {(t << 1) - 1}, - _lheap_mask { _next_pow2((t+1) << 1) - 1 }, - _lheaps { _lheap_mask + 1 } { - - _blocklist_init_head(&_gheap.list); - - for(auto& h : _lheaps) { - for(size_t i=0; i -ObjectPool::~ObjectPool() { - - // clear local heaps - for(auto& h : _lheaps) { - for(size_t i=0; i -size_t ObjectPool::num_bins_per_local_heap() const { - return B; -} - -// Function: num_objects_per_bin -template -size_t ObjectPool::num_objects_per_bin() const { - return W; -} - -// Function: num_objects_per_block -template -size_t ObjectPool::num_objects_per_block() const { - return M; -} - -// Function: emptiness_threshold -template -float ObjectPool::emptiness_threshold() const { - return 1.0f/F; -} - -// Function: num_global_heaps -template -size_t ObjectPool::num_global_heaps() const { - return 1; -} - -// Function: num_lheaps -template -size_t ObjectPool::num_local_heaps() const { - return _lheaps.size(); -} - -// Function: num_heaps -template -size_t ObjectPool::num_heaps() const { - return _lheaps.size() + 1; -} - -// Function: capacity -template -size_t ObjectPool::capacity() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += M; - }; - - // local heap - for(auto& h : _lheaps) { - n += h.a; - } - - return n; -} - -// Function: num_available_objects -template -size_t ObjectPool::num_available_objects() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += (M - _block_of(p)->u); - }; - - // local heap - for(auto& h : _lheaps) { - n += (h.a - h.u); - } - return n; -} - -// Function: num_allocated_objects -template -size_t ObjectPool::num_allocated_objects() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += _block_of(p)->u; - }; - - // local heap - for(auto& h : _lheaps) { - n += h.u; - } - return n; -} - -// Function: _bin -template -size_t ObjectPool::_bin(size_t u) const { - return u == M ? F : u/W; -} - -// Function: _offset_in_class -template -template -constexpr size_t ObjectPool::_offset_in_class( - const Q P::*member) const { - return (size_t) &( reinterpret_cast(0)->*member); -} - -// C macro: parent_class_of(list_pointer, Block, list) -// C++: parent_class_of(list_pointer, &Block::list) -template -template -constexpr P* ObjectPool::_parent_class_of( - Q* ptr, const Q P::*member -) { - return (P*)( (char*)ptr - _offset_in_class(member)); -} - -// Function: _parent_class_of -template -template -constexpr P* ObjectPool::_parent_class_of( - const Q* ptr, const Q P::*member -) const { - return (P*)( (char*)ptr - _offset_in_class(member)); -} - -// Function: _block_of -template -constexpr typename ObjectPool::Block* -ObjectPool::_block_of(Blocklist* list) { - return _parent_class_of(list, &Block::list_node); -} - -// Function: _block_of -template -constexpr typename ObjectPool::Block* -ObjectPool::_block_of(const Blocklist* list) const { - return _parent_class_of(list, &Block::list_node); -} - -// Procedure: initialize a list head -template -void ObjectPool::_blocklist_init_head(Blocklist *list) { - list->next = list; - list->prev = list; -} - -// Procedure: _blocklist_add_impl -// Insert a new entry between two known consecutive entries. -// -// This is only for internal list manipulation where we know -// the prev/next entries already! -template -void ObjectPool::_blocklist_add_impl( - Blocklist *curr, Blocklist *prev, Blocklist *next -) { - next->prev = curr; - curr->next = next; - curr->prev = prev; - prev->next = curr; -} - -// list_push_front - add a new entry -// @curr: curr entry to be added -// @head: list head to add it after -// -// Insert a new entry after the specified head. -// This is good for implementing stacks. -// -template -void ObjectPool::_blocklist_push_front( - Blocklist *curr, Blocklist *head -) { - _blocklist_add_impl(curr, head, head->next); -} - -// list_add_tail - add a new entry -// @curr: curr entry to be added -// @head: list head to add it before -// -// Insert a new entry before the specified head. -// This is useful for implementing queues. -// -template -void ObjectPool::_blocklist_push_back( - Blocklist *curr, Blocklist *head -) { - _blocklist_add_impl(curr, head->prev, head); -} - -// Delete a list entry by making the prev/next entries -// point to each other. -// -// This is only for internal list manipulation where we know -// the prev/next entries already! -// -template -void ObjectPool::_blocklist_del_impl( - Blocklist * prev, Blocklist * next -) { - next->prev = prev; - prev->next = next; -} - -// _blocklist_del - deletes entry from list. -// @entry: the element to delete from the list. -// Note: list_empty() on entry does not return true after this, the entry is -// in an undefined state. -template -void ObjectPool::_blocklist_del(Blocklist *entry) { - _blocklist_del_impl(entry->prev, entry->next); - entry->next = nullptr; - entry->prev = nullptr; -} - -// list_replace - replace old entry by new one -// @old : the element to be replaced -// @curr : the new element to insert -// -// If @old was empty, it will be overwritten. -template -void ObjectPool::_blocklist_replace( - Blocklist *old, Blocklist *curr -) { - curr->next = old->next; - curr->next->prev = curr; - curr->prev = old->prev; - curr->prev->next = curr; -} - -// list_move - delete from one list and add as another's head -// @list: the entry to move -// @head: the head that will precede our entry -template -void ObjectPool::_blocklist_move_front( - Blocklist *list, Blocklist *head -) { - _blocklist_del_impl(list->prev, list->next); - _blocklist_push_front(list, head); -} - -// list_move_tail - delete from one list and add as another's tail -// @list: the entry to move -// @head: the head that will follow our entry -template -void ObjectPool::_blocklist_move_back( - Blocklist *list, Blocklist *head -) { - _blocklist_del_impl(list->prev, list->next); - _blocklist_push_back(list, head); -} - -// list_is_first - tests whether @list is the last entry in list @head -// @list: the entry to test -// @head: the head of the list -template -bool ObjectPool::_blocklist_is_first( - const Blocklist *list, const Blocklist *head -) { - return list->prev == head; -} - -// list_is_last - tests whether @list is the last entry in list @head -// @list: the entry to test -// @head: the head of the list -template -bool ObjectPool::_blocklist_is_last( - const Blocklist *list, const Blocklist *head -) { - return list->next == head; -} - -// list_empty - tests whether a list is empty -// @head: the list to test. -template -bool ObjectPool::_blocklist_is_empty(const Blocklist *head) { - return head->next == head; -} - -// list_is_singular - tests whether a list has just one entry. -// @head: the list to test. -template -bool ObjectPool::_blocklist_is_singular( - const Blocklist *head -) { - return !_blocklist_is_empty(head) && (head->next == head->prev); -} - -// Procedure: _for_each_block -template -template -void ObjectPool::_for_each_block(Blocklist* head, C&& c) { - Blocklist* p; - for(p=head->next; p!=head; p=p->next) { - c(_block_of(p)); - } -} - -// Procedure: _for_each_block_safe -// Iterate each item of a list - safe to free -template -template -void ObjectPool::_for_each_block_safe(Blocklist* head, C&& c) { - Blocklist* p; - Blocklist* t; - for(p=head->next, t=p->next; p!=head; p=t, t=p->next) { - c(_block_of(p)); - } -} - -// Function: _allocate -// allocate a spot from the block -template -T* ObjectPool::_allocate(Block* s) { - if(s->top == nullptr) { - return reinterpret_cast(s->data + s->i++ * X); - } - else { - T* retval = s->top; - s->top = *(reinterpret_cast(s->top)); - return retval; - } -} - -// Procedure: _deallocate -template -void ObjectPool::_deallocate(Block* s, T* ptr) { - *(reinterpret_cast(ptr)) = s->top; - s->top = ptr; -} - -// Function: allocate -template -template -T* ObjectPool::animate(ArgsT&&... args) { - - //std::cout << "construct a new item\n"; - - // my logically mapped heap - LocalHeap& h = _this_heap(); - - Block* s {nullptr}; - - h.mutex.lock(); - - // scan the list of superblocks from most full to least - int f = static_cast(F-1); - for(; f>=0; f--) { - if(!_blocklist_is_empty(&h.lists[f])) { - s = _block_of(h.lists[f].next); - break; - } - } - - // no superblock found - if(f == -1) { - - // check heap 0 for a superblock - _gheap.mutex.lock(); - if(!_blocklist_is_empty(&_gheap.list)) { - - s = _block_of(_gheap.list.next); - - //printf("get a superblock from global heap %lu\n", s->u); - assert(s->u < M && s->heap == nullptr); - f = static_cast(_bin(s->u + 1)); - - _blocklist_move_front(&s->list_node, &h.lists[f]); - - s->heap = &h; // must be within the global heap lock - _gheap.mutex.unlock(); - - h.u = h.u + s->u; - h.a = h.a + M; - } - // create a new block - else { - //printf("create a new superblock\n"); - _gheap.mutex.unlock(); - f = 0; - //s = static_cast(std::malloc(sizeof(Block))); - s = new Block(); - - if(s == nullptr) { - throw std::bad_alloc(); - } - - s->heap = &h; - s->i = 0; - s->u = 0; - s->top = nullptr; - - _blocklist_push_front(&s->list_node, &h.lists[f]); - - h.a = h.a + M; - } - } - - // the superblock must have at least one space - //assert(s->u < M); - //printf("%lu %lu %lu\n", h.u, h.a, s->u); - //assert(h.u < h.a); - - h.u = h.u + 1; - s->u = s->u + 1; - - // take one item from the superblock - T* mem = _allocate(s); - - int b = static_cast(_bin(s->u)); - - if(b != f) { - //printf("move superblock from list[%d] to list[%d]\n", f, b); - _blocklist_move_front(&s->list_node, &h.lists[b]); - } - - //std::cout << "s.i " << s->i << '\n' - // << "s.u " << s->u << '\n' - // << "h.u " << h.u << '\n' - // << "h.a " << h.a << '\n'; - - h.mutex.unlock(); - - //printf("allocate %p (s=%p)\n", mem, s); - - new (mem) T(std::forward(args)...); - - mem->_object_pool_block = s; - - return mem; -} - -// Function: destruct -template -void ObjectPool::recycle(T* mem) { - - //Block* s = *reinterpret_cast( - // reinterpret_cast(mem) - sizeof(Block**) - //); - - //Block* s= *(reinterpret_cast(mem) - O); // (mem) - 1 - - Block* s = static_cast(mem->_object_pool_block); - - mem->~T(); - - //printf("deallocate %p (s=%p) M=%lu W=%lu X=%lu\n", mem, s, M, W, X); - - // here we need a loop because when we lock the heap, - // other threads may have removed the superblock to another heap - bool sync = false; - - do { - LocalHeap* h = s->heap.load(std::memory_order_relaxed); - - // the block is in global heap - if(h == nullptr) { - std::lock_guard glock(_gheap.mutex); - if(s->heap == h) { - sync = true; - _deallocate(s, mem); - s->u = s->u - 1; - } - } - else { - std::lock_guard llock(h->mutex); - if(s->heap == h) { - sync = true; - // deallocate the item from the superblock - size_t f = _bin(s->u); - _deallocate(s, mem); - s->u = s->u - 1; - h->u = h->u - 1; - - size_t b = _bin(s->u); - - if(b != f) { - //printf("move superblock from list[%d] to list[%d]\n", f, b); - _blocklist_move_front(&s->list_node, &h->lists[b]); - } - - // transfer a mostly-empty superblock to global heap - if((h->u + K*M < h->a) && (h->u < ((F-1) * h->a / F))) { - for(size_t i=0; ilists[i])) { - Block* x = _block_of(h->lists[i].next); - //printf("transfer a block (x.u=%lu/x.i=%lu) to the global heap\n", x->u, x->i); - assert(h->u > x->u && h->a > M); - h->u = h->u - x->u; - h->a = h->a - M; - x->heap = nullptr; - std::lock_guard glock(_gheap.mutex); - _blocklist_move_front(&x->list_node, &_gheap.list); - break; - } - } - } - } - } - } while(!sync); - - //std::cout << "s.i " << s->i << '\n' - // << "s.u " << s->u << '\n'; -} - -// Function: _this_heap -template -typename ObjectPool::LocalHeap& -ObjectPool::_this_heap() { - // here we don't use thread local since object pool might be - // created and destroyed multiple times - //thread_local auto hv = std::hash()(std::this_thread::get_id()); - //return _lheaps[hv & _lheap_mask]; - - return _lheaps[ - std::hash()(std::this_thread::get_id()) & _lheap_mask - ]; -} - -// Function: _next_pow2 -template -constexpr unsigned ObjectPool::_next_pow2(unsigned n) const { - if(n == 0) return 1; - n--; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - n |= n >> 16; - n++; - return n; -} - -} // end namespace tf -------------------------------------------------------- diff --git a/SlopeCraftL/prim_glass_builder.cpp b/SlopeCraftL/prim_glass_builder.cpp index 68c151c0..777c5dd8 100644 --- a/SlopeCraftL/prim_glass_builder.cpp +++ b/SlopeCraftL/prim_glass_builder.cpp @@ -127,7 +127,7 @@ glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, const int rowCount = ceil(double(_targetMap.rows()) / unitL); const int colCount = ceil(double(_targetMap.cols()) / unitL); - std::vector> algos(rowCount); + std::vector> algos(rowCount); std::vector> glassMaps(rowCount); std::vector> walkableMaps(rowCount); std::vector> targetMaps(rowCount); @@ -144,14 +144,14 @@ glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, std::min(long(unitL), long(_targetMap.rows() - r * unitL)), std::min(long(unitL), long(_targetMap.cols() - c * unitL))); - algos[r][c] = pgb.animate(); + algos[r][c] = prim_glass_builder{}; } } // qDebug("分区分块完毕,开始在每个分区内搭桥"); for (int r = 0; r < rowCount; r++) { for (int c = 0; c < colCount; c++) { // qDebug()<<"开始处理第 ["<make4SingleMap( + glassMaps[r][c] = algos[r][c].make4SingleMap( targetMaps[r][c], (walkable == nullptr) ? nullptr : (&walkableMaps[r][c])); } @@ -215,9 +215,9 @@ glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, if (walkable != nullptr) interRegionEdges.top().drawEdge(*walkable, true); interRegionEdges.pop(); } - // qDebug("拼合分区完毕,开始 delete 各个分区的 algo"); - for (int r = 0; r < rowCount; r++) - for (int c = 0; c < colCount; c++) pgb.recycle(algos[r][c]); + // // qDebug("拼合分区完毕,开始 delete 各个分区的 algo"); + // for (int r = 0; r < rowCount; r++) + // for (int c = 0; c < colCount; c++) pgb.recycle(algos[r][c]); (*progressRangeSetPtr)(*windPtr, 0, 100, 100); // qDebug()<<"用时"<targetPoints.size() <= 0 || map2->targetPoints.size() <= 0) + if (map1.targetPoints.size() <= 0 || map2.targetPoints.size() <= 0) return pairedEdge(); uint32_t offsetR1 = offset1.row, offsetC1 = offset1.col; @@ -289,9 +289,9 @@ pairedEdge prim_glass_builder::connectSingleMaps(const prim_glass_builder *map1, pairedEdge min; min.lengthSquare = 0x7FFFFFFF; - for (auto it = map1->targetPoints.cbegin(); it != map1->targetPoints.cend(); + for (auto it = map1.targetPoints.cbegin(); it != map1.targetPoints.cend(); it++) - for (auto jt = map2->targetPoints.cbegin(); jt != map2->targetPoints.cend(); + for (auto jt = map2.targetPoints.cbegin(); jt != map2.targetPoints.cend(); jt++) { r1 = offsetR1 + it->row; c1 = offsetC1 + it->col; diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index 89e46441..8bc1b741 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -31,7 +31,6 @@ This file is part of SlopeCraft. #include #include -#include "object_pool.hpp" #include "SCLDefines.h" #include "water_item.h" @@ -88,10 +87,6 @@ class prim_glass_builder { public: prim_glass_builder(); - template - friend class tf::ObjectPool; - void *_object_pool_block; - static const uint32_t unitL = 32; static const uint32_t reportRate = 50; enum blockType { air = 0, glass = 1, target = 127 }; @@ -109,12 +104,11 @@ class prim_glass_builder { void addEdgesToGraph(); void runPrim(); glassMap make4SingleMap(const TokiMap &_targetMap, walkableMap *walkable); - static pairedEdge connectSingleMaps(const prim_glass_builder *map1, + static pairedEdge connectSingleMaps(const prim_glass_builder &map1, rc_pos offset1, - const prim_glass_builder *map2, + const prim_glass_builder &map2, rc_pos offset2); }; -inline tf::ObjectPool pgb; EImage TokiMap2EImage(const TokiMap &); From 21817f8cf5bad77eb40db090fbbf4a760fc42391 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Apr 2024 20:55:45 +0800 Subject: [PATCH 0791/1123] update callbacks of prim glass builder Signed-off-by: ToKiNoBug --- SlopeCraftL/prim_glass_builder.cpp | 12 ++-------- SlopeCraftL/prim_glass_builder.h | 7 +++--- SlopeCraftL/structure_3D.cpp | 37 +++++++++++++++--------------- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/SlopeCraftL/prim_glass_builder.cpp b/SlopeCraftL/prim_glass_builder.cpp index 777c5dd8..662486bb 100644 --- a/SlopeCraftL/prim_glass_builder.cpp +++ b/SlopeCraftL/prim_glass_builder.cpp @@ -155,7 +155,7 @@ glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, targetMaps[r][c], (walkable == nullptr) ? nullptr : (&walkableMaps[r][c])); } - (*progressRangeSetPtr)(*windPtr, 0, rowCount, r); + this->progress_bar.set_range(0, rowCount, r); } // qDebug("每个分区内的搭桥完毕,开始在分区间搭桥"); std::stack interRegionEdges; @@ -219,7 +219,7 @@ glassMap prim_glass_builder::makeBridge(const TokiMap &_targetMap, // for (int r = 0; r < rowCount; r++) // for (int c = 0; c < colCount; c++) pgb.recycle(algos[r][c]); - (*progressRangeSetPtr)(*windPtr, 0, 100, 100); + this->progress_bar.set_range(0, 100, 100); // qDebug()<<"用时"< &raw) noexcept { return result; } -// TokiMap ySlice2TokiMap(const Eigen::Tensor &raw) noexcept { -// return impl_ySlice2TokiMap(raw); -// } -// -// TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &raw) noexcept { -// return impl_ySlice2TokiMap(raw); -// } - TokiMap ySlice2TokiMap_u16(const Eigen::Tensor &xzy, std::span start_xzy, std::span extension_xzy) noexcept { diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index 8bc1b741..6b038ab8 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -92,10 +92,9 @@ class prim_glass_builder { enum blockType { air = 0, glass = 1, target = 127 }; glassMap makeBridge(const TokiMap &_targetMap, walkableMap *walkable = nullptr); - void **windPtr; - void (**progressRangeSetPtr)(void *, int, int, int); - void (**progressAddPtr)(void *, int); - void (**keepAwakePtr)(void *); + + SlopeCraft::ui_callbacks ui; + SlopeCraft::progress_callbacks progress_bar; private: std::vector targetPoints; diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index f25d0d57..009bc117 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -40,11 +40,11 @@ std::optional structure_3D_impl::create( fixed_opt.compress_method = compressSettings::noCompress; fixed_opt.glass_method = glassBridgeSettings::noBridge; } - option.ui.report_working_status(workStatus::buidingHeighMap); - option.main_progressbar.set_range(0, 9 * cvted.size(), 0); + fixed_opt.ui.report_working_status(workStatus::buidingHeighMap); + fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 0); { std::unordered_map water_list; - option.main_progressbar.add(cvted.size()); + fixed_opt.main_progressbar.add(cvted.size()); } Eigen::ArrayXi map_color, base_color, high_map, low_map; @@ -86,7 +86,7 @@ std::optional structure_3D_impl::create( if (yLow >= 1) ret.schem(x, yLow - 1, z) = 1; // 柱底玻璃 } - option.main_progressbar.add(cvted.size()); + fixed_opt.main_progressbar.add(cvted.size()); for (uint32_t r = -1; r < cvted.rows(); r++) // 普通方块 { @@ -97,9 +97,9 @@ std::optional structure_3D_impl::create( const int z = r + 1; if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) ret.schem(x, y - 1, z) = 0 + 1; - if ((option.fire_proof && + if ((fixed_opt.fire_proof && table.blocks[base_color(r + 1, c)].burnable) || - (option.enderman_proof && + (fixed_opt.enderman_proof && table.blocks[base_color(r + 1, c)].endermanPickable)) { if (y >= 1 && ret.schem(x, y - 1, z) == 0) ret.schem(x, y - 1, z) = 0 + 1; @@ -117,10 +117,10 @@ std::optional structure_3D_impl::create( ret.schem(x, y, z) = base_color(r + 1, c) + 1; } - option.main_progressbar.add(cvted.cols()); + fixed_opt.main_progressbar.add(cvted.cols()); } - option.main_progressbar.add(cvted.size()); + fixed_opt.main_progressbar.add(cvted.size()); for (auto it = water_list.cbegin(); it != water_list.cend(); ++it) { const int x = it->first.col + 1; @@ -132,20 +132,21 @@ std::optional structure_3D_impl::create( } } } - option.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); + fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 8 * cvted.size()); // build bridges if (table.map_type() == mapTypes::Slope && fixed_opt.glass_method == glassBridgeSettings::withBridge) { - option.ui.report_working_status(workStatus::constructingBridges); + fixed_opt.ui.report_working_status(workStatus::constructingBridges); - option.sub_progressbar.set_range(0, 100, 0); + fixed_opt.sub_progressbar.set_range(0, 100, 0); const int step = cvted.size() / ret.schem.y_range(); -#warning "todo: Use prograss_callback in prim_glass_builder" prim_glass_builder glass_builder; - option.ui.keep_awake(); + glass_builder.ui = fixed_opt.ui; + glass_builder.progress_bar = fixed_opt.sub_progressbar; + fixed_opt.ui.keep_awake(); for (uint32_t y = 0; y < ret.schem.y_range(); y++) { - option.sub_progressbar.add(step); + fixed_opt.sub_progressbar.add(step); if (y % (fixed_opt.bridge_interval + 1) == 0) { std::array start, extension; // x,z,y start[0] = 0; @@ -168,15 +169,15 @@ std::optional structure_3D_impl::create( continue; } } - option.ui.keep_awake(); - option.sub_progressbar.set_range(0, 100, 100); + fixed_opt.ui.keep_awake(); + fixed_opt.sub_progressbar.set_range(0, 100, 100); } if (fixed_opt.connect_mushrooms) { ret.schem.process_mushroom_states(); } - option.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); - option.ui.report_working_status(workStatus::none); + fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); + fixed_opt.ui.report_working_status(workStatus::none); ret.map_color = map_color.cast(); return ret; From f72de32eee722271c9148dd06cb5b71d4e7581a7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 19 Apr 2024 11:55:45 +0800 Subject: [PATCH 0792/1123] update callbacks of lossy_compressor Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 9 --------- SlopeCraftL/converted_image.cpp | 7 +++++-- SlopeCraftL/lossy_compressor.cpp | 10 +++++----- SlopeCraftL/lossy_compressor.h | 10 ++++------ utilities/MapImageCvter/MapImageCvter.h | 13 +++++-------- 5 files changed, 19 insertions(+), 30 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index a6407551..43f526fe 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -140,15 +140,6 @@ std::vector color_table_impl::block_id_list() const noexcept { return dest; } -// std::string digest_to_string(std::span hash) noexcept { -// std::string ret; -// ret.reserve(hash.size_bytes() * 2); -// for (uint64_t i : hash) { -// fmt::format_to(std::back_insert_iterator(ret), "{:x}", i); -// } -// return ret; -// } - uint64_t color_table_impl::hash() const noexcept { boost::uuids::detail::md5 hash; SC_HASH_ADD_DATA(hash, this->map_type_) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 5a50efd6..c2f0abe5 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -48,6 +48,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); +#warning This may be incorrect const bool allow_lossless_compress = int(option.compress_method) & int(SCL_compressSettings::NaturalOnly); @@ -73,6 +74,8 @@ converted_image_impl::height_info(const build_options &option) const noexcept { std::unordered_map water_list; lossy_compressor compressor; + compressor.ui = option.ui; + compressor.progress_bar = option.sub_progressbar; for (int64_t c = 0; c < map_color.cols(); c++) { // cerr << "Coloumn " << c << '\n'; height_line HL; @@ -84,10 +87,10 @@ converted_image_impl::height_info(const build_options &option) const noexcept { option.compress_method == compressSettings::Both)) { std::vector ptr(map_color.rows()); - this->converter.col_TokiColor_ptrs(c, ptr.data()); + this->converter.col_TokiColor_ptrs(c, ptr); // getTokiColorPtr(c, &ptr[0]); - compressor.setSource(HL.getBase(), &ptr[0]); + compressor.setSource(HL.getBase(), ptr); bool success = compressor.compress(option.max_allowed_height, allow_lossless_compress); if (!success) { diff --git a/SlopeCraftL/lossy_compressor.cpp b/SlopeCraftL/lossy_compressor.cpp index b2d44bc5..43968024 100644 --- a/SlopeCraftL/lossy_compressor.cpp +++ b/SlopeCraftL/lossy_compressor.cpp @@ -90,9 +90,8 @@ class solver_t std::clock_t curClock = std::clock(); if (curClock - prevClock >= CLOCKS_PER_SEC / 2) { prevClock = curClock; - (*(this->_args.ptr->progressRangeSetPtr))( - *(this->_args.ptr->windPtr), 0, lossy_compressor::maxGeneration, - this->generation()); + this->_args.ptr->progress_bar.set_range( + 0, lossy_compressor::maxGeneration, this->generation()); } } } @@ -105,7 +104,8 @@ lossy_compressor::lossy_compressor() : solver{new solver_t{}} { lossy_compressor::~lossy_compressor() {} void lossy_compressor::setSource(const Eigen::ArrayXi &_base, - const TokiColor **src) { + std::span src) { + assert(_base.rows() == static_cast(src.size() + 1)); source.resize(_base.rows() - 1); for (uint16_t idx = 0; idx < _base.rows() - 1; idx++) { @@ -144,7 +144,7 @@ void lossy_compressor::runGenetic(uint16_t maxHeight, } bool lossy_compressor::compress(uint16_t maxHeight, bool allowNaturalCompress) { - (*progressRangeSetPtr)(*windPtr, 0, maxGeneration, 0); + this->progress_bar.set_range(0, maxGeneration, 0); // std::cerr<<"Genetic algorithm started\n"; uint16_t tryTimes = 0; diff --git a/SlopeCraftL/lossy_compressor.h b/SlopeCraftL/lossy_compressor.h index 75b4225b..0a69e3be 100644 --- a/SlopeCraftL/lossy_compressor.h +++ b/SlopeCraftL/lossy_compressor.h @@ -43,15 +43,13 @@ class lossy_compressor { public: lossy_compressor(); ~lossy_compressor(); - void setSource(const Eigen::ArrayXi &, const TokiColor *[]); - bool compress(uint16_t maxHeight, bool allowNaturalCompress = false); + void setSource(const Eigen::ArrayXi &, std::span); + bool compress(uint16_t maxHeight, bool allowNaturalCompress); const Eigen::ArrayX &getResult() const; double resultFitness() const; - void **windPtr; - void (**progressRangeSetPtr)(void *, int min, int max, int val); - void (**progressAddPtr)(void *, int); - void (**keepAwakePtr)(void *); + SlopeCraft::ui_callbacks ui; + SlopeCraft::progress_callbacks progress_bar; private: friend class solver_t; diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 6e2b875a..2ea85be9 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -84,22 +84,19 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { return result; } - void col_TokiColor_ptrs(int64_t col, - const TokiColor_t **const dest) const noexcept { - if (dest == nullptr) { - return; - } - + void col_TokiColor_ptrs( + int64_t col, std::vector &dest) const noexcept { if (col < 0 || col > this->cols()) { return; } - + dest.clear(); for (int64_t r = 0; r < this->rows(); r++) { auto it = this->_color_hash.find( convert_unit(this->_dithered_image(r, col), this->algo)); - dest[r] = &it->second; + dest.emplace_back(&it->second); } } + // temp is a temporary container to pass ownership void load_from_itermediate(MapImageCvter &&temp) noexcept { this->_raw_image = std::move(temp._raw_image); From 032015f77be2a7ee68b4732259058f852006d643 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 19 Apr 2024 12:53:31 +0800 Subject: [PATCH 0793/1123] add selection for BlockListManager Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 23 ++++++----- SlopeCraftL/SlopeCraftL.cpp | 20 ++++++++++ SlopeCraftL/SlopeCraftL.h | 2 + SlopeCraftL/height_line.cpp | 26 +++++++------ utilities/BlockListManager/BaseColor.cpp | 6 +-- .../BlockListManager/BlockListManager.cpp | 39 +++++++++++++++++-- utilities/BlockListManager/BlockListManager.h | 24 +++++++++++- utilities/BlockListManager/CMakeLists.txt | 5 ++- utilities/ColorManip/colorset_maptical.hpp | 5 +-- 9 files changed, 115 insertions(+), 35 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 9c911c52..4d491601 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -98,7 +98,11 @@ class SCWind : public QMainWindow { private: Ui::SCWind* ui; - SlopeCraft::Kernel* kernel; + + std::map> + color_tables; + // SlopeCraft::Kernel* kernel; task_pool_t tasks; CvtPoolModel* cvt_pool_model{nullptr}; @@ -115,7 +119,8 @@ class SCWind : public QMainWindow { // QString fileonly_export_dir{""}; public: - const SlopeCraft::Kernel* kernel_ptr() const noexcept { return this->kernel; } + // const SlopeCraft::Kernel* kernel_ptr() const noexcept { return + // this->kernel; } std::array version_buttons() noexcept; std::array version_buttons() const noexcept; @@ -161,18 +166,18 @@ class SCWind : public QMainWindow { bool is_enderman_proof_selected() const noexcept; bool is_connect_mushroom_selected() const noexcept; - SlopeCraft::Kernel::build_options current_build_option() const noexcept; + SlopeCraft::build_options current_build_option() const noexcept; export_type selected_export_type() const noexcept; - std::optional current_litematic_option( + std::optional current_litematic_option( + QString& err) const noexcept; + std::optional current_nbt_option( + QString& err) const noexcept; + std::optional current_schem_option( QString& err) const noexcept; - std::optional - current_nbt_option(QString& err) const noexcept; - std::optional current_schem_option( + std::optional current_flatdiagram_option( QString& err) const noexcept; - std::optional - current_flatdiagram_option(QString& err) const noexcept; int current_map_begin_seq_number() const noexcept; diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index ca0eb671..a7bc0735 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -380,6 +380,26 @@ SCL_EXPORT void SCL_destroy_color_table(color_table *c) { delete c; } SCL_EXPORT void SCL_destroy_converted_image(converted_image *c) { delete c; } SCL_EXPORT void SCL_destroy_structure_3D(structure_3D *s) { delete s; } + +SCL_EXPORT void SCL_get_base_color_ARGB32(uint32_t dest[64]) { + for (int bc = 0; bc < 64; bc++) { + const int row = bc + 128; + const std::array rgb_f32{ + SlopeCraft::basic_colorset->RGB(row, 0), + SlopeCraft::basic_colorset->RGB(row, 1), + SlopeCraft::basic_colorset->RGB(row, 2), + }; + std::array rgb_u8; + for (int i = 0; i < 3; ++i) { + assert(rgb_f32[i] >= 0); + assert(rgb_f32[i] <= 1.0); + rgb_u8[i] = rgb_f32[i] * 255; + } + + dest[bc] = ARGB32(rgb_u8[0], rgb_u8[1], rgb_u8[2]); + } +} + // SCL_EXPORT int SCL_getBlockPalette(const mc_block_interface **blkpp, // size_t capacity) { // return TokiSlopeCraft::getBlockPalette(blkpp, capacity); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 14ed0a1c..0b757839 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -397,6 +397,8 @@ SCL_EXPORT const char *SCL_getSCLVersion(); SCL_EXPORT const float *SCL_getBasicColorMapPtrs(); SCL_EXPORT uint8_t SCL_maxBaseColor(); +SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); +SCL_EXPORT void SCL_get_base_color_ARGB32(uint32_t dest[64]); // SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor); diff --git a/SlopeCraftL/height_line.cpp b/SlopeCraftL/height_line.cpp index 58c30574..85547143 100644 --- a/SlopeCraftL/height_line.cpp +++ b/SlopeCraftL/height_line.cpp @@ -78,14 +78,16 @@ void height_line::make(const Eigen::ArrayXi &mapColorCol, base.segment(1, picRows) = mapColorCol / 4; Eigen::ArrayXi rawShadow = mapColorCol - 4 * (mapColorCol / 4); - if ((rawShadow >= 3).any()) { -#warning "TODO: Fix this error handling" - std::cerr << "Fatal Error: depth=3 in vanilla map!" << std::endl; - std::cerr << "SlopeCraft will crash." << std::endl; - exit(1); - // delete &rawShadow; - return; - } + assert(!(rawShadow >= 3).any()); + // + // if () { + // #warning "Fix this error handling" + // std::cerr << "Fatal Error: depth=3 in vanilla map!" << std::endl; + // std::cerr << "SlopeCraft will crash." << std::endl; + // exit(1); + // // delete &rawShadow; + // return; + // } Eigen::ArrayXi dealedDepth(picRows + 1); dealedDepth.setZero(); dealedDepth.segment(1, picRows) = rawShadow - 1; @@ -161,13 +163,13 @@ const std::map &height_line::getWaterMap() const { } EImage height_line::toImg() const { - const short rMax = maxHeight() - 1; + const int rMax = maxHeight() - 1; EImage img(maxHeight(), HighLine.size()); img.setConstant(AirColor); - short y = 0, r = rMax - y; + // short y = 0, r = rMax - y; for (uint32_t x = 0; x < HighLine.size(); x++) { - y = HighLine(x); - r = rMax - y; + const int y = HighLine(x); + int r = rMax - y; if (base(x)) { if (base(x) != 12) { img(r, x) = BlockColor; diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index bca3f65e..6c1427ca 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -8,8 +8,9 @@ BaseColorWidget::BaseColorWidget(QWidget* parent, uint8_t _basecolor) connect(this->ui->cb_enable, &QCheckBox::toggled, this, &BaseColorWidget::changed); -}; -BaseColorWidget::~BaseColorWidget(){}; +} + +BaseColorWidget::~BaseColorWidget() {} void BaseColorWidget::set_color(uint32_t color) noexcept { QPalette pl; @@ -148,7 +149,6 @@ int BaseColorWidget::selected_idx() const noexcept { } } assert(false); - return -1; } int BaseColorWidget::prefered_block_idx(int checked_idx, diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 3cde233a..72f1081f 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -1,7 +1,9 @@ -#include "BlockListManager.h" + #include #include #include +#include +#include "BlockListManager.h" extern const std::string_view basecolor_names[64]; @@ -9,15 +11,14 @@ BlockListManager::BlockListManager(QWidget *parent) : QWidget(parent) {} BlockListManager::~BlockListManager() {} -void BlockListManager::setup_basecolors( - const SlopeCraft::Kernel *kernel) noexcept { +void BlockListManager::setup_basecolors() noexcept { this->basecolor_widgets.clear(); this->basecolor_widgets.reserve(64); const int max_basecolor = SlopeCraft::SCL_maxBaseColor(); uint32_t bc_arr[64]; - kernel->getBaseColorInARGB32(bc_arr); + SlopeCraft::SCL_get_base_color_ARGB32(bc_arr); for (int bc = 0; bc <= max_basecolor; bc++) { std::unique_ptr bcw{new BaseColorWidget(this, bc)}; @@ -31,6 +32,23 @@ void BlockListManager::setup_basecolors( } } +uint64_t std::hash::operator()(const selection &s) noexcept { + boost::uuids::detail::md5 hash; + for (auto &id : s.ids) { + hash.process_bytes(id.data(), id.size()); + } + + uint32_t dig[4]{}; + hash.get_digest(dig); + uint64_t fold = 0; + for (size_t i = 0; i < 2; i++) { + const uint64_t cur = + (uint64_t(dig[2 * i]) << 32) | (uint64_t(dig[2 * i + 1])); + fold ^= cur; + } + return fold; +} + // bool callback_load_image(const char *filename, uint32_t *dst_row_major) { // QImage img(QString::fromLocal8Bit(filename)); // @@ -195,6 +213,19 @@ blockListPreset BlockListManager::to_preset() const noexcept { return ret; } +selection BlockListManager::current_selection() const noexcept { + std::vector ret; + ret.reserve(64); + for (auto &bcw : this->basecolor_widgets) { + if (bcw->is_enabled()) { + ret.emplace_back(bcw->selected_block()->getId()); + } else { + ret.emplace_back(""); + } + } + return selection{ret}; +} + const std::string_view basecolor_names[64] = {"00 None", "01 Grass", "02 Sand", diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 8599498e..2c9ce38a 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -29,6 +29,26 @@ class BlockListDeleter { } }; +struct selection { + std::vector ids; + [[nodiscard]] bool operator==(const selection &b) const noexcept { + if (this->ids.size() != b.ids.size()) { + return false; + } + for (size_t i = 0; i < this->ids.size(); i++) { + if (this->ids[i] != b.ids[i]) { + return false; + } + } + return true; + } +}; + +template <> +struct std::hash { + static inline uint64_t operator()(const selection &s) noexcept; +}; + class BlockListManager : public QWidget { Q_OBJECT private: @@ -42,7 +62,7 @@ class BlockListManager : public QWidget { explicit BlockListManager(QWidget *parent = nullptr); ~BlockListManager(); - void setup_basecolors(const SlopeCraft::Kernel *kernel) noexcept; + void setup_basecolors() noexcept; bool add_blocklist(QString filename) noexcept; @@ -83,6 +103,8 @@ class BlockListManager : public QWidget { return this->basecolor_widgets[basecolor].get(); } + [[nodiscard]] selection current_selection() const noexcept; + signals: void changed(); diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 26951333..0bef2d1f 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.5) project(SlopeCraft_BlockListManager VERSION ${SlopeCraft_version} LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 17) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -9,6 +8,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) +find_package(Boost REQUIRED) set(BlockListManager_header_files BlockListManager.h @@ -43,7 +43,8 @@ set(BlockListManager_project_sources add_library(BlockListManager STATIC ${BlockListManager_project_sources}) target_link_libraries(BlockListManager PUBLIC Qt6::Widgets SlopeCraftL) target_include_directories(BlockListManager INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir}) +target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} ${BOOST_INCLUDE_DIRS}) +target_compile_features(BlockListManager PUBLIC cxx_std_23) qt_add_lupdate(BlockListManager TS_FILES ${BlockListManager_ts_files} diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 51d716ce..3358048a 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -71,10 +71,7 @@ class alignas(32) colorset_maptical_basic { colorset_maptical_basic() = delete; /// Construct from color source colorset_maptical_basic(const float *const rgbsrc) { - if (rgbsrc == nullptr) { - exit(1); - return; - } + assert(rgbsrc); memcpy(__rgb.data(), rgbsrc, sizeof(__rgb)); for (int row = 0; row < 256; row++) { From 0572eb87612a789b8a9b7b1dc6e57f8028d3e40f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 19 Apr 2024 14:55:17 +0800 Subject: [PATCH 0794/1123] (partly) remove kernel Signed-off-by: ToKiNoBug --- SlopeCraft/AiCvterParameterDialog.cpp | 7 +- SlopeCraft/AiCvterParameterDialog.h | 3 +- SlopeCraft/PoolModel.cpp | 21 +- SlopeCraft/SCWind.cpp | 342 ++++++++++-------- SlopeCraft/SCWind.h | 45 +-- SlopeCraft/SCWind_slots.cpp | 73 ++-- SlopeCraft/cvt_task.cpp | 12 +- SlopeCraft/cvt_task.h | 40 +- SlopeCraftL/SlopeCraftL.h | 22 ++ utilities/BlockListManager/BlockListManager.h | 1 + 10 files changed, 309 insertions(+), 257 deletions(-) diff --git a/SlopeCraft/AiCvterParameterDialog.cpp b/SlopeCraft/AiCvterParameterDialog.cpp index 6241192b..f85602f1 100644 --- a/SlopeCraft/AiCvterParameterDialog.cpp +++ b/SlopeCraft/AiCvterParameterDialog.cpp @@ -26,13 +26,12 @@ This file is part of SlopeCraft. #include "SCWind.h" using namespace SlopeCraft; -AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent, - SlopeCraft::Kernel *kernelp) - : QDialog(parent), ui(new Ui::AiCvterParameterDialog), kernel(kernelp) { +AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent) + : QDialog(parent), ui(new Ui::AiCvterParameterDialog) { this->ui->setupUi(this); SlopeCraft::GA_converter_option opt = *this->kernel->aiCvterOpt(); - opt.version = SC_VERSION_U64; + opt.caller_api_version = SC_VERSION_U64; this->ui->sb_pop_size->setValue(opt.popSize); this->ui->sb_max_gen->setValue(opt.maxGeneration); diff --git a/SlopeCraft/AiCvterParameterDialog.h b/SlopeCraft/AiCvterParameterDialog.h index f9ea710c..91cda1b7 100644 --- a/SlopeCraft/AiCvterParameterDialog.h +++ b/SlopeCraft/AiCvterParameterDialog.h @@ -39,7 +39,7 @@ class AiCvterParameterDialog : public QDialog { Q_OBJECT public: - explicit AiCvterParameterDialog(SCWind *parent, SlopeCraft::Kernel *kernelp); + explicit AiCvterParameterDialog(SCWind *parent); ~AiCvterParameterDialog(); SlopeCraft::GA_converter_option current_option() const noexcept; @@ -52,7 +52,6 @@ class AiCvterParameterDialog : public QDialog { private: Ui::AiCvterParameterDialog *ui; - SlopeCraft::Kernel *const kernel; }; #endif // AICVTERPARAMETERDIALOG_H diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index d2b5f132..855d40bc 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -34,7 +34,7 @@ QVariant PoolModel::data(const QModelIndex& idx, int role) const { auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - if (!task.is_converted) { + if (!task.is_converted()) { this->draw_icon(img, icon_empty(), 0); } else { this->draw_icon(img, icon_converted(), 0); @@ -69,14 +69,15 @@ void PoolModel::draw_icon(QPixmap& image, const QPixmap& icon, int index, QWidget* ptr_to_report_error) noexcept { assert(index >= 0); if (icon.size() != QSize{32, 32}) [[unlikely]] { - QMessageBox::critical( - ptr_to_report_error, QObject::tr("绘制图标时发现错误"), - tr("被绘制的图标尺寸应当是 32*32,但实际上是%1*%" - "2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。") - .arg(icon.size().height()) - .arg(icon.size().width())); + QMessageBox::critical(ptr_to_report_error, + QObject::tr("绘制图标时发现错误"), + tr("被绘制的图标尺寸应当是 32*32,但实际上是%1*%" + "2。这属于 SlopeCraft " + "内部错误,请向开发者反馈。SlopeCraft 必须崩溃。") + .arg(icon.size().height()) + .arg(icon.size().width())); abort(); - return; + // return; } { const QSize expected_min_size{(index + 1) * 32, 32}; @@ -219,7 +220,7 @@ void map_indices(std::vector& pool, std::vector moved_indices, iterator_add(begin_it, begin_idx); for (auto srcit : src_it_vec) { - temp_pool.emplace(begin_it, *srcit); + temp_pool.emplace(begin_it, std::move(*srcit)); } for (auto srcit : src_it_vec) { @@ -288,7 +289,7 @@ QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { } auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - if (!task.is_built) { + if (!task.is_built()) { this->draw_icon(img, icon_empty(), 0); } else { this->draw_icon(img, icon_converted(), 0); diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index d6b88765..a63666fb 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -12,10 +12,7 @@ const QString SCWind::update_url{ "https://api.github.com/repos/SlopeCraft/SlopeCraft/releases"}; // #include "PoolWidget.h" -SCWind::SCWind(QWidget *parent) - : QMainWindow(parent), - ui(new Ui::SCWind), - kernel(SlopeCraft::SCL_createKernel()) { +SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { this->ui->setupUi(this); this->connect_slots(); @@ -40,53 +37,6 @@ SCWind::SCWind(QWidget *parent) } } - { - const auto pid = QApplication::applicationPid(); - - const QString sys_cache_dir = QDir::tempPath(); - const QString cache_dir = - QStringLiteral("%1/SlopeCraft/pid=%2").arg(sys_cache_dir).arg(pid); - - this->kernel->setCacheDir(cache_dir.toLocal8Bit()); - - this->kernel->setWindPtr(this); - this->kernel->setProgressRangeSet( - [](void *_self, int min, int max, int val) { - SCWind *const self = reinterpret_cast(_self); - QProgressBar *const bar = self->current_bar(); - if (bar == nullptr) return; - - bar->setMinimum(min); - bar->setMaximum(max); - bar->setValue(val); - }); - this->kernel->setProgressAdd([](void *_self, int delta) { - SCWind *const self = reinterpret_cast(_self); - QProgressBar *const bar = self->current_bar(); - if (bar == nullptr) return; - - bar->setValue(bar->value() + delta); - }); - - this->kernel->setKeepAwake([](void *) { QApplication::processEvents(); }); - this->kernel->setReportError( - [](void *_this, ::SCL_errorFlag err, const char *msg) { - reinterpret_cast(_this)->report_error(err, msg); - }); - this->kernel->setReportWorkingStatue([](void *_this, ::SCL_workStatus ws) { - SCWind *const wind = reinterpret_cast(_this); - - const QString status_str = SCWind::workStatus_to_string(ws); - QString wind_title; - if (status_str.isEmpty()) { - wind_title = SCWind::default_wind_title(); - } else { - wind_title = QStringLiteral("%1 | %2") - .arg(SCWind::default_wind_title(), status_str); - } - wind->setWindowTitle(wind_title); - }); - } // initialize cvt pool model { this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; @@ -126,7 +76,7 @@ SCWind::SCWind(QWidget *parent) // initialize blm { - this->ui->blm->setup_basecolors(this->kernel); + this->ui->blm->setup_basecolors(); this->ui->blm->set_version_callback( [this]() { return this->selected_version(); }); @@ -192,18 +142,101 @@ SCWind::SCWind(QWidget *parent) SCWind::~SCWind() { delete this->ui; + { + QDir cache_dir{this->cache_root_dir()}; + if (cache_dir.exists()) { + cache_dir.removeRecursively(); + } + } +} + +QString SCWind::cache_root_dir() const noexcept { + const auto pid = QApplication::applicationPid(); + + const QString sys_cache_dir = QDir::tempPath(); + const QString cache_dir = + QStringLiteral("%1/SlopeCraft/pid=%2").arg(sys_cache_dir).arg(pid); + return cache_dir; +} +SlopeCraft::color_table *SCWind::current_color_table() noexcept { + auto selection = this->ui->blm->current_selection(); { - const char *cd = this->kernel->cacheDir(); - if (cd != nullptr) { - QDir cache_dir{QString::fromLocal8Bit(cd)}; - if (cache_dir.exists()) { - cache_dir.removeRecursively(); - } + auto find = this->color_tables.find(selection); + if (find == this->color_tables.end()) { + return find->second.get(); + } + } + { + std::vector a; + std::vector b; + + this->ui->blm->get_blocklist(a, b); + SlopeCraft::color_table_create_info ci; + ci.map_type = this->selected_type(); + ci.mc_version = this->selected_version(); + for (size_t i = 0; i < 64; i++) { + ci.blocks[i] = b[i]; + ci.basecolor_allow_LUT[i] = a[i]; } + std::unique_ptr ptr{ + SlopeCraft::SCL_create_color_table(ci)}; + if (ptr == nullptr) { + QMessageBox::warning(this, tr("设置方块列表失败"), + tr("您设置的方块列表可能存在错误")); + return nullptr; + } + + auto it = this->color_tables.emplace(selection, std::move(ptr)); + return it.first->second.get(); } +} + +SlopeCraft::ui_callbacks SCWind::ui_callbacks() const noexcept { + return SlopeCraft::ui_callbacks{ + .wind = const_cast(this), + .cb_keep_awake = [](void *) { QApplication::processEvents(); }, + .cb_report_error = + [](void *wind, SCL_errorFlag ef, const char *msg) { + reinterpret_cast(wind)->report_error(ef, msg); + }, + .cb_report_working_status = + [](void *wind, SCL_workStatus ws) { + SCWind *self = reinterpret_cast(wind); + const QString status_str = SCWind::workStatus_to_string(ws); + QString wind_title; + if (status_str.isEmpty()) { + wind_title = SCWind::default_wind_title(); + } else { + wind_title = QStringLiteral("%1 | %2") + .arg(SCWind::default_wind_title(), status_str); + } + self->setWindowTitle(wind_title); + }, + }; +} - SlopeCraft::SCL_destroyKernel(this->kernel); +SlopeCraft::progress_callbacks progress_callback(QProgressBar *bar) noexcept { + return SlopeCraft::progress_callbacks{ + .widget = bar, + .cb_set_range = + [](void *widget, int min, int max, int val) { + if (widget == nullptr) { + return; + } + QProgressBar *bar = reinterpret_cast(widget); + bar->setMinimum(min); + bar->setMaximum(max); + bar->setValue(val); + }, + .cb_add = + [](void *widget, int delta) { + if (widget == nullptr) { + return; + } + QProgressBar *bar = reinterpret_cast(widget); + bar->setValue(bar->value() + delta); + }}; } void SCWind::when_cvt_pool_selectionChanged() noexcept { @@ -249,7 +282,7 @@ SCL_gameVersion SCWind::selected_version() const noexcept { assert(false); - return SCL_gameVersion::ANCIENT; + // return SCL_gameVersion::ANCIENT; } SCL_mapTypes SCWind::selected_type() const noexcept { @@ -266,7 +299,7 @@ SCL_mapTypes SCWind::selected_type() const noexcept { } assert(false); - return {}; + // return {}; } std::vector SCWind::selected_indices() const noexcept { @@ -299,10 +332,10 @@ std::vector SCWind::selected_export_task_list() const noexcept { } return ret; } -std::optional SCWind::selected_export_task() const noexcept { +cvt_task *SCWind::selected_export_task() const noexcept { auto selected = this->selected_export_task_list(); if (selected.empty()) { - return std::nullopt; + return nullptr; } return selected.front(); @@ -329,7 +362,7 @@ SCL_convertAlgo SCWind::selected_algo() const noexcept { } assert(false); - return {}; + // return {}; } bool SCWind::is_dither_selected() const noexcept { @@ -385,16 +418,18 @@ bool SCWind::is_connect_mushroom_selected() const noexcept { return this->ui->cb_connect_mushroom->isChecked(); } -SlopeCraft::Kernel::build_options SCWind::current_build_option() - const noexcept { - return SlopeCraft::Kernel::build_options{ - .maxAllowedHeight = (uint16_t)this->current_max_height(), - .bridgeInterval = (uint16_t)this->current_glass_brigde_interval(), - .compressMethod = this->current_compress_method(), - .glassMethod = this->current_glass_method(), +SlopeCraft::build_options SCWind::current_build_option() const noexcept { + return SlopeCraft::build_options{ + .max_allowed_height = (uint16_t)this->current_max_height(), + .bridge_interval = (uint16_t)this->current_glass_brigde_interval(), + .compress_method = this->current_compress_method(), + .glass_method = this->current_glass_method(), .fire_proof = this->is_fire_proof_selected(), .enderman_proof = this->is_enderman_proof_selected(), - .connect_mushrooms = this->is_connect_mushroom_selected()}; + .connect_mushrooms = this->is_connect_mushroom_selected(), + .ui = this->ui_callbacks(), + .main_progressbar = progress_callback(this->ui->pbar_export), + .sub_progressbar = {}}; } SCWind::export_type SCWind::selected_export_type() const noexcept { @@ -407,7 +442,7 @@ SCWind::export_type SCWind::selected_export_type() const noexcept { } } assert(false); - return {}; + // return {}; } void SCWind::when_version_buttons_toggled() noexcept { @@ -437,21 +472,8 @@ void SCWind::when_blocklist_changed() noexcept { } void SCWind::kernel_set_type() noexcept { - std::vector a; - std::vector b; - - this->ui->blm->get_blocklist(a, b); - - assert(a.size() == b.size()); - if (!this->kernel->setType(this->selected_type(), this->selected_version(), - reinterpret_cast(a.data()), - b.data())) { - QMessageBox::warning(this, tr("设置方块列表失败"), - tr("您设置的方块列表可能存在错误")); - return; - } - int num_colors{0}; - this->kernel->getAvailableColors(nullptr, nullptr, &num_colors); + auto color_table = this->current_color_table(); + const int num_colors = color_table->colors().num_colors; this->ui->lb_avaliable_colors->setText( tr("可用颜色数量:%1").arg(num_colors)); @@ -585,27 +607,56 @@ void SCWind::when_export_type_toggled() noexcept { this->update_button_states(); } -void SCWind::kernel_set_image(int idx) noexcept { +// void SCWind::kernel_set_image(int idx) noexcept { +// assert(idx >= 0); +// assert(idx < (int)this->tasks.size()); +// +// if (this->kernel->queryStep() < SCL_step::wait4Image) { +// this->kernel_set_type(); +// } +// +// const QImage &raw = this->tasks[idx].original_image; +// this->kernel->setRawImage((const uint32_t *)raw.scanLine(0), raw.height(), +// raw.width(), false); +// } +// +// void SCWind::kernel_convert_image() noexcept { +// assert(this->kernel->queryStep() >= SCL_step::convertionReady); +// +// if (!this->kernel->convert(this->selected_algo(), +// this->is_dither_selected())) { +// QMessageBox::warning(this, tr("转化图像失败"), tr("")); +// +// return; +// } +// } + +std::unique_ptr +SCWind::convert_image(int idx) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); - if (this->kernel->queryStep() < SCL_step::wait4Image) { - this->kernel_set_type(); - } + auto ctable = this->current_color_table(); const QImage &raw = this->tasks[idx].original_image; - this->kernel->setRawImage((const uint32_t *)raw.scanLine(0), raw.height(), - raw.width(), false); -} - -void SCWind::kernel_convert_image() noexcept { - assert(this->kernel->queryStep() >= SCL_step::convertionReady); - - if (!this->kernel->convert(this->selected_algo(), - this->is_dither_selected())) { - QMessageBox::warning(this, tr("转化图像失败"), tr("")); - - return; + { + SlopeCraft::const_image_reference img{ + .data = (const uint32_t *)raw.scanLine(0), + .rows = static_cast(raw.height()), + .cols = static_cast(raw.width()), + }; + SlopeCraft::convert_option opt{ + .caller_api_version = SC_VERSION_U64, + .algo = this->selected_algo(), + .dither = this->is_dither_selected(), + .ai_cvter_opt = this->GA_option, + .progress = progress_callback(this->ui->pbar_cvt), + .ui = this->ui_callbacks(), + }; + auto cvted_img = ctable->convert_image(img, opt); + + return std::unique_ptr{ + cvted_img}; } } @@ -636,8 +687,7 @@ QImage SCWind::get_converted_image_from_kernel() const noexcept { } void SCWind::refresh_current_cvt_display( - std::optional selected_idx, - bool is_image_coneverted_in_kernel) noexcept { + std::optional selected_idx) noexcept { if (!selected_idx.has_value()) { this->ui->lb_raw_image->setPixmap({}); this->ui->lb_cvted_image->setPixmap({}); @@ -649,49 +699,32 @@ void SCWind::refresh_current_cvt_display( this->ui->lb_raw_image->setPixmap( QPixmap::fromImage(this->tasks[idx].original_image)); - if (is_image_coneverted_in_kernel) { - assert(this->kernel->queryStep() >= SCL_step::converted); + auto &task = this->tasks[selected_idx.value()]; + // if the image is already + if (task.converted_img) { + QImage img{QSize{static_cast(task.converted_img->cols()), + static_cast(task.converted_img->rows())}, + QImage::Format::Format_ARGB32}; + task.converted_img->get_original_image( + reinterpret_cast(img.scanLine(0))); this->ui->lb_cvted_image->setPixmap( QPixmap::fromImage(this->get_converted_image_from_kernel())); return; } +#warning "TODO: Load cache here" this->ui->lb_cvted_image->setPixmap({}); - if (!this->tasks[idx].is_converted) { - return; - } - - /* - if (!kernel_check_colorset_hash()) { - this->mark_all_task_unconverted(); - emit this->image_changed(); - return; - }*/ - - this->kernel_set_image(idx); - - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - this->tasks[idx].set_unconverted(); - emit this->image_changed(); - return; - } - - this->ui->lb_cvted_image->setPixmap( - QPixmap::fromImage(this->get_converted_image_from_kernel())); } void SCWind::mark_all_task_unconverted() noexcept { for (auto &task : this->tasks) { - task.set_unconverted(); + task.converted_img = nullptr; + task.structure = nullptr; } } void SCWind::when_algo_btn_clicked() noexcept { - for (size_t i = 0; i < this->tasks.size(); i++) { - this->tasks[i].set_unconverted(); - } this->cvt_pool_model->refresh(); this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } @@ -755,7 +788,7 @@ void SCWind::refresh_current_build_display( if (is_image_built_in_kernel) { // the caller garentee that the image is built in kernel } else { - if (taskp.value()->is_built) { + if (taskp.value()->is_built()) { // try to load convert cache if (!this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { @@ -814,8 +847,8 @@ QString extension_of_export_type(SCWind::export_type et) noexcept { return "Invalid_export_type"; } -std::optional -SCWind::current_litematic_option(QString &err) const noexcept { +std::optional SCWind::current_litematic_option( + QString &err) const noexcept { err.clear(); static std::string litename; static std::string region_name; @@ -823,23 +856,28 @@ SCWind::current_litematic_option(QString &err) const noexcept { litename = this->ui->le_lite_name->text().toUtf8().data(); region_name = this->ui->le_lite_region_name->text().toUtf8().data(); - return SlopeCraft::Kernel::litematic_options{ - .litename_utf8 = litename.data(), .region_name_utf8 = region_name.data()}; + return SlopeCraft::litematic_options{ + .caller_api_version = SC_VERSION_U64, + .litename_utf8 = litename.data(), + .region_name_utf8 = region_name.data(), + .ui = this->ui_callbacks(), + .progressbar = progress_callback(this->ui->pbar_export), + }; } -std::optional -SCWind::current_nbt_option(QString &err) const noexcept { +std::optional SCWind::current_nbt_option( + QString &err) const noexcept { err.clear(); - return SlopeCraft::Kernel::vanilla_structure_options{ + return SlopeCraft::vanilla_structure_options{ .is_air_structure_void = this->ui->cb_nbt_air_void->isChecked()}; } -std::optional -SCWind::current_schem_option(QString &err) const noexcept { +std::optional SCWind::current_schem_option( + QString &err) const noexcept { err.clear(); - SlopeCraft::Kernel::WE_schem_options ret; + SlopeCraft::WE_schem_options ret; { const std::array le_offset{this->ui->le_WE_offset_X, @@ -898,10 +936,13 @@ SCWind::current_schem_option(QString &err) const noexcept { ret.num_required_mods = mod_charp.size(); ret.required_mods_name_utf8 = mod_charp.data(); + ret.ui = this->ui_callbacks(); + ret.progressbar = progress_callback(this->ui->pbar_export); + return ret; } -std::optional +std::optional SCWind::current_flatdiagram_option(QString &err) const noexcept { err.clear(); @@ -923,8 +964,13 @@ SCWind::current_flatdiagram_option(QString &err) const noexcept { col_margin = -1; } - return SlopeCraft::Kernel::flag_diagram_options{ - .split_line_row_margin = row_margin, .split_line_col_margin = col_margin}; + return SlopeCraft::flag_diagram_options{ + .caller_api_version = SC_VERSION_U64, + .split_line_row_margin = row_margin, + .split_line_col_margin = col_margin, + .ui = this->ui_callbacks(), + .progressbar = progress_callback(this->ui->pbar_export), + }; } int SCWind::current_map_begin_seq_number() const noexcept { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 4d491601..dc24c536 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -20,6 +20,10 @@ namespace Ui { class SCWind; } +SlopeCraft::progress_callbacks progress_callback(QProgressBar* bar) noexcept; + +SlopeCraft::const_image_reference wrap_image(const QImage& img) noexcept; + class SCWind : public QMainWindow { Q_OBJECT private: @@ -99,9 +103,10 @@ class SCWind : public QMainWindow { private: Ui::SCWind* ui; - std::map> + std::unordered_map< + selection, std::unique_ptr> color_tables; + SlopeCraft::GA_converter_option GA_option{}; // SlopeCraft::Kernel* kernel; task_pool_t tasks; @@ -115,12 +120,13 @@ class SCWind : public QMainWindow { std::vector translators; QString prev_load_image_dir{""}; - // QString fileonly_export_dir{""}; public: - // const SlopeCraft::Kernel* kernel_ptr() const noexcept { return - // this->kernel; } + QString cache_root_dir() const noexcept; + SlopeCraft::color_table* current_color_table() noexcept; + + SlopeCraft::ui_callbacks ui_callbacks() const noexcept; std::array version_buttons() noexcept; std::array version_buttons() const noexcept; @@ -148,7 +154,7 @@ class SCWind : public QMainWindow { std::optional selected_cvt_task_idx() const noexcept; std::vector selected_export_task_list() const noexcept; - std::optional selected_export_task() const noexcept; + cvt_task* selected_export_task() const noexcept; SCL_convertAlgo selected_algo() const noexcept; bool is_dither_selected() const noexcept; @@ -186,34 +192,31 @@ class SCWind : public QMainWindow { private: // kernel related functions - void kernel_set_type() noexcept; + [[deprecated]] void kernel_set_type() noexcept; void update_button_states() noexcept; - void kernel_set_image(int idx) noexcept; - void kernel_convert_image() noexcept; + std::unique_ptr + convert_image(int idx) noexcept; - void kernel_make_cvt_cache() noexcept; + [[deprecated]] void kernel_set_image(int idx) noexcept; + [[deprecated]] void kernel_convert_image() noexcept; - // bool kernel_check_colorset_hash() noexcept; + [[deprecated]] void kernel_make_cvt_cache() noexcept; - void kernel_build_3d() noexcept; - void kernel_make_build_cache() noexcept; + [[deprecated]] void kernel_build_3d() noexcept; + [[deprecated]] void kernel_make_build_cache() noexcept; - void refresh_current_cvt_display(std::optional idx, - bool is_image_coneverted_in_kernel) noexcept; - void refresh_current_cvt_display(std::optional idx) noexcept { - this->refresh_current_cvt_display(idx, false); - } + void refresh_current_cvt_display(std::optional idx) noexcept; void refresh_current_cvt_display() noexcept { this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } - QImage get_converted_image_from_kernel() const noexcept; + [[deprecated]] QImage get_converted_image_from_kernel() const noexcept; - void refresh_current_build_display(std::optional taskp, + void refresh_current_build_display(cvt_task* taskp, bool is_image_built_in_kernel) noexcept; - void refresh_current_build_display(std::optional taskp) noexcept { + void refresh_current_build_display(cvt_task* taskp) noexcept { return this->refresh_current_build_display(taskp, false); } void refresh_current_build_display() noexcept { diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 9ca85b3f..74a759ea 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -28,15 +28,14 @@ void SCWind::on_pb_add_image_clicked() noexcept { std::optional strategy_opt{std::nullopt}; - QString err; for (const auto &filename : files) { - auto task = cvt_task::load(filename, err); + auto task_res = cvt_task::load(filename); - if (!err.isEmpty()) { + if (!task_res) { auto ret = QMessageBox::critical( this, tr("打开图像失败"), tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") - .arg(filename, err), + .arg(filename, task_res.error()), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); @@ -47,6 +46,7 @@ void SCWind::on_pb_add_image_clicked() noexcept { } } + auto task = std::move(task_res.value()); // have transparent pixels if (SlopeCraft::SCL_haveTransparentPixel( (const uint32_t *)task.original_image.scanLine(0), @@ -65,7 +65,7 @@ void SCWind::on_pb_add_image_clicked() noexcept { st.pure_transparent, st.half_transparent, st.background_color); } - this->tasks.emplace_back(task); + this->tasks.emplace_back(std::move(task)); } emit this->image_changed(); @@ -103,13 +103,13 @@ void SCWind::on_pb_replace_image_clicked() noexcept { return; } this->prev_load_image_dir = QFileInfo{file}.dir().absolutePath(); - QString err; - auto task = cvt_task::load(file, err); - if (!err.isEmpty()) { + + auto task_res = cvt_task::load(file); + if (!task_res) { auto ret = QMessageBox::critical( this, tr("打开图像失败"), tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") - .arg(file, err), + .arg(file, task_res.error()), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); @@ -120,7 +120,7 @@ void SCWind::on_pb_replace_image_clicked() noexcept { } } for (const auto &qmi : selected) { - this->tasks[qmi.row()] = task; + this->tasks[qmi.row()] = std::move(task_res.value()); } this->cvt_pool_model->refresh(); } @@ -252,12 +252,16 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { return; } - this->kernel_set_image(sel.value()); - this->kernel_convert_image(); - this->tasks[sel.value()].set_converted(); + { + auto cvted = this->convert_image(sel.value()); + if (!cvted) { + return; + } + this->tasks[sel.value()].converted_img = std::move(cvted); + } - this->kernel_make_cvt_cache(); - this->refresh_current_cvt_display(sel.value(), true); + // this->kernel_make_cvt_cache(); + this->refresh_current_cvt_display(sel.value()); this->ui->tw_cvt_image->setCurrentIndex(1); emit this->image_changed(); @@ -267,7 +271,7 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { void SCWind::on_pb_cvt_all_clicked() noexcept { for (int idx = 0; idx < (int)this->tasks.size(); idx++) { auto &task = this->tasks[idx]; - if (task.is_converted) { + if (task.is_converted()) { continue; } @@ -365,23 +369,23 @@ void SCWind::on_cb_compress_lossy_toggled(bool checked) noexcept { } void SCWind::on_pb_build3d_clicked() noexcept { - auto taskopt = this->selected_export_task(); - if (!taskopt.has_value()) { + auto task_ptr = this->selected_export_task(); + if (task_ptr == nullptr) { QMessageBox::warning(this, tr("未选择图像"), tr("请在左侧任务池选择一个图像")); return; } - assert(taskopt.value() != nullptr); + assert(task_ptr != nullptr); - cvt_task &task = *taskopt.value(); + cvt_task &task = *task_ptr; - if (!task.is_converted) [[unlikely]] { + if (!task.is_converted()) [[unlikely]] { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); return; } { - const int gidx = taskopt.value() - this->tasks.data(); + const int gidx = task_ptr - this->tasks.data(); this->kernel_set_image(gidx); if (!this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { @@ -397,18 +401,18 @@ void SCWind::on_pb_build3d_clicked() noexcept { } void SCWind::on_pb_preview_materials_clicked() noexcept { - auto taskopt = this->selected_export_task(); - if (!taskopt.has_value()) { + auto taskp = this->selected_export_task(); + if (taskp == nullptr) { QMessageBox::warning(this, tr("未选择图像"), tr("请在左侧任务池选择一个图像")); return; } - assert(taskopt.value() != nullptr); + assert(taskp != nullptr); - cvt_task &task = *taskopt.value(); + cvt_task &task = *taskp; const ptrdiff_t index = &task - this->tasks.data(); assert(index >= 0 && index < ptrdiff_t(this->tasks.size())); - if (!task.is_converted) [[unlikely]] { + if (!task.is_converted()) [[unlikely]] { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); return; @@ -458,15 +462,14 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { } void SCWind::on_pb_preview_compress_effect_clicked() noexcept { - auto sel_opt = this->selected_export_task(); - if (!sel_opt.has_value()) { + auto sel = this->selected_export_task(); + if (sel == nullptr) { QMessageBox::warning(this, tr("未选择图像"), tr("请在左侧任务池选择一个图像")); return; } - const auto sel = sel_opt.value(); QString errtitle{""}, errmsg{""}; - if (!sel->is_built) { + if (!sel->is_built()) { errtitle = tr("尚未构建三维结构"); errmsg = tr("在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" @@ -517,10 +520,10 @@ void SCWind::on_pb_export_all_clicked() noexcept { auto tasks_to_export = this->selected_export_task_list(); const auto export_type = this->selected_export_type(); - SlopeCraft::Kernel::litematic_options opt_lite; - SlopeCraft::Kernel::vanilla_structure_options opt_nbt; - SlopeCraft::Kernel::WE_schem_options opt_WE; - SlopeCraft::Kernel::flag_diagram_options opt_fd; + SlopeCraft::litematic_options opt_lite; + SlopeCraft::vanilla_structure_options opt_nbt; + SlopeCraft::WE_schem_options opt_WE; + SlopeCraft::flag_diagram_options opt_fd; { QString err; auto process_err = [this](const QString &err) { diff --git a/SlopeCraft/cvt_task.cpp b/SlopeCraft/cvt_task.cpp index bb7b6e3f..a7c26c58 100644 --- a/SlopeCraft/cvt_task.cpp +++ b/SlopeCraft/cvt_task.cpp @@ -1,16 +1,14 @@ #include "cvt_task.h" #include -cvt_task cvt_task::load(QString filename, QString& err) noexcept { - err.clear(); +tl::expected cvt_task::load(QString filename) noexcept { cvt_task ret; ret.filename = filename; QImage temp; if (!temp.load(filename)) { - err = QObject::tr("加载图片 %1 失败。").arg(filename); - return {}; + return tl::make_unexpected(QObject::tr("加载图片 %1 失败。").arg(filename)); } ret.original_image = temp.convertToFormat(QImage::Format_ARGB32); @@ -20,7 +18,7 @@ cvt_task cvt_task::load(QString filename, QString& err) noexcept { int converted_task_count(const task_pool_t& pool) noexcept { int num = 0; for (const auto& i : pool) { - if (i.is_converted) { + if (i.is_converted()) { num++; } } @@ -30,7 +28,7 @@ int converted_task_count(const task_pool_t& pool) noexcept { int map_export_idx_to_full_idx(const task_pool_t& pool, int eidx) noexcept { assert(eidx >= 0); for (int fidx = 0; fidx < (int)pool.size(); fidx++) { - if (pool.at(fidx).is_converted) { + if (pool.at(fidx).is_converted()) { eidx--; } if (eidx < 0) { @@ -46,7 +44,7 @@ std::vector iteration_map(const task_pool_t& pool) noexcept { std::vector ret; ret.reserve(pool.size()); for (int i = 0; i < (int)pool.size(); i++) { - if (pool.at(i).is_converted) { + if (pool.at(i).is_converted()) { ret.emplace_back(i); } } diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 45190123..64bb9309 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -4,48 +4,28 @@ #include #include #include +#include struct cvt_task { QString filename{""}; QImage original_image; - bool is_converted{false}; - bool is_built{false}; - bool is_exported{false}; + std::unique_ptr + converted_img; + std::unique_ptr structure; - static cvt_task load(QString filename, QString& err) noexcept; - - void set_converted() noexcept { - this->is_converted = true; - this->is_built = false; - this->is_exported = false; - } - - void set_built() noexcept { - assert(this->is_converted); - this->is_built = true; - this->is_exported = false; + [[nodiscard]] bool is_converted() const noexcept { + return this->converted_img != nullptr; } - void set_exported() noexcept { - assert(this->is_converted); - assert(this->is_built); - this->is_exported = true; + [[nodiscard]] bool is_built() const noexcept { + return this->is_converted() && (this->structure != nullptr); } - void set_unconverted() noexcept { - this->is_converted = false; - this->is_built = false; - this->is_exported = false; - } - - void set_unbuilt() noexcept { - this->is_built = false; - this->is_exported = false; - } + static tl::expected load(QString filename) noexcept; }; -Q_DECLARE_METATYPE(cvt_task); +Q_DECLARE_METATYPE(cvt_task) using task_pool_t = std::vector; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 0b757839..8a9f1d4e 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -251,6 +251,28 @@ struct WE_schem_options { progress_callbacks progressbar; }; +struct flag_diagram_options { + uint64_t caller_api_version{SC_VERSION_U64}; + + // 0 or negative number means no split lines + int32_t split_line_row_margin{0}; + // 0 or negative number means no split lines + int32_t split_line_col_margin{0}; + int png_compress_level{9}; + int png_compress_memory_level{8}; + + ui_callbacks ui{}; + progress_callbacks progressbar{}; +}; + +struct test_blocklist_options { + uint64_t caller_api_version{SC_VERSION_U64}; + const mc_block_interface *const *block_ptrs{nullptr}; + const uint8_t *basecolors{nullptr}; + size_t block_count{0}; + string_deliver *err{nullptr}; +}; + struct const_image_reference { const uint32_t *data{nullptr}; size_t rows{0}; diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 2c9ce38a..eca65917 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -31,6 +31,7 @@ class BlockListDeleter { struct selection { std::vector ids; + [[nodiscard]] bool operator==(const selection &b) const noexcept { if (this->ids.size() != b.ids.size()) { return false; From 3bd5b11fbb0677f3758701c01a398e4b4ef9d25c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 19 Apr 2024 18:44:05 +0800 Subject: [PATCH 0795/1123] fix windows build(only for SCL and BlockListManager) Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.cpp | 6 ++++-- SlopeCraftL/color_source.cpp | 2 +- SlopeCraftL/structure_3D.cpp | 6 ++++-- utilities/BlockListManager/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index a7bc0735..9515d16d 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -407,8 +407,10 @@ SCL_EXPORT void SCL_get_base_color_ARGB32(uint32_t dest[64]) { } #include -extern Eigen::Map BasicRGB4External(int channel) { +namespace SlopeCraft { +Eigen::Map BasicRGB4External(int channel) { return Eigen::Map( &SlopeCraft::basic_colorset->RGB_mat()(0, channel), SlopeCraft::basic_colorset->color_count()); -} \ No newline at end of file +} +} // namespace SlopeCraft \ No newline at end of file diff --git a/SlopeCraftL/color_source.cpp b/SlopeCraftL/color_source.cpp index 719842b7..3f8a4504 100644 --- a/SlopeCraftL/color_source.cpp +++ b/SlopeCraftL/color_source.cpp @@ -24,7 +24,7 @@ This file is part of SlopeCraft. namespace SlopeCraft { extern const float RGBBasicSource[256 * 3]; -const std::unique_ptr basic{ +const std::unique_ptr basic_colorset{ new colorset_basic_t{RGBBasicSource}}; const float RGBBasicSource[256 * 3] = { diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 009bc117..244085f5 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -299,7 +299,8 @@ std::string structure_3D_impl::save_cache( params.level = uint32_t(ZSTD_CLEVEL_DEFAULT); #endif ofs.push(boost::iostreams::zstd_compressor{params}); - ofs.push(boost::iostreams::file_sink{filename, std::ios::binary}); + ofs.push( + boost::iostreams::file_sink{filename.string(), std::ios::binary}); } { @@ -321,7 +322,8 @@ tl::expected structure_3D_impl::load_cache( boost::iostreams::filtering_istream ifs; ifs.set_auto_close(true); ifs.push(boost::iostreams::zstd_decompressor{}); - ifs.push(boost::iostreams::file_source{filename, std::ios::binary}); + ifs.push( + boost::iostreams::file_source{filename.string(), std::ios::binary}); { cereal::BinaryInputArchive bia{ifs}; bia(ret); diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 0bef2d1f..7ae8d62d 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -43,7 +43,7 @@ set(BlockListManager_project_sources add_library(BlockListManager STATIC ${BlockListManager_project_sources}) target_link_libraries(BlockListManager PUBLIC Qt6::Widgets SlopeCraftL) target_include_directories(BlockListManager INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} ${BOOST_INCLUDE_DIRS}) +target_include_directories(BlockListManager PRIVATE ${SlopeCraft_Nlohmann_json_include_dir} ${Boost_INCLUDE_DIRS}) target_compile_features(BlockListManager PUBLIC cxx_std_23) qt_add_lupdate(BlockListManager From 15c5825a5d015ac42e5eada9891aafe55f76bc0d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 20 Apr 2024 12:35:59 +0800 Subject: [PATCH 0796/1123] reimplement map data file exporting Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 18 ++++- SlopeCraftL/converted_image.cpp | 132 +++++++++++++++++++++++++++++++- SlopeCraftL/converted_image.h | 8 ++ utilities/SC_GlobalEnums.h | 2 + 4 files changed, 156 insertions(+), 4 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 8a9f1d4e..510eda4b 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -212,6 +212,14 @@ struct convert_option { ui_callbacks ui{}; }; +struct map_data_file_options { + uint64_t caller_api_version{SC_VERSION_U64}; + const char *folder_path{""}; + int begin_index{0}; + progress_callbacks progress{}; + ui_callbacks ui{}; +}; + struct build_options { uint64_t caller_api_version{SC_VERSION_U64}; uint16_t max_allowed_height{256}; @@ -228,6 +236,7 @@ struct build_options { progress_callbacks main_progressbar; progress_callbacks sub_progressbar; }; + struct litematic_options { uint64_t caller_api_version{SC_VERSION_U64}; const char *litename_utf8 = "by SlopeCraft"; @@ -350,6 +359,9 @@ class converted_image { virtual void get_original_image(uint32_t *buffer) const noexcept = 0; // virtual void get_dithered_image(uint32_t *buffer) const noexcept = 0; virtual void get_converted_image(uint32_t *buffer) const noexcept = 0; + + [[nodiscard]] virtual bool export_map_data( + const map_data_file_options &option) const noexcept = 0; }; class structure_3D { @@ -361,12 +373,12 @@ class structure_3D { [[nodiscard]] virtual size_t palette_length() const noexcept = 0; virtual void get_palette(const char **buffer_block_id) const noexcept = 0; - virtual bool export_litematica( + [[nodiscard]] virtual bool export_litematica( const char *filename, const litematic_options &option) const noexcept = 0; - virtual bool export_vanilla_structure( + [[nodiscard]] virtual bool export_vanilla_structure( const char *filename, const vanilla_structure_options &option) const noexcept = 0; - virtual bool export_WE_schem( + [[nodiscard]] virtual bool export_WE_schem( const char *filename, const WE_schem_options &option) const noexcept = 0; }; diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index c2f0abe5..1b0024af 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -10,9 +10,11 @@ #include "color_table.h" #include "height_line.h" #include "lossy_compressor.h" +#include "NBTWriter/NBTWriter.h" converted_image_impl::converted_image_impl(const color_table_impl &table) - : converter{*SlopeCraft::basic_colorset, table.allowed} {} + : converter{*SlopeCraft::basic_colorset, table.allowed}, + game_version{table.mc_version()} {} converted_image *color_table_impl::convert_image( const_image_reference original_img, @@ -41,6 +43,134 @@ converted_image *color_table_impl::convert_image( return new converted_image_impl{std::move(cvted)}; } +bool converted_image_impl::export_map_data( + const SlopeCraft::map_data_file_options &option) const noexcept { + const std::filesystem::path dir{option.folder_path}; + const auto mapPic = this->converter.mapcolor_matrix(); + const int rows = ceil(mapPic.rows() / 128.0f); + const int cols = ceil(mapPic.cols() / 128.0f); + option.progress.set_range(0, 128 * rows * cols, 0); + + // int offset[2] = {0, 0}; // r,c + int currentIndex = option.begin_index; + + option.ui.report_working_status(workStatus::writingMapDataFiles); + + int fail_count = 0; + for (int c = 0; c < cols; c++) { + for (int r = 0; r < rows; r++) { + const std::array offset = {r * 128, c * 128}; + std::filesystem::path current_filename = dir; + current_filename.append(fmt::format("map_{}.dat", currentIndex)); + + NBT::NBTWriter MapFile; + + if (!MapFile.open(current_filename.string().c_str())) { + option.ui.report_error(errorFlag::EXPORT_MAP_DATA_FAILURE, + fmt::format("Failed to create nbt file {}", + current_filename.string()) + .c_str()); + fail_count += 1; + continue; + } + switch (this->game_version) { + case SCL_gameVersion::MC12: + case SCL_gameVersion::MC13: + break; + case SCL_gameVersion::MC14: + case SCL_gameVersion::MC15: + case SCL_gameVersion::MC16: + case SCL_gameVersion::MC17: + case SCL_gameVersion::MC18: + case SCL_gameVersion::MC19: + case SCL_gameVersion::MC20: + MapFile.writeInt( + "DataVersion", + static_cast( + MCDataVersion::suggested_version(this->game_version))); + break; + default: + cerr << "Wrong game version!\n"; + break; + } + + static const std::string ExportedBy = fmt::format( + "Exported by SlopeCraft {}, developed by TokiNoBug", SC_VERSION_STR); + MapFile.writeString("ExportedBy", ExportedBy.data()); + MapFile.writeCompound("data"); + { + MapFile.writeByte("scale", 0); + MapFile.writeByte("trackingPosition", 0); + MapFile.writeByte("unlimitedTracking", 0); + MapFile.writeInt("xCenter", 0); + MapFile.writeInt("zCenter", 0); + switch (this->game_version) { + case SCL_gameVersion::MC12: + MapFile.writeByte("dimension", 114); + MapFile.writeShort("height", 128); + MapFile.writeShort("width", 128); + break; + case SCL_gameVersion::MC13: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 889464); + break; + case SCL_gameVersion::MC14: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 0); + MapFile.writeByte("locked", 1); + break; + case SCL_gameVersion::MC15: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeInt("dimension", 0); + MapFile.writeByte("locked", 1); + break; + case SCL_gameVersion::MC16: + case SCL_gameVersion::MC17: + case SCL_gameVersion::MC18: + case SCL_gameVersion::MC19: + case SCL_gameVersion::MC20: + MapFile.writeListHead("banners", NBT::Compound, 0); + MapFile.writeListHead("frames", NBT::Compound, 0); + MapFile.writeString("dimension", "minecraft:overworld"); + MapFile.writeByte("locked", 1); + break; + default: + cerr << "Wrong game version!\n"; + option.ui.report_error(errorFlag::UNKNOWN_MAJOR_GAME_VERSION, + "Unknown major game version!"); + fail_count += 1; + continue; + } + + MapFile.writeByteArrayHead("colors", 16384); + { + for (short rr = 0; rr < 128; rr++) { + for (short cc = 0; cc < 128; cc++) { + uint8_t ColorCur; + if (rr + offset[0] < mapPic.rows() && + cc + offset[1] < mapPic.cols()) + ColorCur = mapPic(rr + offset[0], cc + offset[1]); + else + ColorCur = 0; + MapFile.writeByte("this should never be seen", ColorCur); + } + option.progress.add(1); + } + } + } + MapFile.endCompound(); + MapFile.close(); + + currentIndex++; + } + } + option.ui.report_working_status(workStatus::none); + return (fail_count == 0); +} + std::optional converted_image_impl::height_info(const build_options &option) const noexcept { // diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index 97732405..410d1439 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -13,6 +13,7 @@ #include "mc_block.h" #include "Schem/Schem.h" #include "water_item.h" +#include "string_deliver.h" class color_table_impl; @@ -24,6 +25,10 @@ class converted_image_impl : public converted_image { Eigen::Array; libMapImageCvt::MapImageCvter converter; + private: + const SCL_gameVersion game_version; + + public: // [[nodiscard]] uint64_t hash() const noexcept; size_t rows() const noexcept final { return this->converter.rows(); } @@ -39,6 +44,9 @@ class converted_image_impl : public converted_image { this->converter.converted_image(buffer, nullptr, nullptr, false); } + bool export_map_data( + const map_data_file_options &option) const noexcept final; + struct height_maps { Eigen::ArrayXXi map_color; Eigen::ArrayXXi base; diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index b0a9a356..998ac0b8 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -159,6 +159,8 @@ enum class SCL_errorFlag : int { /// is greatly different. EXPORT_SCHEM_MC12_NOT_SUPPORTED = 0x0E, + EXPORT_MAP_DATA_FAILURE = 0x0F, + }; enum class SCL_workStatus : int { From 9a786cdd54368e51b978b14345bb8b31f5aa97ed Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 20 Apr 2024 13:24:29 +0800 Subject: [PATCH 0797/1123] reimplement exporting flat diagram Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 3 ++ SlopeCraftL/color_table.cpp | 55 +++++++++++++++++++++ SlopeCraftL/color_table.h | 3 ++ SlopeCraftL/structure_3D.cpp | 95 ++++++++++++++++++++++++++++++++++++ SlopeCraftL/structure_3D.h | 4 ++ utilities/SC_GlobalEnums.h | 4 ++ 6 files changed, 164 insertions(+) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 510eda4b..de7a1662 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -380,6 +380,9 @@ class structure_3D { const vanilla_structure_options &option) const noexcept = 0; [[nodiscard]] virtual bool export_WE_schem( const char *filename, const WE_schem_options &option) const noexcept = 0; + [[nodiscard]] virtual bool export_flat_diagram( + const char *filename, const color_table &table, + const flag_diagram_options &option) const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 43f526fe..217f0b1a 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -8,6 +8,8 @@ #include "color_table.h" #include "water_item.h" #include "structure_3D.h" +#include "utilities/ProcessBlockId/process_block_id.h" +#include "utilities/schem/mushroom.h" std::optional color_table_impl::create( const color_table_create_info &args) noexcept { @@ -140,6 +142,59 @@ std::vector color_table_impl::block_id_list() const noexcept { return dest; } +const mc_block *color_table_impl::find_block_for_index( + int idx, std::string_view blkid) const noexcept { + if (idx < 0) { + return nullptr; + } + + if (idx < (int)this->blocks.size()) { + return &this->blocks[idx]; + } + + // the block must be mushroom + namespace lsi = libSchem::internal; + using lsi::mushroom_type; + + blkid::char_range pure_id_range; + // invalid block id + if (!blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { + return nullptr; + } + + std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; + + auto mush_type_opt = lsi::pureid_to_type(pure_id); + if (!mush_type_opt.has_value()) { + return nullptr; + } + + uint8_t expected_basecolor = 0; + switch (mush_type_opt.value()) { + case mushroom_type::red: + expected_basecolor = 28; + break; + case mushroom_type::brown: + expected_basecolor = 10; + break; + case mushroom_type::stem: + expected_basecolor = 3; + break; + } + + const auto *blkp = this->find_block_for_index(expected_basecolor, {}); + + if (blkp == nullptr) { + return nullptr; + } + + if (lsi::pureid_to_type(blkp->id) != mush_type_opt) { + return nullptr; + } + + return blkp; +} + uint64_t color_table_impl::hash() const noexcept { boost::uuids::detail::md5 hash; SC_HASH_ADD_DATA(hash, this->map_type_) diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 1966c1c0..a2512536 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -53,6 +53,9 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] std::vector block_id_list() const noexcept; + [[nodiscard]] const mc_block *find_block_for_index( + int index, std::string_view block_id) const noexcept; + [[nodiscard]] uint64_t hash() const noexcept; [[nodiscard]] std::filesystem::path self_cache_dir( diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 244085f5..d73f9d67 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -8,11 +8,13 @@ #include #include #include +#include #include "structure_3D.h" #include "color_table.h" #include "lossy_compressor.h" #include "prim_glass_builder.h" +#include "FlatDiagram.h" std::optional structure_3D_impl::create( const color_table_impl &table, const converted_image_impl &cvted, @@ -262,6 +264,99 @@ bool structure_3D_impl::export_WE_schem( return true; } +bool structure_3D_impl::export_flat_diagram( + const char *filename, const SlopeCraft::color_table &table_, + const SlopeCraft::flag_diagram_options &option) const noexcept { + const auto &table = dynamic_cast(table_); + if (table.map_type() != SCL_mapTypes::Flat) { + option.ui.report_error( + SCL_errorFlag::EXPORT_FLAT_DIAGRAM_ON_WRONG_MAP_TYPE, + fmt::format( + "We can only export flat diagram for flat maps, but found {}", + magic_enum::enum_name(table.map_type())) + .c_str()); + return false; + } + const libFlatDiagram::fd_option fdopt{ + .row_start = 0, + .row_end = this->schem.z_range(), + .cols = this->schem.x_range(), + .split_line_row_margin = option.split_line_row_margin, + .split_line_col_margin = option.split_line_col_margin, + .png_compress_level = option.png_compress_level, + .png_compress_memory_level = option.png_compress_memory_level, + }; + + std::vector> img_list_rmj; + img_list_rmj.reserve(this->schem.palette_size()); + + for (int pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { + if (pblkid == 0) { + img_list_rmj.emplace_back(); + img_list_rmj[0].setZero(); + continue; + } + std::string_view id = this->schem.palette()[pblkid]; + const mc_block *blkp = table.find_block_for_index(pblkid - 1, id); + if (blkp == nullptr) { + std::string blkid_full; + blkid_full.reserve(64 * 2048); + for (const auto &blk : table.blocks) { + blkid_full += blk.id; + blkid_full.push_back('\n'); + } + option.ui.report_error( + errorFlag::EXPORT_FLAT_DIAGRAM_FAILURE, + fmt::format("SlopeCraftL internal error. Failed to find block image " + "for \"{}\". " + "In the 3d structure, the corresponding block idx is " + "{}.\nThe whole " + "block palette is as below: {}", + id, pblkid, blkid_full) + .c_str()); + return false; + } + + img_list_rmj.emplace_back(blkp->image.transpose()); + } + + auto block_at_callback = [this, &img_list_rmj]( + int64_t r, + int64_t c) -> libFlatDiagram::block_img_ref_t { + if (r < 0 || c < 0 || r >= this->schem.z_range() || + c >= this->schem.x_range()) { + return libFlatDiagram::block_img_ref_t{img_list_rmj.at(0).data()}; + } + + const int ele = this->schem(c, 0, r); + assert(ele >= 0 && ele < this->schem.palette_size()); + + return libFlatDiagram::block_img_ref_t{img_list_rmj.at(ele).data()}; + }; + + std::array, 4> txt{ + std::make_pair( + "Title", "Flat diagram generated by SlopeCraftL."), + std::make_pair("Software", "SlopeCraftL"), + std::make_pair( + "Description", + "This image is a flat diagram created by SlopeCraftL, which is is " + "a subproject of SlopeCraft, developed by TokiNoBug."), + std::make_pair( + "Comment", + "SlopeCraft is a free software published " + "under GPLv3 license. You can find " + "its repository at https://github.com/SlopeCraft/SlopeCraft")}; + + auto err = libFlatDiagram::export_flat_diagram(filename, fdopt, + block_at_callback, txt); + if (!err.empty()) { + option.ui.report_error(errorFlag::EXPORT_FLAT_DIAGRAM_FAILURE, err.c_str()); + return false; + } + return true; +} + namespace cereal { template void save(archive &ar, const Eigen::ArrayXX &mat) { diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 3acf6ec2..88bf28bc 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -43,6 +43,10 @@ class structure_3D_impl : public structure_3D { bool export_WE_schem(const char *filename, const WE_schem_options &option) const noexcept final; + bool export_flat_diagram( + const char *filename, const color_table &table, + const flag_diagram_options &option) const noexcept final; + [[nodiscard]] std::string save_cache( const std::filesystem::path &file) const noexcept; diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 998ac0b8..2770a4c2 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -161,6 +161,10 @@ enum class SCL_errorFlag : int { EXPORT_MAP_DATA_FAILURE = 0x0F, + EXPORT_FLAT_DIAGRAM_ON_WRONG_MAP_TYPE = 0x10, + + EXPORT_FLAT_DIAGRAM_FAILURE = 0x11, + }; enum class SCL_workStatus : int { From 9ef5dcb731acbb12d9435b67f9a19a02db0dfefc Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 20 Apr 2024 14:39:54 +0800 Subject: [PATCH 0798/1123] fix potential memory problem in SCL Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 35 ++++++++++++++------------------- SlopeCraftL/SlopeCraftL.h | 3 +++ SlopeCraftL/color_table.cpp | 16 +++++++++------ SlopeCraftL/color_table.h | 12 +++++------ SlopeCraftL/converted_image.cpp | 11 +++++++++-- SlopeCraftL/converted_image.h | 4 ++++ 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 74a759ea..44c89ba5 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -274,11 +274,7 @@ void SCWind::on_pb_cvt_all_clicked() noexcept { if (task.is_converted()) { continue; } - - this->kernel_set_image(idx); - this->kernel_convert_image(); - this->kernel_make_cvt_cache(); - task.set_converted(); + task.converted_img = this->convert_image(idx); } emit this->image_changed(); } @@ -735,7 +731,7 @@ void SCWind::on_pb_export_file_clicked() noexcept { auto &task = this->tasks.at(idx); this->kernel_set_image(idx); bool need_to_convert{true}; - if (task.is_converted) { + if (task.is_converted()) { if (this->kernel->loadConvertCache(this->selected_algo(), this->is_dither_selected())) { need_to_convert = false; @@ -748,9 +744,16 @@ void SCWind::on_pb_export_file_clicked() noexcept { const int cur_seq_beg = map_range_at_index(this->tasks, seq_first, idx).first; - - this->kernel->exportAsData(dir.toLocal8Bit().data(), cur_seq_beg, nullptr, - nullptr); + const auto dir_name = dir.toLocal8Bit(); + + const SlopeCraft::map_data_file_options option{ + .caller_api_version = SC_VERSION_U64, + .folder_path = dir_name.data(), + .begin_index = cur_seq_beg, + .progress = progress_callback(this->ui->pbar_export), + .ui = this->ui_callbacks(), + }; + const bool ok = task.converted_img->export_map_data(option); } } @@ -765,23 +768,18 @@ void SCWind::on_ac_GAcvter_options_triggered() noexcept { } void SCWind::on_ac_cache_dir_open_triggered() noexcept { - auto cache_dir = QString::fromLocal8Bit(this->kernel->cacheDir()); + auto cache_dir = this->cache_root_dir(); QDesktopServices::openUrl(QUrl::fromLocalFile(cache_dir)); } void SCWind::on_ac_clear_cache_triggered() noexcept { - const auto cache_dir_name = QString::fromLocal8Bit(this->kernel->cacheDir()); - + const QString cache_dir_name = this->cache_root_dir(); QDir cache_dir{cache_dir_name}; if (!cache_dir.exists()) { return; } - for (auto &task : this->tasks) { - task.set_unconverted(); - } - emit this->image_changed(); const auto entries = cache_dir.entryList(); @@ -891,9 +889,6 @@ void SCWind::on_ac_about_triggered() noexcept { } void SCWind::on_ac_get_current_colorlist_triggered() noexcept { - if (this->kernel->queryStep() < SCL_step::wait4Image) { - this->kernel_set_type(); - } constexpr int basecolors_per_row = 4; constexpr int basecolors_per_col = 16; @@ -981,7 +976,7 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { err.resize(4096); SlopeCraft::string_deliver sd{err.data(), err.size()}; - SlopeCraft::Kernel::test_blocklist_options opt; + SlopeCraft::test_blocklist_options opt; opt.block_count = blks.size(); opt.block_ptrs = blks.data(); opt.basecolors = basecolors.data(); diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index de7a1662..e1426636 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -362,6 +362,9 @@ class converted_image { [[nodiscard]] virtual bool export_map_data( const map_data_file_options &option) const noexcept = 0; + + [[nodiscard]] virtual bool is_converted_from( + const color_table &) const noexcept = 0; }; class structure_3D { diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 217f0b1a..ac938c4d 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -16,7 +16,11 @@ std::optional color_table_impl::create( color_table_impl result; result.mc_version_ = args.mc_version; result.map_type_ = args.map_type; - result.allowed.need_find_side = (args.map_type == mapTypes::Slope); + { + colorset_allowed_t a; + a.need_find_side = (args.map_type == mapTypes::Slope); + result.allowed = std::make_shared(std::move(a)); + } auto report_err = [&args](errorFlag flag, std::string_view msg) { args.ui.report_error(flag, msg.data()); @@ -105,13 +109,13 @@ std::optional color_table_impl::create( } } - if (!result.allowed.apply_allowed(*SlopeCraft::basic_colorset, m_index)) { + if (!result.allowed->apply_allowed(*SlopeCraft::basic_colorset, m_index)) { std::string msg = fmt::format( "Too few usable color(s) : only {} colors\nAvaliable base color(s) : ", - result.allowed.color_count()); + result.allowed->color_count()); - for (int idx = 0; idx < result.allowed.color_count(); idx++) { - msg += std::to_string(result.allowed.Map(idx)) + ", "; + for (int idx = 0; idx < result.allowed->color_count(); idx++) { + msg += std::to_string(result.allowed->Map(idx)) + ", "; } report_err(errorFlag::USEABLE_COLOR_TOO_FEW, msg); @@ -200,7 +204,7 @@ uint64_t color_table_impl::hash() const noexcept { SC_HASH_ADD_DATA(hash, this->map_type_) SC_HASH_ADD_DATA(hash, this->mc_version_) - this->allowed.hash_add_data(hash); + this->allowed->hash_add_data(hash); decltype(hash)::digest_type digest; hash.get_digest(digest); std::array result; diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index a2512536..07954322 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -16,17 +16,17 @@ class color_table_impl : public SlopeCraft::color_table { public: - colorset_allowed_t allowed; + std::shared_ptr allowed{new colorset_allowed_t}; SCL_mapTypes map_type_; SCL_gameVersion mc_version_; std::array blocks; color_map_ptrs colors() const noexcept final { - return color_map_ptrs{.r_data = allowed.rgb_data(0), - .g_data = allowed.rgb_data(1), - .b_data = allowed.rgb_data(2), - .map_data = allowed.map_data(), - .num_colors = allowed.color_count()}; + return color_map_ptrs{.r_data = allowed->rgb_data(0), + .g_data = allowed->rgb_data(1), + .b_data = allowed->rgb_data(2), + .map_data = allowed->map_data(), + .num_colors = allowed->color_count()}; } SCL_mapTypes map_type() const noexcept final { return this->map_type_; } diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 1b0024af..4832440a 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -13,8 +13,9 @@ #include "NBTWriter/NBTWriter.h" converted_image_impl::converted_image_impl(const color_table_impl &table) - : converter{*SlopeCraft::basic_colorset, table.allowed}, - game_version{table.mc_version()} {} + : converter{*SlopeCraft::basic_colorset, *table.allowed}, + game_version{table.mc_version()}, + colorset{table.allowed} {} converted_image *color_table_impl::convert_image( const_image_reference original_img, @@ -299,6 +300,12 @@ converted_image_impl::load_cache(const color_table_impl &table, return ret; } +bool converted_image_impl::is_converted_from( + const color_table &table_) const noexcept { + const auto &table = dynamic_cast(table_); + return (this->colorset.get() == table.allowed.get()); +} + // uint64_t converted_image_impl::hash() const noexcept { // return this->converter.task_hash(); // } \ No newline at end of file diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index 410d1439..dfd6cb60 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "SlopeCraftL.h" #include "SCLDefines.h" #include "mc_block.h" @@ -27,6 +28,7 @@ class converted_image_impl : public converted_image { private: const SCL_gameVersion game_version; + const std::shared_ptr colorset; public: // [[nodiscard]] uint64_t hash() const noexcept; @@ -66,5 +68,7 @@ class converted_image_impl : public converted_image { [[nodiscard]] static tl::expected load_cache(const color_table_impl &table, const std::filesystem::path &file) noexcept; + + bool is_converted_from(const color_table &table_) const noexcept final; }; #endif // SLOPECRAFT_CONVERTED_IMAGE_H From a674960b229a16eda20b6f1878ce9d893afd76db Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 17:43:55 +0800 Subject: [PATCH 0799/1123] fix PoolModel and ExportTableModel Signed-off-by: ToKiNoBug --- SlopeCraft/ExportTableModel.cpp | 63 +++++----- SlopeCraft/ExportTableModel.h | 14 +-- SlopeCraft/PoolModel.cpp | 63 +++++++--- SlopeCraft/PoolModel.h | 46 +++----- SlopeCraft/SCWind.cpp | 27 +++-- SlopeCraft/SCWind.h | 5 +- SlopeCraft/cvt_task.cpp | 124 ++++++++++++++++---- SlopeCraft/cvt_task.h | 200 ++++++++++++++++++++++++++++++-- 8 files changed, 409 insertions(+), 133 deletions(-) diff --git a/SlopeCraft/ExportTableModel.cpp b/SlopeCraft/ExportTableModel.cpp index 8e350f51..55cf531d 100644 --- a/SlopeCraft/ExportTableModel.cpp +++ b/SlopeCraft/ExportTableModel.cpp @@ -1,13 +1,13 @@ #include "ExportTableModel.h" #include "SCWind.h" -ExportTableModel::ExportTableModel(SCWind* parent, const task_pool_t* poolptr) - : QAbstractTableModel(parent), pool{poolptr} {} +ExportTableModel::ExportTableModel(SCWind* parent) + : QAbstractTableModel(parent), pool{parent->get_tasks()} {} ExportTableModel::~ExportTableModel() {} -const SCWind* ExportTableModel::scwind() const noexcept { - return dynamic_cast(this->parent()); +SCWind* ExportTableModel::scwind() const noexcept { + return dynamic_cast(this->parent()); } QSize map_size_of_images(QSize image_size) noexcept { @@ -16,26 +16,26 @@ QSize map_size_of_images(QSize image_size) noexcept { return QSize{width, height}; } -map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, - int asked_idx) noexcept { - assert(asked_idx >= 0 && asked_idx < (int)pool.size()); - - int current_start_seq = first_map_seq_num; - - for (int idx = 0; idx < asked_idx; idx++) { - const auto current_map_size = - map_size_of_images(pool[idx].original_image.size()); - const int current_map_num = - current_map_size.height() * current_map_size.width(); - - current_start_seq += current_map_num; - } - - const auto cms = map_size_of_images(pool[asked_idx].original_image.size()); - const int cmn = cms.height() * cms.width(); - - return map_range{current_start_seq, current_start_seq + cmn - 1}; -} +// map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, +// int asked_idx) noexcept { +// assert(asked_idx >= 0 && asked_idx < (int)pool.size()); +// +// int current_start_seq = first_map_seq_num; +// +// for (int idx = 0; idx < asked_idx; idx++) { +// const auto current_map_size = +// map_size_of_images(pool[idx].original_image.size()); +// const int current_map_num = +// current_map_size.height() * current_map_size.width(); +// +// current_start_seq += current_map_num; +// } +// +// const auto cms = map_size_of_images(pool[asked_idx].original_image.size()); +// const int cmn = cms.height() * cms.width(); +// +// return map_range{current_start_seq, current_start_seq + cmn - 1}; +// } QString map_data_filename(QString dir, int seq_number) noexcept { return QStringLiteral("%1/map_%2.dat").arg(dir).arg(seq_number); @@ -49,7 +49,8 @@ void ExportTableModel::refresh() noexcept { } int ExportTableModel::rowCount(const QModelIndex&) const noexcept { - return ::converted_task_count(*this->pool); + return this->pool.converted_count(this->scwind()->current_color_table(), + this->scwind()->current_convert_option()); } int ExportTableModel::columnCount(const QModelIndex&) const noexcept { @@ -69,15 +70,21 @@ QVariant ExportTableModel::data(const QModelIndex& qmi, return {}; } - const auto& task = - this->pool->at(::map_export_idx_to_full_idx(*this->pool, r)); + const auto& pair = this->pool.converted_task_at_index( + this->scwind()->current_color_table(), + this->scwind()->current_convert_option(), static_cast(r)); + if (!pair) { + return {}; + } + // const auto task_global_index = pair.value().first; + const auto& task = *pair.value().second; if (role == Qt::ItemDataRole::DisplayRole) { const QSize map_size = map_size_of_images(task.original_image.size()); const int map_count = map_size.height() * map_size.width(); const int beg_idx = this->scwind()->current_map_begin_seq_number(); - const auto range = map_range_at_index(*this->pool, beg_idx, r); + const auto range = this->pool.map_range_of(beg_idx, r); switch (c) { case 0: diff --git a/SlopeCraft/ExportTableModel.h b/SlopeCraft/ExportTableModel.h index 61cb73dd..7688c72f 100644 --- a/SlopeCraft/ExportTableModel.h +++ b/SlopeCraft/ExportTableModel.h @@ -9,10 +9,10 @@ class SCWind; class ExportTableModel : public QAbstractTableModel { Q_OBJECT private: - const task_pool_t* pool{nullptr}; + task_pool& pool; public: - explicit ExportTableModel(SCWind* parent, const task_pool_t* poolptr); + explicit ExportTableModel(SCWind* parent); ~ExportTableModel(); int rowCount(const QModelIndex&) const noexcept override; @@ -20,7 +20,7 @@ class ExportTableModel : public QAbstractTableModel { QVariant data(const QModelIndex&, int role) const noexcept override; - const SCWind* scwind() const noexcept; + SCWind* scwind() const noexcept; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const noexcept override; @@ -31,14 +31,6 @@ class ExportTableModel : public QAbstractTableModel { QSize map_size_of_images(QSize image_size) noexcept; -struct map_range { - int first{-1}; - int last{-1}; -}; - -map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, - int asked_idx) noexcept; - QString map_data_filename(QString dir, int seq_number) noexcept; #endif // SLOPECRAFT_SLOPECRAFT_EXPORTTABLEMODEL_H \ No newline at end of file diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 855d40bc..3fd31096 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -1,12 +1,14 @@ #include "PoolModel.h" #include #include -#include #include #include +#include -PoolModel::PoolModel(QObject* parent, task_pool_t* poolptr) - : QAbstractListModel(parent), pool(poolptr) {} +PoolModel::PoolModel(SCWind* scw) + : QAbstractListModel(scw), pool{scw->get_tasks()}, scwind{scw} { + assert(scw != nullptr); +} PoolModel::~PoolModel() {} @@ -21,7 +23,7 @@ const QPixmap& PoolModel::icon_converted() noexcept { } QVariant PoolModel::data(const QModelIndex& idx, int role) const { - const auto& task = this->pool->at(idx.row()); + const auto& task = this->pool.at(idx.row()); if (role == Qt::ItemDataRole::DisplayRole) { return task.filename; } @@ -34,7 +36,8 @@ QVariant PoolModel::data(const QModelIndex& idx, int role) const { auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - if (!task.is_converted()) { + if (!task.is_converted_with(this->scwind->current_color_table(), + this->scwind->current_convert_option())) { this->draw_icon(img, icon_empty(), 0); } else { this->draw_icon(img, icon_converted(), 0); @@ -97,8 +100,7 @@ void PoolModel::draw_icon(QPixmap& image, const QPixmap& icon, int index, painter.end(); } -CvtPoolModel::CvtPoolModel(QObject* parent, task_pool_t* poolptr) - : PoolModel(parent, poolptr) {} +CvtPoolModel::CvtPoolModel(SCWind* scw) : PoolModel{scw} {} CvtPoolModel::~CvtPoolModel() {} @@ -259,24 +261,53 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, if (src_indices.size() <= 0) { return true; } - map_indices(*this->pool, src_indices, begin_row); +#warning "TODO: Implement reshuffling here" + assert(("Reshuffing is not implemented yet", false)); + // map_indices(this->pool, src_indices, begin_row); } this->refresh(); return true; } -ExportPoolModel::ExportPoolModel(QObject* parent, task_pool_t* poolptr) - : PoolModel(parent, poolptr) {} +ExportPoolModel::ExportPoolModel(SCWind* scw) : PoolModel(scw) {} ExportPoolModel::~ExportPoolModel() {} +int ExportPoolModel::rowCount(const QModelIndex& midx) const { + if (midx.isValid()) { + return 0; + } + return this->pool.converted_count(this->scwind->current_color_table(), + this->scwind->current_convert_option()); +} + +std::optional ExportPoolModel::export_index_to_global_index( + int eidx) const noexcept { + if (eidx < 0) { + return std::nullopt; + } + return this->pool.export_index_to_global_index( + this->scwind->current_color_table(), + this->scwind->current_convert_option(), eidx); +} + +cvt_task* ExportPoolModel::export_idx_to_task_ptr(int eidx) const noexcept { + auto global_index = this->export_index_to_global_index(eidx); + if (!global_index) { + return nullptr; + } + return &this->pool[global_index.value()]; +} + QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { - const int fidx = this->export_idx_to_full_idx(midx.row()); - assert(fidx >= 0); - assert(fidx < (int)this->pool->size()); + const auto taskp = this->export_idx_to_task_ptr(midx.row()); + assert(taskp); + if (taskp == nullptr) { + return {}; + } - const auto& task = this->pool->at(fidx); + auto& task = *taskp; if (role == Qt::ItemDataRole::DisplayRole) { return task.filename; @@ -289,7 +320,9 @@ QVariant ExportPoolModel::data(const QModelIndex& midx, int role) const { } auto raw_image = QPixmap::fromImage(task.original_image); auto img = raw_image.scaledToWidth(this->_listview->size().width()); - if (!task.is_built()) { + if (!task.is_built_with(this->scwind->current_color_table(), + this->scwind->current_convert_option(), + this->scwind->current_build_option())) { this->draw_icon(img, icon_empty(), 0); } else { this->draw_icon(img, icon_converted(), 0); diff --git a/SlopeCraft/PoolModel.h b/SlopeCraft/PoolModel.h index bbcdff1e..c9cb3366 100644 --- a/SlopeCraft/PoolModel.h +++ b/SlopeCraft/PoolModel.h @@ -7,24 +7,27 @@ #include #include +class SCWind; + class PoolModel : public QAbstractListModel { Q_OBJECT protected: - task_pool_t* pool{nullptr}; + task_pool& pool; QListView* _listview{nullptr}; + SCWind* const scwind; static const QPixmap& icon_empty() noexcept; static const QPixmap& icon_converted() noexcept; public: - explicit PoolModel(QObject* parent = nullptr, task_pool_t* poolptr = nullptr); + explicit PoolModel(SCWind* scw); ~PoolModel(); int rowCount(const QModelIndex& midx) const override { if (midx.isValid()) { return 0; } - return this->pool->size(); + return this->pool.size(); } QModelIndex parent(const QModelIndex&) const override { @@ -39,9 +42,9 @@ class PoolModel : public QAbstractListModel { } public: - task_pool_t* attached_pool() noexcept { return this->pool; } - const task_pool_t* attached_pool() const noexcept { return this->pool; } - void set_pool(task_pool_t* _pool) noexcept { this->pool = _pool; } + task_pool& attached_pool() noexcept { return this->pool; } + const task_pool& attached_pool() const noexcept { return this->pool; } + // void set_pool(task_pool_t* _pool) noexcept { this->pool = _pool; } QListView* attached_listview() noexcept { return this->_listview; } const QListView* attached_listview() const noexcept { @@ -61,8 +64,7 @@ class PoolModel : public QAbstractListModel { class CvtPoolModel : public PoolModel { Q_OBJECT public: - explicit CvtPoolModel(QObject* parent = nullptr, - task_pool_t* poolptr = nullptr); + explicit CvtPoolModel(SCWind* scw); ~CvtPoolModel(); Qt::DropActions supportedDropActions() const override; @@ -82,32 +84,18 @@ class CvtPoolModel : public PoolModel { class ExportPoolModel : public PoolModel { Q_OBJECT public: - explicit ExportPoolModel(QObject* parent = nullptr, - task_pool_t* poolptr = nullptr); + explicit ExportPoolModel(SCWind* scw); ~ExportPoolModel(); - int rowCount(const QModelIndex& midx) const override { - if (midx.isValid()) { - return 0; - } - return converted_task_count(*this->pool); - } + int rowCount(const QModelIndex& midx) const override; - std::vector iteration_map() const noexcept { - return ::iteration_map(*this->pool); - } + // std::vector iteration_map() const noexcept { + // return ::iteration_map(*this->pool); + // } - int export_idx_to_full_idx(int eidx) const noexcept { - return ::map_export_idx_to_full_idx(*this->pool, eidx); - } + std::optional export_index_to_global_index(int eidx) const noexcept; - cvt_task* export_idx_to_task_ptr(int eidx) const noexcept { - const int pidx = this->export_idx_to_full_idx(eidx); - if (pidx >= (int)this->pool->size()) { - return nullptr; - } - return &this->pool->at(pidx); - } + cvt_task* export_idx_to_task_ptr(int eidx) const noexcept; QVariant data(const QModelIndex& idx, int role) const override; }; diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index a63666fb..0ed8c6c8 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -39,14 +39,14 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { // initialize cvt pool model { - this->cvt_pool_model = new CvtPoolModel{this, &this->tasks}; + this->cvt_pool_model = new CvtPoolModel{this}; this->ui->lview_pool_cvt->setModel(this->cvt_pool_model); this->cvt_pool_model->set_listview(this->ui->lview_pool_cvt); connect(this->ui->lview_pool_cvt->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SCWind::when_cvt_pool_selectionChanged); - this->export_pool_model = new ExportPoolModel{this, &this->tasks}; + this->export_pool_model = new ExportPoolModel{this}; this->ui->lview_pool_export->setModel(this->export_pool_model); this->export_pool_model->set_listview(this->ui->lview_pool_export); connect(this->ui->lview_pool_export->selectionModel(), @@ -63,7 +63,7 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { }); } { - this->export_table_model = new ExportTableModel{this, &this->tasks}; + this->export_table_model = new ExportTableModel{this}; this->ui->tview_export_fileonly->setModel(this->export_table_model); connect(this, &SCWind::image_changed, this->export_table_model, @@ -631,6 +631,17 @@ void SCWind::when_export_type_toggled() noexcept { // } // } +SlopeCraft::convert_option SCWind::current_convert_option() noexcept { + return SlopeCraft::convert_option{ + .caller_api_version = SC_VERSION_U64, + .algo = this->selected_algo(), + .dither = this->is_dither_selected(), + .ai_cvter_opt = this->GA_option, + .progress = progress_callback(this->ui->pbar_cvt), + .ui = this->ui_callbacks(), + }; +} + std::unique_ptr SCWind::convert_image(int idx) noexcept { assert(idx >= 0); @@ -645,15 +656,7 @@ SCWind::convert_image(int idx) noexcept { .rows = static_cast(raw.height()), .cols = static_cast(raw.width()), }; - SlopeCraft::convert_option opt{ - .caller_api_version = SC_VERSION_U64, - .algo = this->selected_algo(), - .dither = this->is_dither_selected(), - .ai_cvter_opt = this->GA_option, - .progress = progress_callback(this->ui->pbar_cvt), - .ui = this->ui_callbacks(), - }; - auto cvted_img = ctable->convert_image(img, opt); + auto cvted_img = ctable->convert_image(img, this->current_convert_option()); return std::unique_ptr{ cvted_img}; diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index dc24c536..f699baa8 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -109,7 +109,7 @@ class SCWind : public QMainWindow { SlopeCraft::GA_converter_option GA_option{}; // SlopeCraft::Kernel* kernel; - task_pool_t tasks; + task_pool tasks; CvtPoolModel* cvt_pool_model{nullptr}; ExportPoolModel* export_pool_model{nullptr}; ExportTableModel* export_table_model{nullptr}; @@ -123,8 +123,11 @@ class SCWind : public QMainWindow { // QString fileonly_export_dir{""}; public: + task_pool& get_tasks() noexcept { return this->tasks; } + QString cache_root_dir() const noexcept; SlopeCraft::color_table* current_color_table() noexcept; + SlopeCraft::convert_option current_convert_option() noexcept; SlopeCraft::ui_callbacks ui_callbacks() const noexcept; diff --git a/SlopeCraft/cvt_task.cpp b/SlopeCraft/cvt_task.cpp index a7c26c58..b55f7ecb 100644 --- a/SlopeCraft/cvt_task.cpp +++ b/SlopeCraft/cvt_task.cpp @@ -1,5 +1,8 @@ -#include "cvt_task.h" + #include +#include +#include "cvt_task.h" +#include "ExportTableModel.h" tl::expected cvt_task::load(QString filename) noexcept { cvt_task ret; @@ -15,38 +18,109 @@ tl::expected cvt_task::load(QString filename) noexcept { return ret; } -int converted_task_count(const task_pool_t& pool) noexcept { - int num = 0; - for (const auto& i : pool) { - if (i.is_converted()) { - num++; +size_t task_pool::converted_count( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option) const noexcept { + size_t counter = 0; + for (const auto& t : *this) { + if (t.is_converted_with(table, cvt_option)) { + counter += 1; } } - return num; + return counter; } -int map_export_idx_to_full_idx(const task_pool_t& pool, int eidx) noexcept { - assert(eidx >= 0); - for (int fidx = 0; fidx < (int)pool.size(); fidx++) { - if (pool.at(fidx).is_converted()) { - eidx--; +const std::vector> task_pool::converted_tasks( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option) noexcept { + std::vector> ret; + ret.reserve(this->size()); + for (auto [idx, task] : *this | std::ranges::views::enumerate) { + if (task.is_converted_with(table, cvt_option)) { + ret.emplace_back(std::pair{idx, &task}); } - if (eidx < 0) { - return fidx; + } + return ret; +} +std::optional> task_pool::converted_task_at_index( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option, size_t eidx) noexcept { + for (auto [idx, task] : *this | std::ranges::views::enumerate) { + if (task.is_converted_with(table, cvt_option)) { + if (eidx == 0) { + return std::pair{idx, &task}; + } + eidx--; } } - - assert(false); - return INT_MAX; + return std::nullopt; } -std::vector iteration_map(const task_pool_t& pool) noexcept { - std::vector ret; - ret.reserve(pool.size()); - for (int i = 0; i < (int)pool.size(); i++) { - if (pool.at(i).is_converted()) { - ret.emplace_back(i); +std::optional task_pool::export_index_to_global_index( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option, size_t e_idx) const noexcept { + for (auto [gidx, task] : *this | std::ranges::views::enumerate) { + if (!task.is_converted_with(table, cvt_option)) { + continue; } + + if (e_idx <= 0) { + return gidx; + } + e_idx--; } - return ret; -} \ No newline at end of file + return std::nullopt; +} + +map_range task_pool::map_range_of(int map_begin_index, + size_t global_index) const noexcept { + assert(global_index < this->size()); + for (size_t i = 0; i < global_index; i++) { + const auto& task = this->at(i); + const auto current_map_size = + map_size_of_images(task.original_image.size()); + const int current_map_num = + current_map_size.height() * current_map_size.width(); + map_begin_index += current_map_num; + } + const auto cms = + map_size_of_images(this->at(global_index).original_image.size()); + const int cmn = cms.height() * cms.width(); + return map_range{map_begin_index, map_begin_index + cmn - 1}; +} + +// int converted_task_count(const task_pool_t& pool) noexcept { +// int num = 0; +// for (const auto& i : pool) { +// if (i.is_converted()) { +// num++; +// } +// } +// return num; +// } +// +// int map_export_idx_to_full_idx(const task_pool_t& pool, int eidx) noexcept { +// assert(eidx >= 0); +// for (int fidx = 0; fidx < (int)pool.size(); fidx++) { +// if (pool.at(fidx).is_converted()) { +// eidx--; +// } +// if (eidx < 0) { +// return fidx; +// } +// } +// +// assert(false); +// return INT_MAX; +// } + +// std::vector iteration_map(const task_pool_t& pool) noexcept { +// std::vector ret; +// ret.reserve(pool.size()); +// for (int i = 0; i < (int)pool.size(); i++) { +// if (pool.at(i).is_converted()) { +// ret.emplace_back(i); +// } +// } +// return ret; +// } \ No newline at end of file diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 64bb9309..08eaaae0 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -6,33 +6,209 @@ #include #include +struct convert_input { + const SlopeCraft::color_table* table{nullptr}; + SlopeCraft::convert_option option; +}; + +struct hasher { + static uint64_t operator()( + const SlopeCraft::GA_converter_option& opt) noexcept { + uint64_t h = 0; + h ^= std::hash()(opt.popSize); + h ^= std::hash()(opt.maxGeneration); + h ^= std::hash()(opt.maxFailTimes); + h ^= std::hash()(opt.crossoverProb); + h ^= std::hash()(opt.mutationProb); + return h; + } + static uint64_t operator()(const SlopeCraft::convert_option& opt) noexcept { + uint64_t h = 0; + h |= static_cast(opt.algo); + h <<= 1; + h |= static_cast(opt.dither); + h ^= hasher{}(opt.ai_cvter_opt); + return h; + } + static uint64_t operator()(const convert_input& pair) noexcept { + return hasher{}(pair.option) ^ std::hash{}(pair.table); + } + static uint64_t operator()(const SlopeCraft::build_options& opt) noexcept { + uint64_t h = 0; + h ^= static_cast(opt.max_allowed_height); + h <<= sizeof(opt.max_allowed_height) * 8; // 16 bits + h ^= static_cast(opt.bridge_interval); + h <<= sizeof(opt.bridge_interval) * 8; // 32 bits + h ^= static_cast(opt.compress_method); + h <<= sizeof(opt.compress_method) * 8; // 40 bits + h ^= static_cast(opt.glass_method); + h <<= sizeof(opt.glass_method) * 8; // 48 bits + h ^= static_cast(opt.fire_proof); + h <<= 1; // 49 bits + h ^= static_cast(opt.enderman_proof); + h <<= 1; // 50 bits + h ^= static_cast(opt.connect_mushrooms); + h <<= 1; // 51 bits + + return h; + } +}; + +struct equal { + static bool operator()(const SlopeCraft::GA_converter_option& a, + const SlopeCraft::GA_converter_option& b) noexcept { + if (a.popSize != b.popSize) return false; + if (a.maxGeneration != b.maxGeneration) return false; + if (a.maxFailTimes != b.maxFailTimes) return false; + if (a.crossoverProb != b.crossoverProb) return false; + if (a.mutationProb != b.mutationProb) return false; + return true; + } + static bool operator()(const SlopeCraft::convert_option& a, + const SlopeCraft::convert_option& b) noexcept { + if (a.algo != b.algo) return false; + if (a.dither != b.dither) return false; + if (!equal{}(a.ai_cvter_opt, b.ai_cvter_opt)) return false; + return true; + } + static bool operator()(const convert_input& a, + const convert_input& b) noexcept { + if (a.table != b.table) return false; + if (!equal{}(a.option, b.option)) return false; + return true; + } + static bool operator()(const SlopeCraft::build_options& a, + const SlopeCraft::build_options& b) noexcept { + if (a.max_allowed_height != b.max_allowed_height) return false; + if (a.bridge_interval != b.bridge_interval) return false; + if (a.compress_method != b.compress_method) return false; + if (a.glass_method != b.glass_method) return false; + if (a.fire_proof != b.fire_proof) return false; + if (a.enderman_proof != b.enderman_proof) return false; + return true; + } +}; + +struct convert_result { + // convert_result() = delete; + + std::unique_ptr + converted_image{nullptr}; + std::unordered_map< + SlopeCraft::build_options, + std::unique_ptr, hasher, + equal> + built_structures; + + [[nodiscard]] bool is_built_with( + const SlopeCraft::build_options& opt) const noexcept { + return this->built_structures.contains(opt); + } + + void set_built(SlopeCraft::build_options opt, + std::unique_ptr + structure) noexcept { + opt.ui = {}; + opt.main_progressbar = {}; + opt.sub_progressbar = {}; + auto it = this->built_structures.find(opt); + if (it == built_structures.end()) { + this->built_structures.emplace(opt, std::move(structure)); + return; + } + it->second = std::move(structure); + } +}; + struct cvt_task { QString filename{""}; QImage original_image; - std::unique_ptr - converted_img; - std::unique_ptr structure; + std::unordered_map + converted_images; - [[nodiscard]] bool is_converted() const noexcept { - return this->converted_img != nullptr; + // std::unique_ptr + // structure; + + [[nodiscard]] bool is_converted_with( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& option) const noexcept { + return this->converted_images.contains(convert_input{table, option}); } - [[nodiscard]] bool is_built() const noexcept { - return this->is_converted() && (this->structure != nullptr); + void set_converted( + const SlopeCraft::color_table* table, SlopeCraft::convert_option option, + std::unique_ptr + converted_image) noexcept { + if (converted_image == nullptr) { + return; + } + option.ui = {}; + option.progress = {}; + auto cvt_input = convert_input{table, option}; + auto it = this->converted_images.find(cvt_input); + if (it == this->converted_images.end()) { + this->converted_images.emplace( + cvt_input, + convert_result{.converted_image = std::move(converted_image), + .built_structures = {}}); + return; + } + it->second.converted_image = std::move(converted_image); } + [[nodiscard]] bool is_built_with( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option, + const SlopeCraft::build_options& build_option) const noexcept { + auto it = this->converted_images.find(convert_input{table, cvt_option}); + if (it == this->converted_images.end()) { + return false; + } + return it->second.is_built_with(build_option); + } static tl::expected load(QString filename) noexcept; }; -Q_DECLARE_METATYPE(cvt_task) +// Q_DECLARE_METATYPE(cvt_task) + +struct map_range { + int first{-1}; + int last{-1}; +}; -using task_pool_t = std::vector; +// map_range map_range_at_index(const task_pool_t& pool, int first_map_seq_num, +// int asked_idx) noexcept; +class task_pool : public std::vector { + public: + [[nodiscard]] size_t converted_count( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option) const noexcept; -int converted_task_count(const task_pool_t&) noexcept; + [[nodiscard]] const std::vector> converted_tasks( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option) noexcept; -int map_export_idx_to_full_idx(const task_pool_t&, int eidx) noexcept; + [[nodiscard]] std::optional> + converted_task_at_index(const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option, + size_t idx) noexcept; + + [[nodiscard]] std::optional export_index_to_global_index( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& cvt_option, + size_t e_idx) const noexcept; + + [[nodiscard]] map_range map_range_of(int map_begin_index, + size_t global_index) const noexcept; +}; -std::vector iteration_map(const task_pool_t& pool) noexcept; +// using task_pool_t = ; +// +// int converted_task_count(const task_pool_t&) noexcept; +// +// int map_export_idx_to_full_idx(const task_pool_t&, int eidx) noexcept; +// +// std::vector iteration_map(const task_pool_t& pool) noexcept; #endif // SLOPECRAFT_SLOPECRAFT_CVT_TASK_H \ No newline at end of file From 3ed8c7137016ef00288b773cd41cbe1fdefc982e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 19:22:14 +0800 Subject: [PATCH 0800/1123] reimplement get_compressed_image Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 3 +++ SlopeCraftL/color_table.cpp | 16 ++++++++++++++++ SlopeCraftL/color_table.h | 2 ++ SlopeCraftL/converted_image.cpp | 23 +++++++++++++++++++++++ SlopeCraftL/converted_image.h | 3 +++ SlopeCraftL/structure_3D.h | 2 +- 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index e1426636..756892f5 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -360,6 +360,9 @@ class converted_image { // virtual void get_dithered_image(uint32_t *buffer) const noexcept = 0; virtual void get_converted_image(uint32_t *buffer) const noexcept = 0; + virtual void get_compressed_image(const structure_3D &structure, + uint32_t *buffer) const noexcept = 0; + [[nodiscard]] virtual bool export_map_data( const map_data_file_options &option) const noexcept = 0; diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index ac938c4d..b9e03316 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -331,4 +331,20 @@ structure_3D *color_table_impl::load_build_cache( } write_to_sd(error, res.error()); return nullptr; +} + +std::array LUT_map_color_to_ARGB() noexcept { + const auto &basic = *SlopeCraft::basic_colorset; + std::array ret; + ret.fill(0); + for (size_t idx = 0; idx < 256; idx++) { + const auto map_color = index2mapColor(idx); + if (index2baseColor(idx) == 0) { + ret[map_color] = 0x00000000; + continue; + } + ret[map_color] = + RGB2ARGB(basic.RGB(idx, 0), basic.RGB(idx, 1), basic.RGB(idx, 2)); + } + return ret; } \ No newline at end of file diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 07954322..2dd19872 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -120,6 +120,8 @@ class color_table_impl : public SlopeCraft::color_table { const char *cache_root_dir, string_deliver *error) const noexcept final; }; +[[nodiscard]] std::array LUT_map_color_to_ARGB() noexcept; + //[[nodiscard]] std::string digest_to_string( // std::span hash) noexcept; diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 4832440a..b77e20f2 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -11,6 +11,7 @@ #include "height_line.h" #include "lossy_compressor.h" #include "NBTWriter/NBTWriter.h" +#include "structure_3D.h" converted_image_impl::converted_image_impl(const color_table_impl &table) : converter{*SlopeCraft::basic_colorset, *table.allowed}, @@ -44,6 +45,28 @@ converted_image *color_table_impl::convert_image( return new converted_image_impl{std::move(cvted)}; } +void converted_image_impl::get_compressed_image( + const structure_3D &structure_, uint32_t *buffer) const noexcept { + const auto &structure = dynamic_cast(structure_); + assert(this->rows() == structure.map_color.rows()); + assert(this->cols() == structure.map_color.cols()); + + const auto LUT = LUT_map_color_to_ARGB(); + Eigen::Map< + Eigen::Array> + dest{buffer, static_cast(this->rows()), + static_cast(this->cols())}; + dest.fill(0); + for (size_t r = 0; r < this->rows(); r++) { + for (size_t c = 0; c < this->cols(); c++) { + const auto map_color = structure.map_color(r, c); + assert(map_color >= 0); + assert(map_color <= 255); + dest(r, c) = LUT[map_color]; + } + } +} + bool converted_image_impl::export_map_data( const SlopeCraft::map_data_file_options &option) const noexcept { const std::filesystem::path dir{option.folder_path}; diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index dfd6cb60..ebed97b3 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -45,6 +45,9 @@ class converted_image_impl : public converted_image { void get_converted_image(uint32_t *buffer) const noexcept final { this->converter.converted_image(buffer, nullptr, nullptr, false); } + + void get_compressed_image(const structure_3D &structure, + uint32_t *buffer) const noexcept final; bool export_map_data( const map_data_file_options &option) const noexcept final; diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 88bf28bc..488a6aba 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -14,11 +14,11 @@ class structure_3D_impl : public structure_3D { private: libSchem::Schem schem; + public: Eigen::ArrayXX map_color; // map color may be modified by lossy // compression,so we store the modified one - public: size_t shape_x() const noexcept final { return this->schem.x_range(); } size_t shape_y() const noexcept final { return this->schem.y_range(); } size_t shape_z() const noexcept final { return this->schem.z_range(); } From 462d473a30376a0b73417fb96b41b45f9df17ce4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 19:26:52 +0800 Subject: [PATCH 0801/1123] fix ExportTableModel Signed-off-by: ToKiNoBug --- SlopeCraft/ExportTableModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraft/ExportTableModel.cpp b/SlopeCraft/ExportTableModel.cpp index 55cf531d..27795c7d 100644 --- a/SlopeCraft/ExportTableModel.cpp +++ b/SlopeCraft/ExportTableModel.cpp @@ -2,7 +2,7 @@ #include "SCWind.h" ExportTableModel::ExportTableModel(SCWind* parent) - : QAbstractTableModel(parent), pool{parent->get_tasks()} {} + : QAbstractTableModel(parent), pool{parent->tasks} {} ExportTableModel::~ExportTableModel() {} From 7b0d538821524a919449235d7e1b8249259409a4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 19:27:03 +0800 Subject: [PATCH 0802/1123] fix AiCvterParameterDialog Signed-off-by: ToKiNoBug --- SlopeCraft/AiCvterParameterDialog.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/SlopeCraft/AiCvterParameterDialog.cpp b/SlopeCraft/AiCvterParameterDialog.cpp index f85602f1..da86b948 100644 --- a/SlopeCraft/AiCvterParameterDialog.cpp +++ b/SlopeCraft/AiCvterParameterDialog.cpp @@ -26,11 +26,12 @@ This file is part of SlopeCraft. #include "SCWind.h" using namespace SlopeCraft; -AiCvterParameterDialog::AiCvterParameterDialog(SCWind *parent) +AiCvterParameterDialog::AiCvterParameterDialog(SCWind* parent) : QDialog(parent), ui(new Ui::AiCvterParameterDialog) { this->ui->setupUi(this); - SlopeCraft::GA_converter_option opt = *this->kernel->aiCvterOpt(); + SlopeCraft::GA_converter_option opt = + dynamic_cast(this->parent())->GA_option; opt.caller_api_version = SC_VERSION_U64; this->ui->sb_pop_size->setValue(opt.popSize); @@ -44,18 +45,20 @@ AiCvterParameterDialog::~AiCvterParameterDialog() { delete this->ui; } SlopeCraft::GA_converter_option AiCvterParameterDialog::current_option() const noexcept { - SlopeCraft::GA_converter_option ret; - ret.crossoverProb = this->ui->dsb_crossover_prob->value(); - ret.mutationProb = this->ui->dsb_mutate_prob->value(); - ret.maxFailTimes = this->ui->sb_max_early_stop->value(); - ret.maxGeneration = this->ui->sb_max_gen->value(); - ret.popSize = this->ui->sb_pop_size->value(); + SlopeCraft::GA_converter_option ret{ + .caller_api_version = SC_VERSION_U64, + .popSize = static_cast(this->ui->sb_pop_size->value()), + .maxGeneration = static_cast(this->ui->sb_max_gen->value()), + .maxFailTimes = static_cast(this->ui->sb_max_early_stop->value()), + .crossoverProb = this->ui->dsb_crossover_prob->value(), + .mutationProb = this->ui->dsb_mutate_prob->value(), + }; return ret; } void AiCvterParameterDialog::on_buttonBox_accepted() noexcept { auto opt = this->current_option(); - this->kernel->setAiCvterOpt(&opt); + dynamic_cast(this->parent())->GA_option = opt; } void AiCvterParameterDialog::on_buttonBox_rejected() noexcept { From ba9794bb196e85bd0e9d92ffed3226441512eb96 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 19:27:14 +0800 Subject: [PATCH 0803/1123] fix CompressEffectViewer Signed-off-by: ToKiNoBug --- SlopeCraft/CompressEffectViewer.cpp | 16 ++++++++-------- SlopeCraft/CompressEffectViewer.h | 9 +++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/SlopeCraft/CompressEffectViewer.cpp b/SlopeCraft/CompressEffectViewer.cpp index 47a27b93..f3aef59b 100644 --- a/SlopeCraft/CompressEffectViewer.cpp +++ b/SlopeCraft/CompressEffectViewer.cpp @@ -6,22 +6,22 @@ #include #include -CompressEffectViewer::CompressEffectViewer(SCWind* parent) +CompressEffectViewer::CompressEffectViewer( + SCWind* parent, const SlopeCraft::converted_image& cvted, + const SlopeCraft::structure_3D& structure) : QDialog{parent}, ui{new Ui::CompressEffectViewer} { this->ui->setupUi(this); - auto kernel = parent->kernel_ptr(); - const int rows = kernel->getImageRows(); - const int cols = kernel->getImageCols(); + const int rows = cvted.rows(); + const int cols = cvted.cols(); QImage img{cols, rows, QImage::Format_ARGB32}; - - kernel->getCompressedImage( - nullptr, nullptr, reinterpret_cast(img.scanLine(0)), false); + cvted.get_compressed_image(structure, + reinterpret_cast(img.scanLine(0))); this->ui->lb_display->setPixmap(QPixmap::fromImage(img)); } -CompressEffectViewer::~CompressEffectViewer() { delete this->ui; } +CompressEffectViewer::~CompressEffectViewer() {} void CompressEffectViewer::on_pb_save_image_clicked() noexcept { static QString prev_dir; diff --git a/SlopeCraft/CompressEffectViewer.h b/SlopeCraft/CompressEffectViewer.h index 5a21762b..f9b40453 100644 --- a/SlopeCraft/CompressEffectViewer.h +++ b/SlopeCraft/CompressEffectViewer.h @@ -2,6 +2,9 @@ #define SLOPECRAFT_SLOPECRAFT_COMPRESSEFFECTVIEWER_H #include +#include +#include + class SCWind; class CompressEffectViewer; @@ -13,10 +16,12 @@ class CompressEffectViewer; class CompressEffectViewer : public QDialog { Q_OBJECT private: - Ui::CompressEffectViewer* const ui; + std::unique_ptr ui; public: - explicit CompressEffectViewer(SCWind* parent); + explicit CompressEffectViewer(SCWind* parent, + const SlopeCraft::converted_image&, + const SlopeCraft::structure_3D&); ~CompressEffectViewer(); private slots: void on_pb_save_image_clicked() noexcept; From 782ccf57bf25e68df6729562d7ce23928f0122a2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 19:27:32 +0800 Subject: [PATCH 0804/1123] fix ExportModelViewer Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index f699baa8..a1bc8172 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -106,10 +106,8 @@ class SCWind : public QMainWindow { std::unordered_map< selection, std::unique_ptr> color_tables; - SlopeCraft::GA_converter_option GA_option{}; // SlopeCraft::Kernel* kernel; - task_pool tasks; CvtPoolModel* cvt_pool_model{nullptr}; ExportPoolModel* export_pool_model{nullptr}; ExportTableModel* export_table_model{nullptr}; @@ -123,7 +121,9 @@ class SCWind : public QMainWindow { // QString fileonly_export_dir{""}; public: - task_pool& get_tasks() noexcept { return this->tasks; } + SlopeCraft::GA_converter_option GA_option{}; + task_pool tasks; + [[deprecated]] task_pool& get_tasks() noexcept { return this->tasks; } QString cache_root_dir() const noexcept; SlopeCraft::color_table* current_color_table() noexcept; From f50493907a2e7a85786ab9ef7fa19867cd6ccaa1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 20:08:10 +0800 Subject: [PATCH 0805/1123] reimplement stat_blocks Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 3 +++ SlopeCraftL/color_table.cpp | 24 ++++++++++++++++++++++++ SlopeCraftL/color_table.h | 3 +++ SlopeCraftL/structure_3D.h | 3 +-- utilities/Schem/Schem.cpp | 10 ++++++++++ utilities/Schem/Schem.h | 9 ++++++++- 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 756892f5..b31a83e7 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -339,6 +339,9 @@ class color_table { [[nodiscard]] virtual structure_3D *load_build_cache( const converted_image &, const build_options &, const char *cache_root_dir, string_deliver *error) const noexcept = 0; + + virtual void stat_blocks(const structure_3D &, + size_t buffer[64]) const noexcept = 0; }; class converted_image { diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index b9e03316..0ecee7a6 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -333,6 +333,30 @@ structure_3D *color_table_impl::load_build_cache( return nullptr; } +void color_table_impl::stat_blocks(const structure_3D &s, + size_t buffer[64]) const noexcept { + std::fill(buffer, buffer + 64, 0); + const auto &structure = dynamic_cast(s); + + const auto schem_stat = structure.schem.stat_blocks(); + for (size_t schem_blk_id = 0; schem_blk_id < structure.schem.palette_size(); + schem_blk_id++) { + const auto strid = structure.schem.palette()[schem_blk_id]; + const auto blkp = this->find_block_for_index(schem_blk_id, strid); + if (blkp == nullptr) { + std::cerr << fmt::format( + "Failed to find \"{}\" in color_table, this type of block will not " + "be counted.\n", + strid); + continue; + } + const ptrdiff_t index_in_palette = blkp - this->blocks.data(); + assert(index_in_palette >= 0); + assert(index_in_palette < this->blocks.size()); + buffer[index_in_palette] += schem_stat[schem_blk_id]; + } +} + std::array LUT_map_color_to_ARGB() noexcept { const auto &basic = *SlopeCraft::basic_colorset; std::array ret; diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 2dd19872..9c4af611 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -118,6 +118,9 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] structure_3D *load_build_cache( const converted_image &, const build_options &, const char *cache_root_dir, string_deliver *error) const noexcept final; + + void stat_blocks(const structure_3D &s, + size_t buffer[64]) const noexcept final; }; [[nodiscard]] std::array LUT_map_color_to_ARGB() noexcept; diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 488a6aba..563a8dad 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -12,9 +12,8 @@ class structure_3D_impl : public structure_3D { private: - libSchem::Schem schem; - public: + libSchem::Schem schem; Eigen::ArrayXX map_color; // map color may be modified by lossy // compression,so we store the modified one diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 93d1c165..895b532c 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -60,6 +60,16 @@ std::string Schem::check_size(int64_t x, int64_t y, int64_t z) noexcept { return {}; } +void Schem::stat_blocks(std::vector &dest) const noexcept { + dest.resize(this->palette_size()); + std::fill(dest.begin(), dest.end(), 0); + + for (ele_t block_index : *this) { + assert(block_index < this->palette_size()); + dest[block_index] += 1; + } +} + void Schem::set_block_id(const char *const *const block_ids, const int num) noexcept { if (num < 0) { diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 302c29a4..b35d29d0 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -158,11 +158,18 @@ class Schem { } } + void stat_blocks(std::vector &dest) const noexcept; + [[nodiscard]] std::vector stat_blocks() const noexcept { + std::vector buf; + this->stat_blocks(buf); + return buf; + } + inline int64_t x_range() const noexcept { return xzy.dimension(0); } inline int64_t y_range() const noexcept { return xzy.dimension(2); } inline int64_t z_range() const noexcept { return xzy.dimension(1); } - inline int palette_size() const noexcept { return block_id_list.size(); } + inline size_t palette_size() const noexcept { return block_id_list.size(); } inline int64_t size() const noexcept { return xzy.size(); } From 11cb28280ae671570b87d5d1152b72d3cf4b3871 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Apr 2024 20:18:35 +0800 Subject: [PATCH 0806/1123] reimplement PreviewWind Signed-off-by: ToKiNoBug --- SlopeCraft/PreviewWind.cpp | 35 +++++++++++++++++++---------------- SlopeCraft/PreviewWind.h | 12 +++++++----- SlopeCraftL/SlopeCraftL.h | 10 ++++++++++ 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 6eb5b312..8b0b030f 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -28,9 +28,9 @@ PreviewWind::PreviewWind(QWidget* parent) }); } -PreviewWind::~PreviewWind() { delete this->ui; } +PreviewWind::~PreviewWind() {} -void PreviewWind::set_size(std::span size) & noexcept { +void PreviewWind::set_size(std::span size) & noexcept { QString size_str = tr("大小:%1 × %2 × %3").arg(size[0]).arg(size[1]).arg(size[2]); @@ -40,25 +40,28 @@ void PreviewWind::set_size(std::span size) & noexcept { tr("体积:%1").arg(size[0] * size[1] * size[2])); } -void PreviewWind::set_total_count(int count) & noexcept { +void PreviewWind::set_total_count(size_t count) & noexcept { this->ui->lb_block_count->setText(tr("方块总数:%1").arg(count)); } -void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { - std::array count_list; +void PreviewWind::setup_data( + const SlopeCraft::color_table& table, + const SlopeCraft::structure_3D& structure) noexcept { + std::array count_list; count_list.fill(0); - + table.stat_blocks(structure, count_list.data()); { - int total_blks{0}; - kernel->getBlockCounts(&total_blks, count_list.data()); - this->set_total_count(total_blks); + size_t total_blocks{0}; + for (auto c : count_list) { + total_blocks += c; + } + this->set_total_count(total_blocks); } + std::vector blkp_arr; - { - const size_t num = kernel->getBlockPalette(nullptr, 0); - blkp_arr.resize(num); - kernel->getBlockPalette(blkp_arr.data(), blkp_arr.size()); - } + table.visit_blocks([&blkp_arr](const SlopeCraft::mc_block_interface* b) { + blkp_arr.emplace_back(b); + }); this->mat_list.resize(blkp_arr.size()); for (size_t idx = 0; idx < blkp_arr.size(); idx++) { @@ -67,8 +70,8 @@ void PreviewWind::setup_data(const SlopeCraft::Kernel* kernel) noexcept { } { - std::array sz; - kernel->get3DSize(&sz[0], &sz[1], &sz[2]); + std::array sz{structure.shape_x(), structure.shape_y(), + structure.shape_z()}; this->set_size(sz); } diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h index 537095d3..62ec4eca 100644 --- a/SlopeCraft/PreviewWind.h +++ b/SlopeCraft/PreviewWind.h @@ -5,6 +5,7 @@ #include #include #include +#include #include class PreviewWind; @@ -16,25 +17,26 @@ class PreviewWind; struct material_item { const SlopeCraft::mc_block_interface* blk{nullptr}; - int count{0}; + size_t count{0}; }; class PreviewWind : public QDialog { Q_OBJECT private: - Ui::PreviewWind* ui; + std::unique_ptr ui; std::vector mat_list; MaterialModel* mmp{nullptr}; - void set_size(std::span size) & noexcept; - void set_total_count(int count) & noexcept; + void set_size(std::span size) & noexcept; + void set_total_count(size_t count) & noexcept; public: explicit PreviewWind(QWidget* parent = nullptr); ~PreviewWind(); const auto& material_list() const noexcept { return this->mat_list; } - void setup_data(const SlopeCraft::Kernel* kernel) noexcept; + void setup_data(const SlopeCraft::color_table&, + const SlopeCraft::structure_3D&) noexcept; enum class sort_option { no_sort, ascending, descending }; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index b31a83e7..9d0dd134 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -312,6 +312,16 @@ class color_table { void *custom_data), void *custom_data) const = 0; + template + void visit_blocks(visitor v) const { + this->visit_blocks( + [](const mc_block_interface *b, void *custom_data) { + visitor *fun = reinterpret_cast(custom_data); + (*fun)(b); + }, + &v); + } + [[nodiscard]] virtual converted_image *convert_image( const_image_reference original_img, const convert_option &option) const noexcept = 0; From 7e7e4557935104f6d2193a6617563147477daef6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 22 Apr 2024 21:31:28 +0800 Subject: [PATCH 0807/1123] fix TransparentStrategyWind and cvt task Signed-off-by: ToKiNoBug --- SlopeCraft/TransparentStrategyWind.cpp | 2 +- SlopeCraft/TransparentStrategyWind.h | 2 +- SlopeCraft/cvt_task.h | 96 ++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/TransparentStrategyWind.cpp b/SlopeCraft/TransparentStrategyWind.cpp index 3a1b9aad..9af2df16 100644 --- a/SlopeCraft/TransparentStrategyWind.cpp +++ b/SlopeCraft/TransparentStrategyWind.cpp @@ -9,7 +9,7 @@ TransparentStrategyWind::TransparentStrategyWind(QWidget* parent) this->on_pb_reset_clicked(); } -TransparentStrategyWind::~TransparentStrategyWind() { delete this->ui; } +TransparentStrategyWind::~TransparentStrategyWind() {} SCL_PureTpPixelSt TransparentStrategyWind::pure_strategy() const noexcept { if (this->ui->cb_pure_air->isChecked()) { diff --git a/SlopeCraft/TransparentStrategyWind.h b/SlopeCraft/TransparentStrategyWind.h index 51d4e5e0..2d84cd51 100644 --- a/SlopeCraft/TransparentStrategyWind.h +++ b/SlopeCraft/TransparentStrategyWind.h @@ -12,7 +12,7 @@ class TransparentStrategyWind; class TransparentStrategyWind : public QDialog { Q_OBJECT private: - Ui::TransparentStrategyWind *const ui; + std::unique_ptr ui; private slots: void on_pb_confirm_clicked() noexcept; void on_pb_cancel_clicked() noexcept; diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 08eaaae0..6556e3d5 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -5,6 +5,7 @@ #include #include #include +#include struct convert_input { const SlopeCraft::color_table* table{nullptr}; @@ -105,6 +106,71 @@ struct convert_result { return this->built_structures.contains(opt); } + void cache_all_structures(const SlopeCraft::color_table& table, + const SlopeCraft::converted_image& cvted, + const QString& cache_root_dir) noexcept { + this->cache_all_structures(table, cvted, cache_root_dir, + [](auto) { return true; }); + } + + void cache_all_structures( + const SlopeCraft::color_table& table, + const SlopeCraft::converted_image& cvted, const QString& cache_root_dir, + const std::function& + cache_or_not) noexcept { + for (auto& pair : this->built_structures) { + if (!cache_or_not(pair.first)) { + continue; + } + [[maybe_unused]] const bool ok = + table.save_build_cache(cvted, pair.first, *pair.second, + cache_root_dir.toLocal8Bit().data(), nullptr); + } + } + + void cache_structure(const SlopeCraft::color_table& table, + const SlopeCraft::converted_image& cvted, + const SlopeCraft::build_options& opt, + const QString& cache_root_dir) noexcept { + auto it = this->built_structures.find(opt); + if (it == this->built_structures.end()) { + return; + } + if (it->second == nullptr) { + return; + } + const bool ok = table.save_build_cache( + cvted, opt, *it->second, cache_root_dir.toLocal8Bit().data(), nullptr); + if (ok) { + it->second.reset(); + } + return; + } + + const SlopeCraft::structure_3D* load_build_cache( + const SlopeCraft::color_table& table, + const SlopeCraft::converted_image& cvted, + const SlopeCraft::build_options& opt, + const QString& cache_root_dir) noexcept { + auto it = this->built_structures.find(opt); + if (it == this->built_structures.end()) { + return nullptr; + } + + if (it->second != nullptr) { // the structure exist in memory + return it->second.get(); + } + + // the structure is cached + SlopeCraft::structure_3D* p = table.load_build_cache( + cvted, opt, cache_root_dir.toLocal8Bit().data(), nullptr); + if (p == nullptr) { // failed to load cache + return nullptr; + } + it->second.reset(p); + return it->second.get(); + } + void set_built(SlopeCraft::build_options opt, std::unique_ptr structure) noexcept { @@ -167,6 +233,36 @@ struct cvt_task { } return it->second.is_built_with(build_option); } + + // [[nodiscard]] const SlopeCraft::structure_3D* load_build_cache( + // const SlopeCraft::color_table* table, + // const SlopeCraft::convert_option& cvt_option, + // const SlopeCraft::build_options& build_option, + // const QString& cache_dir) noexcept { + // + // } + + void cache_all_structures(const SlopeCraft::color_table& table, + const QString& cache_root_dir) noexcept { + this->cache_all_structures(table, cache_root_dir, + [](auto, auto) { return true; }); + } + + void cache_all_structures( + const SlopeCraft::color_table& table, const QString& cache_root_dir, + const std::function& + cache_or_not) noexcept { + for (auto& cvt : this->converted_images) { + const auto& cvted_img = cvt.second.converted_image; + cvt.second.cache_all_structures( + table, *cvted_img, cache_root_dir, + [cache_or_not, &cvt](const SlopeCraft::build_options& bopt) { + return cache_or_not(cvt.first.option, bopt); + }); + } + } + static tl::expected load(QString filename) noexcept; }; From e4595bdb5b24cced8c9bce51cc389c20c6a4e632 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 22 Apr 2024 21:31:45 +0800 Subject: [PATCH 0808/1123] fix SCWind(partly) Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 7 ++++++ SlopeCraft/SCWind.h | 6 ++++- SlopeCraft/SCWind_slots.cpp | 45 ++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0ed8c6c8..0724e17a 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -663,6 +663,13 @@ SCWind::convert_image(int idx) noexcept { } } +std::unique_ptr SCWind::build_3D( + const SlopeCraft::converted_image &cvted) noexcept { + auto ctable = this->current_color_table(); + auto str = ctable->build(cvted, this->current_build_option()); + return std::unique_ptr{str}; +} + void SCWind::kernel_make_cvt_cache() noexcept { std::string err; err.resize(4096); diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index a1bc8172..a0253d8e 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -199,9 +199,13 @@ class SCWind : public QMainWindow { void update_button_states() noexcept; - std::unique_ptr + [[nodiscard]] std::unique_ptr convert_image(int idx) noexcept; + [[nodiscard]] std::unique_ptr + build_3D(const SlopeCraft::converted_image&) noexcept; + [[deprecated]] void kernel_set_image(int idx) noexcept; [[deprecated]] void kernel_convert_image() noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 44c89ba5..aa0fdf87 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -257,7 +257,9 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { if (!cvted) { return; } - this->tasks[sel.value()].converted_img = std::move(cvted); + this->tasks[sel.value()].set_converted(this->current_color_table(), + this->current_convert_option(), + std::move(cvted)); } // this->kernel_make_cvt_cache(); @@ -271,10 +273,13 @@ void SCWind::on_pb_cvt_current_clicked() noexcept { void SCWind::on_pb_cvt_all_clicked() noexcept { for (int idx = 0; idx < (int)this->tasks.size(); idx++) { auto &task = this->tasks[idx]; - if (task.is_converted()) { + if (task.is_converted_with(this->current_color_table(), + this->current_convert_option())) { continue; } - task.converted_img = this->convert_image(idx); + auto cvted = this->convert_image(idx); + task.set_converted(this->current_color_table(), + this->current_convert_option(), std::move(cvted)); } emit this->image_changed(); } @@ -375,24 +380,32 @@ void SCWind::on_pb_build3d_clicked() noexcept { cvt_task &task = *task_ptr; - if (!task.is_converted()) [[unlikely]] { + if (!task.is_converted_with(this->current_color_table(), + this->current_convert_option())) [[unlikely]] { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); return; } - { - const int gidx = task_ptr - this->tasks.data(); - this->kernel_set_image(gidx); - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - this->kernel_convert_image(); - } - } - this->kernel_build_3d(); - this->kernel_make_build_cache(); + const int gidx = task_ptr - this->tasks.data(); + auto table = this->current_color_table(); + const auto cvt_option = this->current_convert_option(); + if (!task.is_converted_with(table, cvt_option)) { + task.set_converted(table, cvt_option, this->convert_image(gidx)); + } + auto &cvted = + task.converted_images.find(convert_input{table, cvt_option})->second; + // this->kernel_set_image(gidx); + // if (!this->kernel->loadConvertCache(this->selected_algo(), + // this->is_dither_selected())) { + // this->kernel_convert_image(); + // } - task.set_built(); + const auto build_option = this->current_build_option(); + if (!cvted.is_built_with(build_option)) { + cvted.set_built(build_option, this->build_3D(*cvted.converted_image)); + } + // load cache if converted this->refresh_current_build_display(&task, true); } @@ -758,7 +771,7 @@ void SCWind::on_pb_export_file_clicked() noexcept { } void SCWind::on_ac_GAcvter_options_triggered() noexcept { - AiCvterParameterDialog *acpd = new AiCvterParameterDialog{this, this->kernel}; + AiCvterParameterDialog *acpd = new AiCvterParameterDialog{this}; acpd->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); acpd->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); From 50fe673576c413d3a0d400a7761b7122478f7efb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 24 Apr 2024 14:22:20 +0800 Subject: [PATCH 0809/1123] fix SCWind(partly) Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 43 +++++++- SlopeCraft/SCWind.h | 24 ++++- SlopeCraft/SCWind_slots.cpp | 207 +++++++++++++++++------------------- 3 files changed, 159 insertions(+), 115 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0724e17a..36e6bd39 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -646,10 +646,14 @@ std::unique_ptr SCWind::convert_image(int idx) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); + return this->convert_image(this->tasks[idx]); +} +std::unique_ptr +SCWind::convert_image(const cvt_task &task) noexcept { auto ctable = this->current_color_table(); - const QImage &raw = this->tasks[idx].original_image; + const QImage &raw = task.original_image; { SlopeCraft::const_image_reference img{ .data = (const uint32_t *)raw.scanLine(0), @@ -663,6 +667,19 @@ SCWind::convert_image(int idx) noexcept { } } +const SlopeCraft::converted_image &SCWind::convert_if_need( + cvt_task &task) noexcept { + const auto table = this->current_color_table(); + const auto opt = this->current_convert_option(); + if (!task.is_converted_with(table, opt)) { + task.set_converted(table, opt, this->convert_image(task)); + } + + auto &cvted = task.converted_images[{table, opt}].converted_image; + assert(cvted != nullptr); + return *cvted; +} + std::unique_ptr SCWind::build_3D( const SlopeCraft::converted_image &cvted) noexcept { auto ctable = this->current_color_table(); @@ -670,6 +687,30 @@ std::unique_ptr SCWind::build_3D( return std::unique_ptr{str}; } +std::tuple +SCWind::convert_and_build_if_need(cvt_task &task) noexcept { + const auto table = this->current_color_table(); + const auto &cvted = this->convert_if_need(task); + + assert(task.is_converted_with(table, this->current_convert_option())); + auto &cvt_result = + task.converted_images.at({table, this->current_convert_option()}); + const auto build_opt = this->current_build_option(); + + if (auto str_3D = cvt_result.load_build_cache(*table, cvted, build_opt, + this->cache_root_dir())) { + // The 3D structure is built, it exists in memory or can be loaded + return {cvted, *str_3D}; + } + // Build 3D structure now + auto s = this->build_3D(cvted); + auto ptr = s.get(); + assert(ptr != nullptr); + cvt_result.set_built(build_opt, std::move(s)); + return {cvted, *ptr}; +} + void SCWind::kernel_make_cvt_cache() noexcept { std::string err; err.resize(4096); diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index a0253d8e..de961aca 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -1,15 +1,16 @@ #ifndef SLOPECRAFT_SLOPECRAFT_SCWIND_H #define SLOPECRAFT_SLOPECRAFT_SCWIND_H -#include -#include +#include +#include #include +#include #include -#include -#include #include #include #include +#include +#include #include "cvt_task.h" #include "PoolModel.h" #include "ExportTableModel.h" @@ -203,9 +204,24 @@ class SCWind : public QMainWindow { SlopeCraft::deleter> convert_image(int idx) noexcept; + [[nodiscard]] std::unique_ptr + convert_image(const cvt_task&) noexcept; + + [[nodiscard]] const SlopeCraft::converted_image& convert_if_need( + cvt_task&) noexcept; + + [[nodiscard]] std::tuple + convert_and_build_if_need(cvt_task&) noexcept; + [[nodiscard]] std::unique_ptr build_3D(const SlopeCraft::converted_image&) noexcept; + std::tuple + load_selected_3D() noexcept; + [[deprecated]] void kernel_set_image(int idx) noexcept; [[deprecated]] void kernel_convert_image() noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index aa0fdf87..8aa3eda9 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "PreviewWind.h" #include "AiCvterParameterDialog.h" #include "VersionDialog.h" @@ -410,99 +411,93 @@ void SCWind::on_pb_build3d_clicked() noexcept { } void SCWind::on_pb_preview_materials_clicked() noexcept { + auto [cvted_img, structure_3D] = this->load_selected_3D(); + if (cvted_img == nullptr || structure_3D == nullptr) { + return; + } + + PreviewWind *pw = new PreviewWind{this}; + + pw->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); + pw->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); + // bb->setAttribute(Qt::WidgetAttribute::WA_NativeWindow, true); + pw->setWindowFlag(Qt::WindowType::Window, true); + + // connect(this, &VCWind::signal_allowed_colorset_changed, pw, + // &QWidget::deleteLater); + + pw->show(); + + pw->setup_data(*this->current_color_table(), *structure_3D); +} + +std::tuple +SCWind::load_selected_3D() noexcept { +#warning "TODO: Move this function into SCWind.cpp" auto taskp = this->selected_export_task(); if (taskp == nullptr) { QMessageBox::warning(this, tr("未选择图像"), tr("请在左侧任务池选择一个图像")); - return; + return {nullptr, nullptr}; } assert(taskp != nullptr); cvt_task &task = *taskp; const ptrdiff_t index = &task - this->tasks.data(); assert(index >= 0 && index < ptrdiff_t(this->tasks.size())); - if (!task.is_converted()) [[unlikely]] { + if (!task.is_converted_with(this->current_color_table(), + this->current_convert_option())) { QMessageBox::warning(this, tr("该图像尚未被转化"), tr("必须先转化一个图像,然后再为它构建三维结构")); - return; + return {nullptr, nullptr}; } QString errtitle; QString errmsg; - this->kernel_set_image(index); // try to load cache - [this, &errtitle, &errmsg]() { - if (this->kernel->queryStep() >= SCL_step::builded) { - return; - } - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { + auto [cvted_img, structure_3D] = + [this, &task, &errtitle, + &errmsg]() -> std::pair { + auto it = task.converted_images.find(convert_input{ + this->current_color_table(), this->current_convert_option()}); + if (it == task.converted_images.end()) { errtitle = tr("该图像尚未被转化"); errmsg = tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" "新转化该图像。"); - return; + return {nullptr, nullptr}; } - if (!this->kernel->loadBuildCache(this->current_build_option())) { + auto str_3D = it->second.load_build_cache( + *this->current_color_table(), *it->second.converted_image, + this->current_build_option(), this->cache_root_dir()); + + if (str_3D == nullptr) { errtitle = tr("尚未构建三维结构"); errmsg = tr( "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + return {it->second.converted_image.get(), nullptr}; } + return {it->second.converted_image.get(), str_3D}; }(); if (!errtitle.isEmpty()) { QMessageBox::warning(this, errtitle, errmsg); - return; + return {nullptr, nullptr}; } - PreviewWind *pw = new PreviewWind{this}; - - pw->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); - pw->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); - // bb->setAttribute(Qt::WidgetAttribute::WA_NativeWindow, true); - pw->setWindowFlag(Qt::WindowType::Window, true); - - // connect(this, &VCWind::signal_allowed_colorset_changed, pw, - // &QWidget::deleteLater); - - pw->show(); - - pw->setup_data(this->kernel); + return {cvted_img, structure_3D}; } void SCWind::on_pb_preview_compress_effect_clicked() noexcept { - auto sel = this->selected_export_task(); - if (sel == nullptr) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个图像")); - return; - } - QString errtitle{""}, errmsg{""}; - if (!sel->is_built()) { - errtitle = tr("尚未构建三维结构"); - errmsg = - tr("在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" - "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); - } - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - errtitle = tr("该图像尚未被转化"); - errmsg = - tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" - "新转化该图像。"); - } - if (!this->kernel->loadBuildCache(this->current_build_option())) { - errtitle = tr("尚未构建三维结构"); - errmsg = - tr("在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" - "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); - } - if (!errtitle.isEmpty()) { - QMessageBox::warning(this, errtitle, errmsg); + auto [cvted_img, structure_3D] = this->load_selected_3D(); + if (cvted_img == nullptr || structure_3D == nullptr) { return; } - CompressEffectViewer *cev = new CompressEffectViewer{this}; + CompressEffectViewer *cev = + new CompressEffectViewer{this, *cvted_img, *structure_3D}; cev->setAttribute(Qt::WidgetAttribute::WA_DeleteOnClose, true); cev->setWindowFlag(Qt::WindowType::Window, true); @@ -625,30 +620,7 @@ void SCWind::on_pb_export_all_clicked() noexcept { } for (auto taskp : tasks_to_export) { - auto set_img_and_convert = [this, taskp]() { - this->kernel_set_image(taskp - this->tasks.data()); - this->kernel_convert_image(); - taskp->set_converted(); - }; - - // this step make sure the image is converted in kernel - if (!taskp->is_converted) { - set_img_and_convert(); - } else { - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - set_img_and_convert(); - } - } - - if (!taskp->is_built) { - this->kernel_build_3d(); - } else { - if (!this->kernel->loadBuildCache(this->current_build_option())) { - this->kernel_build_3d(); - } - } - taskp->set_built(); + auto [cvted, str3D] = this->convert_and_build_if_need(*taskp); const std::string export_name = get_export_name(*taskp).toLocal8Bit().data(); @@ -667,23 +639,24 @@ void SCWind::on_pb_export_all_clicked() noexcept { switch (export_type) { case export_type::litematica: - if (!this->kernel->exportAsLitematic(export_name.c_str(), opt_lite)) { + if (!str3D.export_litematica(export_name.c_str(), opt_lite)) { SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; } break; case export_type::vanilla_structure: - if (!this->kernel->exportAsStructure(export_name.c_str(), opt_nbt)) { + if (!str3D.export_vanilla_structure(export_name.c_str(), opt_nbt)) { SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; } break; case export_type::WE_schem: - if (!this->kernel->exportAsWESchem(export_name.c_str(), opt_WE)) { + if (!str3D.export_WE_schem(export_name.c_str(), opt_WE)) { SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; } break; case export_type::flat_diagram: - if (!this->kernel->exportAsFlatDiagram(export_name.c_str(), opt_fd)) { + if (!str3D.export_flat_diagram(export_name.c_str(), + *this->current_color_table(), opt_fd)) { SC_PRIVATE_MARCO_PROCESS_EXPORT_ERROR_on_pb_export_all_clicked; } break; @@ -712,7 +685,7 @@ void SCWind::on_pb_export_file_clicked() noexcept { to_be_replaced.reserve(4096); const int seq_last = - map_range_at_index(this->tasks, seq_first, this->tasks.size() - 1).last; + this->tasks.map_range_of(seq_first, this->tasks.size() - 1).last; for (int seq = seq_first; seq <= seq_last; seq++) { QString filename = map_data_filename(dir, seq); @@ -740,25 +713,27 @@ void SCWind::on_pb_export_file_clicked() noexcept { } } + size_t fail_count = 0; + QString fail_tasks = ""; for (int idx = 0; idx < int(this->tasks.size()); idx++) { auto &task = this->tasks.at(idx); - this->kernel_set_image(idx); - bool need_to_convert{true}; - if (task.is_converted()) { - if (this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - need_to_convert = false; - } - } - - if (need_to_convert) { - this->kernel_convert_image(); - } - - const int cur_seq_beg = - map_range_at_index(this->tasks, seq_first, idx).first; + auto &cvted_img = this->convert_if_need(task); + // this->kernel_set_image(idx); + // bool need_to_convert{true}; + // if (task.is_converted()) { + // if (this->kernel->loadConvertCache(this->selected_algo(), + // this->is_dither_selected())) { + // need_to_convert = false; + // } + // } + // + // if (need_to_convert) { + // this->kernel_convert_image(); + // } + // + const int cur_seq_beg = this->tasks.map_range_of(seq_first, idx).last; const auto dir_name = dir.toLocal8Bit(); - + // const SlopeCraft::map_data_file_options option{ .caller_api_version = SC_VERSION_U64, .folder_path = dir_name.data(), @@ -766,7 +741,17 @@ void SCWind::on_pb_export_file_clicked() noexcept { .progress = progress_callback(this->ui->pbar_export), .ui = this->ui_callbacks(), }; - const bool ok = task.converted_img->export_map_data(option); + const bool ok = cvted_img.export_map_data(option); + if (!ok) { + fail_count++; + fail_tasks.append(task.filename); + fail_tasks.push_back('\n'); + } + } + + if (fail_count > 0) { + QMessageBox::warning(this, tr("%1 个图片导出失败").arg(fail_count), + tr("导出失败的图片依次为:\n%1").arg(fail_tasks)); } } @@ -937,10 +922,10 @@ void SCWind::on_ac_get_current_colorlist_triggered() noexcept { map(reinterpret_cast(img.scanLine(0)), row_pixels, col_pixels); */ - uint32_t argb_colors[256]; - uint8_t map_colors[256]; - const int available_colors = kernel->getColorCount(); - kernel->getAvailableColors(argb_colors, map_colors); + // uint32_t argb_colors[256]; + // uint8_t map_colors[256]; + const auto color_ptrs = this->current_color_table()->colors(); + const int available_colors = color_ptrs.num_colors; for (int cidx = 0; cidx < available_colors; cidx++) { /* @@ -949,7 +934,13 @@ void SCWind::on_ac_get_current_colorlist_triggered() noexcept { const int pixel_row = basecolor / basecolors_per_col; const int pixel_col = (basecolor % basecolors_per_col) * 4 + shade; */ - img_data[map_colors[cidx]] = argb_colors[cidx]; + const uint32_t argb = + QColor{static_cast(color_ptrs.r_data[cidx] * 255), + static_cast(color_ptrs.g_data[cidx] * 255), + static_cast(color_ptrs.b_data[cidx] * 255)} + .rgb(); + + img_data[color_ptrs.map_data[cidx]] = argb; // map(map_colors[cidx]) = argb_colors[cidx]; } @@ -960,10 +951,6 @@ void SCWind::on_ac_get_current_colorlist_triggered() noexcept { } void SCWind::on_ac_test_blocklist_triggered() noexcept { - if (this->kernel->queryStep() < SCL_step::wait4Image) { - this->kernel_set_type(); - } - static QString prev_dir; QString filename = QFileDialog::getSaveFileName(this, tr("保存测试文件"), prev_dir, "*.nbt"); From da0b35ba93d26049960ee00b2698bfba27599fb6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 24 Apr 2024 22:33:27 +0800 Subject: [PATCH 0810/1123] reimplement generating test schematic Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 5 ++- SlopeCraftL/SlopeCraftL.h | 4 ++ SlopeCraftL/color_table.cpp | 73 +++++++++++++++++++++++++++++++++++++ SlopeCraftL/color_table.h | 12 ++++++ 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 8aa3eda9..fb424b04 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -974,7 +974,7 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { std::string err; err.resize(4096); - SlopeCraft::string_deliver sd{err.data(), err.size()}; + auto sd = SlopeCraft::string_deliver::from_string(err); SlopeCraft::test_blocklist_options opt; opt.block_count = blks.size(); @@ -982,7 +982,8 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { opt.basecolors = basecolors.data(); opt.err = &sd; - if (!this->kernel->makeTests(filename.toLocal8Bit().data(), opt)) { + if (!this->current_color_table()->generate_test_schematic( + filename.toLocal8Bit().data(), opt)) { QString qerr = QString::fromUtf8(err.data()); QMessageBox::warning(this, tr("输出测试文件失败"), tr("保存测试文件 %1 时出现错误。详细信息:\n%2") diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 9d0dd134..2d7dbc45 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -352,6 +352,10 @@ class color_table { virtual void stat_blocks(const structure_3D &, size_t buffer[64]) const noexcept = 0; + + [[nodiscard]] virtual bool generate_test_schematic( + const char *filename, + const test_blocklist_options &option) const noexcept = 0; }; class converted_image { diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 0ecee7a6..00d6513b 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -357,6 +357,79 @@ void color_table_impl::stat_blocks(const structure_3D &s, } } +std::string color_table_impl::impl_generate_test_schematic( + std::string_view filename, + const test_blocklist_options &option) const noexcept { + if (!filename.ends_with(".nbt")) { + return "File name should ends with \".nbt\""; + } + libSchem::Schem test; + test.set_MC_major_version_number(this->mc_version_); + test.set_MC_version_number( + MCDataVersion::suggested_version(this->mc_version_)); + // const simpleBlock ** realSrc=(const simpleBlock **)src; + std::vector realSrc; + std::vector realBaseColor; + realSrc.clear(); + realBaseColor.clear(); + for (size_t idx = 0; idx < option.block_count; idx++) { + if (option.block_ptrs[idx]->getVersion() > (int)this->mc_version_) { + continue; + } + realSrc.emplace_back(static_cast(option.block_ptrs[idx])); + realBaseColor.emplace_back(option.basecolors[idx]); + } + + std::vector> block_counter; + block_counter.resize(64); + + for (uint32_t idx = 0; idx < realSrc.size(); idx++) { + block_counter[realBaseColor[idx]].push_back(idx); + } + + { + std::vector ids; + ids.reserve(realSrc.size() + 1); + ids.emplace_back("minecraft:air"); + for (auto i : realSrc) { + ids.emplace_back(i->idForVersion(this->mc_version_)); + } + + test.set_block_id(ids.data(), ids.size()); + } + + int xSize = 0; + constexpr int zSize = 64, ySize = 2; + for (const auto &it : block_counter) { + xSize = std::max(size_t(xSize), it.size()); + } + test.resize(xSize + 1, ySize, zSize); + test.set_zero(); + + for (uint8_t base = 0; base < 64; base++) { + for (uint32_t idx = 0; idx < block_counter[base].size(); idx++) { + int xPos = idx; + int yPos = 0; + int zPos = base; + + test(xPos, yPos, zPos) = block_counter[base][idx] + 1; + } + test(block_counter[base].size(), 1, base) = 1; // glass block + } + + SCL_errorFlag err; + std::string detail; + const bool success = test.export_structure(filename, true, &err, &detail); + + if (!success) { + return fmt::format( + "Failed to export structure file {}, error code = {}, detail: {}", + filename, int(err), detail); + } else { + return {}; + } +} + std::array LUT_map_color_to_ARGB() noexcept { const auto &basic = *SlopeCraft::basic_colorset; std::array ret; diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 9c4af611..0ba13274 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -121,6 +121,18 @@ class color_table_impl : public SlopeCraft::color_table { void stat_blocks(const structure_3D &s, size_t buffer[64]) const noexcept final; + + bool generate_test_schematic( + const char *filename, + const test_blocklist_options &option) const noexcept final { + auto err = this->impl_generate_test_schematic(filename, option); + write_to_sd(option.err, err); + return err.empty(); + } + + std::string impl_generate_test_schematic( + std::string_view filename, + const test_blocklist_options &option) const noexcept; }; [[nodiscard]] std::array LUT_map_color_to_ARGB() noexcept; From dfe96b4e61785226c65c1229723d945d1b8e4e1b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 25 Apr 2024 14:33:26 +0800 Subject: [PATCH 0811/1123] fix SlopeCraft build Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 188 +++++++++--------- SlopeCraft/SCWind.h | 19 +- SlopeCraft/SCWind_slots.cpp | 6 +- SlopeCraft/cvt_task.h | 51 ++++- SlopeCraftL/SlopeCraftL.cpp | 12 +- SlopeCraftL/SlopeCraftL.h | 2 + SlopeCraftL/structure_3D.cpp | 23 +++ SlopeCraftL/structure_3D.h | 2 + utilities/BlockListManager/BlockListManager.h | 4 +- 9 files changed, 185 insertions(+), 122 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 36e6bd39..f0f99d83 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -281,6 +281,7 @@ SCL_gameVersion SCWind::selected_version() const noexcept { } assert(false); + abort(); // return SCL_gameVersion::ANCIENT; } @@ -698,7 +699,7 @@ SCWind::convert_and_build_if_need(cvt_task &task) noexcept { task.converted_images.at({table, this->current_convert_option()}); const auto build_opt = this->current_build_option(); - if (auto str_3D = cvt_result.load_build_cache(*table, cvted, build_opt, + if (auto str_3D = cvt_result.load_build_cache(*table, build_opt, this->cache_root_dir())) { // The 3D structure is built, it exists in memory or can be loaded return {cvted, *str_3D}; @@ -711,29 +712,38 @@ SCWind::convert_and_build_if_need(cvt_task &task) noexcept { return {cvted, *ptr}; } -void SCWind::kernel_make_cvt_cache() noexcept { - std::string err; - err.resize(4096); - SlopeCraft::string_deliver sd{err.data(), err.size()}; - - if (!this->kernel->saveConvertCache(sd)) { - QString qerr = QString::fromUtf8(sd.data); - QMessageBox::warning(this, tr("缓存失败"), - tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); - } -} - -QImage SCWind::get_converted_image_from_kernel() const noexcept { - assert(this->kernel->queryStep() >= SCL_step::converted); - - const int rows = this->kernel->getImageRows(); - const int cols = this->kernel->getImageCols(); - - QImage img{cols, rows, QImage::Format_ARGB32}; +// void SCWind::kernel_make_cvt_cache() noexcept { +// std::string err; +// err.resize(4096); +// SlopeCraft::string_deliver sd{err.data(), err.size()}; +// +// if (!this->kernel->saveConvertCache(sd)) { +// QString qerr = QString::fromUtf8(sd.data); +// QMessageBox::warning(this, tr("缓存失败"), +// tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); +// } +// } - this->kernel->getConvertedImage(nullptr, nullptr, (uint32_t *)img.scanLine(0), - false); +// QImage SCWind::get_converted_image_from_kernel() const noexcept { +// assert(this->kernel->queryStep() >= SCL_step::converted); +// +// const int rows = this->kernel->getImageRows(); +// const int cols = this->kernel->getImageCols(); +// +// QImage img{cols, rows, QImage::Format_ARGB32}; +// +// this->kernel->getConvertedImage(nullptr, nullptr, (uint32_t +// *)img.scanLine(0), +// false); +// +// return img; +// } +QImage get_converted_image(const SlopeCraft::converted_image &cvted) noexcept { + QImage img{ + QSize{static_cast(cvted.cols()), static_cast(cvted.rows())}, + QImage::Format::Format_ARGB32}; + cvted.get_original_image(reinterpret_cast(img.scanLine(0))); return img; } @@ -752,28 +762,24 @@ void SCWind::refresh_current_cvt_display( auto &task = this->tasks[selected_idx.value()]; - // if the image is already - if (task.converted_img) { - QImage img{QSize{static_cast(task.converted_img->cols()), - static_cast(task.converted_img->rows())}, - QImage::Format::Format_ARGB32}; - task.converted_img->get_original_image( - reinterpret_cast(img.scanLine(0))); + auto it = task.converted_images.find( + {this->current_color_table(), this->current_convert_option()}); + if (it != task.converted_images.end() && + it->second.converted_image != nullptr) { this->ui->lb_cvted_image->setPixmap( - QPixmap::fromImage(this->get_converted_image_from_kernel())); - return; + QPixmap::fromImage(get_converted_image(*it->second.converted_image))); } -#warning "TODO: Load cache here" + // #warning "TODO: Load cache here" this->ui->lb_cvted_image->setPixmap({}); } -void SCWind::mark_all_task_unconverted() noexcept { - for (auto &task : this->tasks) { - task.converted_img = nullptr; - task.structure = nullptr; - } -} +// void SCWind::mark_all_task_unconverted() noexcept { +// for (auto &task : this->tasks) { +// task.converted_img = nullptr; +// task.structure = nullptr; +// } +// } void SCWind::when_algo_btn_clicked() noexcept { this->cvt_pool_model->refresh(); @@ -784,31 +790,30 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { assert(idx >= 0); assert(idx < (int)this->tasks.size()); - bool have_image_cvted{false}; - - this->kernel_set_image(idx); - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { + auto &task = this->tasks[idx]; + auto cvted = task.get_converted_image(this->current_color_table(), + this->current_convert_option()); + if (cvted == nullptr) { const auto ret = QMessageBox::warning( this, tr("无法保存第%1个转化后图像").arg(idx + 1), tr("该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。"), QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ignore}); if (ret == QMessageBox::StandardButton::Ok) { - this->kernel_convert_image(); - this->kernel_make_cvt_cache(); - this->tasks[idx].set_converted(); - have_image_cvted = true; + auto cvted_uptr = this->convert_image(task); + task.set_converted(this->current_color_table(), + this->current_convert_option(), std::move(cvted_uptr)); + cvted = task.get_converted_image(this->current_color_table(), + this->current_convert_option()); } else { return; } } + assert(cvted != nullptr); - if (have_image_cvted) { - emit this->image_changed(); - } + auto img = get_converted_image(*cvted); + bool ok = img.save(filename); - bool ok = this->get_converted_image_from_kernel().save(filename); if (!ok) { QMessageBox::warning( this, tr("保存图像失败"), @@ -818,67 +823,56 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { } } -void SCWind::kernel_build_3d() noexcept { - if (!this->kernel->build(this->current_build_option())) { - QMessageBox::warning(this, tr("构建三维结构失败"), - tr("构建三维结构时,出现错误。可能是因为尝试跳步。")); - return; - } -} +// void SCWind::kernel_build_3d() noexcept { +// if (!this->kernel->build(this->current_build_option())) { +// QMessageBox::warning(this, tr("构建三维结构失败"), +// tr("构建三维结构时,出现错误。可能是因为尝试跳步。")); +// return; +// } +// } void SCWind::refresh_current_build_display( - std::optional taskp, bool is_image_built_in_kernel) noexcept { + cvt_task *taskp, bool is_image_built_in_kernel) noexcept { this->ui->lb_show_3dsize->setText(tr("大小:")); this->ui->lb_show_block_count->setText(tr("方块数量:")); - if (!taskp.has_value()) { + if (taskp == nullptr) { return; } - int x{-1}, y{-1}, z{-1}; - { - if (is_image_built_in_kernel) { - // the caller garentee that the image is built in kernel - } else { - if (taskp.value()->is_built()) { - // try to load convert cache - if (!this->kernel->loadConvertCache(this->selected_algo(), - this->is_dither_selected())) { - taskp.value()->set_unconverted(); - return; - } - // try to load build cache - if (!this->kernel->loadBuildCache(this->current_build_option())) { - taskp.value()->set_unbuilt(); - return; - } - } else { - return; - } - } + auto &task = *taskp; + const auto cvted_it = task.get_convert_result(this->current_color_table(), + this->current_convert_option()); + if (cvted_it != task.converted_images.end()) { + return; } - this->kernel->get3DSize(&x, &y, &z); - const int64_t block_count = this->kernel->getBlockCounts(); + if (auto str_3D = cvted_it->second.load_build_cache( + *this->current_color_table(), this->current_build_option(), + this->cache_root_dir())) { + const auto x = str_3D->shape_x(), y = str_3D->shape_y(), + z = str_3D->shape_z(); - this->ui->lb_show_3dsize->setText( - tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); - this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); + const auto block_count = str_3D->block_count(); + this->ui->lb_show_3dsize->setText( + tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); + this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); + } } void SCWind::when_export_pool_selectionChanged() noexcept { this->refresh_current_build_display(this->selected_export_task()); } -void SCWind::kernel_make_build_cache() noexcept { - std::string err; - err.resize(4096); - SlopeCraft::string_deliver sd{err.data(), err.size()}; - - if (!this->kernel->saveBuildCache(sd)) { - QString qerr = QString::fromUtf8(sd.data); - QMessageBox::warning(this, tr("缓存失败"), - tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); - } -} +// void SCWind::kernel_make_build_cache() noexcept { +// std::string err; +// err.resize(4096); +// SlopeCraft::string_deliver sd{err.data(), err.size()}; +// +// if (!this->kernel->saveBuildCache(sd)) { +// QString qerr = QString::fromUtf8(sd.data); +// QMessageBox::warning(this, tr("缓存失败"), +// tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); +// } +// } QString extension_of_export_type(SCWind::export_type et) noexcept { switch (et) { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index de961aca..901eb830 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -25,6 +25,9 @@ SlopeCraft::progress_callbacks progress_callback(QProgressBar* bar) noexcept; SlopeCraft::const_image_reference wrap_image(const QImage& img) noexcept; +[[nodiscard]] QImage get_converted_image( + const SlopeCraft::converted_image&) noexcept; + class SCWind : public QMainWindow { Q_OBJECT private: @@ -222,20 +225,20 @@ class SCWind : public QMainWindow { const SlopeCraft::structure_3D*> load_selected_3D() noexcept; - [[deprecated]] void kernel_set_image(int idx) noexcept; - [[deprecated]] void kernel_convert_image() noexcept; - - [[deprecated]] void kernel_make_cvt_cache() noexcept; + // [[deprecated]] void kernel_set_image(int idx) noexcept; + // [[deprecated]] void kernel_convert_image() noexcept; + // + // [[deprecated]] void kernel_make_cvt_cache() noexcept; - [[deprecated]] void kernel_build_3d() noexcept; - [[deprecated]] void kernel_make_build_cache() noexcept; + // [[deprecated]] void kernel_build_3d() noexcept; + // [[deprecated]] void kernel_make_build_cache() noexcept; void refresh_current_cvt_display(std::optional idx) noexcept; void refresh_current_cvt_display() noexcept { this->refresh_current_cvt_display(this->selected_cvt_task_idx()); } - [[deprecated]] QImage get_converted_image_from_kernel() const noexcept; + // [[deprecated]] QImage get_converted_image_from_kernel() const noexcept; void refresh_current_build_display(cvt_task* taskp, bool is_image_built_in_kernel) noexcept; @@ -246,7 +249,7 @@ class SCWind : public QMainWindow { this->refresh_current_build_display(this->selected_export_task()); } - void mark_all_task_unconverted() noexcept; + // void mark_all_task_unconverted() noexcept; void export_current_cvted_image(int idx, QString filename) noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index fb424b04..fe5429dc 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -468,9 +468,9 @@ SCWind::load_selected_3D() noexcept { "新转化该图像。"); return {nullptr, nullptr}; } - auto str_3D = it->second.load_build_cache( - *this->current_color_table(), *it->second.converted_image, - this->current_build_option(), this->cache_root_dir()); + auto str_3D = it->second.load_build_cache(*this->current_color_table(), + this->current_build_option(), + this->cache_root_dir()); if (str_3D == nullptr) { errtitle = tr("尚未构建三维结构"); diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 6556e3d5..2ce396f2 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -8,6 +8,12 @@ #include struct convert_input { + convert_input() = default; + convert_input(convert_input&&) = default; + convert_input(const SlopeCraft::color_table* t, + const SlopeCraft::convert_option& o) + : table{t}, option{o} {} + const SlopeCraft::color_table* table{nullptr}; SlopeCraft::convert_option option; }; @@ -129,7 +135,6 @@ struct convert_result { } void cache_structure(const SlopeCraft::color_table& table, - const SlopeCraft::converted_image& cvted, const SlopeCraft::build_options& opt, const QString& cache_root_dir) noexcept { auto it = this->built_structures.find(opt); @@ -139,8 +144,9 @@ struct convert_result { if (it->second == nullptr) { return; } - const bool ok = table.save_build_cache( - cvted, opt, *it->second, cache_root_dir.toLocal8Bit().data(), nullptr); + const bool ok = + table.save_build_cache(*this->converted_image, opt, *it->second, + cache_root_dir.toLocal8Bit().data(), nullptr); if (ok) { it->second.reset(); } @@ -149,7 +155,6 @@ struct convert_result { const SlopeCraft::structure_3D* load_build_cache( const SlopeCraft::color_table& table, - const SlopeCraft::converted_image& cvted, const SlopeCraft::build_options& opt, const QString& cache_root_dir) noexcept { auto it = this->built_structures.find(opt); @@ -162,8 +167,9 @@ struct convert_result { } // the structure is cached - SlopeCraft::structure_3D* p = table.load_build_cache( - cvted, opt, cache_root_dir.toLocal8Bit().data(), nullptr); + SlopeCraft::structure_3D* p = + table.load_build_cache(*this->converted_image, opt, + cache_root_dir.toLocal8Bit().data(), nullptr); if (p == nullptr) { // failed to load cache return nullptr; } @@ -187,12 +193,17 @@ struct convert_result { }; struct cvt_task { + cvt_task() = default; + cvt_task(cvt_task&&) = default; + QString filename{""}; QImage original_image; std::unordered_map converted_images; + cvt_task& operator=(cvt_task&&) = default; + // std::unique_ptr // structure; @@ -202,6 +213,30 @@ struct cvt_task { return this->converted_images.contains(convert_input{table, option}); } + [[nodiscard]] std::unordered_map::iterator + get_convert_result(const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& option) noexcept { + return this->converted_images.find({table, option}); + } + + [[nodiscard]] std::unordered_map::const_iterator + get_convert_result(const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& option) const noexcept { + return this->converted_images.find({table, option}); + } + + [[nodiscard]] const SlopeCraft::converted_image* get_converted_image( + const SlopeCraft::color_table* table, + const SlopeCraft::convert_option& option) const noexcept { + auto it = this->get_convert_result(table, option); + if (it == this->converted_images.cend()) { + return nullptr; + } + return it->second.converted_image.get(); + } + void set_converted( const SlopeCraft::color_table* table, SlopeCraft::convert_option option, std::unique_ptr @@ -211,11 +246,11 @@ struct cvt_task { } option.ui = {}; option.progress = {}; - auto cvt_input = convert_input{table, option}; + convert_input cvt_input = convert_input{table, option}; auto it = this->converted_images.find(cvt_input); if (it == this->converted_images.end()) { this->converted_images.emplace( - cvt_input, + std::move(cvt_input), convert_result{.converted_image = std::move(converted_image), .built_structures = {}}); return; diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 9515d16d..81528950 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -288,10 +288,10 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { } extern "C" { -SCL_EXPORT mc_block_interface *SCL_createBlock() { return new mc_block; } -SCL_EXPORT void SCL_destroyBlock(mc_block_interface *b) { delete b; } +SCL_EXPORT mc_block_interface *SCL_create_block() { return new mc_block; } +SCL_EXPORT void SCL_destroy_block(mc_block_interface *b) { delete b; } -SCL_EXPORT block_list_interface *SCL_createBlockList( +SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option) { auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); @@ -304,7 +304,9 @@ SCL_EXPORT block_list_interface *SCL_createBlockList( return res.value(); } -SCL_EXPORT void SCL_destroyBlockList(block_list_interface *) {} +SCL_EXPORT void SCL_destroy_block_list(block_list_interface *bli) { + delete bli; +} SCL_EXPORT GA_converter_option *SCL_createAiCvterOpt() { return new GA_converter_option; @@ -350,6 +352,8 @@ double SCL_EXPORT SCL_getMutationProb(const GA_converter_option *a) { // TokiSlopeCraft::getColorMapPtrs(rdata, gdata, bdata, mapdata, num); // } +SCL_EXPORT const char *SCL_getSCLVersion() { return SC_VERSION_STR; } + SCL_EXPORT SCL_gameVersion SCL_basecolor_version(uint8_t basecolor) { if (basecolor <= 51) { return SCL_gameVersion::ANCIENT; diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 2d7dbc45..92724e01 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -406,6 +406,8 @@ class structure_3D { [[nodiscard]] virtual bool export_flat_diagram( const char *filename, const color_table &table, const flag_diagram_options &option) const noexcept = 0; + + [[nodiscard]] virtual uint64_t block_count() const noexcept = 0; }; } // namespace SlopeCraft diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index d73f9d67..db45de2b 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -428,4 +428,27 @@ tl::expected structure_3D_impl::load_cache( } return ret; +} + +uint64_t structure_3D_impl::block_count() const noexcept { + std::vector LUT_is_air; + LUT_is_air.reserve(this->schem.palette_size()); + for (auto [idx, id] : this->schem.palette() | std::ranges::views::enumerate) { + if (id == "air" || id == "minecraft:air") { + LUT_is_air[idx] = true; + } else { + LUT_is_air[idx] = false; + } + } + + uint64_t counter = 0; + for (int64_t i = 0; i < this->schem.size(); i++) { + const auto cur_blk_id = this->schem(i); + if (cur_blk_id >= LUT_is_air.size()) [[unlikely]] { + counter++; + continue; + } + counter += LUT_is_air[cur_blk_id]; + } + return counter; } \ No newline at end of file diff --git a/SlopeCraftL/structure_3D.h b/SlopeCraftL/structure_3D.h index 563a8dad..672c108d 100644 --- a/SlopeCraftL/structure_3D.h +++ b/SlopeCraftL/structure_3D.h @@ -52,6 +52,8 @@ class structure_3D_impl : public structure_3D { [[nodiscard]] static tl::expected load_cache( const std::filesystem::path &file) noexcept; + uint64_t block_count() const noexcept final; + template void load(archive &ar) { ar(this->map_color); diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index eca65917..215dd1c6 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -31,7 +31,7 @@ class BlockListDeleter { struct selection { std::vector ids; - + [[nodiscard]] bool operator==(const selection &b) const noexcept { if (this->ids.size() != b.ids.size()) { return false; @@ -47,7 +47,7 @@ struct selection { template <> struct std::hash { - static inline uint64_t operator()(const selection &s) noexcept; + static uint64_t operator()(const selection &s) noexcept; }; class BlockListManager : public QWidget { From 4fef3769210e30386b9923c74199b627f4206a4c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 25 Apr 2024 15:52:27 +0800 Subject: [PATCH 0812/1123] fix block list loading in SC Signed-off-by: ToKiNoBug --- .../{BlockList.json => block_list.json} | 0 .../{BlockList.json => block_list.json} | 0 SlopeCraft/CMakeLists.txt | 2 + SlopeCraft/SCWind.cpp | 60 ++++++++++--------- SlopeCraft/main.cpp | 8 ++- SlopeCraftL/CMakeLists.txt | 4 +- 6 files changed, 41 insertions(+), 33 deletions(-) rename Blocks/CustomBlocks/{BlockList.json => block_list.json} (100%) rename Blocks/FixedBlocks/{BlockList.json => block_list.json} (100%) diff --git a/Blocks/CustomBlocks/BlockList.json b/Blocks/CustomBlocks/block_list.json similarity index 100% rename from Blocks/CustomBlocks/BlockList.json rename to Blocks/CustomBlocks/block_list.json diff --git a/Blocks/FixedBlocks/BlockList.json b/Blocks/FixedBlocks/block_list.json similarity index 100% rename from Blocks/FixedBlocks/BlockList.json rename to Blocks/FixedBlocks/block_list.json diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index c822e992..c39960f7 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) find_package(magic_enum REQUIRED) +find_package(fmt REQUIRED) set(SlopeCraft_rc_files) @@ -81,6 +82,7 @@ target_link_libraries(SlopeCraft PRIVATE Qt6::Widgets Qt6::Network magic_enum::magic_enum + fmt::fmt SlopeCraftL AdaptiveLabel diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index f0f99d83..09a57847 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -37,6 +37,37 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { } } + // initialize blm + { + this->ui->blm->setup_basecolors(); + this->ui->blm->set_version_callback( + [this]() { return this->selected_version(); }); + + QDir::setCurrent(QCoreApplication::applicationDirPath()); + + this->ui->blm->add_blocklist( + QStringLiteral("%1/Blocks/FixedBlocks.zip") + .arg(QCoreApplication::applicationDirPath())); + this->ui->blm->add_blocklist( + QStringLiteral("%1/Blocks/CustomBlocks.zip") + .arg(QCoreApplication::applicationDirPath())); + + this->ui->blm->finish_blocklist(); + + for (auto btnp : this->version_buttons()) { + connect(btnp, &QRadioButton::toggled, this, + &SCWind::when_version_buttons_toggled); + } + + for (auto btnp : this->type_buttons()) { + connect(btnp, &QRadioButton::toggled, this, + &SCWind::when_type_buttons_toggled); + } + + connect(this->ui->blm, &BlockListManager::changed, this, + &SCWind::when_blocklist_changed); + } + // initialize cvt pool model { this->cvt_pool_model = new CvtPoolModel{this}; @@ -74,33 +105,6 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { &ExportTableModel::refresh); } - // initialize blm - { - this->ui->blm->setup_basecolors(); - this->ui->blm->set_version_callback( - [this]() { return this->selected_version(); }); - - QDir::setCurrent(QCoreApplication::applicationDirPath()); - - this->ui->blm->add_blocklist("./Blocks/FixedBlocks.zip"); - this->ui->blm->add_blocklist("./Blocks/CustomBlocks.zip"); - - this->ui->blm->finish_blocklist(); - - for (auto btnp : this->version_buttons()) { - connect(btnp, &QRadioButton::toggled, this, - &SCWind::when_version_buttons_toggled); - } - - for (auto btnp : this->type_buttons()) { - connect(btnp, &QRadioButton::toggled, this, - &SCWind::when_type_buttons_toggled); - } - - connect(this->ui->blm, &BlockListManager::changed, this, - &SCWind::when_blocklist_changed); - } - for (QRadioButton *rbp : this->export_type_buttons()) { connect(rbp, &QRadioButton::clicked, this, &SCWind::when_export_type_toggled); @@ -163,7 +167,7 @@ SlopeCraft::color_table *SCWind::current_color_table() noexcept { auto selection = this->ui->blm->current_selection(); { auto find = this->color_tables.find(selection); - if (find == this->color_tables.end()) { + if (find != this->color_tables.end()) { return find->second.get(); } } diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index 73384a19..cec2bba5 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -1,18 +1,20 @@ +#include +#include #include +#include #include "SCWind.h" #include "VersionDialog.h" -#include int main(int argc, char** argv) { QApplication qapp(argc, argv); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + SCWind wind; wind.show(); wind.setWindowTitle(SCWind::default_wind_title()); - QDir::setCurrent(QCoreApplication::applicationDirPath()); - bool is_language_ZH = QLocale::system().uiLanguages().contains("zh"); // this line is used to test the translation diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 677a01e6..df02a21f 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -130,8 +130,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") endif () function(SC_create_SCL_block_list src_dir archive_path) - if (NOT EXISTS "${src_dir}/BlockList.json") - message(FATAL_ERROR "${src_dir}/BlockList.json doesn't exist, block list json is missing") + if (NOT EXISTS "${src_dir}/block_list.json") + message(FATAL_ERROR "${src_dir}/block_list.json doesn't exist, block list json is missing") endif () cmake_path(GET archive_path PARENT_PATH archive_dir) From 0b3a04cc7e0368badf7acce60aaf0b42cb64ac08 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 26 Apr 2024 09:09:58 +0800 Subject: [PATCH 0813/1123] fix refreshing converted image Signed-off-by: ToKiNoBug --- SlopeCraft/PoolModel.cpp | 2 +- SlopeCraft/SCWind.cpp | 65 +++++++++++++++++++++++++++++++++++-- SlopeCraft/SCWind.h | 3 +- SlopeCraft/SCWind_slots.cpp | 59 --------------------------------- 4 files changed, 64 insertions(+), 65 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 3fd31096..bc473c11 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -6,7 +6,7 @@ #include PoolModel::PoolModel(SCWind* scw) - : QAbstractListModel(scw), pool{scw->get_tasks()}, scwind{scw} { + : QAbstractListModel(scw), pool{scw->tasks}, scwind{scw} { assert(scw != nullptr); } diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 09a57847..1ea42ef0 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -471,12 +471,12 @@ void SCWind::when_type_buttons_toggled() noexcept { } void SCWind::when_blocklist_changed() noexcept { - this->kernel_set_type(); + this->set_colorset(); this->ui->rb_preset_custom->setChecked(true); // this->ui->rb_preset_ } -void SCWind::kernel_set_type() noexcept { +void SCWind::set_colorset() noexcept { auto color_table = this->current_color_table(); const int num_colors = color_table->colors().num_colors; @@ -747,7 +747,7 @@ QImage get_converted_image(const SlopeCraft::converted_image &cvted) noexcept { QImage img{ QSize{static_cast(cvted.cols()), static_cast(cvted.rows())}, QImage::Format::Format_ARGB32}; - cvted.get_original_image(reinterpret_cast(img.scanLine(0))); + cvted.get_converted_image(reinterpret_cast(img.scanLine(0))); return img; } @@ -772,6 +772,7 @@ void SCWind::refresh_current_cvt_display( it->second.converted_image != nullptr) { this->ui->lb_cvted_image->setPixmap( QPixmap::fromImage(get_converted_image(*it->second.converted_image))); + return; } // #warning "TODO: Load cache here" @@ -1107,4 +1108,62 @@ QString SCWind::workStatus_to_string(::SCL_workStatus status) noexcept { } return {}; +} + +std::tuple +SCWind::load_selected_3D() noexcept { + auto taskp = this->selected_export_task(); + if (taskp == nullptr) { + QMessageBox::warning(this, tr("未选择图像"), + tr("请在左侧任务池选择一个图像")); + return {nullptr, nullptr}; + } + assert(taskp != nullptr); + + cvt_task &task = *taskp; + const ptrdiff_t index = &task - this->tasks.data(); + assert(index >= 0 && index < ptrdiff_t(this->tasks.size())); + if (!task.is_converted_with(this->current_color_table(), + this->current_convert_option())) { + QMessageBox::warning(this, tr("该图像尚未被转化"), + tr("必须先转化一个图像,然后再为它构建三维结构")); + return {nullptr, nullptr}; + } + QString errtitle; + QString errmsg; + // try to load cache + auto [cvted_img, structure_3D] = + [this, &task, &errtitle, + &errmsg]() -> std::pair { + auto it = task.converted_images.find(convert_input{ + this->current_color_table(), this->current_convert_option()}); + if (it == task.converted_images.end()) { + errtitle = tr("该图像尚未被转化"); + errmsg = + tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" + "新转化该图像。"); + return {nullptr, nullptr}; + } + auto str_3D = it->second.load_build_cache(*this->current_color_table(), + this->current_build_option(), + this->cache_root_dir()); + + if (str_3D == nullptr) { + errtitle = tr("尚未构建三维结构"); + errmsg = tr( + "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" + "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); + return {it->second.converted_image.get(), nullptr}; + } + return {it->second.converted_image.get(), str_3D}; + }(); + + if (!errtitle.isEmpty()) { + QMessageBox::warning(this, errtitle, errmsg); + return {nullptr, nullptr}; + } + + return {cvted_img, structure_3D}; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 901eb830..b22be00f 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -127,7 +127,6 @@ class SCWind : public QMainWindow { public: SlopeCraft::GA_converter_option GA_option{}; task_pool tasks; - [[deprecated]] task_pool& get_tasks() noexcept { return this->tasks; } QString cache_root_dir() const noexcept; SlopeCraft::color_table* current_color_table() noexcept; @@ -199,7 +198,7 @@ class SCWind : public QMainWindow { private: // kernel related functions - [[deprecated]] void kernel_set_type() noexcept; + void set_colorset() noexcept; void update_button_states() noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index fe5429dc..608eb197 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -431,65 +431,6 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { pw->setup_data(*this->current_color_table(), *structure_3D); } -std::tuple -SCWind::load_selected_3D() noexcept { -#warning "TODO: Move this function into SCWind.cpp" - auto taskp = this->selected_export_task(); - if (taskp == nullptr) { - QMessageBox::warning(this, tr("未选择图像"), - tr("请在左侧任务池选择一个图像")); - return {nullptr, nullptr}; - } - assert(taskp != nullptr); - - cvt_task &task = *taskp; - const ptrdiff_t index = &task - this->tasks.data(); - assert(index >= 0 && index < ptrdiff_t(this->tasks.size())); - if (!task.is_converted_with(this->current_color_table(), - this->current_convert_option())) { - QMessageBox::warning(this, tr("该图像尚未被转化"), - tr("必须先转化一个图像,然后再为它构建三维结构")); - return {nullptr, nullptr}; - } - QString errtitle; - QString errmsg; - // try to load cache - auto [cvted_img, structure_3D] = - [this, &task, &errtitle, - &errmsg]() -> std::pair { - auto it = task.converted_images.find(convert_input{ - this->current_color_table(), this->current_convert_option()}); - if (it == task.converted_images.end()) { - errtitle = tr("该图像尚未被转化"); - errmsg = - tr("可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重" - "新转化该图像。"); - return {nullptr, nullptr}; - } - auto str_3D = it->second.load_build_cache(*this->current_color_table(), - this->current_build_option(), - this->cache_root_dir()); - - if (str_3D == nullptr) { - errtitle = tr("尚未构建三维结构"); - errmsg = tr( - "在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你" - "在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。"); - return {it->second.converted_image.get(), nullptr}; - } - return {it->second.converted_image.get(), str_3D}; - }(); - - if (!errtitle.isEmpty()) { - QMessageBox::warning(this, errtitle, errmsg); - return {nullptr, nullptr}; - } - - return {cvted_img, structure_3D}; -} - void SCWind::on_pb_preview_compress_effect_clicked() noexcept { auto [cvted_img, structure_3D] = this->load_selected_3D(); if (cvted_img == nullptr || structure_3D == nullptr) { From 2ab3e493ca2ab82488ffb482476d22a49bcd8b08 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 26 Apr 2024 09:11:11 +0800 Subject: [PATCH 0814/1123] fix building 3D Signed-off-by: ToKiNoBug --- SlopeCraftL/converted_image.cpp | 6 +++--- SlopeCraftL/height_line.cpp | 5 ----- SlopeCraftL/height_line.h | 8 +++++--- SlopeCraftL/structure_3D.cpp | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index b77e20f2..2348c163 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -223,8 +223,8 @@ converted_image_impl::height_info(const build_options &option) const noexcept { Eigen::ArrayXXi base, high_map, low_map; base.setZero(this->rows(), this->cols()); - high_map.setZero(this->rows(), this->cols()); - low_map.setZero(this->rows(), this->cols()); + high_map.setZero(this->rows() + 1, this->cols()); + low_map.setZero(this->rows() + 1, this->cols()); std::unordered_map water_list; lossy_compressor compressor; @@ -258,7 +258,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); map_color.col(c) = temp; } - base.col(c) = HL.getBase(); + base.col(c) = HL.getBase().segment(1, base.rows()); high_map.col(c) = HL.getHighLine(); low_map.col(c) = HL.getLowLine(); diff --git a/SlopeCraftL/height_line.cpp b/SlopeCraftL/height_line.cpp index 85547143..ef6b8d0e 100644 --- a/SlopeCraftL/height_line.cpp +++ b/SlopeCraftL/height_line.cpp @@ -153,11 +153,6 @@ void height_line::updateWaterMap() { } } -const Eigen::ArrayXi &height_line::getHighLine() const { return HighLine; } -const Eigen::ArrayXi &height_line::getLowLine() const { return LowLine; } - -const Eigen::ArrayXi &height_line::getBase() const { return base; } - const std::map &height_line::getWaterMap() const { return waterMap; } diff --git a/SlopeCraftL/height_line.h b/SlopeCraftL/height_line.h index 0976b588..86ec7515 100644 --- a/SlopeCraftL/height_line.h +++ b/SlopeCraftL/height_line.h @@ -39,9 +39,11 @@ class height_line { void make(const Eigen::ArrayXi &mapColorCol, bool allowNaturalCompress); void updateWaterMap(); uint32_t maxHeight() const; - const Eigen::ArrayXi &getHighLine() const; - const Eigen::ArrayXi &getLowLine() const; - const Eigen::ArrayXi &getBase() const; + + const Eigen::ArrayXi &getHighLine() const noexcept { return HighLine; } + const Eigen::ArrayXi &getLowLine() const noexcept { return LowLine; } + + auto &getBase() const noexcept { return this->base; } const std::map &getWaterMap() const; EImage toImg() const; diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index db45de2b..1de611dd 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -49,7 +49,7 @@ std::optional structure_3D_impl::create( fixed_opt.main_progressbar.add(cvted.size()); } - Eigen::ArrayXi map_color, base_color, high_map, low_map; + Eigen::ArrayXXi map_color, base_color, high_map, low_map; std::unordered_map water_list; { auto opt = cvted.height_info(fixed_opt); From 52c3e6b6bd505332421f629a1b2984849d485b6f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 26 Apr 2024 09:20:58 +0800 Subject: [PATCH 0815/1123] fix previewing structures Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 1ea42ef0..6d1fe697 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -847,7 +847,7 @@ void SCWind::refresh_current_build_display( auto &task = *taskp; const auto cvted_it = task.get_convert_result(this->current_color_table(), this->current_convert_option()); - if (cvted_it != task.converted_images.end()) { + if (cvted_it == task.converted_images.end()) { return; } if (auto str_3D = cvted_it->second.load_build_cache( From c1100f7bf244d52e59feb17bd35639da71e53582 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 27 Apr 2024 22:24:58 +0800 Subject: [PATCH 0816/1123] fix building and previewing structures in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 15 +++++++-- SlopeCraftL/color_table.h | 3 +- SlopeCraftL/converted_image.cpp | 4 +-- SlopeCraftL/converted_image.h | 2 +- SlopeCraftL/structure_3D.cpp | 54 +++++++++++++++++++++------------ 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 00d6513b..a77ec7a2 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -137,9 +137,13 @@ structure_3D *color_table_impl::build( return nullptr; } -std::vector color_table_impl::block_id_list() const noexcept { +std::vector color_table_impl::block_id_list( + bool contain_air) const noexcept { std::vector dest; - dest.reserve(this->blocks.size()); + dest.reserve(this->blocks.size() + 1); + if (contain_air) { + dest.emplace_back("minecraft:air"); + } for (auto &blk : this->blocks) { dest.emplace_back(blk.id); } @@ -153,6 +157,7 @@ const mc_block *color_table_impl::find_block_for_index( } if (idx < (int)this->blocks.size()) { + // assert(this->blocks[idx].id == blkid); return &this->blocks[idx]; } @@ -341,8 +346,12 @@ void color_table_impl::stat_blocks(const structure_3D &s, const auto schem_stat = structure.schem.stat_blocks(); for (size_t schem_blk_id = 0; schem_blk_id < structure.schem.palette_size(); schem_blk_id++) { + if (schem_blk_id == 0) { // ignore air + continue; + } + assert(schem_blk_id > 0); const auto strid = structure.schem.palette()[schem_blk_id]; - const auto blkp = this->find_block_for_index(schem_blk_id, strid); + const auto blkp = this->find_block_for_index(schem_blk_id - 1, strid); if (blkp == nullptr) { std::cerr << fmt::format( "Failed to find \"{}\" in color_table, this type of block will not " diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index 0ba13274..b5117d2d 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -51,7 +51,8 @@ class color_table_impl : public SlopeCraft::color_table { [[nodiscard]] static std::optional create( const color_table_create_info &args) noexcept; - [[nodiscard]] std::vector block_id_list() const noexcept; + [[nodiscard]] std::vector block_id_list( + bool contain_air) const noexcept; [[nodiscard]] const mc_block *find_block_for_index( int index, std::string_view block_id) const noexcept; diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 2348c163..1b5fe987 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -222,7 +222,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { } Eigen::ArrayXXi base, high_map, low_map; - base.setZero(this->rows(), this->cols()); + base.setZero(this->rows() + 1, this->cols()); high_map.setZero(this->rows() + 1, this->cols()); low_map.setZero(this->rows() + 1, this->cols()); std::unordered_map water_list; @@ -258,7 +258,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); map_color.col(c) = temp; } - base.col(c) = HL.getBase().segment(1, base.rows()); + base.col(c) = HL.getBase(); high_map.col(c) = HL.getHighLine(); low_map.col(c) = HL.getLowLine(); diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index ebed97b3..3c9c1c41 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -45,7 +45,7 @@ class converted_image_impl : public converted_image { void get_converted_image(uint32_t *buffer) const noexcept final { this->converter.converted_image(buffer, nullptr, nullptr, false); } - + void get_compressed_image(const structure_3D &structure, uint32_t *buffer) const noexcept final; diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 1de611dd..d8f6843b 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -33,7 +33,7 @@ std::optional structure_3D_impl::create( ret.schem.set_MC_major_version_number(table.mc_version_); ret.schem.set_MC_version_number( MCDataVersion::suggested_version(table.mc_version_)); - auto id = table.block_id_list(); + auto id = table.block_id_list(true); ret.schem.set_block_id(id); } @@ -43,7 +43,7 @@ std::optional structure_3D_impl::create( fixed_opt.glass_method = glassBridgeSettings::noBridge; } fixed_opt.ui.report_working_status(workStatus::buidingHeighMap); - fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 0); + fixed_opt.main_progressbar.set_range(0, 10 * cvted.size(), 0); { std::unordered_map water_list; fixed_opt.main_progressbar.add(cvted.size()); @@ -62,6 +62,10 @@ std::optional structure_3D_impl::create( low_map = std::move(opt.value().low_map); water_list = std::move(opt.value().water_list); } + assert((high_map >= low_map).all()); + assert(low_map.minCoeff() == 0); + + // std::cout << base_color << std::endl; ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, 2 + cvted.rows()); ret.schem.set_zero(); @@ -71,9 +75,8 @@ std::optional structure_3D_impl::create( // 为了区分玻璃与空气,张量中存储的是 Base+1.所以元素为 1 对应着玻璃,0 // 对应空气 - for (auto it = water_list.begin(); it != water_list.end(); - it++) // 水柱周围的玻璃 - { + // 水柱周围的玻璃 + for (auto it = water_list.begin(); it != water_list.end(); it++) { const int x = it->first.col + 1; const int z = it->first.row; const int y = it->second.high_y; @@ -85,24 +88,35 @@ std::optional structure_3D_impl::create( ret.schem(x + 0, yDynamic, z - 1) = 1; ret.schem(x + 0, yDynamic, z + 1) = 1; } - if (yLow >= 1) ret.schem(x, yLow - 1, z) = 1; // 柱底玻璃 + if (yLow >= 1) { + ret.schem(x, yLow - 1, z) = 1; + } // 柱底玻璃 } fixed_opt.main_progressbar.add(cvted.size()); - for (uint32_t r = -1; r < cvted.rows(); r++) // 普通方块 - { - for (uint32_t c = 0; c < cvted.cols(); c++) { - if (base_color(r + 1, c) == 12 || base_color(r + 1, c) == 0) continue; + // fmt::println("{} rows, {} cols", cvted.rows(), cvted.cols()); + // Common blocks + for (int64_t r = -1; r < int64_t(cvted.rows()); r++) { + for (int64_t c = 0; c < int64_t(cvted.cols()); c++) { + // fmt::println("r = {}, c = {}", r, c); + const int cur_base_color = base_color(r + 1, c); + if (cur_base_color == 12 || cur_base_color == 0) { + // water or air + continue; + } const int x = c + 1; const int y = low_map(r + 1, c); const int z = r + 1; - if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) + if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) { ret.schem(x, y - 1, z) = 0 + 1; - if ((fixed_opt.fire_proof && - table.blocks[base_color(r + 1, c)].burnable) || - (fixed_opt.enderman_proof && - table.blocks[base_color(r + 1, c)].endermanPickable)) { + } + const bool fire_proof = + fixed_opt.fire_proof && table.blocks[base_color(r + 1, c)].burnable; + const bool enderman_proof = + fixed_opt.enderman_proof && + table.blocks[base_color(r + 1, c)].endermanPickable; + if (fire_proof || enderman_proof) { if (y >= 1 && ret.schem(x, y - 1, z) == 0) ret.schem(x, y - 1, z) = 0 + 1; if (x >= 1 && ret.schem(x - 1, y, z) == 0) @@ -117,7 +131,7 @@ std::optional structure_3D_impl::create( ret.schem(x, y, z + 1) = 0 + 1; } - ret.schem(x, y, z) = base_color(r + 1, c) + 1; + ret.schem(x, y, z) = cur_base_color + 1; } fixed_opt.main_progressbar.add(cvted.cols()); } @@ -435,9 +449,9 @@ uint64_t structure_3D_impl::block_count() const noexcept { LUT_is_air.reserve(this->schem.palette_size()); for (auto [idx, id] : this->schem.palette() | std::ranges::views::enumerate) { if (id == "air" || id == "minecraft:air") { - LUT_is_air[idx] = true; + LUT_is_air.emplace_back(1); } else { - LUT_is_air[idx] = false; + LUT_is_air.emplace_back(0); } } @@ -448,7 +462,9 @@ uint64_t structure_3D_impl::block_count() const noexcept { counter++; continue; } - counter += LUT_is_air[cur_blk_id]; + if (!LUT_is_air[cur_blk_id]) { + counter++; + } } return counter; } \ No newline at end of file From 1c63ed6f88e5bc845b1665377a54a4dd994f9d05 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 27 Apr 2024 22:31:14 +0800 Subject: [PATCH 0817/1123] fix previewing material list Signed-off-by: ToKiNoBug --- SlopeCraft/PreviewWind.cpp | 8 +++++--- SlopeCraft/SCWind.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 8b0b030f..8139719b 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -63,10 +63,12 @@ void PreviewWind::setup_data( blkp_arr.emplace_back(b); }); - this->mat_list.resize(blkp_arr.size()); + this->mat_list.reserve(blkp_arr.size()); for (size_t idx = 0; idx < blkp_arr.size(); idx++) { - this->mat_list[idx] = - material_item{.blk = blkp_arr[idx], .count = count_list[idx]}; + if (count_list[idx] > 0) { + this->mat_list.emplace_back( + material_item{.blk = blkp_arr[idx], .count = count_list[idx]}); + } } { diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 6d1fe697..5e46275a 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -905,6 +905,12 @@ std::optional SCWind::current_litematic_option( litename = this->ui->le_lite_name->text().toUtf8().data(); region_name = this->ui->le_lite_region_name->text().toUtf8().data(); + if (litename.empty()) { + litename = "UnnamedLitematica"; + } + if (region_name.empty()) { + region_name = "UnnamedRegion"; + } return SlopeCraft::litematic_options{ .caller_api_version = SC_VERSION_U64, From d4569fa61081db2ad6650b37f1085b7e85a26697 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 10:08:57 +0800 Subject: [PATCH 0818/1123] fix MapViewer build Signed-off-by: ToKiNoBug --- MapViewer/CMakeLists.txt | 2 +- MapViewer/MapViewerWind.cpp | 9 +++++---- MapViewer/MapViewerWind.h | 27 +++++++++------------------ SlopeCraftL/CMakeLists.txt | 17 ++++++----------- SlopeCraftL/SCLDefines.h | 4 ++-- SlopeCraftL/SlopeCraftL.cpp | 5 +++++ SlopeCraftL/SlopeCraftL.h | 2 ++ SlopeCraftL/color_source.cpp | 1 + 8 files changed, 31 insertions(+), 36 deletions(-) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index 23c3b294..d855cb63 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -21,7 +21,6 @@ set(MapViewer_header_files set(MapViewer_source_files main.cpp - ../SlopeCraftL/color_source.cpp processMapFiles.cpp MapViewerWind.cpp resource_manually.cpp @@ -57,6 +56,7 @@ find_package(Eigen3 REQUIRED) target_link_libraries(MapViewer PRIVATE + SlopeCraftL ZLIB::ZLIB Qt6::Widgets OpenMP::OpenMP_CXX diff --git a/MapViewer/MapViewerWind.cpp b/MapViewer/MapViewerWind.cpp index bfde47e2..5de96e40 100644 --- a/MapViewer/MapViewerWind.cpp +++ b/MapViewer/MapViewerWind.cpp @@ -20,8 +20,6 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "MapViewerWind.h" - #include #include #include @@ -31,6 +29,9 @@ This file is part of SlopeCraft. #include #include +#include "SlopeCraftL.h" + +#include "MapViewerWind.h" #include "processMapFiles.h" #include "ui_MapViewerWind.h" @@ -52,7 +53,7 @@ std::array make_map_LUT() { result.fill(0x7FFF0000); const Eigen::Map> src( - SlopeCraft::RGBBasicSource); + SlopeCraft::SCL_get_rgb_basic_colorset_source()); for (int row_idx = 0; row_idx < 256; row_idx++) { ARGB a, r, g, b; @@ -102,7 +103,7 @@ std::array make_inverse_map_LUT(const std::array &src) { const ARGB argb = src[idx]; ARGB r = (argb >> 16) & 0xFF; ARGB g = (argb >> 8) & 0xFF; - ARGB b = (argb)&0xFF; + ARGB b = (argb) & 0xFF; double x, y, z, _r, _g, _b; RGB2XYZ(r / 255.0, g / 255.0, g / 255.0, &x, &y, &z); diff --git a/MapViewer/MapViewerWind.h b/MapViewer/MapViewerWind.h index 415405b3..87fd9f14 100644 --- a/MapViewer/MapViewerWind.h +++ b/MapViewer/MapViewerWind.h @@ -24,18 +24,13 @@ This file is part of SlopeCraft. #define MAPVIEWERWIND_H #include - +#include #include -#include - #include - +#include #include - #include -#include - using std::cout, std::endl; QT_BEGIN_NAMESPACE @@ -44,17 +39,13 @@ class MapViewerWind; } QT_END_NAMESPACE -namespace SlopeCraft { -extern const float RGBBasicSource[256 * 3]; -} - using ARGB = uint32_t; using u8Array128RowMajor = Eigen::Array; using u32Array128RowMajor = Eigen::Array; extern const std::array map_color_to_ARGB; -enum single_map_draw_type { // the value of draw_type is the digits required +enum single_map_draw_type { // the value of draw_type is the digits required color_only = 0, map_color = 3, base_color = 2, @@ -62,7 +53,7 @@ enum single_map_draw_type { // the value of draw_type is the digits required }; struct map { -public: + public: map() : map_content(new u8Array128RowMajor){}; ~map() = default; map(map &&) = default; @@ -90,18 +81,18 @@ struct map { class MapViewerWind : public QMainWindow { Q_OBJECT -public: + public: MapViewerWind(QWidget *parent = nullptr); ~MapViewerWind(); -private: + private: Ui::MapViewerWind *ui; std::vector maps; std::vector labels; -private: -private slots: + private: + private slots: void update_contents(); void reshape_tables(); void render_single_image(); @@ -113,4 +104,4 @@ private slots: void on_button_save_composed_clicked(); }; -#endif // MAPVIEWERWIND_H +#endif // MAPVIEWERWIND_H diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index df02a21f..25694958 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -25,18 +25,18 @@ set(Slope_SCL_internal_headers ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h # GA_converter_option.h - height_line.h - optimize_chain.h - prim_glass_builder.h SCLDefines.h - # to_be_removed/TokiSlopeCraft.h water_item.h - lossy_compressor.h - mc_block.h string_deliver.h structure_3D.h + color_table.h converted_image.h + height_line.h + lossy_compressor.h + mc_block.h + optimize_chain.h + prim_glass_builder.h ) set(SlopeCraft_SCL_sources @@ -48,11 +48,6 @@ set(SlopeCraft_SCL_sources height_line.cpp optimize_chain.cpp prim_glass_builder.cpp - # to_be_removed/TokiSlopeCraft.cpp - # to_be_removed/TokiSlopeCraft_static_funs.cpp - # to_be_removed/TokiSlopeCraft_build.cpp - # to_be_removed/TokiSlopeCraft_convert.cpp - # to_be_removed/TokiSlopeCraft_cache.cpp image_preprocess.cpp lossy_compressor.cpp mc_block.cpp diff --git a/SlopeCraftL/SCLDefines.h b/SlopeCraftL/SCLDefines.h index 39a39df0..3be45c82 100644 --- a/SlopeCraftL/SCLDefines.h +++ b/SlopeCraftL/SCLDefines.h @@ -32,11 +32,11 @@ This file is part of SlopeCraft. #define EIGEN_NO_DEBUG #include #include - -#include "SlopeCraftL.h" #include #include +#include "SlopeCraftL.h" + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 81528950..c6a8208e 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -288,6 +288,11 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { } extern "C" { + +SCL_EXPORT const float *SCL_get_rgb_basic_colorset_source() { + return SlopeCraft::RGBBasicSource; +} + SCL_EXPORT mc_block_interface *SCL_create_block() { return new mc_block; } SCL_EXPORT void SCL_destroy_block(mc_block_interface *b) { delete b; } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 92724e01..2c05ea42 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -416,6 +416,8 @@ class structure_3D { extern "C" { namespace SlopeCraft { +[[nodiscard]] SCL_EXPORT const float *SCL_get_rgb_basic_colorset_source(); + [[nodiscard]] SCL_EXPORT mc_block_interface *SCL_create_block(); SCL_EXPORT void SCL_destroy_block(mc_block_interface *); diff --git a/SlopeCraftL/color_source.cpp b/SlopeCraftL/color_source.cpp index 3f8a4504..a170ef62 100644 --- a/SlopeCraftL/color_source.cpp +++ b/SlopeCraftL/color_source.cpp @@ -21,6 +21,7 @@ This file is part of SlopeCraft. */ #include "SCLDefines.h" + namespace SlopeCraft { extern const float RGBBasicSource[256 * 3]; From 1101d0ed6840c7a9a96e92aadf0e7eb2b7998ce7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 11:45:23 +0800 Subject: [PATCH 0819/1123] fix exporting litematica Signed-off-by: ToKiNoBug --- utilities/Schem/bit_shrink.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index 396ff3c9..9900b379 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -115,10 +115,10 @@ void shrink_bits(const uint16_t *const src, const size_t src_count, // } const size_t total_bits = bits_per_element * src_count; - const size_t bytes_required = libSchem::ceil_up_to(total_bits, 8); + const size_t bytes_required = libSchem::ceil_up_to(total_bits, 8) / 8; const size_t uint64_t_required = - libSchem::ceil_up_to(bytes_required, sizeof(uint64_t)); + libSchem::ceil_up_to(bytes_required, sizeof(uint64_t)) / sizeof(uint64_t); dest->resize(uint64_t_required); memset(dest->data(), 0, bytes_required); From ba940eb5d80fb7038bd2f4a6f1ddf5ed2fc76e8f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 13:49:36 +0800 Subject: [PATCH 0820/1123] fix linux build Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 2 +- utilities/Schem/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index a77ec7a2..b6b7809d 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -9,7 +9,7 @@ #include "water_item.h" #include "structure_3D.h" #include "utilities/ProcessBlockId/process_block_id.h" -#include "utilities/schem/mushroom.h" +#include "utilities/Schem/mushroom.h" std::optional color_table_impl::create( const color_table_create_info &args) noexcept { diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index c9427848..7e13ce28 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -22,7 +22,7 @@ target_link_libraries(Schem PUBLIC cereal::cereal fmt::fmt magic_enum::magic_enum) -target_compile_features(Schem PUBLIC cxx_std_20) +target_compile_features(Schem PUBLIC cxx_std_23) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) if (CMAKE_SYSTEM_NAME MATCHES "Linux") From 72a155f45144dce834d99eed13b738db6b1cafaf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 13:52:25 +0800 Subject: [PATCH 0821/1123] fix macos and gcc build Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index d8f6843b..3a77a6db 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -1,6 +1,7 @@ // // Created by joseph on 4/17/24. // +#include #include #include #include From 46c856aa3acefee74e755400944745feb35065a3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 13:54:49 +0800 Subject: [PATCH 0822/1123] [CI] fix clang-msvc build Signed-off-by: ToKiNoBug --- SlopeCraft/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index c39960f7..0a2abefb 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -10,6 +10,7 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) find_package(magic_enum REQUIRED) find_package(fmt REQUIRED) +find_package(tl-expected REQUIRED) set(SlopeCraft_rc_files) @@ -83,6 +84,7 @@ target_link_libraries(SlopeCraft PRIVATE Qt6::Network magic_enum::magic_enum fmt::fmt + tl::expected SlopeCraftL AdaptiveLabel From 81c0b9c03f2d9bdf8cb57c33a6953b57c7de8c06 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:14:13 +0800 Subject: [PATCH 0823/1123] [CI] fix windows build Signed-off-by: ToKiNoBug --- SlopeCraftL/install.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraftL/install.cmake b/SlopeCraftL/install.cmake index ae0f848c..26c4dc21 100644 --- a/SlopeCraftL/install.cmake +++ b/SlopeCraftL/install.cmake @@ -11,7 +11,7 @@ set(SlopeCraft_SCL_Cpp_include_files ${CMAKE_SOURCE_DIR}/utilities/SC_GlobalEnums.h ${CMAKE_CURRENT_SOURCE_DIR}/SlopeCraftL.h - ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraftL_global.h + ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraftL_export.h ) install(FILES ${SlopeCraft_SCL_Cpp_include_files} DESTINATION include/SlopeCraft) From 0b38b2db3066e7103f36256cd82d001e0ca8a180 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:15:56 +0800 Subject: [PATCH 0824/1123] [CI] remove usages of to support gcc12.2 and macos Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 3a77a6db..b7791f3b 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -1,7 +1,6 @@ // // Created by joseph on 4/17/24. // -#include #include #include #include @@ -448,7 +447,7 @@ tl::expected structure_3D_impl::load_cache( uint64_t structure_3D_impl::block_count() const noexcept { std::vector LUT_is_air; LUT_is_air.reserve(this->schem.palette_size()); - for (auto [idx, id] : this->schem.palette() | std::ranges::views::enumerate) { + for (auto &id : this->schem.palette()) { if (id == "air" || id == "minecraft:air") { LUT_is_air.emplace_back(1); } else { From a170487fb7eae8474545e5be390e25ef0b3ed64e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:23:10 +0800 Subject: [PATCH 0825/1123] remove use of Signed-off-by: ToKiNoBug --- SlopeCraft/cvt_task.cpp | 10 ++++++---- SlopeCraft/cvt_task.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/cvt_task.cpp b/SlopeCraft/cvt_task.cpp index b55f7ecb..143f2a44 100644 --- a/SlopeCraft/cvt_task.cpp +++ b/SlopeCraft/cvt_task.cpp @@ -1,6 +1,5 @@ #include -#include #include "cvt_task.h" #include "ExportTableModel.h" @@ -35,7 +34,8 @@ const std::vector> task_pool::converted_tasks( const SlopeCraft::convert_option& cvt_option) noexcept { std::vector> ret; ret.reserve(this->size()); - for (auto [idx, task] : *this | std::ranges::views::enumerate) { + for (size_t idx = 0; idx < this->size(); idx++) { + auto& task = this->at(idx); if (task.is_converted_with(table, cvt_option)) { ret.emplace_back(std::pair{idx, &task}); } @@ -45,7 +45,8 @@ const std::vector> task_pool::converted_tasks( std::optional> task_pool::converted_task_at_index( const SlopeCraft::color_table* table, const SlopeCraft::convert_option& cvt_option, size_t eidx) noexcept { - for (auto [idx, task] : *this | std::ranges::views::enumerate) { + for (size_t idx = 0; idx < this->size(); idx++) { + auto& task = this->at(idx); if (task.is_converted_with(table, cvt_option)) { if (eidx == 0) { return std::pair{idx, &task}; @@ -59,7 +60,8 @@ std::optional> task_pool::converted_task_at_index( std::optional task_pool::export_index_to_global_index( const SlopeCraft::color_table* table, const SlopeCraft::convert_option& cvt_option, size_t e_idx) const noexcept { - for (auto [gidx, task] : *this | std::ranges::views::enumerate) { + for (size_t gidx = 0; gidx < this->size(); gidx++) { + auto& task = this->at(gidx); if (!task.is_converted_with(table, cvt_option)) { continue; } diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 2ce396f2..1245581a 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -1,11 +1,11 @@ #ifndef SLOPECRAFT_SLOPECRAFT_CVT_TASK_H #define SLOPECRAFT_SLOPECRAFT_CVT_TASK_H +#include #include #include #include #include -#include struct convert_input { convert_input() = default; From c513f1e9a49bf36302e086596bbff1678e749a39 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:25:44 +0800 Subject: [PATCH 0826/1123] [CI] fix linux build Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BlockListManager.cpp | 2 +- utilities/BlockListManager/BlockListManager.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 72f1081f..9b3a37c6 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -32,7 +32,7 @@ void BlockListManager::setup_basecolors() noexcept { } } -uint64_t std::hash::operator()(const selection &s) noexcept { +uint64_t std::hash::operator()(const selection &s) const noexcept { boost::uuids::detail::md5 hash; for (auto &id : s.ids) { hash.process_bytes(id.data(), id.size()); diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 215dd1c6..8cd4f58e 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -24,7 +24,7 @@ QString serialize_preset(const blockListPreset &preset) noexcept; class BlockListDeleter { public: - void operator()(SlopeCraft::block_list_interface *ptr) noexcept { + void operator()(SlopeCraft::block_list_interface *ptr) const noexcept { SlopeCraft::SCL_destroy_block_list(ptr); } }; @@ -47,7 +47,7 @@ struct selection { template <> struct std::hash { - static uint64_t operator()(const selection &s) noexcept; + uint64_t operator()(const selection &s) const noexcept; }; class BlockListManager : public QWidget { From ceced742182e4e9ffe52162edc2fafeb5a66a410 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:36:32 +0800 Subject: [PATCH 0827/1123] [CI] enable vulkan on windows Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 3c5314d2..9b922e6c 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL ] + gpu_api: [ None, OpenCL, Vulkan ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL @@ -65,12 +65,12 @@ jobs: - name: Install Vulkan with vcpkg if: matrix.gpu_api == 'Vulkan' - run: | - cmd - curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" - 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z - exit - tree /f "C:\Program Files\VulkanSDK" + run: winget install KhronosGroup.VulkanSDK + # cmd + # curl -JL -o bin/VulkanSDK.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/vulkan1.3.250.1-windows/VulkanSDK-1.3.250.1.7z" + # 7z x -o"C:\Program Files\VulkanSDK" bin/VulkanSDK.7z + # exit + # tree /f "C:\Program Files\VulkanSDK" - name: Download Qt6.5.0-msvc-shared and extract run: | From a6de555d255d5228357505338ae45ee4cc1911f2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:45:14 +0800 Subject: [PATCH 0828/1123] [CI] remove use of static operator() Signed-off-by: ToKiNoBug --- SlopeCraft/cvt_task.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 1245581a..32f3ce1d 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -19,8 +19,8 @@ struct convert_input { }; struct hasher { - static uint64_t operator()( - const SlopeCraft::GA_converter_option& opt) noexcept { + uint64_t operator()( + const SlopeCraft::GA_converter_option& opt) const noexcept { uint64_t h = 0; h ^= std::hash()(opt.popSize); h ^= std::hash()(opt.maxGeneration); @@ -29,7 +29,7 @@ struct hasher { h ^= std::hash()(opt.mutationProb); return h; } - static uint64_t operator()(const SlopeCraft::convert_option& opt) noexcept { + uint64_t operator()(const SlopeCraft::convert_option& opt) const noexcept { uint64_t h = 0; h |= static_cast(opt.algo); h <<= 1; @@ -37,10 +37,10 @@ struct hasher { h ^= hasher{}(opt.ai_cvter_opt); return h; } - static uint64_t operator()(const convert_input& pair) noexcept { + uint64_t operator()(const convert_input& pair) const noexcept { return hasher{}(pair.option) ^ std::hash{}(pair.table); } - static uint64_t operator()(const SlopeCraft::build_options& opt) noexcept { + uint64_t operator()(const SlopeCraft::build_options& opt) const noexcept { uint64_t h = 0; h ^= static_cast(opt.max_allowed_height); h <<= sizeof(opt.max_allowed_height) * 8; // 16 bits @@ -62,8 +62,8 @@ struct hasher { }; struct equal { - static bool operator()(const SlopeCraft::GA_converter_option& a, - const SlopeCraft::GA_converter_option& b) noexcept { + bool operator()(const SlopeCraft::GA_converter_option& a, + const SlopeCraft::GA_converter_option& b) const noexcept { if (a.popSize != b.popSize) return false; if (a.maxGeneration != b.maxGeneration) return false; if (a.maxFailTimes != b.maxFailTimes) return false; @@ -71,21 +71,21 @@ struct equal { if (a.mutationProb != b.mutationProb) return false; return true; } - static bool operator()(const SlopeCraft::convert_option& a, - const SlopeCraft::convert_option& b) noexcept { + bool operator()(const SlopeCraft::convert_option& a, + const SlopeCraft::convert_option& b) const noexcept { if (a.algo != b.algo) return false; if (a.dither != b.dither) return false; if (!equal{}(a.ai_cvter_opt, b.ai_cvter_opt)) return false; return true; } - static bool operator()(const convert_input& a, - const convert_input& b) noexcept { + bool operator()(const convert_input& a, + const convert_input& b) const noexcept { if (a.table != b.table) return false; if (!equal{}(a.option, b.option)) return false; return true; } - static bool operator()(const SlopeCraft::build_options& a, - const SlopeCraft::build_options& b) noexcept { + bool operator()(const SlopeCraft::build_options& a, + const SlopeCraft::build_options& b) const noexcept { if (a.max_allowed_height != b.max_allowed_height) return false; if (a.bridge_interval != b.bridge_interval) return false; if (a.compress_method != b.compress_method) return false; From dbfe8b7aa358bd1ba1db3cf0fad034a07fa7e1e6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:47:28 +0800 Subject: [PATCH 0829/1123] [CI] install winget on windows Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 9b922e6c..e777c071 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -63,6 +63,19 @@ jobs: mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty + - name: Install winget + if: matrix.gpu_api == 'Vulkan' + shell: pwsh + run: | + $progressPreference = 'silentlyContinue' + Write-Information "Downloading WinGet and its dependencies..." + Invoke-WebRequest -Uri https://aka.ms/getwinget -OutFile Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle + Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -OutFile Microsoft.VCLibs.x64.14.00.Desktop.appx + Invoke-WebRequest -Uri https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.6/Microsoft.UI.Xaml.2.8.x64.appx -OutFile Microsoft.UI.Xaml.2.8.x64.appx + Add-AppxPackage Microsoft.VCLibs.x64.14.00.Desktop.appx + Add-AppxPackage Microsoft.UI.Xaml.2.8.x64.appx + Add-AppxPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle + - name: Install Vulkan with vcpkg if: matrix.gpu_api == 'Vulkan' run: winget install KhronosGroup.VulkanSDK @@ -106,7 +119,7 @@ jobs: cd ./build cpack -G ZIP -B "$basedir/pack" cpack -G 7Z -B "$basedir/pack" - + #- name: Upload zip pack # uses: actions/upload-artifact@v3 # with: From 4b3b5643913499605e957b8e7c0825714657ad07 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 14:56:23 +0800 Subject: [PATCH 0830/1123] [CI] disable vulkan on windows-build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index e777c071..71bd2565 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, OpenCL, Vulkan ] + gpu_api: [ None, OpenCL ] vectorize: [ true, false ] exclude: - gpu_api: OpenCL From 30422576acd0848aefe99909ee9678cbe4717f36 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 28 Apr 2024 19:44:54 +0800 Subject: [PATCH 0831/1123] update version of dependent cli11 and magic_enum Signed-off-by: ToKiNoBug --- cmake/required_deps/cli11.cmake | 45 ++++++++++++++-------------- cmake/required_deps/magic_enum.cmake | 2 +- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/cmake/required_deps/cli11.cmake b/cmake/required_deps/cli11.cmake index d6e8c39e..91773429 100644 --- a/cmake/required_deps/cli11.cmake +++ b/cmake/required_deps/cli11.cmake @@ -1,33 +1,34 @@ cmake_minimum_required(VERSION 3.19) -if(DEFINED cli11_include_dir) - if(EXISTS ${cli11_include_dir}/CLI11.hpp) - message(STATUS "cli11 found at " ${cli11_include_dir}/CLI11.hpp) - return() - else() - message(WARNING "Assigned cli11_include_dir to be " ${cli11_include_dir} - " but failed to find CLI11.hpp") - unset(cli11_include_dir) - endif() -endif() +if (DEFINED cli11_include_dir) + if (EXISTS ${cli11_include_dir}/CLI11.hpp) + message(STATUS "cli11 found at " ${cli11_include_dir}/CLI11.hpp) + return() + else () + message(WARNING "Assigned cli11_include_dir to be " ${cli11_include_dir} + " but failed to find CLI11.hpp") + unset(cli11_include_dir) + endif () +endif () -if(EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) - message(STATUS "cli11 found at " ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) - set(cli11_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/cli11) - return() -endif() +if (EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) + message(STATUS "cli11 found at " ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) + set(cli11_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/cli11) + return() +endif () message(STATUS "Downloading cli11.hpp ......") file(DOWNLOAD - https://github.com/CLIUtils/CLI11/releases/download/v2.3.2/CLI11.hpp - ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp - SHOW_PROGRESS) + https://github.com/CLIUtils/CLI11/releases/download/v2.4.1/CLI11.hpp + ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp + EXPECTED_HASH SHA512=7DB1F5B879DF99639ADA29AD313D5E344E1B0FD30A44116DA00A6CA53BEF4BA840684CBC64290CF365569095B0915D181039777FCE780BC60E20F624623B98B9 + SHOW_PROGRESS) -if(NOT EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) - message(ERROR "Failed to download cli11.") - return() -endif() +if (NOT EXISTS ${CMAKE_SOURCE_DIR}/3rdParty/cli11/CLI11.hpp) + message(ERROR "Failed to download cli11.") + return() +endif () message(STATUS "cli11 downloaded successfully.") set(cli11_include_dir ${CMAKE_SOURCE_DIR}/3rdParty/cli11) diff --git a/cmake/required_deps/magic_enum.cmake b/cmake/required_deps/magic_enum.cmake index 43d2fab3..c72dbbaa 100644 --- a/cmake/required_deps/magic_enum.cmake +++ b/cmake/required_deps/magic_enum.cmake @@ -14,7 +14,7 @@ FetchContent_Declare(magic_enum # URL https://github.com/Neargye/magic_enum/releases/download/v0.8.2/magic_enum.hpp GIT_REPOSITORY https://github.com/Neargye/magic_enum.git - GIT_TAG "v0.8.2" + GIT_TAG "v0.9.5" OVERRIDE_FIND_PACKAGE ) From 02612a0be22183fb968e3b290acb0cca05af1957 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Jul 2024 15:40:25 +0800 Subject: [PATCH 0832/1123] implement stat memory Signed-off-by: ToKiNoBug --- utilities/CMakeLists.txt | 1 + utilities/StatMemory/CMakeLists.txt | 29 +++++ utilities/StatMemory/MemoryPolicyDialog.cpp | 40 +++++++ utilities/StatMemory/MemoryPolicyDialog.h | 68 +++++++++++ utilities/StatMemory/MemoryPolicyDialog.ui | 119 +++++++++++++++++++ utilities/StatMemory/stat_memory.h | 29 +++++ utilities/StatMemory/stat_memory_windows.cpp | 35 ++++++ 7 files changed, 321 insertions(+) create mode 100644 utilities/StatMemory/CMakeLists.txt create mode 100644 utilities/StatMemory/MemoryPolicyDialog.cpp create mode 100644 utilities/StatMemory/MemoryPolicyDialog.h create mode 100644 utilities/StatMemory/MemoryPolicyDialog.ui create mode 100644 utilities/StatMemory/stat_memory.h create mode 100644 utilities/StatMemory/stat_memory_windows.cpp diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 9dac3819..0fe95201 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(VersionDialog) add_subdirectory(VCLConfigLoader) add_subdirectory(FlatDiagram) add_subdirectory(libpngReader) +add_subdirectory(StatMemory) function(SC_process_boolean value_name) if (${${value_name}}) diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt new file mode 100644 index 00000000..90ff98e3 --- /dev/null +++ b/utilities/StatMemory/CMakeLists.txt @@ -0,0 +1,29 @@ +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +find_package(Qt6 COMPONENTS Widgets REQUIRED) +add_library(MemoryPolicyDialog STATIC + MemoryPolicyDialog.h + MemoryPolicyDialog.cpp + MemoryPolicyDialog.ui +) +target_link_libraries(MemoryPolicyDialog PUBLIC Qt6::Widgets) + + +add_library(StatMemory STATIC stat_memory.h) +find_package(tl-expected REQUIRED) +target_link_libraries(StatMemory PUBLIC tl::expected) +target_include_directories(StatMemory PUBLIC $) + +target_link_libraries(MemoryPolicyDialog PUBLIC StatMemory) + +if (${WIN32}) + target_sources(StatMemory PRIVATE stat_memory_windows.cpp) + target_link_libraries(StatMemory PUBLIC psapi.lib) + return() +endif () + +message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") \ No newline at end of file diff --git a/utilities/StatMemory/MemoryPolicyDialog.cpp b/utilities/StatMemory/MemoryPolicyDialog.cpp new file mode 100644 index 00000000..57b3f557 --- /dev/null +++ b/utilities/StatMemory/MemoryPolicyDialog.cpp @@ -0,0 +1,40 @@ +// +// Created by Joseph on 2024/7/16. +// + +#include + +#include "MemoryPolicyDialog.h" +#include "ui_MemoryPolicyDialog.h" + +MemoryPolicyDialog::MemoryPolicyDialog(QWidget *parent) + : QDialog{parent}, ui{new Ui::MemoryPolicyDialog} { + this->ui->setupUi(this); + this->reset(memory_policy{}); +} + +MemoryPolicyDialog::MemoryPolicyDialog(QWidget *parent, + const memory_policy &value) + : MemoryPolicyDialog{parent} { + this->reset(value); +} + +MemoryPolicyDialog::~MemoryPolicyDialog() { this->ui.reset(); } + +memory_policy MemoryPolicyDialog::current_value() const noexcept { + return memory_policy{ + .auto_cache = this->ui->cb_auto_cache->isChecked(), + .self_maximum_memory = + uint64_t(this->ui->sb_self_limit->value()) * 1024 * 1024 * 1024, + .system_minimum_free = this->ui->dsb_system_limit->value(), + }; +} + +void MemoryPolicyDialog::reset(const memory_policy &value) noexcept { + this->ui->cb_auto_cache->setCheckState( + value.auto_cache ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + this->ui->sb_self_limit->setValue( + uint64_t(std::round(value.self_maximum_memory / (1024.0 * 1024 * 1024)))); + + this->ui->dsb_system_limit->setValue(value.system_minimum_free); +} \ No newline at end of file diff --git a/utilities/StatMemory/MemoryPolicyDialog.h b/utilities/StatMemory/MemoryPolicyDialog.h new file mode 100644 index 00000000..64a6409b --- /dev/null +++ b/utilities/StatMemory/MemoryPolicyDialog.h @@ -0,0 +1,68 @@ +// +// Created by Joseph on 2024/7/16. +// + +#ifndef SLOPECRAFT_MEMORYPOLICYDIALOG_H +#define SLOPECRAFT_MEMORYPOLICYDIALOG_H + +#include +#include + +#include "stat_memory.h" + +struct memory_policy { + bool auto_cache{true}; + uint64_t self_maximum_memory = 4 << 30; + double system_minimum_free = 0.2; + + [[nodiscard]] bool should_cache( + const system_memory_info& smi) const noexcept { + if (not this->auto_cache) { + return false; + } + return double(smi.free) < smi.total * this->self_maximum_memory; + } + + [[nodiscard]] bool should_cache(const self_memory_usage& smu) const noexcept { + if (not this->auto_cache) { + return false; + } + return smu.used > this->self_maximum_memory; + } + + [[nodiscard]] bool should_cache() const noexcept { + if (not this->auto_cache) { + return false; + } + const auto sys_info_opt = get_self_memory_info(); + if (sys_info_opt and this->should_cache(sys_info_opt.value())) { + return true; + } + const auto self_info_opt = get_self_memory_info(); + if (self_info_opt and this->should_cache(self_info_opt.value())) { + return true; + } + return false; + } +}; + +class MemoryPolicyDialog; +namespace Ui { +class MemoryPolicyDialog; +} + +class MemoryPolicyDialog : public QDialog { + Q_OBJECT + private: + std::unique_ptr ui; + + public: + explicit MemoryPolicyDialog(QWidget* parent); + MemoryPolicyDialog(QWidget* parent, const memory_policy&); + ~MemoryPolicyDialog(); + + [[nodiscard]] memory_policy current_value() const noexcept; + void reset(const memory_policy&) noexcept; +}; + +#endif // SLOPECRAFT_MEMORYPOLICYDIALOG_H diff --git a/utilities/StatMemory/MemoryPolicyDialog.ui b/utilities/StatMemory/MemoryPolicyDialog.ui new file mode 100644 index 00000000..bc29f2e9 --- /dev/null +++ b/utilities/StatMemory/MemoryPolicyDialog.ui @@ -0,0 +1,119 @@ + + + MemoryPolicyDialog + + + + 0 + 0 + 400 + 195 + + + + 内存使用策略 + + + + + + Gib时自动缓存 + + + 当本进程占用> + + + 1 + + + 16384 + + + 4 + + + + + + + 当系统剩余内存< + + + %时自动缓存 + + + 1 + + + 0.000000000000000 + + + 5.000000000000000 + + + 20.000000000000000 + + + + + + + 提示:以上只是缓存数据的目标,不能保证内存占用一定小于设置的上限。缓存数据的实质是将构建的三维结构暂存硬盘(并释放相应内存),需要时再读取,因此必然使导出地图画变慢。 + + + false + + + true + + + + + + + 自动缓存数据以节约内存 + + + true + + + + + + + 确定 + + + + + + + 取消 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 恢复默认 + + + + + + + + diff --git a/utilities/StatMemory/stat_memory.h b/utilities/StatMemory/stat_memory.h new file mode 100644 index 00000000..d80ca2f3 --- /dev/null +++ b/utilities/StatMemory/stat_memory.h @@ -0,0 +1,29 @@ +// +// Created by Joseph on 2024/7/16. +// + +#ifndef SLOPECRAFT_STAT_MEMORY_H +#define SLOPECRAFT_STAT_MEMORY_H + +#include +#include +#include + +// All units in byte +struct system_memory_info { + uint64_t total; + uint64_t free; +}; + +[[nodiscard]] tl::expected +get_system_memory_info() noexcept; + +// All units in byte +struct self_memory_usage { + uint64_t used; +}; + +[[nodiscard]] tl::expected +get_self_memory_info() noexcept; + +#endif // SLOPECRAFT_STAT_MEMORY_H diff --git a/utilities/StatMemory/stat_memory_windows.cpp b/utilities/StatMemory/stat_memory_windows.cpp new file mode 100644 index 00000000..8389b2ac --- /dev/null +++ b/utilities/StatMemory/stat_memory_windows.cpp @@ -0,0 +1,35 @@ +#include "stat_memory.h" +#include +#include + +#ifdef max +#undef max +#endif + +#include + +tl::expected +get_system_memory_info() noexcept { + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + + return system_memory_info{ + .total = ms.dwTotalPhys, + .free = ms.dwAvailPhys, + }; +} + +[[nodiscard]] tl::expected +get_self_memory_info() noexcept { + HANDLE handle = GetCurrentProcess(); + if (handle == nullptr) { + return tl::make_unexpected( + "win32 api failed, GetCurrentProcess returned nullptr instead of a " + "handle to current process."); + } + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(handle, &pmc, sizeof(pmc)); + self_memory_usage result{.used = + std::max(pmc.PagefileUsage, pmc.WorkingSetSize)}; + return result; +} \ No newline at end of file From 2282c6389c39b6d71d76421cbbfb3300b544a0b6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Jul 2024 16:44:04 +0800 Subject: [PATCH 0833/1123] implement auto caching Signed-off-by: ToKiNoBug --- SlopeCraft/CMakeLists.txt | 5 ++- SlopeCraft/SCWind.cpp | 70 +++++++++++++++++++++++++++++++++++++ SlopeCraft/SCWind.h | 11 ++++++ SlopeCraft/SCWind_slots.cpp | 7 ++++ SlopeCraft/cvt_task.h | 23 ++++++++---- 5 files changed, 108 insertions(+), 8 deletions(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index 0a2abefb..a9374514 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -89,7 +89,10 @@ target_link_libraries(SlopeCraft PRIVATE SlopeCraftL AdaptiveLabel VersionDialog - BlockListManager) + BlockListManager + StatMemory + MemoryPolicyDialog +) target_include_directories(SlopeCraft PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 5e46275a..2d0e8ebe 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -1172,4 +1172,74 @@ SCWind::load_selected_3D() noexcept { } return {cvted_img, structure_3D}; +} + +bool SCWind::should_auto_cache(bool suppress_warnings) noexcept { + bool result = false; + const auto self_used = get_self_memory_info(); + QString error_template = + tr("这不是严重的问题,你可以直接忽略这个警告,或者把它反馈给开发者," + "不影响正常使用。只是 Slopecraft " + "可能占用更多的内存。\n详细信息:\n%1"); + + if (not self_used) { + if (not suppress_warnings) { + QMessageBox::warning( + this, tr("获取本进程的内存占用失败"), + error_template.arg(QString::fromLocal8Bit(self_used.error().c_str())), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok}); + } + } else { + result = this->mem_policy.should_cache(self_used.value()) or result; + } + + const auto system_info = get_system_memory_info(); + if (not system_info) { + if (not suppress_warnings) { + QMessageBox::warning( + this, tr("获取操作系统内存占用失败"), + error_template.arg(QString::fromLocal8Bit(self_used.error().c_str())), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ok}); + } + } else { + result = this->mem_policy.should_cache(system_info.value()) or result; + } + return result; +} + +SCWind::auto_cache_report SCWind::auto_cache_3D() noexcept { + // const auto colortable = this->current_color_table(); + // const auto build_opt = this->current_build_option(); + auto_cache_report report{ + .structures_cached = 0, + .memory_saved = 0, + }; + const auto self_mem_before = get_self_memory_info(); + const QString cache_root = this->cache_root_dir(); + + auto go_through = [this, cache_root]() -> size_t { + size_t cached = 0; + for (auto &task : this->tasks) { + for (auto &[cvt_input, cvted] : task.converted_images) { + // if we don't need to cache, return. + if (not this->should_auto_cache(true)) { + return cached; + } + + auto report = cvted.cache_all_structures( + *cvt_input.table, *cvted.converted_image, cache_root); + cached += report.cache_num; + } + } + return cached; + }; + + report.structures_cached = go_through(); + const auto self_mem_current = get_self_memory_info(); + if (self_mem_before and self_mem_current) { + report.memory_saved = + self_mem_before.value().used - self_mem_current.value().used; + } + + return report; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index b22be00f..0a924322 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -14,6 +14,7 @@ #include "cvt_task.h" #include "PoolModel.h" #include "ExportTableModel.h" +#include "MemoryPolicyDialog.h" class SCWind; @@ -122,6 +123,8 @@ class SCWind : public QMainWindow { std::vector translators; QString prev_load_image_dir{""}; + + memory_policy mem_policy{}; // QString fileonly_export_dir{""}; public: @@ -254,6 +257,14 @@ class SCWind : public QMainWindow { void report_error(::SCL_errorFlag flag, const char* msg) noexcept; + [[nodiscard]] bool should_auto_cache(bool suppress_warnings) noexcept; + + struct auto_cache_report { + size_t structures_cached; + int64_t memory_saved; + }; + auto_cache_report auto_cache_3D() noexcept; + signals: void image_changed(); }; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 608eb197..59ff2033 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -12,6 +12,8 @@ #include "TransparentStrategyWind.h" #include "CompressEffectViewer.h" +#include "stat_memory.h" + #ifdef WIN32 const char *SC_image_filter = "*.png;*.jpg"; #else @@ -371,6 +373,11 @@ void SCWind::on_cb_compress_lossy_toggled(bool checked) noexcept { } void SCWind::on_pb_build3d_clicked() noexcept { + if (this->should_auto_cache(false)) { + [[maybe_unused]] const auto report = this->auto_cache_3D(); + ; + } + auto task_ptr = this->selected_export_task(); if (task_ptr == nullptr) { QMessageBox::warning(this, tr("未选择图像"), diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 32f3ce1d..41dc8e9f 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -112,26 +112,35 @@ struct convert_result { return this->built_structures.contains(opt); } - void cache_all_structures(const SlopeCraft::color_table& table, - const SlopeCraft::converted_image& cvted, - const QString& cache_root_dir) noexcept { - this->cache_all_structures(table, cvted, cache_root_dir, - [](auto) { return true; }); + struct cache_report { + size_t cache_num{0}; + }; + + cache_report cache_all_structures(const SlopeCraft::color_table& table, + const SlopeCraft::converted_image& cvted, + const QString& cache_root_dir) noexcept { + return this->cache_all_structures(table, cvted, cache_root_dir, + [](auto) { return true; }); } - void cache_all_structures( + cache_report cache_all_structures( const SlopeCraft::color_table& table, const SlopeCraft::converted_image& cvted, const QString& cache_root_dir, const std::function& cache_or_not) noexcept { + size_t num = 0; for (auto& pair : this->built_structures) { if (!cache_or_not(pair.first)) { continue; } - [[maybe_unused]] const bool ok = + const bool ok = table.save_build_cache(cvted, pair.first, *pair.second, cache_root_dir.toLocal8Bit().data(), nullptr); + if (ok) { + num++; + } } + return cache_report{.cache_num = num}; } void cache_structure(const SlopeCraft::color_table& table, From 75f38ffa37eadafc5d64dcc7e6e7e3e1e3016b13 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Jul 2024 21:34:08 +0800 Subject: [PATCH 0834/1123] fix crashing caused by auto caching Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 3 +++ SlopeCraft/cvt_task.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 2d0e8ebe..b13a3da2 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -304,6 +304,7 @@ SCL_mapTypes SCWind::selected_type() const noexcept { } assert(false); + return SCL_mapTypes::Slope; // return {}; } @@ -367,6 +368,7 @@ SCL_convertAlgo SCWind::selected_algo() const noexcept { } assert(false); + return SCL_convertAlgo::RGB_Better; // return {}; } @@ -447,6 +449,7 @@ SCWind::export_type SCWind::selected_export_type() const noexcept { } } assert(false); + return SCWind::export_type::litematica; // return {}; } diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 41dc8e9f..5da1a50d 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -130,12 +130,16 @@ struct convert_result { cache_or_not) noexcept { size_t num = 0; for (auto& pair : this->built_structures) { + if (pair.second.get() == nullptr) { // already cached + continue; + } if (!cache_or_not(pair.first)) { continue; } const bool ok = table.save_build_cache(cvted, pair.first, *pair.second, cache_root_dir.toLocal8Bit().data(), nullptr); + pair.second.reset(); if (ok) { num++; } From b7db81c37fc0549df58cf1d008297cbdc5b7dbf4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Jul 2024 22:17:23 +0800 Subject: [PATCH 0835/1123] avoid loading cached structure when selecting it Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 9 +++--- SlopeCraft/SCWind_slots.cpp | 12 ++++++++ SlopeCraft/cvt_task.h | 55 ++++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index b13a3da2..367ddac1 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -853,13 +853,14 @@ void SCWind::refresh_current_build_display( if (cvted_it == task.converted_images.end()) { return; } - if (auto str_3D = cvted_it->second.load_build_cache( + if (auto str_with_info = cvted_it->second.get_build_cache_with_info_noload( *this->current_color_table(), this->current_build_option(), this->cache_root_dir())) { - const auto x = str_3D->shape_x(), y = str_3D->shape_y(), - z = str_3D->shape_z(); + // const SlopeCraft::structure_3D *str_3D = str_with_info->handle.get(); + const auto x = str_with_info->shape[0], y = str_with_info->shape[1], + z = str_with_info->shape[2]; - const auto block_count = str_3D->block_count(); + const auto block_count = str_with_info->block_count; this->ui->lb_show_3dsize->setText( tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 59ff2033..791ce33d 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -418,6 +418,10 @@ void SCWind::on_pb_build3d_clicked() noexcept { } void SCWind::on_pb_preview_materials_clicked() noexcept { + if (this->should_auto_cache(false)) { + this->auto_cache_3D(); + } + auto [cvted_img, structure_3D] = this->load_selected_3D(); if (cvted_img == nullptr || structure_3D == nullptr) { return; @@ -439,6 +443,10 @@ void SCWind::on_pb_preview_materials_clicked() noexcept { } void SCWind::on_pb_preview_compress_effect_clicked() noexcept { + if (this->should_auto_cache(false)) { + this->auto_cache_3D(); + } + auto [cvted_img, structure_3D] = this->load_selected_3D(); if (cvted_img == nullptr || structure_3D == nullptr) { return; @@ -568,6 +576,10 @@ void SCWind::on_pb_export_all_clicked() noexcept { } for (auto taskp : tasks_to_export) { + if (this->should_auto_cache(false)) { + this->auto_cache_3D(); + } + auto [cvted, str3D] = this->convert_and_build_if_need(*taskp); const std::string export_name = diff --git a/SlopeCraft/cvt_task.h b/SlopeCraft/cvt_task.h index 5da1a50d..60761b6e 100644 --- a/SlopeCraft/cvt_task.h +++ b/SlopeCraft/cvt_task.h @@ -96,15 +96,26 @@ struct equal { } }; +struct structure_with_info { + std::unique_ptr handle; + + const std::array shape; + const uint64_t block_count; + + explicit structure_with_info( + std::unique_ptr&& src) + : handle{std::move(src)}, + shape{{handle->shape_x(), handle->shape_y(), handle->shape_z()}}, + block_count{handle->block_count()} {} +}; + struct convert_result { // convert_result() = delete; std::unique_ptr converted_image{nullptr}; - std::unordered_map< - SlopeCraft::build_options, - std::unique_ptr, hasher, - equal> + std::unordered_map built_structures; [[nodiscard]] bool is_built_with( @@ -130,16 +141,16 @@ struct convert_result { cache_or_not) noexcept { size_t num = 0; for (auto& pair : this->built_structures) { - if (pair.second.get() == nullptr) { // already cached + if (pair.second.handle.get() == nullptr) { // already cached continue; } if (!cache_or_not(pair.first)) { continue; } const bool ok = - table.save_build_cache(cvted, pair.first, *pair.second, + table.save_build_cache(cvted, pair.first, *pair.second.handle, cache_root_dir.toLocal8Bit().data(), nullptr); - pair.second.reset(); + pair.second.handle.reset(); if (ok) { num++; } @@ -154,18 +165,29 @@ struct convert_result { if (it == this->built_structures.end()) { return; } - if (it->second == nullptr) { + if (it->second.handle == nullptr) { return; } const bool ok = - table.save_build_cache(*this->converted_image, opt, *it->second, + table.save_build_cache(*this->converted_image, opt, *it->second.handle, cache_root_dir.toLocal8Bit().data(), nullptr); if (ok) { - it->second.reset(); + it->second.handle.reset(); } return; } + const structure_with_info* get_build_cache_with_info_noload( + const SlopeCraft::color_table& table, + const SlopeCraft::build_options& opt, + const QString& cache_root_dir) const noexcept { + auto it = this->built_structures.find(opt); + if (it == this->built_structures.end()) { + return nullptr; + } + return &it->second; + } + const SlopeCraft::structure_3D* load_build_cache( const SlopeCraft::color_table& table, const SlopeCraft::build_options& opt, @@ -175,8 +197,8 @@ struct convert_result { return nullptr; } - if (it->second != nullptr) { // the structure exist in memory - return it->second.get(); + if (it->second.handle != nullptr) { // the structure exist in memory + return it->second.handle.get(); } // the structure is cached @@ -186,8 +208,8 @@ struct convert_result { if (p == nullptr) { // failed to load cache return nullptr; } - it->second.reset(p); - return it->second.get(); + it->second.handle.reset(p); + return it->second.handle.get(); } void set_built(SlopeCraft::build_options opt, @@ -198,10 +220,11 @@ struct convert_result { opt.sub_progressbar = {}; auto it = this->built_structures.find(opt); if (it == built_structures.end()) { - this->built_structures.emplace(opt, std::move(structure)); + this->built_structures.emplace(opt, + structure_with_info{std::move(structure)}); return; } - it->second = std::move(structure); + it->second.handle = std::move(structure); } }; From 5098e7afddc2d6783a51a36d17acec1bcaec5127 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Jul 2024 22:17:28 +0800 Subject: [PATCH 0836/1123] fix warnings Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BaseColor.cpp | 1 + utilities/BlockListManager/BlockListManager.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index 6c1427ca..038a27f2 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -149,6 +149,7 @@ int BaseColorWidget::selected_idx() const noexcept { } } assert(false); + return 0; } int BaseColorWidget::prefered_block_idx(int checked_idx, diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 9b3a37c6..faed871e 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -99,7 +99,9 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { base_colors.resize(bli->size()); blockps.resize(bli->size()); - bli->get_blocks(blockps.data(), base_colors.data(), blockps.size()); + const size_t size_2 = + bli->get_blocks(blockps.data(), base_colors.data(), blockps.size()); + assert(size_2 == base_colors.size() and base_colors.size() == blockps.size()); for (size_t idx = 0; idx < bli->size(); idx++) { this->basecolor_widgets[base_colors[idx]]->add_block(blockps[idx]); From ff298ace39128d0317dc680e37baf75528f68e45 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Jul 2024 22:17:56 +0800 Subject: [PATCH 0837/1123] outputs when bad_alloc Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 6 +++--- SlopeCraft/SCWind.h | 6 +++++- SlopeCraftL/structure_3D.cpp | 19 +++++++++++++++++-- utilities/SC_GlobalEnums.h | 29 ++++++++++++++++------------- utilities/Schem/Schem.cpp | 4 ++-- utilities/Schem/Schem.h | 2 +- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 367ddac1..5416da65 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -1211,7 +1211,7 @@ bool SCWind::should_auto_cache(bool suppress_warnings) noexcept { return result; } -SCWind::auto_cache_report SCWind::auto_cache_3D() noexcept { +SCWind::auto_cache_report SCWind::auto_cache_3D(bool cache_all) noexcept { // const auto colortable = this->current_color_table(); // const auto build_opt = this->current_build_option(); auto_cache_report report{ @@ -1221,12 +1221,12 @@ SCWind::auto_cache_report SCWind::auto_cache_3D() noexcept { const auto self_mem_before = get_self_memory_info(); const QString cache_root = this->cache_root_dir(); - auto go_through = [this, cache_root]() -> size_t { + auto go_through = [this, cache_root, cache_all]() -> size_t { size_t cached = 0; for (auto &task : this->tasks) { for (auto &[cvt_input, cvted] : task.converted_images) { // if we don't need to cache, return. - if (not this->should_auto_cache(true)) { + if ((not cache_all) and (not this->should_auto_cache(true))) { return cached; } diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 0a924322..ff8b1889 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -105,6 +105,10 @@ class SCWind : public QMainWindow { void on_ac_get_current_colorlist_triggered() noexcept; void on_ac_test_blocklist_triggered() noexcept; + void on_ac_cache_all_3d_triggered() noexcept; + + void on_ac_memory_policy_triggered() noexcept; + private: Ui::SCWind* ui; @@ -263,7 +267,7 @@ class SCWind : public QMainWindow { size_t structures_cached; int64_t memory_saved; }; - auto_cache_report auto_cache_3D() noexcept; + auto_cache_report auto_cache_3D(bool cache_all = false) noexcept; signals: void image_changed(); diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index b7791f3b..c8a99a41 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -67,8 +67,23 @@ std::optional structure_3D_impl::create( // std::cout << base_color << std::endl; - ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, 2 + cvted.rows()); - ret.schem.set_zero(); + try { + ret.schem.resize(2 + cvted.cols(), high_map.maxCoeff() + 1, + 2 + cvted.rows()); + ret.schem.set_zero(); + } catch (const std::bad_alloc &e) { + const std::array shape{ + 2 + cvted.cols(), static_cast(high_map.maxCoeff() + 1), + 2 + cvted.rows()}; + const uint64_t bytes_required = shape[0] * shape[1] * shape[2]; + option.ui.report_error( + errorFlag::MEMORY_ALLOCATE_FAILED, + fmt::format("Failed to allocate memory for this structure, " + "required {} GiB. The exception says: \"{}\"", + double(bytes_required) / (uint64_t{1} << 30), e.what()) + .c_str()); + return std::nullopt; + } // make 3D { // base_color(r+1,c)<->High(r+1,c)<->Build(c+1,High(r+1,c),r+1) diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 2770a4c2..3d187877 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -107,19 +107,19 @@ enum class SCL_mapTypes : int { FileOnly = 2 }; -enum class SCL_step : int { - /// the instance is created - nothing, - /// map type is set and waitting for image - wait4Image, - /// image is ready and ready for converting - convertionReady, - /// image is converted and ready for building 3D structure, exporting as - /// file-only map(s) can be done in this step - converted, - /// 3D structure is built and ready for exporting 3d structure - builded, -}; +// enum class SCL_step : int { +// /// the instance is created +// nothing, +// /// map type is set and waitting for image +// wait4Image, +// /// image is ready and ready for converting +// convertionReady, +// /// image is converted and ready for building 3D structure, exporting as +// /// file-only map(s) can be done in this step +// converted, +// /// 3D structure is built and ready for exporting 3d structure +// builded, +// }; enum class SCL_errorFlag : int { /// no error @@ -164,6 +164,9 @@ enum class SCL_errorFlag : int { EXPORT_FLAT_DIAGRAM_ON_WRONG_MAP_TYPE = 0x10, EXPORT_FLAT_DIAGRAM_FAILURE = 0x11, + /// Failed to allocate memory. Upto 5.3, it will only appear when building 3D + /// for a huge image + MEMORY_ALLOCATE_FAILED = 0x12, }; diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 895b532c..ecd62a5a 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -40,7 +40,7 @@ litematic_info::litematic_info() : time_created(std::time(nullptr) * 1000), time_modified(std::time(nullptr) * 1000) {} -void Schem::resize(int64_t x, int64_t y, int64_t z) noexcept { +void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } @@ -63,7 +63,7 @@ std::string Schem::check_size(int64_t x, int64_t y, int64_t z) noexcept { void Schem::stat_blocks(std::vector &dest) const noexcept { dest.resize(this->palette_size()); std::fill(dest.begin(), dest.end(), 0); - + for (ele_t block_index : *this) { assert(block_index < this->palette_size()); dest[block_index] += 1; diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index b35d29d0..df0d4ea5 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -97,7 +97,7 @@ class Schem { inline const ele_t *data() const noexcept { return xzy.data(); } - void resize(int64_t x, int64_t y, int64_t z) noexcept; + void resize(int64_t x, int64_t y, int64_t z); inline bool check_version_id() const noexcept { return MCDataVersion::is_data_version_suitable(this->MC_major_ver, From e5ebc8fec1fa4a818e440be64032310f5cbe3ed4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Jul 2024 22:20:02 +0800 Subject: [PATCH 0838/1123] fix a segfault caused by caching Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 791ce33d..6a8d7e6a 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -411,7 +411,10 @@ void SCWind::on_pb_build3d_clicked() noexcept { const auto build_option = this->current_build_option(); if (!cvted.is_built_with(build_option)) { - cvted.set_built(build_option, this->build_3D(*cvted.converted_image)); + auto structure = this->build_3D(*cvted.converted_image); + if (structure not_eq nullptr) { + cvted.set_built(build_option, std::move(structure)); + } } // load cache if converted this->refresh_current_build_display(&task, true); @@ -950,4 +953,18 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { .arg(filename) .arg(qerr)); } +} + +void SCWind::on_ac_cache_all_3d_triggered() noexcept { + this->auto_cache_3D(true); +} + +void SCWind::on_ac_memory_policy_triggered() noexcept { + MemoryPolicyDialog diag{this, this->mem_policy}; + const auto result = diag.exec(); + + if (result) { + this->mem_policy = diag.current_value(); + this->auto_cache_3D(); + } } \ No newline at end of file From ee0c8dcd777af7449a7b4bb21440d4a0264f344c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Jul 2024 22:20:15 +0800 Subject: [PATCH 0839/1123] remove SCL_step Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 2c05ea42..e6422087 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -42,7 +42,7 @@ This file is part of SlopeCraft. namespace SlopeCraft { -using step = ::SCL_step; +// using step = ::SCL_step; using mapTypes = ::SCL_mapTypes; using compressSettings = ::SCL_compressSettings; using convertAlgo = ::SCL_convertAlgo; From 845698ee02cc56959ec488af277e3691a2f1b646 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 18 Jul 2024 22:20:37 +0800 Subject: [PATCH 0840/1123] implement MemoryPolicyDialog for SC Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.ui | 96 ++++++++++++--------- utilities/StatMemory/MemoryPolicyDialog.cpp | 12 ++- utilities/StatMemory/MemoryPolicyDialog.h | 11 ++- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index d8795cad..ed98fcd6 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -48,7 +48,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -241,7 +241,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -312,8 +312,8 @@ 0 0 - 753 - 664 + 750 + 653 @@ -336,16 +336,16 @@ - QTabWidget::North + QTabWidget::TabPosition::North - QTabWidget::Rounded + QTabWidget::TabShape::Rounded 0 - Qt::ElideNone + Qt::TextElideMode::ElideNone false @@ -373,10 +373,10 @@ true - QFrame::Box + QFrame::Shape::Box - QFrame::Sunken + QFrame::Shadow::Sunken 1 @@ -388,7 +388,7 @@ false - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -411,10 +411,10 @@ true - QFrame::Box + QFrame::Shape::Box - QFrame::Sunken + QFrame::Shadow::Sunken 1 @@ -423,7 +423,7 @@ - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -458,7 +458,7 @@ false - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed true @@ -467,34 +467,34 @@ false - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove - Qt::CopyAction + Qt::DropAction::CopyAction - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - Qt::ElideLeft + Qt::TextElideMode::ElideLeft - QListView::Snap + QListView::Movement::Snap - QListView::TopToBottom + QListView::Flow::TopToBottom false - QListView::Fixed + QListView::ResizeMode::Fixed 10 - QListView::IconMode + QListView::ViewMode::IconMode 0 @@ -520,7 +520,7 @@ 项目池 - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -643,7 +643,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -687,7 +687,7 @@ 项目池 - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -697,7 +697,7 @@ false - QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed true @@ -706,34 +706,34 @@ false - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove - Qt::CopyAction + Qt::DropAction::CopyAction - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - Qt::ElideLeft + Qt::TextElideMode::ElideLeft - QListView::Snap + QListView::Movement::Snap - QListView::TopToBottom + QListView::Flow::TopToBottom false - QListView::Fixed + QListView::ResizeMode::Fixed 10 - QListView::IconMode + QListView::ViewMode::IconMode 0 @@ -968,7 +968,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -998,7 +998,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1212,7 +1212,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1269,7 +1269,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1330,7 +1330,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1377,7 +1377,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1407,7 +1407,7 @@ 在下面的表格里可以看到每个图像对应的文件名。 - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -1430,7 +1430,7 @@ 0 0 920 - 22 + 33 @@ -1450,11 +1450,13 @@ + + @@ -1583,6 +1585,16 @@ 常见问题 + + + 内存使用策略 + + + + + 缓存全部三维结构 + + diff --git a/utilities/StatMemory/MemoryPolicyDialog.cpp b/utilities/StatMemory/MemoryPolicyDialog.cpp index 57b3f557..6bce66ae 100644 --- a/utilities/StatMemory/MemoryPolicyDialog.cpp +++ b/utilities/StatMemory/MemoryPolicyDialog.cpp @@ -34,7 +34,17 @@ void MemoryPolicyDialog::reset(const memory_policy &value) noexcept { this->ui->cb_auto_cache->setCheckState( value.auto_cache ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); this->ui->sb_self_limit->setValue( - uint64_t(std::round(value.self_maximum_memory / (1024.0 * 1024 * 1024)))); + uint64_t(std::ceil(value.self_maximum_memory / (1024.0 * 1024 * 1024)))); this->ui->dsb_system_limit->setValue(value.system_minimum_free); +} + +void MemoryPolicyDialog::on_pb_ok_clicked() noexcept { emit this->accept(); } + +void MemoryPolicyDialog::on_pb_cancel_clicked() noexcept { + emit this->reject(); +} + +void MemoryPolicyDialog::on_pb_reset_clicked() noexcept { + this->reset(memory_policy{}); } \ No newline at end of file diff --git a/utilities/StatMemory/MemoryPolicyDialog.h b/utilities/StatMemory/MemoryPolicyDialog.h index 64a6409b..99f121e6 100644 --- a/utilities/StatMemory/MemoryPolicyDialog.h +++ b/utilities/StatMemory/MemoryPolicyDialog.h @@ -12,8 +12,10 @@ struct memory_policy { bool auto_cache{true}; - uint64_t self_maximum_memory = 4 << 30; - double system_minimum_free = 0.2; + uint64_t self_maximum_memory{4ull << 30}; + double system_minimum_free{0.2}; + + // memory_policy() = default; [[nodiscard]] bool should_cache( const system_memory_info& smi) const noexcept { @@ -63,6 +65,11 @@ class MemoryPolicyDialog : public QDialog { [[nodiscard]] memory_policy current_value() const noexcept; void reset(const memory_policy&) noexcept; + + private slots: + void on_pb_ok_clicked() noexcept; + void on_pb_cancel_clicked() noexcept; + void on_pb_reset_clicked() noexcept; }; #endif // SLOPECRAFT_MEMORYPOLICYDIALOG_H From 46d32fcd5061d6b5aa9effbb0c261ee7bbbcb43d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 19 Jul 2024 13:38:44 +0800 Subject: [PATCH 0841/1123] fake implementation of stat memory for other os Signed-off-by: ToKiNoBug --- utilities/StatMemory/CMakeLists.txt | 12 +++++++++++- utilities/StatMemory/stat_memory_src/linux.cpp | 10 ++++++++++ utilities/StatMemory/stat_memory_src/macos.cpp | 10 ++++++++++ .../windows.cpp} | 4 ++-- 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 utilities/StatMemory/stat_memory_src/linux.cpp create mode 100644 utilities/StatMemory/stat_memory_src/macos.cpp rename utilities/StatMemory/{stat_memory_windows.cpp => stat_memory_src/windows.cpp} (95%) diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 90ff98e3..674140fc 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -21,9 +21,19 @@ target_include_directories(StatMemory PUBLIC $ +get_system_memory_info() noexcept { + return tl::make_unexpected("Yet not implemented for Linux"); +} + +[[nodiscard]] tl::expected +get_self_memory_info() noexcept { + return tl::make_unexpected("Yet not implemented for Linux"); +} \ No newline at end of file diff --git a/utilities/StatMemory/stat_memory_src/macos.cpp b/utilities/StatMemory/stat_memory_src/macos.cpp new file mode 100644 index 00000000..bf110e8a --- /dev/null +++ b/utilities/StatMemory/stat_memory_src/macos.cpp @@ -0,0 +1,10 @@ +#include "stat_memory.h" +tl::expected +get_system_memory_info() noexcept { + return tl::make_unexpected("Yet not implemented for macos"); +} + +[[nodiscard]] tl::expected +get_self_memory_info() noexcept { + return tl::make_unexpected("Yet not implemented for macos"); +} \ No newline at end of file diff --git a/utilities/StatMemory/stat_memory_windows.cpp b/utilities/StatMemory/stat_memory_src/windows.cpp similarity index 95% rename from utilities/StatMemory/stat_memory_windows.cpp rename to utilities/StatMemory/stat_memory_src/windows.cpp index 8389b2ac..06ca89b8 100644 --- a/utilities/StatMemory/stat_memory_windows.cpp +++ b/utilities/StatMemory/stat_memory_src/windows.cpp @@ -1,6 +1,6 @@ #include "stat_memory.h" -#include -#include +#include +#include #ifdef max #undef max From b5f60d7c4e726113802797e1456c616de68a94ea Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Jul 2024 11:37:46 +0800 Subject: [PATCH 0842/1123] implement stat memory for Linux Signed-off-by: ToKiNoBug --- utilities/StatMemory/CMakeLists.txt | 43 +++--- .../StatMemory/others/test_stat_memory.cpp | 30 ++++ .../StatMemory/stat_memory_src/linux.cpp | 145 +++++++++++++++++- 3 files changed, 194 insertions(+), 24 deletions(-) create mode 100644 utilities/StatMemory/others/test_stat_memory.cpp diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 674140fc..6001debd 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -4,36 +4,35 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -find_package(Qt6 COMPONENTS Widgets REQUIRED) -add_library(MemoryPolicyDialog STATIC - MemoryPolicyDialog.h - MemoryPolicyDialog.cpp - MemoryPolicyDialog.ui -) -target_link_libraries(MemoryPolicyDialog PUBLIC Qt6::Widgets) - add_library(StatMemory STATIC stat_memory.h) find_package(tl-expected REQUIRED) -target_link_libraries(StatMemory PUBLIC tl::expected) +find_package(fmt REQUIRED) +target_link_libraries(StatMemory PUBLIC tl::expected fmt::fmt) target_include_directories(StatMemory PUBLIC $) - -target_link_libraries(MemoryPolicyDialog PUBLIC StatMemory) - +target_compile_features(StatMemory PUBLIC cxx_std_23) +# Set source file by system if (${WIN32}) target_sources(StatMemory PRIVATE stat_memory_src/windows.cpp) target_link_libraries(StatMemory PUBLIC psapi.lib) - return() -endif () - -if (${LINUX}) +elseif (${LINUX}) target_sources(StatMemory PRIVATE stat_memory_src/linux.cpp) - return() -endif () - -if (${APPLE}) +elseif (${APPLE}) target_sources(StatMemory PRIVATE stat_memory_src/macos.cpp) - return() +elseif () + message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") endif () -message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") \ No newline at end of file +add_executable(test_stat_memory others/test_stat_memory.cpp) +target_link_libraries(test_stat_memory PRIVATE StatMemory) +add_test(NAME stat_memory + COMMAND test_stat_memory) + +find_package(Qt6 COMPONENTS Widgets REQUIRED) +add_library(MemoryPolicyDialog STATIC + MemoryPolicyDialog.h + MemoryPolicyDialog.cpp + MemoryPolicyDialog.ui +) +target_link_libraries(MemoryPolicyDialog PUBLIC Qt6::Widgets) +target_link_libraries(MemoryPolicyDialog PUBLIC StatMemory) diff --git a/utilities/StatMemory/others/test_stat_memory.cpp b/utilities/StatMemory/others/test_stat_memory.cpp new file mode 100644 index 00000000..a7495055 --- /dev/null +++ b/utilities/StatMemory/others/test_stat_memory.cpp @@ -0,0 +1,30 @@ +#include "stat_memory.h" +#include +#include +#include + +int main() { + int fail_count = 0; + { + const auto sys_info = get_system_memory_info(); + if (sys_info) { + const auto &val = sys_info.value(); + fmt::print("System free memory: {}\n", val.free); + fmt::print("System total memory: {}\n", val.total); + } else { + fmt::print("Failed to get system memory info:\n{}\n", sys_info.error()); + fail_count++; + } + } + + const auto self_info = get_self_memory_info(); + if (self_info) { + const auto &val = self_info.value(); + fmt::print("Memory used by this process: \"{}\"\n", val.used); + } else { + fmt::print("Failed to get self memory info:\n{}\n", self_info.error()); + fail_count++; + } + + return fail_count; +} \ No newline at end of file diff --git a/utilities/StatMemory/stat_memory_src/linux.cpp b/utilities/StatMemory/stat_memory_src/linux.cpp index 64d06c2c..4625ef9f 100644 --- a/utilities/StatMemory/stat_memory_src/linux.cpp +++ b/utilities/StatMemory/stat_memory_src/linux.cpp @@ -1,10 +1,151 @@ #include "stat_memory.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +tl::expected, std::string> parse_linux_file( + const char* filename, + const std::function& skip_this_line = {}) noexcept { + std::map fields; + std::string mem_info; + { + FILE* fd = fopen(filename, "r"); + if (fd == nullptr) { + return tl::make_unexpected( + fmt::format("Failed to read \"{}\", fopen returned NULL", filename)); + } + std::array buf; + while (true) { + const size_t bytes = fread(buf.data(), 1, buf.size(), fd); + mem_info.append(buf.data(), bytes); + if (bytes < buf.size()) { // end of file + break; + } + } + fclose(fd); + } + for (auto line : std::views::split(mem_info, '\n')) { + std::string_view line_sv{line.data(), line.size()}; + if (skip_this_line and skip_this_line(line_sv)) { + // if skip_this_line is not null, and this line is considered to be + // skipped + continue; + } + + if (line_sv.empty()) { + continue; + } + const size_t idx_of_colon = line_sv.find_first_of(':'); + if (idx_of_colon == line_sv.npos) { // Failed to parse this line, skip it. + continue; + // return tl::make_unexpected( + // fmt::format("Failed to parse \"{}\" from {}", line_sv, + // filename)); + } + + std::string_view key{line_sv.begin(), idx_of_colon}; + + std::string_view value_str{line_sv.begin() + idx_of_colon + 1, + line_sv.end()}; + std::string number_str{value_str.begin(), value_str.end()}; + uint64_t amplifier = 1; + for (char& c : number_str) { // to lower + if (c >= 'A' and c <= 'Z') { + c = std::tolower(c); + } + } + if (number_str.ends_with("kb")) { + amplifier = 1000; + for (int i = 0; i < 2; i++) number_str.pop_back(); + } + if (number_str.ends_with("kib")) { + amplifier = 1024; + for (int i = 0; i < 3; i++) number_str.pop_back(); + } + if (number_str.ends_with("mb")) { + amplifier = 1000 * 1000; + for (int i = 0; i < 2; i++) number_str.pop_back(); + } + if (number_str.ends_with("mib")) { + amplifier = 1024 * 1024; + for (int i = 0; i < 3; i++) number_str.pop_back(); + } + if (number_str.ends_with("gb")) { + amplifier = 1000 * 1000 * 1000; + for (int i = 0; i < 2; i++) number_str.pop_back(); + } + if (number_str.ends_with("gib")) { + amplifier = 1024 * 1024 * 1024; + for (int i = 0; i < 3; i++) number_str.pop_back(); + } + + const int64_t number = std::atoll(number_str.c_str()) * amplifier; + + fields.emplace(key, number); + } + + return fields; +} + tl::expected get_system_memory_info() noexcept { - return tl::make_unexpected("Yet not implemented for Linux"); + auto fileds = parse_linux_file("/proc/meminfo", [](std::string_view line) { + if (line.starts_with("MemTotal")) return false; + if (line.starts_with("MemFree")) return false; + return true; + }); + if (not fileds) { + return tl::make_unexpected(std::move(fileds).error()); + } + auto& value = fileds.value(); + system_memory_info ret; + auto it = value.find("MemTotal"); + if (it != value.end()) { + ret.total = it->second; + } else { + return tl::make_unexpected( + "Failed to parse field \"MemTotal\" from /proc/meminfo"); + } + it = value.find("MemFree"); + if (it not_eq value.end()) { + ret.free = it->second; + } else { + return tl::make_unexpected( + "Failed to parse field \"MemFree\" from /proc/meminfo"); + } + return ret; } [[nodiscard]] tl::expected get_self_memory_info() noexcept { - return tl::make_unexpected("Yet not implemented for Linux"); + const int64_t pid = getpid(); + const std::string file = fmt::format("/proc/{}/status", pid); + auto fields = parse_linux_file(file.c_str(), [](std::string_view line) { + return not line.starts_with("VmSize"); + }); + if (not fields) { + return tl::make_unexpected(std::move(fields.error())); + } + + auto& val = fields.value(); + auto it = val.find("VmSize"); + if (it not_eq val.end()) { + const int64_t used_memory = it->second; + if (used_memory < 0) { + return tl::make_unexpected(fmt::format( + "VmSize from {} is negative(the value is {})", file, used_memory)); + } + return self_memory_usage{uint64_t(used_memory)}; + } + + return tl::make_unexpected( + fmt::format("Failed to parse field VmSize from {}", file)); } \ No newline at end of file From 882f8c3166dbc4b305b19c6f92e922c990414a40 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Jul 2024 11:39:27 +0800 Subject: [PATCH 0843/1123] fix warnings Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 8 +++++--- SlopeCraft/SCWind.h | 6 +----- SlopeCraft/SCWind_slots.cpp | 4 ++-- SlopeCraftL/structure_3D.cpp | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 5416da65..ebba632d 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -839,8 +839,7 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { // } // } -void SCWind::refresh_current_build_display( - cvt_task *taskp, bool is_image_built_in_kernel) noexcept { +void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { this->ui->lb_show_3dsize->setText(tr("大小:")); this->ui->lb_show_block_count->setText(tr("方块数量:")); if (taskp == nullptr) { @@ -930,7 +929,10 @@ std::optional SCWind::current_nbt_option( err.clear(); return SlopeCraft::vanilla_structure_options{ - .is_air_structure_void = this->ui->cb_nbt_air_void->isChecked()}; + .is_air_structure_void = this->ui->cb_nbt_air_void->isChecked(), + .ui{}, + .progressbar{}, + }; } std::optional SCWind::current_schem_option( diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index ff8b1889..750dcddd 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -246,11 +246,7 @@ class SCWind : public QMainWindow { // [[deprecated]] QImage get_converted_image_from_kernel() const noexcept; - void refresh_current_build_display(cvt_task* taskp, - bool is_image_built_in_kernel) noexcept; - void refresh_current_build_display(cvt_task* taskp) noexcept { - return this->refresh_current_build_display(taskp, false); - } + void refresh_current_build_display(cvt_task* taskp) noexcept; void refresh_current_build_display() noexcept { this->refresh_current_build_display(this->selected_export_task()); } diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 6a8d7e6a..00d60375 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -417,7 +417,7 @@ void SCWind::on_pb_build3d_clicked() noexcept { } } // load cache if converted - this->refresh_current_build_display(&task, true); + this->refresh_current_build_display(&task); } void SCWind::on_pb_preview_materials_clicked() noexcept { @@ -962,7 +962,7 @@ void SCWind::on_ac_cache_all_3d_triggered() noexcept { void SCWind::on_ac_memory_policy_triggered() noexcept { MemoryPolicyDialog diag{this, this->mem_policy}; const auto result = diag.exec(); - + if (result) { this->mem_policy = diag.current_value(); this->auto_cache_3D(); diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index c8a99a41..b817d0cd 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -319,7 +319,7 @@ bool structure_3D_impl::export_flat_diagram( std::vector> img_list_rmj; img_list_rmj.reserve(this->schem.palette_size()); - for (int pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { + for (size_t pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { if (pblkid == 0) { img_list_rmj.emplace_back(); img_list_rmj[0].setZero(); @@ -358,7 +358,7 @@ bool structure_3D_impl::export_flat_diagram( } const int ele = this->schem(c, 0, r); - assert(ele >= 0 && ele < this->schem.palette_size()); + assert(ele >= 0 and ele < ptrdiff_t(this->schem.palette_size())); return libFlatDiagram::block_img_ref_t{img_list_rmj.at(ele).data()}; }; From 52b6b207f4d9032579b336600bb46957931338e1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Jul 2024 13:22:00 +0800 Subject: [PATCH 0844/1123] add filed stackSize to SCL block json Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 3 ++- SlopeCraftL/SlopeCraftL.cpp | 7 +++++++ SlopeCraftL/SlopeCraftL.h | 4 ++++ SlopeCraftL/mc_block.h | 5 +++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index f4816d9d..1f4b79f5 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -394,7 +394,8 @@ "nameEN": "Water", "icon": "water.png", "version": 0, - "wallUseable": false + "wallUseable": false, + "stackSize": 1 }, { "baseColor": 13, diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index c6a8208e..e61dcdec 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -84,6 +84,13 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( if (jo.contains("needGlass")) { ret.needGlass = jo.at("needGlass"); } + if (jo.contains("stackSize")) { + const int val = jo.at("stackSize"); + if (val <= 0 or val > 64) { + throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; + } + ret.stackSize = val; + } return {basecolor, ret}; } diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index e6422087..44e6bd52 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -99,6 +99,8 @@ class mc_block_interface { /// if this block can be burnt virtual bool getBurnable() const noexcept = 0; + virtual uint8_t getStackSize() const noexcept = 0; + virtual const char *getNameZH() const noexcept = 0; virtual const char *getNameEN() const noexcept = 0; virtual const char *getImageFilename() const noexcept = 0; @@ -123,6 +125,8 @@ class mc_block_interface { /// set if this block can be burnt virtual void setBurnable(bool) noexcept = 0; + virtual void setStackSize(uint8_t) noexcept = 0; + virtual void setNameZH(const char *) noexcept = 0; virtual void setNameEN(const char *) noexcept = 0; virtual void setImageFilename(const char *) noexcept = 0; diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index 389fb0e2..51b94f29 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -49,6 +49,7 @@ class mc_block : public ::SlopeCraft::mc_block_interface { bool doGlow{false}; bool endermanPickable{false}; bool burnable{false}; + uint8_t stackSize{64}; const char *getId() const noexcept override { return id.data(); }; uint8_t getVersion() const noexcept override { return version; }; @@ -59,6 +60,7 @@ class mc_block : public ::SlopeCraft::mc_block_interface { return endermanPickable; }; bool getBurnable() const noexcept override { return burnable; }; + uint8_t getStackSize() const noexcept override { return this->stackSize; } const char *getNameZH() const noexcept override { return this->nameZH.c_str(); } @@ -86,6 +88,9 @@ class mc_block : public ::SlopeCraft::mc_block_interface { endermanPickable = _enderman; }; void setBurnable(bool _burn) noexcept override { burnable = _burn; }; + void setStackSize(uint8_t stack_size) noexcept override { + this->stackSize = std::max(stack_size, 1); + } void setNameZH(const char *__nzh) noexcept override { this->nameZH = __nzh; } void setNameEN(const char *__nen) noexcept override { this->nameEN = __nen; } From 4536c5c0801dbc4880606fb7ea57c1361ca10cf1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Jul 2024 13:22:17 +0800 Subject: [PATCH 0845/1123] fix #116 Signed-off-by: ToKiNoBug --- SlopeCraft/PreviewWind.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 8139719b..61fd9019 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -196,8 +196,7 @@ QVariant MaterialModel::data(const QModelIndex& qmi, int role) const noexcept { if (!this->pwind->is_unit_stack()) { return QString::number(mat.count); } - - const int stack_size = (r == 12) ? 1 : 64; + const int stack_size = std::max(1, mat.blk->getStackSize()); return format_num(mat.count, stack_size); } } From 373fcc54cfa920e67e5bd029cf685d3930533ffb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 21 Jul 2024 15:20:45 +0800 Subject: [PATCH 0846/1123] support selecting-all, deselecting-all and inverse selecting Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 42 ++++- SlopeCraft/SCWind.h | 4 + SlopeCraft/SCWind.ui | 162 +++++++++--------- SlopeCraft/SCWind_slots.cpp | 28 +++ utilities/BlockListManager/BlockListManager.h | 9 + utilities/ColorManip/colorset_maptical.hpp | 4 +- 6 files changed, 158 insertions(+), 91 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index ebba632d..e77906b9 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -92,6 +92,9 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { this->ui->lview_pool_cvt->doItemsLayout(); this->ui->lview_pool_export->doItemsLayout(); }); + + connect(this->ui->tw_cvt_image, &QTabWidget::currentChanged, this, + &SCWind::when_cvt_pool_selectionChanged); } { this->export_table_model = new ExportTableModel{this}; @@ -109,7 +112,6 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { connect(rbp, &QRadioButton::clicked, this, &SCWind::when_export_type_toggled); } - for (QRadioButton *rbp : this->preset_buttons_no_custom()) { connect(rbp, &QRadioButton::clicked, this, &SCWind::when_preset_clicked); } @@ -186,8 +188,8 @@ SlopeCraft::color_table *SCWind::current_color_table() noexcept { std::unique_ptr ptr{ SlopeCraft::SCL_create_color_table(ci)}; if (ptr == nullptr) { - QMessageBox::warning(this, tr("设置方块列表失败"), - tr("您设置的方块列表可能存在错误")); + // QMessageBox::warning(this, tr("设置方块列表失败"), + // tr("您设置的方块列表可能存在错误")); return nullptr; } @@ -481,7 +483,8 @@ void SCWind::when_blocklist_changed() noexcept { void SCWind::set_colorset() noexcept { auto color_table = this->current_color_table(); - const int num_colors = color_table->colors().num_colors; + const int num_colors = + (color_table not_eq nullptr) ? color_table->colors().num_colors : 0; this->ui->lb_avaliable_colors->setText( tr("可用颜色数量:%1").arg(num_colors)); @@ -660,6 +663,28 @@ SCWind::convert_image(int idx) noexcept { std::unique_ptr SCWind::convert_image(const cvt_task &task) noexcept { auto ctable = this->current_color_table(); + if (ctable == nullptr) { + QMessageBox::critical( + this, tr("没有可用颜色"), + tr("没有勾选任何颜色,无法转化图像。请至少勾选3~16种颜色。")); + return nullptr; + } + + const auto num_blocks = ctable->num_blocks(); + if (num_blocks <= 3) { + const auto reply = QMessageBox::warning( + this, tr("勾选颜色太少"), + tr("仅仅勾选了%" + "1种颜色,颜色过少,转化效率可能非常差。您可以点Yes继续" + "转化,但非常建议请尽量多勾选一些颜色。") + .arg(num_blocks), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, + QMessageBox::StandardButton::No}, + QMessageBox::StandardButton::No); + if (reply not_eq QMessageBox::StandardButton::Yes) { + return nullptr; + } + } const QImage &raw = task.original_image; { @@ -679,8 +704,10 @@ const SlopeCraft::converted_image &SCWind::convert_if_need( cvt_task &task) noexcept { const auto table = this->current_color_table(); const auto opt = this->current_convert_option(); - if (!task.is_converted_with(table, opt)) { - task.set_converted(table, opt, this->convert_image(task)); + if (not task.is_converted_with(table, opt)) { + auto cvted = this->convert_image(task); + assert(cvted); + task.set_converted(table, opt, std::move(cvted)); } auto &cvted = task.converted_images[{table, opt}].converted_image; @@ -809,6 +836,9 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { QMessageBox::StandardButton::Ignore}); if (ret == QMessageBox::StandardButton::Ok) { auto cvted_uptr = this->convert_image(task); + if (cvted_uptr == nullptr) { + return; + } task.set_converted(this->current_color_table(), this->current_convert_option(), std::move(cvted_uptr)); cvted = task.get_converted_image(this->current_color_table(), diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 750dcddd..263c99ad 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -74,6 +74,10 @@ class SCWind : public QMainWindow { void on_pb_prefer_logs_clicked() noexcept; void on_pb_prefer_slabs_clicked() noexcept; + void on_pb_select_all_clicked() noexcept; + void on_pb_deselect_all_clicked() noexcept; + void on_pb_invselect_clicked() noexcept; + void when_cvt_pool_selectionChanged() noexcept; void when_export_pool_selectionChanged() noexcept; void when_version_buttons_toggled() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index ed98fcd6..9b9d0a30 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -31,14 +31,14 @@ 方块列表预设 - - + + - 加载预设 + 可用方块数量: - + 保存当前预设 @@ -46,26 +46,13 @@ - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - + - 可用方块数量: + 加载预设 - + 0 @@ -241,7 +228,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -265,13 +252,6 @@ - - - - 优先混凝土 - - - @@ -300,6 +280,34 @@ + + + + 优先混凝土 + + + + + + + 全选 + + + + + + + 全不选 + + + + + + + 反选 + + + @@ -312,8 +320,8 @@ 0 0 - 750 - 653 + 627 + 644 @@ -336,16 +344,16 @@ - QTabWidget::TabPosition::North + QTabWidget::North - QTabWidget::TabShape::Rounded + QTabWidget::Rounded 0 - Qt::TextElideMode::ElideNone + Qt::ElideLeft false @@ -373,10 +381,7 @@ true - QFrame::Shape::Box - - - QFrame::Shadow::Sunken + QFrame::NoFrame 1 @@ -387,9 +392,6 @@ false - - Qt::AlignmentFlag::AlignCenter - @@ -411,10 +413,7 @@ true - QFrame::Shape::Box - - - QFrame::Shadow::Sunken + QFrame::NoFrame 1 @@ -422,9 +421,6 @@ - - Qt::AlignmentFlag::AlignCenter - @@ -458,7 +454,7 @@ false - QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed + QAbstractItemView::NoEditTriggers true @@ -467,34 +463,34 @@ false - QAbstractItemView::DragDropMode::InternalMove + QAbstractItemView::NoDragDrop - Qt::DropAction::CopyAction + Qt::IgnoreAction - QAbstractItemView::SelectionMode::ExtendedSelection + QAbstractItemView::ExtendedSelection - Qt::TextElideMode::ElideLeft + Qt::ElideLeft - QListView::Movement::Snap + QListView::Static - QListView::Flow::TopToBottom + QListView::TopToBottom false - QListView::ResizeMode::Fixed + QListView::Adjust 10 - QListView::ViewMode::IconMode + QListView::IconMode 0 @@ -505,6 +501,9 @@ true + + Qt::AlignHCenter|Qt::AlignTop + @@ -519,9 +518,6 @@ 项目池 - - Qt::AlignmentFlag::AlignCenter - @@ -643,7 +639,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -686,9 +682,6 @@ 项目池 - - Qt::AlignmentFlag::AlignCenter - @@ -697,7 +690,7 @@ false - QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed + QAbstractItemView::NoEditTriggers true @@ -706,34 +699,37 @@ false - QAbstractItemView::DragDropMode::InternalMove + QAbstractItemView::NoDragDrop - Qt::DropAction::CopyAction + Qt::IgnoreAction - QAbstractItemView::SelectionMode::ExtendedSelection + QAbstractItemView::ExtendedSelection - Qt::TextElideMode::ElideLeft + Qt::ElideLeft - QListView::Movement::Snap + QListView::Static - QListView::Flow::TopToBottom + QListView::TopToBottom false - QListView::ResizeMode::Fixed + QListView::Adjust + + + QListView::SinglePass 10 - QListView::ViewMode::IconMode + QListView::IconMode 0 @@ -744,6 +740,9 @@ true + + Qt::AlignHCenter|Qt::AlignTop + @@ -968,7 +967,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -998,7 +997,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -1212,7 +1211,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -1269,7 +1268,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -1328,9 +1327,9 @@ 0 - + - Qt::Orientation::Horizontal + Qt::Horizontal @@ -1377,7 +1376,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -1406,9 +1405,6 @@ 在下面的表格里可以看到每个图像对应的文件名。 - - Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop - true @@ -1430,7 +1426,7 @@ 0 0 920 - 33 + 23 diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 00d60375..636b018a 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -246,6 +246,24 @@ void SCWind::on_pb_prefer_slabs_clicked() noexcept { -> int { return impl_select_blk_by_id(blks, "_slab"); }); } +void SCWind::on_pb_select_all_clicked() noexcept { + for (size_t bc = 0; bc < this->ui->blm->num_basecolor_widgets(); bc++) { + this->ui->blm->basecolorwidget_at(bc)->set_enabled(true); + } +} +void SCWind::on_pb_deselect_all_clicked() noexcept { + for (size_t bc = 1; bc < this->ui->blm->num_basecolor_widgets(); bc++) { + this->ui->blm->basecolorwidget_at(bc)->set_enabled(false); + } +} +void SCWind::on_pb_invselect_clicked() noexcept { + for (size_t bc = 1; bc < this->ui->blm->num_basecolor_widgets(); bc++) { + BaseColorWidget *bcw = this->ui->blm->basecolorwidget_at(bc); + assert(bcw not_eq nullptr); + bcw->set_enabled(not bcw->is_enabled()); + } +} + void SCWind::on_pb_cvt_current_clicked() noexcept { const auto sel = this->selected_cvt_task_idx(); @@ -480,6 +498,16 @@ void SCWind::on_pb_preview_compress_effect_clicked() noexcept { } void SCWind::on_pb_export_all_clicked() noexcept { + { + auto ctable = this->current_color_table(); + if (ctable == nullptr) { + QMessageBox::critical( + this, tr("没有可用颜色"), + tr("没有勾选任何颜色,无法转化图像。请至少勾选3~16种颜色。")); + return; + } + } + auto tasks_to_export = this->selected_export_task_list(); const auto export_type = this->selected_export_type(); diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 8cd4f58e..43d662a3 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -100,6 +100,15 @@ class BlockListManager : public QWidget { blockListPreset to_preset() const noexcept; + size_t num_basecolor_widgets() const noexcept { + assert(this->basecolor_widgets.size() < 256); + return this->basecolor_widgets.size(); + } + + BaseColorWidget *basecolorwidget_at(size_t basecolor) noexcept { + return this->basecolor_widgets[basecolor].get(); + } + const BaseColorWidget *basecolorwidget_at(size_t basecolor) const noexcept { return this->basecolor_widgets[basecolor].get(); } diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 3358048a..5b5e7930 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -125,7 +125,7 @@ class alignas(32) colorset_maptical_allowed { std::array __xyz; Eigen::Array __map; // std::array __map; - int _color_count; + int _color_count{0}; std::array depth_counter; @@ -231,7 +231,7 @@ class alignas(32) colorset_maptical_allowed { } } this->depth_counter.fill(0); - for (int idx = 0; idx < this->color_count(); idx++) { + for (int idx = 0; idx < new_color_count; idx++) { const uint8_t mapcolor = this->Map(idx); const uint8_t base = mapcolor >> 2; if (base != 0) { From c75ee13b92876824f02159dd202ee658c6b90c4b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 23 Jul 2024 17:35:58 +0800 Subject: [PATCH 0847/1123] fix LSP warnings in SCWind_slots.cpp Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 636b018a..b2ecbdef 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -155,7 +155,7 @@ void SCWind::on_pb_load_preset_clicked() noexcept { blockListPreset preset = load_preset(file, err); if (!err.isEmpty()) { QMessageBox::warning(this, tr("解析预设文件失败"), - tr("预设文件%1存在错误:%2").arg(file).arg(err)); + tr("预设文件%1存在错误:%2").arg(file, err)); return; } @@ -181,10 +181,9 @@ void SCWind::on_pb_save_preset_clicked() noexcept { qf.open(QFile::OpenMode{QIODevice::WriteOnly | QIODevice::Text}); if (!qf.isOpen()) { - QMessageBox::warning(this, tr("保存预设文件失败"), - tr("无法生成预设文件%1,错误信息:%2") - .arg(file) - .arg(qf.errorString())); + QMessageBox::warning( + this, tr("保存预设文件失败"), + tr("无法生成预设文件%1,错误信息:%2").arg(file, qf.errorString())); return; } @@ -260,7 +259,7 @@ void SCWind::on_pb_invselect_clicked() noexcept { for (size_t bc = 1; bc < this->ui->blm->num_basecolor_widgets(); bc++) { BaseColorWidget *bcw = this->ui->blm->basecolorwidget_at(bc); assert(bcw not_eq nullptr); - bcw->set_enabled(not bcw->is_enabled()); + bcw->set_enabled(not(bcw->is_enabled())); } } @@ -339,8 +338,7 @@ void SCWind::on_pb_save_converted_clicked() noexcept { for (int idx : selected) { auto &task = this->tasks[idx]; QString filename = QStringLiteral("%1/%2.png") - .arg(out_dir) - .arg(QFileInfo{task.filename}.baseName()); + .arg(out_dir, QFileInfo{task.filename}.baseName()); if (QFile{filename}.exists()) { if (no_to_all_replace_existing) { @@ -573,9 +571,8 @@ void SCWind::on_pb_export_all_clicked() noexcept { auto get_export_name = [dir, this](const cvt_task &t) -> QString { return QStringLiteral("%1/%2.%3") - .arg(dir) - .arg(QFileInfo{t.filename}.baseName()) - .arg(extension_of_export_type(this->selected_export_type())); + .arg(dir, QFileInfo{t.filename}.baseName(), + extension_of_export_type(this->selected_export_type())); }; // warn if some files will be covered @@ -622,8 +619,7 @@ void SCWind::on_pb_export_all_clicked() noexcept { this, tr("导出失败"), tr("导出%1时失败。原图像文件名为%" "2\n点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。") - .arg(export_name.data()) - .arg(taskp->filename), + .arg(export_name.data(), taskp->filename), QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, QMessageBox::StandardButton::Cancel}); }; @@ -786,7 +782,7 @@ void SCWind::on_ac_clear_cache_triggered() noexcept { continue; } - QString filename = QStringLiteral("%1/%2").arg(cache_dir_name).arg(name); + QString filename = QStringLiteral("%1/%2").arg(cache_dir_name, name); while (true) { if (remove_cache_fun(filename)) { @@ -976,10 +972,9 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { if (!this->current_color_table()->generate_test_schematic( filename.toLocal8Bit().data(), opt)) { QString qerr = QString::fromUtf8(err.data()); - QMessageBox::warning(this, tr("输出测试文件失败"), - tr("保存测试文件 %1 时出现错误。详细信息:\n%2") - .arg(filename) - .arg(qerr)); + QMessageBox::warning( + this, tr("输出测试文件失败"), + tr("保存测试文件 %1 时出现错误。详细信息:\n%2").arg(filename, qerr)); } } From 694cfa8c73ad4d36deb24d6849c93392af1c1f0f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 24 Jul 2024 00:50:07 +0800 Subject: [PATCH 0848/1123] fix material indexing of mushrooms Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index b6b7809d..ff45c4e3 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -197,7 +197,7 @@ const mc_block *color_table_impl::find_block_for_index( return nullptr; } - if (lsi::pureid_to_type(blkp->id) != mush_type_opt) { + if (lsi::pureid_to_type(pure_id) != mush_type_opt) { return nullptr; } @@ -350,6 +350,10 @@ void color_table_impl::stat_blocks(const structure_3D &s, continue; } assert(schem_blk_id > 0); + if (schem_stat[schem_blk_id] <= 0) { + continue; + } + const auto strid = structure.schem.palette()[schem_blk_id]; const auto blkp = this->find_block_for_index(schem_blk_id - 1, strid); if (blkp == nullptr) { From 540d58e1e6941c341ac099be811fcf9819cd71b7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 24 Jul 2024 12:51:29 +0800 Subject: [PATCH 0849/1123] add button to export material list Signed-off-by: ToKiNoBug --- SlopeCraft/PreviewWind.cpp | 42 ++++++++++++-- SlopeCraft/PreviewWind.h | 5 ++ SlopeCraft/PreviewWind.ui | 113 +++++++++++++++++++++++-------------- 3 files changed, 113 insertions(+), 47 deletions(-) diff --git a/SlopeCraft/PreviewWind.cpp b/SlopeCraft/PreviewWind.cpp index 61fd9019..243a97f9 100644 --- a/SlopeCraft/PreviewWind.cpp +++ b/SlopeCraft/PreviewWind.cpp @@ -1,8 +1,10 @@ -#include "PreviewWind.h" -#include "ui_PreviewWind.h" #include #include +#include +#include #include +#include "PreviewWind.h" +#include "ui_PreviewWind.h" #include "SCWind.h" #include "CopyableTableView.h" @@ -22,10 +24,13 @@ PreviewWind::PreviewWind(QWidget* parent) &MaterialModel::refresh); this->ui->tv_mat->setModel(this->mmp); - connect(this->ui->tv_mat, &CopyableTableView::copied, [this]() noexcept { + auto on_copied = [this]() noexcept { this->setWindowTitle( tr("%1 -- 表格内容已复制到剪贴板").arg(tr("查看材料列表"))); - }); + }; + connect(this->ui->tv_mat, &CopyableTableView::copied, on_copied); + connect(this->ui->pb_copy_to_clipboard, &QPushButton::clicked, + this->ui->tv_mat, &CopyableTableView::copied); } PreviewWind::~PreviewWind() {} @@ -99,6 +104,35 @@ PreviewWind::sort_option PreviewWind::current_sort_option() const noexcept { } } +void PreviewWind::on_pb_export_file_clicked() noexcept { + const QString out_file = QFileDialog::getSaveFileName( + this, tr("保存材料表"), this->export_mat_list_prev_dir, "*.csv"); + if (out_file.isEmpty()) { + return; + } + this->export_mat_list_prev_dir = QFileInfo{out_file}.dir().path(); + + QFile ofile{out_file, this}; + if (not ofile.open(QIODevice::OpenMode::enum_type::WriteOnly)) { + QMessageBox::warning(this, tr("保存材料表失败"), + tr("无法打开文件 \"%1\",详细信息:%2") + .arg(out_file, ofile.errorString())); + return; + } + + ofile.write("\"Block name\",\"Block id\",\"Count\"\n"); + const auto current_version = + dynamic_cast(this->parent())->selected_version(); + for (const auto& mat : this->mat_list) { + QString line = + QStringLiteral("\"%1\",\"%2\",%3\n") + .arg(mat.blk->getNameEN(), mat.blk->idForVersion(current_version)) + .arg(mat.count); + ofile.write(line.toLocal8Bit()); + } + ofile.close(); +} + MaterialModel::MaterialModel(PreviewWind* parent) : QAbstractTableModel(parent), pwind(parent) {} diff --git a/SlopeCraft/PreviewWind.h b/SlopeCraft/PreviewWind.h index 62ec4eca..fd8b7941 100644 --- a/SlopeCraft/PreviewWind.h +++ b/SlopeCraft/PreviewWind.h @@ -27,6 +27,8 @@ class PreviewWind : public QDialog { std::vector mat_list; MaterialModel* mmp{nullptr}; + QString export_mat_list_prev_dir; + void set_size(std::span size) & noexcept; void set_total_count(size_t count) & noexcept; @@ -42,6 +44,9 @@ class PreviewWind : public QDialog { bool is_unit_stack() const noexcept; sort_option current_sort_option() const noexcept; + + private slots: + void on_pb_export_file_clicked() noexcept; }; class MaterialModel : public QAbstractTableModel { diff --git a/SlopeCraft/PreviewWind.ui b/SlopeCraft/PreviewWind.ui index e841a577..ff1533cb 100644 --- a/SlopeCraft/PreviewWind.ui +++ b/SlopeCraft/PreviewWind.ui @@ -14,35 +14,6 @@ 查看材料列表 - - - - - 0 - 0 - - - - 按组显示 - - - true - - - - - - - - - - QFrame::StyledPanel - - - - - - @@ -55,20 +26,7 @@ - QFrame::StyledPanel - - - - - - - - - - - - - QFrame::StyledPanel + QFrame::Shape::StyledPanel @@ -119,6 +77,75 @@ + + + + + + + QFrame::Shape::StyledPanel + + + + + + + + + + + + + QFrame::Shape::StyledPanel + + + + + + + + + + + 0 + 0 + + + + 按组显示 + + + true + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 导出为文件 + + + + + + + 复制到剪贴板 + + + From bcbc5262d92773a046b581388e183d2fb707fdd6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 24 Jul 2024 23:17:27 +0800 Subject: [PATCH 0850/1123] new dep: libnbt++ Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 5 ++++- cmake/required_deps/boost.cmake | 5 ++++- cmake/required_deps/libnbt++.cmake | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 cmake/required_deps/libnbt++.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 25694958..9f6ec5d2 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -5,11 +5,12 @@ find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) -find_package(Boost COMPONENTS iostreams REQUIRED) +find_package(Boost COMPONENTS iostreams multi_array REQUIRED) find_package(libzip REQUIRED) find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) find_package(cereal REQUIRED) +find_package(libnbt++ REQUIRED) #find_package(zstd REQUIRED) set(SlopeCraft_SCL_windows_rc_files) @@ -96,9 +97,11 @@ set(SlopeCraft_SCL_link_libs Eigen3::Eigen Heu::Genetic Boost::iostreams + Boost::multi_array libzip::zip tl::expected cereal::cereal + nbt++ ${SC_zstd_target_name}) # link to dependents diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 33c965b2..1e17b466 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,7 +1,10 @@ find_package(Boost - COMPONENTS iostreams + COMPONENTS iostreams multi_array REQUIRED) if (NOT TARGET Boost::iostreams) message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") +endif () +if (NOT TARGET Boost::multi_array) + message(FATAL_ERROR "Failed to find Boost::multi_array, install boost first") endif () \ No newline at end of file diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake new file mode 100644 index 00000000..02cbd48c --- /dev/null +++ b/cmake/required_deps/libnbt++.cmake @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.29) +set(NBT_BUILD_SHARED OFF CACHE BOOL "") +set(NBT_BUILD_TESTS OFF CACHE BOOL "") +FetchContent_Declare(libnbt++ + GIT_REPOSITORY https://github.com/PrismLauncher/libnbtplusplus + GIT_TAG 23b955121b8217c1c348a9ed2483167a6f3ff4ad #Merge pull request #3 from TheKodeToad/max-depth-attempt2 + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL) +message(STATUS "Cloning libnbt++...") +FetchContent_MakeAvailable(libnbt++) +find_package(libnbt++ REQUIRED) + +find_package(zlib REQUIRED) +target_link_libraries(nbt++ ZLIB::ZLIB) \ No newline at end of file From 314cd0368951ca77cbaccb5fce0301778ffde5d9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 25 Jul 2024 20:02:44 +0800 Subject: [PATCH 0851/1123] add sNBT formatter Signed-off-by: ToKiNoBug --- utilities/CMakeLists.txt | 1 + utilities/sNBT_formatter/CMakeLists.txt | 4 + utilities/sNBT_formatter/sNBT_formatter.cpp | 98 +++++++++++++++++++++ utilities/sNBT_formatter/sNBT_formatter.h | 55 ++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 utilities/sNBT_formatter/CMakeLists.txt create mode 100644 utilities/sNBT_formatter/sNBT_formatter.cpp create mode 100644 utilities/sNBT_formatter/sNBT_formatter.h diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 0fe95201..56d378b9 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -16,6 +16,7 @@ add_subdirectory(VCLConfigLoader) add_subdirectory(FlatDiagram) add_subdirectory(libpngReader) add_subdirectory(StatMemory) +add_subdirectory(sNBT_formatter) function(SC_process_boolean value_name) if (${${value_name}}) diff --git a/utilities/sNBT_formatter/CMakeLists.txt b/utilities/sNBT_formatter/CMakeLists.txt new file mode 100644 index 00000000..e2b7c364 --- /dev/null +++ b/utilities/sNBT_formatter/CMakeLists.txt @@ -0,0 +1,4 @@ +find_package(libnbt++ REQUIRED) + +add_library(sNBT-formatter STATIC sNBT_formatter.h sNBT_formatter.cpp) +target_link_libraries(sNBT-formatter PUBLIC nbt++) \ No newline at end of file diff --git a/utilities/sNBT_formatter/sNBT_formatter.cpp b/utilities/sNBT_formatter/sNBT_formatter.cpp new file mode 100644 index 00000000..4fa04bef --- /dev/null +++ b/utilities/sNBT_formatter/sNBT_formatter.cpp @@ -0,0 +1,98 @@ +// +// Created by Joseph on 2024/7/25. +// + +#include "sNBT_formatter.h" + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_byte &b) { + os << static_cast(b.get()) << "b"; +} // We don't want to print a character + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_short &s) { + this->os << s.get() << 's'; +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_int &i) { + this->os << i.get(); +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_long &l) { + this->os << l.get() << 'l'; +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_float &f) { + this->os << f.get() << 'f'; +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_double &d) { + this->os << d.get() << 'd'; +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_byte_array &ba) { + this->os << "[B;"; + for (size_t i = 0; i < ba.size() - 1; i++) { + this->os << ba[i] << 'b'; + } + if (ba.size() > 0) { + this->os << ba[ba.size() - 1] << "b]"; + } else { + os << "]"; + } +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_int_array &ia) { + this->os << "[I;"; + for (size_t i = 0; i < ia.size() - 1; i++) { + this->os << ia[i]; + } + if (ia.size() > 0) { + this->os << ia[ia.size() - 1] << ']'; + } else { + os << "]"; + } +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_long_array &la) { + this->os << "[L;"; + for (size_t i = 0; i < la.size() - 1; i++) { + this->os << la[i] << 'l'; + } + if (la.size() > 0) { + this->os << la[la.size() - 1] << "l]"; + } else { + os << "]"; + } +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_string &s) { + os << '"' << s.get() << '"'; +} // TODO: escape special characters + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_list &l) { + os << "["; + for (size_t idx = 0; idx < l.size(); idx++) { + l[idx].get().accept(*this); + if (idx < l.size() - 1) { + os << ','; + } + } + os << "]"; +} + +void sNBT::sNBT_format_visitor::visit(const nbt::tag_compound &c) { + if (c.size() == 0) { + this->os << "{}"; + return; + } + this->os << "{"; + size_t idx = 0; + for (auto &[key, val] : c) { + this->os << '\"' << key << "\":"; + val.get().accept(*this); + if (idx < c.size() - 1) { + this->os << ','; + } + idx++; + } + this->os << "}"; +} \ No newline at end of file diff --git a/utilities/sNBT_formatter/sNBT_formatter.h b/utilities/sNBT_formatter/sNBT_formatter.h new file mode 100644 index 00000000..73a5c007 --- /dev/null +++ b/utilities/sNBT_formatter/sNBT_formatter.h @@ -0,0 +1,55 @@ +// +// Created by Joseph on 2024/7/25. +// + +#ifndef SLOPECRAFT_SNBT_FORMATTOR_H +#define SLOPECRAFT_SNBT_FORMATTOR_H + +#include +#include +#include +#include + +#include +#include + +namespace sNBT { + +class sNBT_format_visitor : public nbt::const_nbt_visitor { + private: + std::ostream &os; + + auto iterator() const noexcept { + return std::ostream_iterator{this->os}; + } + + public: + sNBT_format_visitor(std::ostream &dest) : os{dest} {} + + void visit(const nbt::tag_byte &b) override; + + void visit(const nbt::tag_short &s) override; + + void visit(const nbt::tag_int &i) override; + + void visit(const nbt::tag_long &l) override; + + void visit(const nbt::tag_float &f) override; + + void visit(const nbt::tag_double &d) override; + + void visit(const nbt::tag_byte_array &ba) override; + + void visit(const nbt::tag_int_array &ia) override; + + void visit(const nbt::tag_long_array &la) override; + + void visit(const nbt::tag_string &s) override; + + void visit(const nbt::tag_list &l) override; + + void visit(const nbt::tag_compound &c) override; +}; +} // namespace sNBT + +#endif // SLOPECRAFT_SNBT_FORMATTOR_H From 1ace7af9e764aef9b41934fa5dd92edceba6b92e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 25 Jul 2024 21:33:00 +0800 Subject: [PATCH 0852/1123] generate /give command to give map items Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 1 + SlopeCraftL/SlopeCraftL.h | 43 +++++++- SlopeCraftL/converted_image.cpp | 181 +++++++++++++++++++++++++++++++- SlopeCraftL/converted_image.h | 6 ++ 4 files changed, 228 insertions(+), 3 deletions(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 9f6ec5d2..f2fa2f82 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -90,6 +90,7 @@ set(SlopeCraft_SCL_link_libs MapImageCvter FlatDiagram libpng_reader + sNBT-formatter ZLIB::ZLIB OpenMP::OpenMP_CXX diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 44e6bd52..f10bce24 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -24,6 +24,7 @@ This file is part of SlopeCraft. #define KERNEL_H #include #include +#include #include "SlopeCraftL_export.h" @@ -78,6 +79,34 @@ struct string_deliver { return string_deliver{s.data(), s.size()}; } }; +/// Struct to wrap anything like ostream, safe to use in ABI +struct ostream_wrapper { + void *handle{nullptr}; + + using write_fun = void (*)(const void *data, size_t len_bytes, void *handle); + write_fun callback_write_data{nullptr}; + + inline void write(const void *data, size_t len_bytes) { + this->callback_write_data(data, len_bytes, this->handle); + } + inline void write(const char *str) { + this->write(reinterpret_cast(str), strlen(str)); + } + + template + [[nodiscard]] inline static ostream_wrapper wrap_std_ostream( + ostream_t &os) noexcept { + return ostream_wrapper{ + .handle = reinterpret_cast(&os), + .callback_write_data = [](const void *data, size_t len_bytes, + void *h) -> size_t { + ostream_t &os = *reinterpret_cast(h); + os.write(reinterpret_cast(data), len_bytes); + return len_bytes; + }, + }; + } +}; class mc_block_interface { public: @@ -224,6 +253,16 @@ struct map_data_file_options { ui_callbacks ui{}; }; +struct map_data_file_give_command_options { + uint64_t caller_api_version{SC_VERSION_U64}; + ostream_wrapper *destination{}; + int begin_index{0}; + uint8_t stack_count{1}; /// <- Stack count of filed_map + bool set_name_as_index{true}; + bool after_1_12{false}; + bool after_1_20_5{false}; +}; + struct build_options { uint64_t caller_api_version{SC_VERSION_U64}; uint16_t max_allowed_height{256}; @@ -389,6 +428,9 @@ class converted_image { [[nodiscard]] virtual bool is_converted_from( const color_table &) const noexcept = 0; + + [[nodiscard]] virtual bool get_map_command( + const map_data_file_give_command_options &option) const = 0; }; class structure_3D { @@ -489,7 +531,6 @@ class deleter { SCL_destroy_structure_3D(s); } }; - } // namespace SlopeCraft } // extern "C" diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 1b5fe987..a1dbe3d3 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -71,8 +71,10 @@ bool converted_image_impl::export_map_data( const SlopeCraft::map_data_file_options &option) const noexcept { const std::filesystem::path dir{option.folder_path}; const auto mapPic = this->converter.mapcolor_matrix(); - const int rows = ceil(mapPic.rows() / 128.0f); - const int cols = ceil(mapPic.cols() / 128.0f); + const int rows = this->map_rows(); + const int cols = this->map_cols(); + // const int rows = ceil(mapPic.rows() / 128.0f); + // const int cols = ceil(mapPic.cols() / 128.0f); option.progress.set_range(0, 128 * rows * cols, 0); // int offset[2] = {0, 0}; // r,c @@ -328,6 +330,181 @@ bool converted_image_impl::is_converted_from( const auto &table = dynamic_cast(table_); return (this->colorset.get() == table.allowed.get()); } +#include +#include +#include +#include +#include +#include + +constexpr int chest_rows = 3; +constexpr int chest_cols = 9; + +int8_t chest_index_to_slot(int row, int col) noexcept { + assert(row >= 0 and row < chest_rows); + assert(col >= 0 and col < chest_cols); + return static_cast(row * chest_cols + col); +} + +nbt::tag_compound &get_or_setup_field(nbt::tag_compound &parent, + const std::string &key) noexcept { + if (parent.has_key(key, nbt::tag_type::Compound)) { + return parent[key].as(); + } + auto ret = parent.emplace(key, nbt::tag_compound{}); + return ret.first->second.as(); +} + +// Merge each 3*9 zone into a chest recursively, until whole item matrix is +// merged into one chest item +nbt::tag_compound merge_with_chest( + boost::multi_array item_matrix, + const map_data_file_give_command_options &option) noexcept { + const size_t new_rows = std::ceil(float(item_matrix.shape()[0]) / chest_rows); + const size_t new_cols = std::ceil(float(item_matrix.shape()[1]) / chest_cols); + boost::multi_array merged_chests{ + boost::extents[new_rows][new_cols]}; + // Move and merge previous data into new 2d array + for (int merged_col = 0; merged_col < new_cols; merged_col++) { + for (int merged_row = 0; merged_row < new_rows; merged_row++) { + nbt::tag_list item_list; + for (int c_offset = 0; c_offset < chest_cols; c_offset++) { + for (int r_offset = 0; r_offset < chest_rows; r_offset++) { + const int c_original = c_offset + merged_col * chest_cols; + const int r_original = r_offset + merged_row * chest_rows; + if (r_original >= item_matrix.shape()[0] or + c_original >= item_matrix.shape()[1]) { + continue; + } + nbt::tag_compound cur_item{ + std::move(item_matrix[r_original][c_original])}; + if (cur_item.size() <= 0) { + // skip empty item + continue; + } + const int8_t slot = chest_index_to_slot(r_offset, c_offset); + // set slot + cur_item.emplace("Slot", slot); + item_list.emplace_back(std::move(cur_item)); + } + } + + nbt::tag_compound chest_item; + chest_item.emplace("id", "minecraft:chest"); + if (not option.after_1_20_5) { + chest_item.emplace("Count", 1); + } else { + chest_item.emplace("count", 1); + } +#warning "This should be corrected for 1.20.5+" + nbt::tag_compound blk_entity_tag; + blk_entity_tag.emplace("Items", std::move(item_list)); + get_or_setup_field(chest_item, "tag") + .emplace("BlockEntityTag", + std::move(blk_entity_tag)); + + merged_chests[merged_row][merged_col] = std::move(chest_item); + } + } + + if (new_rows <= 1 and new_cols <= 1) { + return merged_chests[0][0]; + } + + return merge_with_chest(std::move(merged_chests), option); +} + +bool converted_image_impl::get_map_command( + const map_data_file_give_command_options &option) const { + if (option.destination == nullptr) { + return false; + } + + const int map_rows = this->map_rows(); + const int map_cols = this->map_cols(); + if (map_rows <= 0 or map_cols <= 0) { + std::string err_msg = + fmt::format("Invalid map size: {} rows, {} cols", map_rows, map_cols); + option.destination->write(err_msg.c_str(), err_msg.size()); + return false; + } + + auto item_of_location = [map_rows, map_cols, option]( + int r, int c) -> nbt::tag_compound { + assert(r >= 0 and r < map_rows); + assert(c >= 0 and c < map_cols); + // Maps are placed in col-major + const int index = option.begin_index + r + c * map_rows; + + std::string name; + if (option.set_name_as_index) + name = fmt::format("{{\"text\":\"[{},{}]\"}}", r, c); + + nbt::tag_compound result; + nbt::tag_compound tag; + result.emplace("id", "minecraft:filled_map"); + // set up item name + if (option.set_name_as_index and not option.after_1_20_5) { + nbt::tag_compound display; + display.emplace("Name", + nbt::tag_string{std::move(name)}); + tag.emplace("display", std::move(display)); + } + // set up item properties + if (not option.after_1_12) { + result.emplace("Count", option.stack_count); + result.emplace("Damage", index); + result.emplace("tag", std::move(tag)); + return result; + } + if (not option.after_1_20_5) { + result.emplace("Count", option.stack_count); + tag.emplace("map", index); + result.emplace("tag", std::move(tag)); + return result; + } + result.emplace("count", option.stack_count); + tag.emplace("minecraft:map_id", index); + tag.emplace("minecraft:custom_name", + nbt::tag_string{std::move(name)}); + result.emplace("components", std::move(tag)); + return result; + }; + + nbt::tag_compound chest_all_in_one; + auto erase_if = [&chest_all_in_one](const char *key) noexcept { + if (chest_all_in_one.has_key(key)) { + chest_all_in_one.erase(key); + } + }; + { + boost::multi_array maps{ + boost::extents[map_rows][map_cols]}; + for (int r = 0; r < map_rows; r++) { + for (int c = 0; c < map_cols; c++) { + maps[r][c] = item_of_location(r, c); + } + } + chest_all_in_one = merge_with_chest(std::move(maps), option); + } + + const std::string item_id = + chest_all_in_one.at("id").as().get(); + option.destination->write(fmt::format("/give @p {}", item_id).c_str()); + erase_if("Count"); + erase_if("count"); + erase_if("id"); + std::ostringstream oss; + { + sNBT::sNBT_format_visitor formatter{oss}; + chest_all_in_one.at("tag").as().accept(formatter); + } + std::string_view snbt = oss.view(); + option.destination->write(snbt.data(), snbt.size()); + option.destination->write(" 1"); + + return true; +} // uint64_t converted_image_impl::hash() const noexcept { // return this->converter.task_hash(); diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index 3c9c1c41..de614a51 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -36,6 +36,9 @@ class converted_image_impl : public converted_image { size_t rows() const noexcept final { return this->converter.rows(); } size_t cols() const noexcept final { return this->converter.cols(); } + int map_rows() const noexcept { return ceil(this->rows() / 128.0f); } + int map_cols() const noexcept { return ceil(this->cols() / 128.0f); } + void get_original_image(uint32_t *buffer) const noexcept final { Eigen::Map buf{buffer, static_cast(this->rows()), static_cast(this->cols())}; @@ -73,5 +76,8 @@ class converted_image_impl : public converted_image { const std::filesystem::path &file) noexcept; bool is_converted_from(const color_table &table_) const noexcept final; + + bool get_map_command( + const map_data_file_give_command_options &option) const final; }; #endif // SLOPECRAFT_CONVERTED_IMAGE_H From c91cd87241c2ff6b1e72de6e553f577e7b69f73d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 25 Jul 2024 21:33:44 +0800 Subject: [PATCH 0853/1123] generate /give command to give map items Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 32 ++++- SlopeCraft/SCWind.ui | 134 ++++++++++++-------- utilities/sNBT_formatter/sNBT_formatter.cpp | 9 +- 3 files changed, 119 insertions(+), 56 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index e77906b9..8a9b9b03 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -445,9 +445,14 @@ SCWind::export_type SCWind::selected_export_type() const noexcept { auto btns = this->export_type_buttons(); static_assert(btns.size() == 5); + constexpr std::array export_type_list{ + export_type::litematica, export_type::vanilla_structure, + export_type::WE_schem, export_type::flat_diagram, + export_type::data_file, + }; for (int i = 0; i < 5; i++) { if (btns[i]->isChecked()) { - return SCWind::export_type{i}; + return export_type_list[i]; } } assert(false); @@ -894,6 +899,31 @@ void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { tr("大小: %1 × %2 × %3").arg(x).arg(y).arg(z)); this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); } + + if (this->selected_export_type() == SCWind::export_type::data_file) { + QString command; + SlopeCraft::ostream_wrapper os{ + .handle = &command, + .callback_write_data = + [](const void *data, size_t len, void *handle) { + QString *buf = reinterpret_cast(handle); + QLatin1StringView qlsv{reinterpret_cast(data), + static_cast(len)}; + buf->append(qlsv); + }, + }; + + SlopeCraft::map_data_file_give_command_options opt{}; + opt.destination = &os; + opt.begin_index = this->ui->sb_file_start_idx->value(); + opt.after_1_12 = (this->selected_version() > SCL_gameVersion::MC12); + opt.after_1_20_5 = false; + const bool ok = cvted_it->second.converted_image->get_map_command(opt); + if (!ok) { + command = tr("生成命令失败:\n%1").arg(command); + } + this->ui->pte_command->setPlainText(command); + } } void SCWind::when_export_pool_selectionChanged() noexcept { diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 9b9d0a30..a1a1cb78 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -228,7 +228,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -320,8 +320,8 @@ 0 0 - 627 - 644 + 622 + 653 @@ -344,16 +344,16 @@ - QTabWidget::North + QTabWidget::TabPosition::North - QTabWidget::Rounded + QTabWidget::TabShape::Rounded 0 - Qt::ElideLeft + Qt::TextElideMode::ElideLeft false @@ -381,7 +381,7 @@ true - QFrame::NoFrame + QFrame::Shape::NoFrame 1 @@ -413,7 +413,7 @@ true - QFrame::NoFrame + QFrame::Shape::NoFrame 1 @@ -454,7 +454,7 @@ false - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::NoEditTriggers true @@ -463,34 +463,34 @@ false - QAbstractItemView::NoDragDrop + QAbstractItemView::DragDropMode::NoDragDrop - Qt::IgnoreAction + Qt::DropAction::IgnoreAction - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - Qt::ElideLeft + Qt::TextElideMode::ElideLeft - QListView::Static + QListView::Movement::Static - QListView::TopToBottom + QListView::Flow::TopToBottom false - QListView::Adjust + QListView::ResizeMode::Adjust 10 - QListView::IconMode + QListView::ViewMode::IconMode 0 @@ -502,7 +502,7 @@ true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop @@ -639,7 +639,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -690,7 +690,7 @@ false - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::NoEditTriggers true @@ -699,37 +699,37 @@ false - QAbstractItemView::NoDragDrop + QAbstractItemView::DragDropMode::NoDragDrop - Qt::IgnoreAction + Qt::DropAction::IgnoreAction - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - Qt::ElideLeft + Qt::TextElideMode::ElideLeft - QListView::Static + QListView::Movement::Static - QListView::TopToBottom + QListView::Flow::TopToBottom false - QListView::Adjust + QListView::ResizeMode::Adjust - QListView::SinglePass + QListView::LayoutMode::SinglePass 10 - QListView::IconMode + QListView::ViewMode::IconMode 0 @@ -741,7 +741,7 @@ true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop @@ -967,7 +967,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -997,7 +997,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1211,7 +1211,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1268,7 +1268,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1321,7 +1321,7 @@ - + 0 @@ -1329,7 +1329,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1348,6 +1348,28 @@ + + + + + + + others/images/map_icon.png + + + + + + + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 + +在下面的表格里可以看到每个图像对应的文件名。 + + + true + + + @@ -1365,6 +1387,12 @@ + + + 0 + 0 + + 地图画起始序号: @@ -1376,7 +1404,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1388,25 +1416,25 @@ - - - + + + + + 0 + 0 + + + - - others/images/map_icon.png + + true - - - - - - 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 - -在下面的表格里可以看到每个图像对应的文件名。 + + - - true + + 批量获得地图物品的指令 @@ -1426,7 +1454,7 @@ 0 0 920 - 23 + 33 diff --git a/utilities/sNBT_formatter/sNBT_formatter.cpp b/utilities/sNBT_formatter/sNBT_formatter.cpp index 4fa04bef..6d7cbb36 100644 --- a/utilities/sNBT_formatter/sNBT_formatter.cpp +++ b/utilities/sNBT_formatter/sNBT_formatter.cpp @@ -65,7 +65,11 @@ void sNBT::sNBT_format_visitor::visit(const nbt::tag_long_array &la) { } void sNBT::sNBT_format_visitor::visit(const nbt::tag_string &s) { - os << '"' << s.get() << '"'; + if (s.get().find('\"') not_eq s.get().npos) { + os << '\'' << s.get() << '\''; + } else { + os << '"' << s.get() << '"'; + } } // TODO: escape special characters void sNBT::sNBT_format_visitor::visit(const nbt::tag_list &l) { @@ -87,7 +91,8 @@ void sNBT::sNBT_format_visitor::visit(const nbt::tag_compound &c) { this->os << "{"; size_t idx = 0; for (auto &[key, val] : c) { - this->os << '\"' << key << "\":"; + this->os << key << ':'; + // this->os << '\"' << key << "\":"; val.get().accept(*this); if (idx < c.size() - 1) { this->os << ','; From f5ac5c01a54e12a02bacabce611745f92c09179c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 12:42:20 +0800 Subject: [PATCH 0854/1123] fixed lossy compress input Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 24 +++++++++++------------- SlopeCraftL/converted_image.cpp | 18 ++++++++++-------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 8a9b9b03..be492130 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -389,19 +389,14 @@ int SCWind::current_max_height() const noexcept { } SCL_compressSettings SCWind::current_compress_method() const noexcept { + auto result = static_cast(SCL_compressSettings::noCompress); if (this->is_lossless_compression_selected()) { - if (this->is_lossy_compression_selected()) { - return SCL_compressSettings::Both; - } else { - return SCL_compressSettings::NaturalOnly; - } - } else { - if (this->is_lossless_compression_selected()) { - return SCL_compressSettings::ForcedOnly; - } else { - return SCL_compressSettings::noCompress; - } + result = result bitor int(SCL_compressSettings::NaturalOnly); } + if (this->is_lossy_compression_selected()) { + result = result bitor int(SCL_compressSettings::ForcedOnly); + } + return static_cast(result); } bool SCWind::is_glass_bridge_selected() const noexcept { @@ -723,7 +718,8 @@ const SlopeCraft::converted_image &SCWind::convert_if_need( std::unique_ptr SCWind::build_3D( const SlopeCraft::converted_image &cvted) noexcept { auto ctable = this->current_color_table(); - auto str = ctable->build(cvted, this->current_build_option()); + const auto opt = this->current_build_option(); + auto str = ctable->build(cvted, opt); return std::unique_ptr{str}; } @@ -848,11 +844,13 @@ void SCWind::export_current_cvted_image(int idx, QString filename) noexcept { this->current_convert_option(), std::move(cvted_uptr)); cvted = task.get_converted_image(this->current_color_table(), this->current_convert_option()); + if (cvted == nullptr) { + return; + } } else { return; } } - assert(cvted != nullptr); auto img = get_converted_image(*cvted); bool ok = img.save(filename); diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index a1dbe3d3..9345561a 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -204,9 +204,10 @@ converted_image_impl::height_info(const build_options &option) const noexcept { Eigen::ArrayXXi map_color = this->converter.mapcolor_matrix().cast(); -#warning This may be incorrect const bool allow_lossless_compress = - int(option.compress_method) & int(SCL_compressSettings::NaturalOnly); + int(option.compress_method) bitand int(SCL_compressSettings::NaturalOnly); + const bool allow_lossy_compress = + int(option.compress_method) bitand int(compressSettings::ForcedOnly); if (((map_color - 4 * (map_color / 4)) >= 3).any()) { std::string msg = @@ -238,9 +239,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { // getTokiColorPtr(c,&src[0]); HL.make(map_color.col(c), allow_lossless_compress); - if (HL.maxHeight() > option.max_allowed_height && - (option.compress_method == compressSettings::ForcedOnly || - option.compress_method == compressSettings::Both)) { + if ((HL.maxHeight() > option.max_allowed_height) and allow_lossy_compress) { std::vector ptr(map_color.rows()); this->converter.col_TokiColor_ptrs(c, ptr); @@ -249,15 +248,18 @@ converted_image_impl::height_info(const build_options &option) const noexcept { compressor.setSource(HL.getBase(), ptr); bool success = compressor.compress(option.max_allowed_height, allow_lossless_compress); + Eigen::ArrayXi temp; + HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); if (!success) { option.ui.report_error( SCL_errorFlag::LOSSYCOMPRESS_FAILED, - fmt::format("Failed to compress the 3D structure at column {}.", c) + fmt::format("Failed to compress the 3D structure at column {}. You " + "have required that max height <= {}, but SlopeCraft " + "is only able to this column to max height = {}.", + c, option.max_allowed_height, HL.maxHeight()) .data()); return std::nullopt; } - Eigen::ArrayXi temp; - HL.make(&ptr[0], compressor.getResult(), allow_lossless_compress, &temp); map_color.col(c) = temp; } base.col(c) = HL.getBase(); From b7aaa5fe15bfd27cff258636683980b03a27d86b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 13:35:43 +0800 Subject: [PATCH 0855/1123] try to fix find_package Boost::multi_array on ubuntu and macos Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 1e17b466..6d5d6749 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,10 +1,42 @@ find_package(Boost - COMPONENTS iostreams multi_array - REQUIRED) + COMPONENTS iostreams + multi_array +) if (NOT TARGET Boost::iostreams) message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") endif () if (NOT TARGET Boost::multi_array) - message(FATAL_ERROR "Failed to find Boost::multi_array, install boost first") + message(WARNING "find_package failed to find Boost::multi_array, trying to find its headers manually...") + set(hints) + foreach (prefix ${CMAKE_PREFIX_PATH}) + list(APPEND hints "${prefix}/include/boost/multi_array.hpp") + endforeach () + find_file(multi_array_hpp_location NAMES multi_array.hpp + HINTS ${hints} + PATH_SUFFIXES "include/boost" + ) + unset(hpp_count) + list(LENGTH multi_array_hpp_location hpp_count) + if ((NOT multi_array_hpp_location) OR (${hpp_count} LESS_EQUAL 0)) + message(FATAL_ERROR "Boost::multi_array is not installed or not accessible, + you should install it and add the installation prefix to CMAKE_PREFIX_PATH") + endif () + + if (${hpp_count} GREATER 1) + message(STATUS "Found multiple installation of \"include/boost/multi_array.hpp\": \n\"${multi_array_hpp_location}\", select the first.") + list(GET multi_array_hpp_location 0 multi_array_hpp_location) + else () + message(STATUS "Manually found Boost::multi_array at \"${multi_array_hpp_location}\"") + endif () + message(STATUS "Making fake target named Boost::multi_array to replace the missing one. \n + Сука, what's wrong with BoostConfig.cmake and FindBoost.cmake? I have to write moooore code to fix it on ubuntu and mac. I don't experience such bug with vcpkg+windows") + + cmake_path(GET multi_array_hpp_location PARENT_PATH boost_dir_boost) + cmake_path(GET boost_dir_boost PARENT_PATH boost_dir_include) + + add_library(boost_fake_target_multi_array INTERFACE) + target_include_directories(boost_fake_target_multi_array INTERFACE ${boost_dir_include}) + add_library(Boost::multi_array ALIAS boost_fake_target_multi_array) + endif () \ No newline at end of file From eab1348c2bbd41bb994b36cbbb1f882757f3fc84 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 13:39:16 +0800 Subject: [PATCH 0856/1123] try to fix find_package Boost::multi_array on windows Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 71bd2565..9abd1e2a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -41,7 +41,7 @@ jobs: run: | mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected + vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' @@ -209,7 +209,7 @@ jobs: echo "env:path = $env:path" mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid tl-expected magic-enum + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected magic-enum - name: Install OpenCL with vcpkg From e83d6aa25a63ae62535ed6d9a9419b1b87756f7e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:08:18 +0800 Subject: [PATCH 0857/1123] try to fix find_package Boost::multi_array for mac Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 6d5d6749..0946ba67 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,6 +1,6 @@ find_package(Boost COMPONENTS iostreams - multi_array + OPTIONAL_COMPONENTS multi_array ) if (NOT TARGET Boost::iostreams) From 430c8fd2cf115be2a9b047c88c70a21086a0fa23 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:09:01 +0800 Subject: [PATCH 0858/1123] try to fix find libnbt++ for ubuntu Signed-off-by: ToKiNoBug --- cmake/required_deps/libnbt++.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 02cbd48c..ea041e29 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.29) + +find_package(zlib REQUIRED) + set(NBT_BUILD_SHARED OFF CACHE BOOL "") set(NBT_BUILD_TESTS OFF CACHE BOOL "") FetchContent_Declare(libnbt++ @@ -10,5 +13,4 @@ message(STATUS "Cloning libnbt++...") FetchContent_MakeAvailable(libnbt++) find_package(libnbt++ REQUIRED) -find_package(zlib REQUIRED) target_link_libraries(nbt++ ZLIB::ZLIB) \ No newline at end of file From 2ad5dbc5149d8b7c580c928a6ba131816d46188e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:23:32 +0800 Subject: [PATCH 0859/1123] try to fix find libnbt++ for ubuntu Signed-off-by: ToKiNoBug --- cmake/required_deps/libnbt++.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index ea041e29..c4deea70 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.29) -find_package(zlib REQUIRED) +find_package(ZLIB REQUIRED) set(NBT_BUILD_SHARED OFF CACHE BOOL "") set(NBT_BUILD_TESTS OFF CACHE BOOL "") From 38845b042ac9c9fb3882e0b4a4996151eb021cac Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:23:43 +0800 Subject: [PATCH 0860/1123] try to fix find libnbt++ for mac Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 0946ba67..54641d33 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,7 +1,13 @@ -find_package(Boost - COMPONENTS iostreams - OPTIONAL_COMPONENTS multi_array -) +if (NOT ${APPLE}) + find_package(Boost + COMPONENTS iostreams multi_array + ) +else () + message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake only happened in macos") + find_package(Boost + COMPONENTS iostreams + ) +endif () if (NOT TARGET Boost::iostreams) message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") From 53f4ce7aca8f013747807f953614b9f6136a71ee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:30:28 +0800 Subject: [PATCH 0861/1123] try to fix find libnbt++ for mac Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 54641d33..ee21ad3c 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,9 +1,10 @@ -if (NOT ${APPLE}) +if (${WIN32}) find_package(Boost - COMPONENTS iostreams multi_array + COMPONENTS iostreams + OPTIONAL_COMPONENTS multi_array ) else () - message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake only happened in macos") + message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") find_package(Boost COMPONENTS iostreams ) From b6569f977727022f0dae2994864f3190368d99ac Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:47:46 +0800 Subject: [PATCH 0862/1123] try to fix find boost Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 904da150..10f4b3fe 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -56,7 +56,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_PREFIX_PATH="$HOME/Downloads/qt6.6.0-arm64-apple-darwin" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ "-DCMAKE_PREFIX_PATH=$HOME/Downloads/qt6.6.0-arm64-apple-darwin;/opt/homebrew" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 1ee820eb..30b5ebe5 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -74,7 +74,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build From 44c0c8a86e73ac54b8945eebba3e99edaa8c1062 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 14:54:10 +0800 Subject: [PATCH 0863/1123] try to fix find boost Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index ee21ad3c..53686ccb 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,14 +1,14 @@ -if (${WIN32}) - find_package(Boost - COMPONENTS iostreams - OPTIONAL_COMPONENTS multi_array - ) -else () - message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") - find_package(Boost - COMPONENTS iostreams - ) -endif () +#if (${WIN32}) +# find_package(Boost +# COMPONENTS iostreams +# OPTIONAL_COMPONENTS multi_array +# ) +#else () +message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") +find_package(Boost + COMPONENTS iostreams +) +#endif () if (NOT TARGET Boost::iostreams) message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") From db9a76785cad24fd71ac3b164ab5677695a7006a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 29 Jul 2024 15:14:10 +0800 Subject: [PATCH 0864/1123] try to fix find boost Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 1a06be22..e4e0576a 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: - sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libexpected-dev p7zip-full + sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libboost-tools-dev libboost-doc libexpected-dev p7zip-full - name: Install xsimd run: | From 188689d748a9064cd6d8274d5a8bf7d9be8287bb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 10:33:09 +0800 Subject: [PATCH 0865/1123] try to fix find boost Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 +- cmake/required_deps/boost.cmake | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index f2fa2f82..4b6aab28 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) -find_package(Boost COMPONENTS iostreams multi_array REQUIRED) +find_package(Boost COMPONENTS iostreams OPTIONAL_COMPONENTS multi_array REQUIRED) find_package(libzip REQUIRED) find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index 53686ccb..ee21ad3c 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -1,14 +1,14 @@ -#if (${WIN32}) -# find_package(Boost -# COMPONENTS iostreams -# OPTIONAL_COMPONENTS multi_array -# ) -#else () -message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") -find_package(Boost - COMPONENTS iostreams -) -#endif () +if (${WIN32}) + find_package(Boost + COMPONENTS iostreams + OPTIONAL_COMPONENTS multi_array + ) +else () + message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") + find_package(Boost + COMPONENTS iostreams + ) +endif () if (NOT TARGET Boost::iostreams) message(FATAL_ERROR "Failed to find Boost::iostreams, install boost first") From c95fbe638f2e8f22db2c553e53eaff68d22e1335 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 11:32:45 +0800 Subject: [PATCH 0866/1123] fix linux build Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index be492130..aab1a9fb 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -905,8 +905,8 @@ void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { .callback_write_data = [](const void *data, size_t len, void *handle) { QString *buf = reinterpret_cast(handle); - QLatin1StringView qlsv{reinterpret_cast(data), - static_cast(len)}; + QUtf8StringView qlsv{reinterpret_cast(data), + static_cast(len)}; buf->append(qlsv); }, }; From 5806b2eb56855206ffd3be545026ca9662ce8fdf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 11:35:04 +0800 Subject: [PATCH 0867/1123] replace clang-cl with cl in windows action Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- utilities/ExternalConverters/GAConverter/GACvterDefines.hpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 9abd1e2a..25b05b71 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -100,8 +100,8 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + # -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc - name: CMake build shell: cmd run: | diff --git a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp index 27fcaf7c..c023536a 100644 --- a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp +++ b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp @@ -27,6 +27,7 @@ This file is part of SlopeCraft. #define _USE_MATH_DEFINES #endif +#include #include #include #include From 7bc174cf908eb9869f5630ec5d95675313d23b74 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 11:36:26 +0800 Subject: [PATCH 0868/1123] replace clang-cl with cl in windows action Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 25b05b71..fe77b1fd 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -7,7 +7,7 @@ on: - dev jobs: - clang: + msvc: runs-on: windows-latest strategy: matrix: From 774717655cc0d8104a599c4aa43250329cb18d96 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 11:43:33 +0800 Subject: [PATCH 0869/1123] fix windows ci Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index fe77b1fd..adc62ed7 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -41,7 +41,7 @@ jobs: run: | mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected + vcpkg install --triplet=x64-windows zlib libpng bzip2 zstd liblzma libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected fmt cereal magic-enum - name: Install OpenCL with vcpkg if: matrix.gpu_api == 'OpenCL' From 5c5013afbeb8a207592d3e6cef04e7f460780448 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 12:04:53 +0800 Subject: [PATCH 0870/1123] fix windows ci Signed-off-by: ToKiNoBug --- SlopeCraft/PoolModel.cpp | 2 +- SlopeCraftL/converted_image.cpp | 2 +- cmake/required_deps/libnbt++.cmake | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index bc473c11..f8dc1379 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -261,7 +261,7 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, if (src_indices.size() <= 0) { return true; } -#warning "TODO: Implement reshuffling here" +#pragma warning "TODO: Implement reshuffling here" assert(("Reshuffing is not implemented yet", false)); // map_indices(this->pool, src_indices, begin_row); } diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 9345561a..ba89cfbc 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -398,7 +398,7 @@ nbt::tag_compound merge_with_chest( } else { chest_item.emplace("count", 1); } -#warning "This should be corrected for 1.20.5+" +#pragma warning "This should be corrected for 1.20.5+" nbt::tag_compound blk_entity_tag; blk_entity_tag.emplace("Items", std::move(item_list)); get_or_setup_field(chest_item, "tag") diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index c4deea70..60439d03 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -13,4 +13,5 @@ message(STATUS "Cloning libnbt++...") FetchContent_MakeAvailable(libnbt++) find_package(libnbt++ REQUIRED) -target_link_libraries(nbt++ ZLIB::ZLIB) \ No newline at end of file +target_link_libraries(nbt++ ZLIB::ZLIB) +target_compile_features(nbt++ PUBLIC cxx_std_23) \ No newline at end of file From 2b5160442045f3c7bb89e553c0c4635a63c417a6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 13:42:55 +0800 Subject: [PATCH 0871/1123] fix map command display Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 53 +++++++++---------------------------- SlopeCraft/SCWind.ui | 7 +++++ SlopeCraft/SCWind_slots.cpp | 2 +- 3 files changed, 21 insertions(+), 41 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index aab1a9fb..2745deea 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -618,30 +618,6 @@ void SCWind::when_export_type_toggled() noexcept { this->update_button_states(); } -// void SCWind::kernel_set_image(int idx) noexcept { -// assert(idx >= 0); -// assert(idx < (int)this->tasks.size()); -// -// if (this->kernel->queryStep() < SCL_step::wait4Image) { -// this->kernel_set_type(); -// } -// -// const QImage &raw = this->tasks[idx].original_image; -// this->kernel->setRawImage((const uint32_t *)raw.scanLine(0), raw.height(), -// raw.width(), false); -// } -// -// void SCWind::kernel_convert_image() noexcept { -// assert(this->kernel->queryStep() >= SCL_step::convertionReady); -// -// if (!this->kernel->convert(this->selected_algo(), -// this->is_dither_selected())) { -// QMessageBox::warning(this, tr("转化图像失败"), tr("")); -// -// return; -// } -// } - SlopeCraft::convert_option SCWind::current_convert_option() noexcept { return SlopeCraft::convert_option{ .caller_api_version = SC_VERSION_U64, @@ -905,17 +881,26 @@ void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { .callback_write_data = [](const void *data, size_t len, void *handle) { QString *buf = reinterpret_cast(handle); - QUtf8StringView qlsv{reinterpret_cast(data), - static_cast(len)}; - buf->append(qlsv); + QString temp = + QString::fromUtf8(reinterpret_cast(data), + static_cast(len)); + buf->append(temp); }, }; + bool after_1_20_5 = false; + if (this->selected_version() < SCL_gameVersion::MC20) { + after_1_20_5 = true; + } else if (this->selected_version() > SCL_gameVersion::MC20) { + after_1_20_5 = true; + } else { + after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); + } SlopeCraft::map_data_file_give_command_options opt{}; opt.destination = &os; opt.begin_index = this->ui->sb_file_start_idx->value(); opt.after_1_12 = (this->selected_version() > SCL_gameVersion::MC12); - opt.after_1_20_5 = false; + opt.after_1_20_5 = after_1_20_5; const bool ok = cvted_it->second.converted_image->get_map_command(opt); if (!ok) { command = tr("生成命令失败:\n%1").arg(command); @@ -928,18 +913,6 @@ void SCWind::when_export_pool_selectionChanged() noexcept { this->refresh_current_build_display(this->selected_export_task()); } -// void SCWind::kernel_make_build_cache() noexcept { -// std::string err; -// err.resize(4096); -// SlopeCraft::string_deliver sd{err.data(), err.size()}; -// -// if (!this->kernel->saveBuildCache(sd)) { -// QString qerr = QString::fromUtf8(sd.data); -// QMessageBox::warning(this, tr("缓存失败"), -// tr("未能创建缓存文件,错误信息:\n%1").arg(qerr)); -// } -// } - QString extension_of_export_type(SCWind::export_type et) noexcept { switch (et) { case SCWind::export_type::litematica: diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index a1a1cb78..e9aa2e78 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1326,6 +1326,13 @@ 0 + + + + MC版本≥1.20.5+ + + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index b2ecbdef..09d885f6 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -718,7 +718,7 @@ void SCWind::on_pb_export_file_clicked() noexcept { // this->kernel_convert_image(); // } // - const int cur_seq_beg = this->tasks.map_range_of(seq_first, idx).last; + const int cur_seq_beg = this->tasks.map_range_of(seq_first, idx).first; const auto dir_name = dir.toLocal8Bit(); // const SlopeCraft::map_data_file_options option{ From eb89f8be297118f06a1c5775130cb64e0d3ca6f3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 22:56:30 +0800 Subject: [PATCH 0872/1123] fix map command for 1.20.5+ Signed-off-by: ToKiNoBug --- SlopeCraftL/converted_image.cpp | 48 +++++++++++++++------ utilities/sNBT_formatter/sNBT_formatter.cpp | 6 ++- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index ba89cfbc..6713d9b9 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -385,9 +385,16 @@ nbt::tag_compound merge_with_chest( continue; } const int8_t slot = chest_index_to_slot(r_offset, c_offset); - // set slot - cur_item.emplace("Slot", slot); - item_list.emplace_back(std::move(cur_item)); + if (not option.after_1_20_5) { + // set slot + cur_item.emplace("Slot", slot); + item_list.emplace_back(std::move(cur_item)); + } else { + nbt::tag_compound item; + item.emplace("item", std::move(cur_item)); + item.emplace("slot", slot); + item_list.emplace_back(std::move(item)); + } } } @@ -398,12 +405,17 @@ nbt::tag_compound merge_with_chest( } else { chest_item.emplace("count", 1); } -#pragma warning "This should be corrected for 1.20.5+" - nbt::tag_compound blk_entity_tag; - blk_entity_tag.emplace("Items", std::move(item_list)); - get_or_setup_field(chest_item, "tag") - .emplace("BlockEntityTag", - std::move(blk_entity_tag)); + if (not option.after_1_20_5) { + nbt::tag_compound blk_entity_tag; + blk_entity_tag.emplace("Items", std::move(item_list)); + get_or_setup_field(chest_item, "tag") + .emplace("BlockEntityTag", + std::move(blk_entity_tag)); + } else { + get_or_setup_field(chest_item, "components") + .emplace("minecraft:container", + std::move(item_list)); + } merged_chests[merged_row][merged_col] = std::move(chest_item); } @@ -466,8 +478,8 @@ bool converted_image_impl::get_map_command( return result; } result.emplace("count", option.stack_count); - tag.emplace("minecraft:map_id", index); - tag.emplace("minecraft:custom_name", + tag.emplace("map_id", index); + tag.emplace("custom_name", nbt::tag_string{std::move(name)}); result.emplace("components", std::move(tag)); return result; @@ -499,7 +511,19 @@ bool converted_image_impl::get_map_command( std::ostringstream oss; { sNBT::sNBT_format_visitor formatter{oss}; - chest_all_in_one.at("tag").as().accept(formatter); + if (not option.after_1_20_5) { + chest_all_in_one.at("tag").as().accept(formatter); + } else { + const nbt::tag_compound &components = + chest_all_in_one.at("components").as(); + oss << '['; + for (auto &[key, val] : components) { + oss << key << '='; + val.get().accept(formatter); + oss << ','; + } + oss << ']'; + } } std::string_view snbt = oss.view(); option.destination->write(snbt.data(), snbt.size()); diff --git a/utilities/sNBT_formatter/sNBT_formatter.cpp b/utilities/sNBT_formatter/sNBT_formatter.cpp index 6d7cbb36..7d792776 100644 --- a/utilities/sNBT_formatter/sNBT_formatter.cpp +++ b/utilities/sNBT_formatter/sNBT_formatter.cpp @@ -91,7 +91,11 @@ void sNBT::sNBT_format_visitor::visit(const nbt::tag_compound &c) { this->os << "{"; size_t idx = 0; for (auto &[key, val] : c) { - this->os << key << ':'; + if (key.contains(':')) { + this->os << '\"' << key << '\"' << ':'; + } else { + this->os << key << ':'; + } // this->os << '\"' << key << "\":"; val.get().accept(*this); if (idx < c.size() - 1) { From 59c4b5208b70e3bd3479679f8ad1900a3b8891b9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 5 Aug 2024 22:57:00 +0800 Subject: [PATCH 0873/1123] use SharedLibDeployer 1.5.1 Signed-off-by: ToKiNoBug --- SlopeCraft/install.cmake | 2 +- cmake/required_deps/_DLLDeployer.cmake | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index befb0784..59d1911f 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -87,7 +87,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows") DLLD_add_deploy(SlopeCraft BUILD_MODE INSTALL_MODE INSTALL_DESTINATION . - IGNORE SlopeCraftL.dll) + OPTIONAL_DLLS "imageformats/*.dll") # Install all block list archives install(FILES ${SlopeCraft_block_list_archives} diff --git a/cmake/required_deps/_DLLDeployer.cmake b/cmake/required_deps/_DLLDeployer.cmake index 06eb5eab..3318de64 100644 --- a/cmake/required_deps/_DLLDeployer.cmake +++ b/cmake/required_deps/_DLLDeployer.cmake @@ -23,18 +23,20 @@ set(DLLD_download_dir ${CMAKE_BINARY_DIR}/3rdParty/DLLDeployer) set(DLLD_file ${DLLD_download_dir}/DLLDeployer.cmake) set(QD_file ${DLLD_download_dir}/QtDeployer.cmake) if (${WIN32}) - file(DOWNLOAD https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/DLLDeployer.cmake + file(DOWNLOAD https://github.com/SlopeCraft/SharedLibDeployer/releases/download/v1.5.1/DLLDeployer.cmake ${DLLD_file} - EXPECTED_HASH SHA512=6044ACEA50BFC9EACA37357BF2CD1497908905DAE0971F74B4BE4BAED6633420BDD38105FE21E47724B9653DEC4880BEBCA1341DC95AA9BD8144356C7DAB1899) + EXPECTED_HASH SHA512=255C1390363E74EE0538F9CC003EAA00B039B55CBB2E17E940EE5B365D4F8FADEBAFD0DF21339FC52A10AD61A1F82FB56E080FDC96B5A617F2EAEC6D8770645A + ) # SC_download(https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/DLLDeployer.cmake # ${DLLD_file}) include(${DLLD_file}) endif () if (WIN32 OR APPLE) - file(DOWNLOAD https://github.com/ToKiNoBug/SharedLibDeployer/releases/download/v1.4.0/QtDeployer.cmake + file(DOWNLOAD https://github.com/SlopeCraft/SharedLibDeployer/releases/download/v1.5.1/QtDeployer.cmake ${QD_file} - EXPECTED_HASH SHA512=7A6E7FEE90DEBC0A4E6BDC4CB65D87DF453E8B24C6ED9E188C174BF64C526CA232FA63211CA661E4B26D06A141291AB0AB3CC499B64775B23FC0E622E0CEA0B4) + EXPECTED_HASH SHA512=7A6E7FEE90DEBC0A4E6BDC4CB65D87DF453E8B24C6ED9E188C174BF64C526CA232FA63211CA661E4B26D06A141291AB0AB3CC499B64775B23FC0E622E0CEA0B4 + ) # SC_download(https://github.com/SlopeCraft/DLLDeployer/releases/download/v1.3/QtDeployer.cmake # ${QD_file}) include(${QD_file}) From 6e3f96760d7ded1372b8e9664440a55139ee3786 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 11:18:56 +0800 Subject: [PATCH 0874/1123] refresh command at correctly Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 85 +++++++++++++++++++++++-------------- SlopeCraft/SCWind.h | 8 +++- SlopeCraft/SCWind.ui | 16 ++++++- SlopeCraft/SCWind_slots.cpp | 34 +++++++++++++++ 4 files changed, 110 insertions(+), 33 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 2745deea..1280d006 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -106,6 +106,14 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { this->export_table_model, &ExportTableModel::refresh); connect(this, &SCWind::image_changed, this->export_table_model, &ExportTableModel::refresh); + + connect(this->ui->lview_pool_export->selectionModel(), + &QItemSelectionModel::selectionChanged, this, + &SCWind::when_data_file_command_changed); + connect(this->ui->sb_file_start_idx, &QSpinBox::valueChanged, this, + &SCWind::when_data_file_command_changed); + connect(this->ui->cb_mc_version_geq_1_20_5, &QCheckBox::clicked, this, + &SCWind::when_data_file_command_changed); } for (QRadioButton *rbp : this->export_type_buttons()) { @@ -458,6 +466,16 @@ SCWind::export_type SCWind::selected_export_type() const noexcept { void SCWind::when_version_buttons_toggled() noexcept { this->ui->blm->when_version_updated(); this->when_blocklist_changed(); + + // When mc version is not 1.20, it must be greater or less than 1.20.5, this + // checkbox is useless and can be fixed + const bool fix_geq_btn = + (this->selected_version() not_eq SCL_gameVersion::MC20); + if (this->selected_version() not_eq SCL_gameVersion::MC20) { + this->ui->cb_mc_version_geq_1_20_5->setChecked(this->selected_version() > + SCL_gameVersion::MC20); + } + this->ui->cb_mc_version_geq_1_20_5->setDisabled(fix_geq_btn); } void SCWind::when_type_buttons_toggled() noexcept { @@ -874,39 +892,44 @@ void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { this->ui->lb_show_block_count->setText(tr("方块数量:%1").arg(block_count)); } - if (this->selected_export_type() == SCWind::export_type::data_file) { - QString command; - SlopeCraft::ostream_wrapper os{ - .handle = &command, - .callback_write_data = - [](const void *data, size_t len, void *handle) { - QString *buf = reinterpret_cast(handle); - QString temp = - QString::fromUtf8(reinterpret_cast(data), - static_cast(len)); - buf->append(temp); - }, - }; - bool after_1_20_5 = false; - if (this->selected_version() < SCL_gameVersion::MC20) { - after_1_20_5 = true; - } else if (this->selected_version() > SCL_gameVersion::MC20) { - after_1_20_5 = true; - } else { - after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); - } + // if (this->selected_export_type() == SCWind::export_type::data_file) { + // this->when_data_file_command_changed(); + // } +} - SlopeCraft::map_data_file_give_command_options opt{}; - opt.destination = &os; - opt.begin_index = this->ui->sb_file_start_idx->value(); - opt.after_1_12 = (this->selected_version() > SCL_gameVersion::MC12); - opt.after_1_20_5 = after_1_20_5; - const bool ok = cvted_it->second.converted_image->get_map_command(opt); - if (!ok) { - command = tr("生成命令失败:\n%1").arg(command); - } - this->ui->pte_command->setPlainText(command); +tl::expected SCWind::get_command( + const SlopeCraft::converted_image &cvted) const noexcept { + QString command; + SlopeCraft::ostream_wrapper os{ + .handle = &command, + .callback_write_data = + [](const void *data, size_t len, void *handle) { + QString *buf = reinterpret_cast(handle); + QString temp = + QString::fromUtf8(reinterpret_cast(data), + static_cast(len)); + buf->append(temp); + }, + }; + bool after_1_20_5 = false; + if (this->selected_version() < SCL_gameVersion::MC20) { + after_1_20_5 = true; + } else if (this->selected_version() > SCL_gameVersion::MC20) { + after_1_20_5 = true; + } else { + after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); + } + + SlopeCraft::map_data_file_give_command_options opt{}; + opt.destination = &os; + opt.begin_index = this->ui->sb_file_start_idx->value(); + opt.after_1_12 = (this->selected_version() > SCL_gameVersion::MC12); + opt.after_1_20_5 = after_1_20_5; + const bool ok = cvted.get_map_command(opt); + if (!ok) { + return tl::make_unexpected(tr("生成命令失败:\n%1").arg(command)); } + return command; } void SCWind::when_export_pool_selectionChanged() noexcept { diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 263c99ad..1c20f828 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -95,8 +95,11 @@ class SCWind : public QMainWindow { void on_pb_preview_materials_clicked() noexcept; void on_pb_preview_compress_effect_clicked() noexcept; void on_pb_export_all_clicked() noexcept; - + // exports for data file void on_pb_export_file_clicked() noexcept; + void on_pb_export_data_command() noexcept; + void on_pb_export_data_vanilla_structure() noexcept; + void when_data_file_command_changed() noexcept; private slots: void on_ac_GAcvter_options_triggered() noexcept; @@ -269,6 +272,9 @@ class SCWind : public QMainWindow { }; auto_cache_report auto_cache_3D(bool cache_all = false) noexcept; + [[nodiscard]] tl::expected get_command( + const SlopeCraft::converted_image&) const noexcept; + signals: void image_changed(); }; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index e9aa2e78..eb4be85b 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1346,10 +1346,24 @@ + + + + 导出命令 + + + + + + + 导出地图画结构 + + + - 导出 + 导出地图文件 diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 09d885f6..ddf0acf5 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -990,4 +990,38 @@ void SCWind::on_ac_memory_policy_triggered() noexcept { this->mem_policy = diag.current_value(); this->auto_cache_3D(); } +} + +void SCWind::on_pb_export_data_command() noexcept {} +void SCWind::on_pb_export_data_vanilla_structure() noexcept {} + +void SCWind::when_data_file_command_changed() noexcept { + const auto export_tasks = this->selected_export_task_list(); + if (export_tasks.empty()) { + this->ui->pte_command->clear(); + return; + } + if (export_tasks.size() >= 2) { + this->ui->pte_command->setPlainText( + tr("同时选中多个图片时,不显示 /give " + "命令。如果想预览导出的命令,请只选择一个图片。")); + return; + } + const auto task = export_tasks.front(); + if (task == nullptr) { + this->ui->pte_command->clear(); + return; + } + auto it = task->converted_images.find( + {this->current_color_table(), this->current_convert_option()}); + if (it == task->converted_images.end() or + it->second.converted_image == nullptr) { + this->ui->pte_command->clear(); + return; + } + const SlopeCraft::converted_image &cvted = *it->second.converted_image; + + auto command_res = this->get_command(cvted); + this->ui->pte_command->setPlainText(command_res ? command_res.value() + : command_res.error()); } \ No newline at end of file From 2eddc4d670cec52e97d9eb94274f89d2c4873b3a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 13:19:43 +0800 Subject: [PATCH 0875/1123] export commands in txt Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 4 +-- SlopeCraft/SCWind.h | 6 ++-- SlopeCraft/SCWind_slots.cpp | 71 +++++++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 1280d006..41731ab8 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -898,7 +898,7 @@ void SCWind::refresh_current_build_display(cvt_task *taskp) noexcept { } tl::expected SCWind::get_command( - const SlopeCraft::converted_image &cvted) const noexcept { + const SlopeCraft::converted_image &cvted, int begin_idx) const noexcept { QString command; SlopeCraft::ostream_wrapper os{ .handle = &command, @@ -922,7 +922,7 @@ tl::expected SCWind::get_command( SlopeCraft::map_data_file_give_command_options opt{}; opt.destination = &os; - opt.begin_index = this->ui->sb_file_start_idx->value(); + opt.begin_index = begin_idx; opt.after_1_12 = (this->selected_version() > SCL_gameVersion::MC12); opt.after_1_20_5 = after_1_20_5; const bool ok = cvted.get_map_command(opt); diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 1c20f828..f6c7b22a 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -97,8 +97,8 @@ class SCWind : public QMainWindow { void on_pb_export_all_clicked() noexcept; // exports for data file void on_pb_export_file_clicked() noexcept; - void on_pb_export_data_command() noexcept; - void on_pb_export_data_vanilla_structure() noexcept; + void on_pb_export_data_command_clicked() noexcept; + void on_pb_export_data_vanilla_structure_clicked() noexcept; void when_data_file_command_changed() noexcept; private slots: @@ -273,7 +273,7 @@ class SCWind : public QMainWindow { auto_cache_report auto_cache_3D(bool cache_all = false) noexcept; [[nodiscard]] tl::expected get_command( - const SlopeCraft::converted_image&) const noexcept; + const SlopeCraft::converted_image&, int begin_idx) const noexcept; signals: void image_changed(); diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index ddf0acf5..2ff38370 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -662,7 +662,6 @@ void SCWind::on_pb_export_file_clicked() noexcept { if (dir.isEmpty()) { return; } - prev_dir = dir; const int seq_first = this->current_map_begin_seq_number(); @@ -992,9 +991,6 @@ void SCWind::on_ac_memory_policy_triggered() noexcept { } } -void SCWind::on_pb_export_data_command() noexcept {} -void SCWind::on_pb_export_data_vanilla_structure() noexcept {} - void SCWind::when_data_file_command_changed() noexcept { const auto export_tasks = this->selected_export_task_list(); if (export_tasks.empty()) { @@ -1012,6 +1008,9 @@ void SCWind::when_data_file_command_changed() noexcept { this->ui->pte_command->clear(); return; } + const ptrdiff_t global_index = task - this->tasks.data(); + assert(global_index >= 0 and global_index < this->tasks.size()); + auto it = task->converted_images.find( {this->current_color_table(), this->current_convert_option()}); if (it == task->converted_images.end() or @@ -1020,8 +1019,68 @@ void SCWind::when_data_file_command_changed() noexcept { return; } const SlopeCraft::converted_image &cvted = *it->second.converted_image; + const auto range = this->tasks.map_range_of( + this->ui->sb_file_start_idx->value(), global_index); - auto command_res = this->get_command(cvted); + auto command_res = this->get_command(cvted, range.first); this->ui->pte_command->setPlainText(command_res ? command_res.value() : command_res.error()); -} \ No newline at end of file +} + +void SCWind::on_pb_export_data_command_clicked() noexcept { + static QString prev_dir{""}; + const QString dir = + QFileDialog::getExistingDirectory(this, tr("设置导出位置"), prev_dir); + + if (dir.isEmpty()) { + return; + } + prev_dir = dir; + const auto converted_tasks = this->tasks.converted_tasks( + this->current_color_table(), this->current_convert_option()); + const int begin_idx = this->ui->sb_file_start_idx->value(); + int fail_count = 0; + QString fail_messages; + for (const auto [g_idx, task] : converted_tasks) { + assert(task != nullptr); + assert(g_idx < this->tasks.size()); + + const auto map_range = this->tasks.map_range_of(begin_idx, g_idx); + const auto command_res = this->get_command( + *(task->converted_images + .at({this->current_color_table(), this->current_convert_option()}) + .converted_image), + map_range.first); + const QString ofilename = + QStringLiteral("%1/%2.txt") + .arg(dir, QFileInfo{task->filename}.baseName()); + if (not command_res) { + fail_count++; + fail_messages.append( + tr("无法为 %1 生成命令:%2\n").arg(ofilename, command_res.error())); + continue; + } + QFile ofile{ofilename, this}; + if (not ofile.open(QIODevice::OpenModeFlag::Text bitor + QIODevice::OpenModeFlag::Truncate bitor + QIODevice::OpenModeFlag::WriteOnly)) { + fail_count++; + fail_messages.append( + tr("无法创建/打开文件 %1:%2\n").arg(ofilename, ofile.errorString())); + continue; + } + ofile.write(command_res.value().toLocal8Bit()); + if (ofile.error()) { + fail_count++; + fail_messages.append( + tr("无法写入文件 %1:%2\n").arg(ofilename, ofile.errorString())); + continue; + } + ofile.close(); + } + if (fail_count > 0) { + QMessageBox::critical(this, tr("%1 个文件保存失败").arg(fail_count), + fail_messages); + } +} +void SCWind::on_pb_export_data_vanilla_structure_clicked() noexcept {} From 1fa0986e2c9cdb823d85b8e20edd35a82e4dcd4c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 15:28:28 +0800 Subject: [PATCH 0876/1123] remove AbstractGUI Signed-off-by: ToKiNoBug --- utilities/libAbstractGUI/CMakeLists.txt | 4 - utilities/libAbstractGUI/libAbstractGUI.cpp | 91 ------------ utilities/libAbstractGUI/libAbstractGUI.h | 156 -------------------- 3 files changed, 251 deletions(-) delete mode 100644 utilities/libAbstractGUI/CMakeLists.txt delete mode 100644 utilities/libAbstractGUI/libAbstractGUI.cpp delete mode 100644 utilities/libAbstractGUI/libAbstractGUI.h diff --git a/utilities/libAbstractGUI/CMakeLists.txt b/utilities/libAbstractGUI/CMakeLists.txt deleted file mode 100644 index f40cd20f..00000000 --- a/utilities/libAbstractGUI/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -project(SlopeCraft_libSCGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 20) - -add_library(AbstractGUI STATIC libAbstractGUI.h libAbstractGUI.cpp) \ No newline at end of file diff --git a/utilities/libAbstractGUI/libAbstractGUI.cpp b/utilities/libAbstractGUI/libAbstractGUI.cpp deleted file mode 100644 index 42474a12..00000000 --- a/utilities/libAbstractGUI/libAbstractGUI.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "libAbstractGUI.h" - -using namespace libAbstractGUI; - -abstract_widget (*callback_create_widget)(const widget_type) noexcept = nullptr; -void (*callback_destroy_widget)(abstract_widget) noexcept = nullptr; - -::std::string (*callback_get_text)(const abstract_widget) noexcept = nullptr; -void (*callback_set_text)(abstract_widget, - ::std::string_view text) noexcept = nullptr; - -bool (*callback_is_enabled)(const abstract_widget) noexcept = nullptr; -void (*callback_set_enabled)(abstract_widget, - const bool set_enabled) noexcept = nullptr; - -void (*callback_set_freezed)(abstract_widget, - const bool set_to_freezed) noexcept = nullptr; - -extern bool (*callback_is_checked)(const state_button) noexcept; -extern void (*callback_set_checked)(state_button, - const bool set_to_checked) noexcept; - -void (*callback_get_image)(const label, uint32_t *const dest_ARGB32, - const size_t dest_capacity_in_bytes, int *const rows, - int *const cols) noexcept = nullptr; -void (*callback_set_image)(label, const uint32_t *data_ARGB32, const int rows, - const int cols, const bool) noexcept = nullptr; -void (*callback_fill_label_with_color)(label, const uint32_t ARGB32) noexcept = - nullptr; - -// manipulate progress bar -void (*callback_get_progress_bar)(const progress_bar, int *const min, - int *const max, - int *const val) noexcept = nullptr; -void (*callback_set_progress_bar)(progress_bar, const int min, const int max, - const int val) noexcept = nullptr; - -// manipulate grid layout -void (*callback_get_gird_layout_size)(const grid_layout, int *const rows, - int *const cols) noexcept = nullptr; -void (*callback_set_grid_layout_size)(grid_layout, const int rows, - const int cols) noexcept = nullptr; -abstract_widget (*callback_get_widget_at)(const grid_layout, const int r, - const int c) noexcept = nullptr; -void (*callback_set_widget_at)(grid_layout, abstract_widget, const int r, - const int c) noexcept = nullptr; - -// image io -bool (*callback_read_image_from_file)( - ::std::string_view filename, uint32_t *const dest_ARGB32, - const size_t dest_capacity_in_bytes, int *const rows, int *const cols, - bool *const is_row_major) noexcept = nullptr; -bool (*callback_write_image_to_file)( - ::std::string_view filename, const uint32_t *const data_ARGB32, - const int rows, const int cols, const bool is_row_major) noexcept = nullptr; -// File dialogs -::std::string (*callback_get_open_filename)( - ::std::string_view window_caption, ::std::string_view start_dir, - ::std::string_view filter) noexcept = nullptr; -::std::vector<::std::string> (*callback_get_open_filenames)( - ::std::string_view window_title, ::std::string_view start_dir, - ::std::string_view filter) noexcept = nullptr; - -::std::string (*callback_get_exisiting_directory_name)( - ::std::string_view window_caption, - ::std::string_view start_dir) noexcept = nullptr; -::std::vector<::std::string> (*callback_get_exisiting_directory_names)( - ::std::string_view window_caption, - ::std::string_view start_dir) noexcept = nullptr; \ No newline at end of file diff --git a/utilities/libAbstractGUI/libAbstractGUI.h b/utilities/libAbstractGUI/libAbstractGUI.h deleted file mode 100644 index 3001999d..00000000 --- a/utilities/libAbstractGUI/libAbstractGUI.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef SLOPECRAFT_UTILITIES_LIBABSTRACTGUI_LIBABSTRACTGUI_H -#define SLOPECRAFT_UTILITIES_LIBABSTRACTGUI_LIBABSTRACTGUI_H - -#include -#include -#include - -namespace libAbstractGUI { -/// @brief Supported language -enum class language : uint8_t { en_US, zh_CN }; - -enum class widget_type : size_t { - unknown, - radio_button, - check_box, - push_button, - progress_bar, - label, - grid_layout -}; - -struct abstract_widget { - void *ptr = nullptr; - widget_type type = widget_type::unknown; - - inline bool is_null() const noexcept { return ptr == nullptr; } - - inline bool is_unknown() const noexcept { - return type == widget_type::unknown; - } -}; - -struct abstract_button : public abstract_widget {}; - -struct push_button : public abstract_button { - push_button() { this->type = widget_type::push_button; } -}; - -struct state_button : public abstract_button {}; -struct radio_button : public state_button { - radio_button() { this->type = widget_type::radio_button; } -}; -struct check_box : public state_button { - check_box() { this->type = widget_type::check_box; } -}; - -struct progress_bar : public abstract_widget { - progress_bar() { this->type = widget_type::progress_bar; } -}; - -struct label : public abstract_widget { - label() { this->type = widget_type::label; } -}; - -struct grid_layout : public abstract_widget { - grid_layout() { this->type = widget_type::grid_layout; } -}; - -// Global function ptrs starts with callback_ shoule be implemented by gui lib, -// and libAbstractGUI will call them when necessary. Their default value is -// nullptr -// -// Functions starts with on_ are implemented in this lib. -extern abstract_widget (*callback_create_widget)(const widget_type) noexcept; -extern void (*callback_destroy_widget)(abstract_widget) noexcept; - -extern ::std::string (*callback_get_text)(const abstract_widget) noexcept; -extern void (*callback_set_text)(abstract_widget, - ::std::string_view text) noexcept; - -extern bool (*callback_is_enabled)(const abstract_widget) noexcept; -extern void (*callback_set_enabled)(abstract_widget, - const bool set_enabled) noexcept; - -extern void (*callback_set_freezed)(abstract_widget, - const bool set_to_freezed) noexcept; - -// manipulate buttons -extern bool (*callback_is_checked)(const state_button) noexcept; -extern void (*callback_set_checked)(state_button, - const bool set_to_checked) noexcept; - -// manipulate labels -extern void (*callback_get_image)(const label, uint32_t *const dest_ARGB32, - const size_t dest_capacity_in_bytes, - int *const rows, int *const cols) noexcept; -extern void (*callback_set_image)(label, const uint32_t *data_ARGB32, - const int rows, const int cols, - const bool is_row_major) noexcept; -extern void (*callback_fill_label_with_color)(label, - const uint32_t ARGB32) noexcept; - -// manipulate progress bar -extern void (*callback_get_progress_bar)(const progress_bar, int *const min, - int *const max, - int *const val) noexcept; -extern void (*callback_set_progress_bar)(progress_bar, const int min, - const int max, const int val) noexcept; - -// manipulate grid layout -extern void (*callback_get_gird_layout_size)(const grid_layout, int *const rows, - int *const cols) noexcept; -extern void (*callback_set_grid_layout_size)(grid_layout, const int rows, - const int cols) noexcept; -extern abstract_widget (*callback_get_widget_at)(const grid_layout, const int r, - const int c) noexcept; -extern void (*callback_set_widget_at)(grid_layout, abstract_widget, const int r, - const int c) noexcept; - -// image file io -extern bool (*callback_read_image_from_file)( - ::std::string_view filename, uint32_t *const dest_ARGB32, - const size_t dest_capacity_in_bytes, int *const rows, int *const cols, - bool *const is_row_major) noexcept; -extern bool (*callback_write_image_to_file)(::std::string_view filename, - const uint32_t *const data_ARGB32, - const int rows, const int cols, - const bool is_row_major) noexcept; -// File dialogs -extern ::std::string (*callback_get_open_filename)( - ::std::string_view window_caption, ::std::string_view start_dir, - ::std::string_view filter) noexcept; -extern ::std::vector<::std::string> (*callback_get_open_filenames)( - ::std::string_view window_title, ::std::string_view start_dir, - ::std::string_view filter) noexcept; - -extern ::std::string (*callback_get_exisiting_directory_name)( - ::std::string_view window_caption, ::std::string_view start_dir) noexcept; -extern ::std::vector<::std::string> (*callback_get_exisiting_directory_names)( - ::std::string_view window_caption, ::std::string_view start_dir) noexcept; - -} // namespace libAbstractGUI - -#endif // SLOPECRAFT_UTILITIES_LIBABSTRACTGUI_LIBABSTRACTGUI_H \ No newline at end of file From c18ad337639f2e38b3b2d4924e6b8ce0b0b5dd42 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 15:28:59 +0800 Subject: [PATCH 0877/1123] update data version to 1.20.5 Signed-off-by: ToKiNoBug --- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.h | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index e69cedf6..3c144191 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -66,7 +66,7 @@ MCDataVersion::MCDataVersion_t MCDataVersion::max_supported_version( case SCL_gameVersion::MC19: return MCDataVersion_t::Java_1_19_3; case SCL_gameVersion::MC20: - return MCDataVersion_t::Java_1_20_1; + return MCDataVersion_t::Java_1_20_5; default: abort(); return {}; diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index 00992e19..abbf5198 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,6 +30,19 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + Java_1_20_5 = 3837, + Snapshot_23w51b = 3802, + Snapshot_23w51a = 3801, + Java_1_20_4 = 3700, + Java_1_20_4_rc1 = 3699, + Java_1_20_3 = 3698, + Java_1_20_3__rc2 = 3577, + Java_1_20_3__rc1 = 3576, + Java_1_20_2_pre4 = 3575, + Java_1_20_2_pre3 = 3574, + Java_1_20_2_pre2 = 3573, + Java_1_20_2_pre1 = 3572, + Snapshot_23w35a = 3571, Snapshot_23w33a = 3570, Snapshot_23w32a = 3569, Snapshot_23w31a = 3567, From 3537037a1344f298c27607e474293ef557c1cc42 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 15:29:21 +0800 Subject: [PATCH 0878/1123] add items and entities to libSchem Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 11 ++- utilities/Schem/entity.cpp | 88 ++++++++++++++++++++++++ utilities/Schem/entity.h | 122 +++++++++++++++++++++++++++++++++ utilities/Schem/item.cpp | 77 +++++++++++++++++++++ utilities/Schem/item.h | 54 +++++++++++++++ 5 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 utilities/Schem/entity.cpp create mode 100644 utilities/Schem/entity.h create mode 100644 utilities/Schem/item.cpp create mode 100644 utilities/Schem/item.h diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 7e13ce28..0951543d 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -8,7 +8,12 @@ add_library(Schem bit_shrink.h bit_shrink.cpp mushroom.h - mushroom.cpp) + mushroom.cpp + entity.h + entity.cpp + item.cpp + item.h +) find_package(Eigen3 REQUIRED) find_package(cereal REQUIRED) @@ -21,7 +26,9 @@ target_link_libraries(Schem PUBLIC Eigen3::Eigen cereal::cereal fmt::fmt - magic_enum::magic_enum) + magic_enum::magic_enum + NBTWriter +) target_compile_features(Schem PUBLIC cxx_std_23) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) diff --git a/utilities/Schem/entity.cpp b/utilities/Schem/entity.cpp new file mode 100644 index 00000000..60f348a3 --- /dev/null +++ b/utilities/Schem/entity.cpp @@ -0,0 +1,88 @@ +// +// Created by Joseph on 2024/8/6. +// + +#include +#include + +#include "entity.h" + +tl::expected libSchem::entity::dump( + NBT::NBTWriter &destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + if (not destination.isInCompound()) { + return tl::make_unexpected( + "You should write entities fields into a compound, but the NBTWriter " + "is not writing a compound."); + } + size_t bytes = 0; + + if (this->id() not_eq "player") { + bytes += destination.writeString("id", this->id().data()); + } + { + destination.writeListHead("Pos", NBT::tagType::Double, 3); + for (double cord : this->position()) { + bytes += destination.writeDouble("", cord); + } + assert(destination.isInCompound()); + } + { + bytes += destination.writeListHead("Rotation", NBT::tagType::Float, 2); + for (float rot : this->rotation()) { + bytes += destination.writeFloat("", rot); + } + assert(destination.isInCompound()); + } + + return bytes; +} + +tl::expected libSchem::hangable::dump( + NBT::NBTWriter &destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + auto res = entity::dump(destination, data_version); + if (not res) { + return res; + } + size_t bytes = res.value(); + bytes += + destination.writeByte("Facing", static_cast(this->direction_)); + + const std::array keys{"TileX", "TileY", "TileZ"}; + for (size_t dim = 0; dim < 3; dim++) { + bytes += destination.writeInt(keys[dim], this->tile_position_[dim]); + } + return bytes; +} + +tl::expected libSchem::item_frame::dump( + NBT::NBTWriter &destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + auto res = hangable::dump(destination, data_version); + if (not res) { + return res; + } + size_t bytes = res.value(); + bytes += destination.writeByte("Fixed", this->fixed_); + bytes += destination.writeByte("Invisible", this->invisible_); + bytes += destination.writeFloat("ItemDropChance", this->item_drop_chance); + if (this->item_rotation < 0 or this->item_rotation > 7) { + return tl::make_unexpected( + fmt::format("Invalid item rotation {}, expected in range [0,7]", + int(this->item_rotation))); + } + bytes += destination.writeByte("ItemRotation", this->item_rotation); + + if (this->item not_eq nullptr) { + bytes += destination.writeCompound("Item"); + auto res_item = this->item->dump(destination, data_version); + if (not res_item) { + return tl::make_unexpected( + fmt::format("Failed to dump item fields: {}", res_item.error())); + } + bytes += res_item.value(); + bytes += destination.endCompound(); + } + return bytes; +} \ No newline at end of file diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h new file mode 100644 index 00000000..191469b6 --- /dev/null +++ b/utilities/Schem/entity.h @@ -0,0 +1,122 @@ +// +// Created by Joseph on 2024/8/6. +// + +#ifndef SLOPECRAFT_ENTITY_H +#define SLOPECRAFT_ENTITY_H + +#include +#include +#include +#include +#include + +#include +#include +#include "item.h" + +namespace NBT { +template +class NBTWriter; +} + +namespace libSchem { +class entity { + public: + virtual std::string_view id() const noexcept = 0; + virtual ~entity() = default; + + /// xyz + [[nodiscard]] virtual std::array position() const noexcept = 0; + /// [horizontal, vertical]. north = [-180,0], east = [-90,0], south = [0,0], + /// west = [90,0], north(again) = [180,0]. + [[nodiscard]] virtual std::array rotation() const noexcept = 0; + + virtual tl::expected dump( + NBT::NBTWriter& destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept; +}; + +enum class hangable_facing_direction : int8_t { + south = 3, + west = 4, + north = 2, + east = 5, + top = 1, + bottom = 0, +}; + +class hangable : public entity { + public: + hangable_facing_direction direction_{hangable_facing_direction::north}; + std::array tile_position_{0, 0, 0}; + + std::array position() const noexcept override { + std::array ret; + for (size_t i = 0; i < 3; i++) { + ret[i] = this->tile_position_[i]; + } + return ret; + } + + std::array rotation() const noexcept override { + using hfd = hangable_facing_direction; + switch (this->direction_) { + case hfd::north: + return {-180, 0}; + case hfd::east: + return {-90, 0}; + case hfd::south: + return {0, 0}; + case hfd::west: + return {90, 0}; + case hfd::top: + return {0, 90}; + case hfd::bottom: + return {0, -90}; + } + } + + tl::expected dump( + NBT::NBTWriter& destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept override; +}; + +enum class item_frame_variant : uint8_t { + common, + glowing, +}; + +class item_frame : public hangable { + public: + /// true to prevent it from dropping if it has no support block, being moved + /// (e.g. by pistons), taking damage (except from creative players), and + /// placing an item in it, removing its item, or rotating it. + bool fixed_{false}; + /// Whether the item frame is invisible. The contained item or map remains + /// visible. + bool invisible_{false}; + + int8_t item_rotation{0}; + float item_drop_chance{1}; + + std::unique_ptr item{nullptr}; + + item_frame_variant variant_{item_frame_variant::common}; + + std::string_view id() const noexcept override { + switch (this->variant_) { + case item_frame_variant::common: + return "item_frame"; + case item_frame_variant::glowing: + return "glow_item_frame"; + } + } + + tl::expected dump( + NBT::NBTWriter& destination, + MCDataVersion::MCDataVersion_t data_version) const noexcept override; +}; +} // namespace libSchem + +#endif // SLOPECRAFT_ENTITY_H diff --git a/utilities/Schem/item.cpp b/utilities/Schem/item.cpp new file mode 100644 index 00000000..9d7e1c61 --- /dev/null +++ b/utilities/Schem/item.cpp @@ -0,0 +1,77 @@ +// +// Created by Joseph on 2024/8/6. +// + +#include "item.h" +#include + +tl::expected libSchem::item::dump( + NBT::NBTWriter &dest, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + auto res = this->dump_basic_fields(dest, data_version); + if (not res) { + return res; + } + size_t bytes = res.value(); + const char *key = nullptr; + if (data_version < MCDataVersion::MCDataVersion_t::Java_1_20_5) { + key = "tags"; + } else { + key = "components"; + } + { + bytes += dest.writeCompound(key); + auto res_tags = this->dump_tags(dest, data_version); + if (not res_tags) { + dest.endCompound(); + return res_tags; + } + bytes += res_tags.value(); + bytes += dest.endCompound(); + } + return bytes; +} + +tl::expected libSchem::item::dump_basic_fields( + NBT::NBTWriter &dest, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + if (not dest.isInCompound()) { + return tl::make_unexpected( + "You should dump item fields into a compound, but the NBT write is not " + "writing a compound."); + } + + size_t bytes = 0; + bytes += dest.writeString("id", this->id().data()); + if (data_version < MCDataVersion::MCDataVersion_t::Java_1_20_5) { + bytes += dest.writeByte("Count", this->count_); + } else { + bytes += dest.writeInt("count", this->count_); + } + return bytes; +} + +tl::expected libSchem::item::dump_tags( + NBT::NBTWriter &dest, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + if (not dest.isInCompound()) { + return tl::make_unexpected("You should dump item tags into a compound."); + } + return 0; +} + +tl::expected libSchem::filled_map::dump_tags( + NBT::NBTWriter &dest, + MCDataVersion::MCDataVersion_t data_version) const noexcept { + auto res = item::dump_tags(dest, data_version); + if (not res) { + return res; + } + size_t bytes = res.value(); + if (data_version < MCDataVersion::MCDataVersion_t::Java_1_20_5) { + bytes += dest.writeInt("map", this->map_id); + } else { + bytes += dest.writeInt("minecraft:map_id", this->map_id); + } + return bytes; +} \ No newline at end of file diff --git a/utilities/Schem/item.h b/utilities/Schem/item.h new file mode 100644 index 00000000..ca53d1c6 --- /dev/null +++ b/utilities/Schem/item.h @@ -0,0 +1,54 @@ +// +// Created by Joseph on 2024/8/6. +// + +#ifndef SLOPECRAFT_ITEM_H +#define SLOPECRAFT_ITEM_H + +#include +#include +#include +#include + +#include +#include + +namespace NBT { +template +class NBTWriter; +} + +namespace libSchem { +class item { + public: + virtual ~item() = default; + + virtual std::string_view id() const noexcept = 0; + + int8_t count_{1}; + virtual tl::expected dump( + NBT::NBTWriter&, + MCDataVersion::MCDataVersion_t data_version) const noexcept; + + protected: + virtual tl::expected dump_basic_fields( + NBT::NBTWriter&, + MCDataVersion::MCDataVersion_t data_version) const noexcept; + virtual tl::expected dump_tags( + NBT::NBTWriter&, + MCDataVersion::MCDataVersion_t data_version) const noexcept; +}; + +class filled_map : public item { + public: + /// The map number + int map_id{0}; + + protected: + tl::expected dump_tags( + NBT::NBTWriter&, + MCDataVersion::MCDataVersion_t data_version) const noexcept override; +}; +} // namespace libSchem + +#endif // SLOPECRAFT_ITEM_H From 15ee55f530bdb48db13151877edfc78e48cf6861 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 15:29:38 +0800 Subject: [PATCH 0879/1123] add map facing to global enums Signed-off-by: ToKiNoBug --- utilities/SC_GlobalEnums.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 3d187877..d89c33d0 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -213,4 +213,19 @@ enum class SCL_HalfTpPixelSt : char { enum class SCL_language : int { Chinese = 0, English = 1 }; +enum class SCL_map_facing : int { + wall_north, + wall_south, + wall_east, + wall_west, + top_north, + top_south, + top_east, + top_west, + bottom_north, + bottom_south, + bottom_east, + bottom_west, +}; + #endif \ No newline at end of file From 9d9f662a1c128a8d943da96ea1c16293f95d76c4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 16:25:45 +0800 Subject: [PATCH 0880/1123] export litematica with entities Signed-off-by: ToKiNoBug --- utilities/SC_GlobalEnums.h | 1 + utilities/Schem/Schem.cpp | 85 ++++++++++++++++---------------------- utilities/Schem/Schem.h | 40 ++++++++++++++++-- 3 files changed, 73 insertions(+), 53 deletions(-) diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index d89c33d0..94e0ff32 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -168,6 +168,7 @@ enum class SCL_errorFlag : int { /// for a huge image MEMORY_ALLOCATE_FAILED = 0x12, + EXPORT_SCHEM_HAS_INVALID_ENTITY = 0x13, }; enum class SCL_workStatus : int { diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index ecd62a5a..20ee50c2 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -289,50 +289,32 @@ void Schem::process_mushroom_states() noexcept { } return; } - -bool Schem::export_litematic(std::string_view filename, - const litematic_info &info, - SCL_errorFlag *const error_flag, - std::string *const error_str) const noexcept { +tl::expected> +Schem::export_litematic(std::string_view filename, + const litematic_info &info) const noexcept { if (std::filesystem::path(filename).extension() != ".litematic") { // wrong extension - - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION; - } - if (error_str != nullptr) { - *error_str = "The filename externsion must be \".litematic\"."; - } - return false; + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION, + "The filename externsion must be \".litematic\".")); } // check for invalid blocks { std::array pos; if (this->have_invalid_block(&pos[0], &pos[1], &pos[2])) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS; - } - if (error_str != nullptr) { - *error_str = "The first invalid block is at x="; - *error_str += std::to_string(pos[0]) + ", y="; - *error_str += std::to_string(pos[1]) + ", z="; - *error_str += std::to_string(pos[2]); - } - return false; + return tl::make_unexpected(std::make_pair( + SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS, + fmt::format("The first invalid block is at x={}, y={}, z={}", pos[0], + pos[1], pos[2]))); } } NBT::NBTWriter lite; if (!lite.open(filename.data())) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE; - } - if (error_str != nullptr) { - *error_str = "Failed to open file : "; - *error_str += filename; - } - return false; + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, + fmt::format("Failed to open file: {}", filename))); } lite.writeCompound("Metadata"); @@ -432,6 +414,23 @@ bool Schem::export_litematic(std::string_view filename, } } // progressAdd(wind, size3D[0]); + + if (not this->entities.empty()) { + lite.writeListHead("Entities", NBT::tagType::Compound, + this->entities.size()); + for (auto &entity : this->entities) { + assert(entity); + lite.writeCompound(); + auto res = entity->dump(lite, this->MC_data_ver); + if (not res) { + lite.endCompound(); + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, + std::move(res.error()))); + } + lite.endCompound(); + } + } } lite.endCompound(); // end current region } @@ -454,28 +453,16 @@ bool Schem::export_litematic(std::string_view filename, lite.writeInt("Version", 5); break; default: - std::cerr << "Wrong game version!" << std::endl; lite.close(); - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION; - } - if (error_str != nullptr) { - *error_str = - "Unknown major game version! Only 1.12 to 1.19 is " - "supported, but given value " + - std::to_string((int)this->MC_major_ver); - } - return false; + return tl::make_unexpected(std::make_pair( + SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION, + fmt::format("Unknown major game version! Only 1.12 to 1.19 is " + "supported, but given value {}", + int(this->MC_major_ver)))); } lite.close(); - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::NO_ERROR_OCCUR; - } - if (error_str != nullptr) { - *error_str = ""; - } - return true; + return {}; } bool Schem::export_structure(std::string_view filename, diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index df0d4ea5..17e1ff4e 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -38,6 +38,7 @@ This file is part of SlopeCraft. #include #include "SC_GlobalEnums.h" +#include "entity.h" namespace libSchem { // template @@ -81,8 +82,12 @@ class Schem { ::SCL_gameVersion MC_major_ver; MCDataVersion::MCDataVersion_t MC_data_ver; + std::vector> entities; + public: Schem() { xzy.resize(0, 0, 0); } + Schem(const Schem &) = delete; + Schem(Schem &&) = default; Schem(int64_t x, int64_t y, int64_t z) { xzy.resize(x, y, z); xzy.setZero(); @@ -228,10 +233,37 @@ class Schem { void process_mushroom_states_fast() noexcept; public: - bool export_litematic(std::string_view filename, - const litematic_info &info = litematic_info(), - SCL_errorFlag *const error_flag = nullptr, - std::string *const error_str = nullptr) const noexcept; + static void update_error_dest( + const tl::expected> &result, + SCL_errorFlag *const error_flag, std::string *const error_str) noexcept { + if (result) { + if (error_flag not_eq nullptr) { + *error_flag = SCL_errorFlag::NO_ERROR_OCCUR; + } + if (error_str not_eq nullptr) { + error_str->clear(); + } + } else { + auto &err = result.error(); + if (error_flag not_eq nullptr) { + *error_flag = err.first; + } + if (error_str not_eq nullptr) { + *error_str = err.second; + } + } + } + tl::expected> export_litematic( + std::string_view filename, const litematic_info &info) const noexcept; + + [[deprecated]] bool export_litematic( + std::string_view filename, const litematic_info &info, + SCL_errorFlag *const error_flag, + std::string *const error_str) const noexcept { + auto res = this->export_litematic(filename, info); + update_error_dest(res, error_flag, error_str); + return res.has_value(); + } bool export_structure(std::string_view filename, const bool is_air_structure_void = true, From 2e4796f66cf1436d16ec4f97625379704b1ba94e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 16:47:25 +0800 Subject: [PATCH 0881/1123] fix stupid error handling in libSchem Signed-off-by: ToKiNoBug --- VisualCraftL/TokiVC_export_test.cpp | 9 +- utilities/Schem/Schem.cpp | 173 ++++++++-------------------- utilities/Schem/Schem.h | 35 ++++-- 3 files changed, 81 insertions(+), 136 deletions(-) diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index db5d2f2e..bab897ed 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -26,9 +26,9 @@ This file is part of SlopeCraft. #include #include -const VCL_block * -find_first_mark_block(const std::unordered_map - &blocks_allowed) noexcept { +const VCL_block *find_first_mark_block( + const std::unordered_map + &blocks_allowed) noexcept { const VCL_block *p = nullptr; for (const auto &pair : blocks_allowed) { if (pair.first->is_air()) { @@ -46,7 +46,6 @@ find_first_mark_block(const std::unordered_map } bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { - if (!TokiVC_internal::is_basic_color_set_ready || !TokiVC_internal::is_allowed_color_set_ready) { VCL_report( @@ -142,6 +141,6 @@ bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { info.author_utf8 = "VisualCraftL"; info.destricption_utf8 = "This litematic is generated by VisualCraft."; - return schem.export_litematic(filename, info); + return schem.export_litematic(filename, info, nullptr, nullptr); } } diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 20ee50c2..e04e42ef 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -289,14 +289,14 @@ void Schem::process_mushroom_states() noexcept { } return; } -tl::expected> -Schem::export_litematic(std::string_view filename, - const litematic_info &info) const noexcept { - if (std::filesystem::path(filename).extension() != ".litematic") { + +tl::expected> Schem::pre_check( + std::string_view filename, std::string_view extension) const noexcept { + if (std::filesystem::path(filename).extension() != extension) { // wrong extension - return tl::make_unexpected( - std::make_pair(SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION, - "The filename externsion must be \".litematic\".")); + return tl::make_unexpected(std::make_pair( + SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION, + fmt::format("The filename extension must be \"{}\".", extension))); } // check for invalid blocks { @@ -308,7 +308,18 @@ Schem::export_litematic(std::string_view filename, pos[1], pos[2]))); } } + return {}; +} +tl::expected> +Schem::export_litematic(std::string_view filename, + const litematic_info &info) const noexcept { + { + auto res = this->pre_check(filename, ".litematic"); + if (not res) { + return res; + } + } NBT::NBTWriter lite; if (!lite.open(filename.data())) { @@ -465,36 +476,13 @@ Schem::export_litematic(std::string_view filename, return {}; } -bool Schem::export_structure(std::string_view filename, - const bool is_air_structure_void, - SCL_errorFlag *const error_flag, - std::string *const error_str) const noexcept { - if (std::filesystem::path(filename).extension() != ".nbt") { - // wrong extension - - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION; - } - if (error_str != nullptr) { - *error_str = "The filename externsion must be \".nbt\"."; - } - return false; - } - - // check for invalid blocks +tl::expected> +Schem::export_structure(std::string_view filename, + const bool is_air_structure_void) const noexcept { { - std::array pos; - if (this->have_invalid_block(&pos[0], &pos[1], &pos[2])) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS; - } - if (error_str != nullptr) { - *error_str = "The first invalid block is at x="; - *error_str += std::to_string(pos[0]) + ", y="; - *error_str += std::to_string(pos[1]) + ", z="; - *error_str += std::to_string(pos[2]); - } - return false; + auto res = this->pre_check(filename, ".nbt"); + if (not res) { + return res; } } @@ -513,15 +501,10 @@ bool Schem::export_structure(std::string_view filename, "minecraft:air in your block palette." << std::endl; - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_STRUCTURE_REQUIRES_AIR; - } - if (error_str != nullptr) { - *error_str = - "You assigned is_air_structure_void=false, but there is no " - "minecraft:air in your block palette."; - } - return false; + return tl::make_unexpected(std::make_pair( + SCL_errorFlag::EXPORT_SCHEM_STRUCTURE_REQUIRES_AIR, + "You assigned is_air_structure_void=false, but there is no " + "minecraft:air in your block palette.")); } /* @@ -531,14 +514,9 @@ bool Schem::export_structure(std::string_view filename, NBT::NBTWriter file; if (!file.open(filename.data())) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE; - } - if (error_str != nullptr) { - *error_str = "Failed to open file : "; - *error_str += filename; - } - return false; + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, + fmt::format("Failed to open file {}", filename))); } file.writeListHead("entities", NBT::Byte, 0); @@ -637,85 +615,40 @@ bool Schem::export_structure(std::string_view filename, default: std::cerr << "Wrong game version!" << std::endl; file.close(); - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION; - } - if (error_str != nullptr) { - *error_str = - "Unknown major game version! Only 1.12 to 1.19 is " - "supported, but given value " + - std::to_string((int)this->MC_major_ver); - } - return false; + return tl::make_unexpected(std::make_pair( + SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION, + fmt::format("Unknown major game version! Only 1.12 to 1.19 is " + "supported, but given value {}", + (int)this->MC_major_ver))); } } file.close(); - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::NO_ERROR_OCCUR; - } - if (error_str != nullptr) { - *error_str = ""; - } - return true; + return {}; } -bool Schem::export_WESchem(std::string_view filename, - const WorldEditSchem_info &info, - SCL_errorFlag *const error_flag, - std::string *const error_str) const noexcept { - if (std::filesystem::path(filename).extension() != ".schem") { - // wrong extension - - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION; - } - if (error_str != nullptr) { - *error_str = "The filename externsion must be \".schem\"."; - } - return false; - } - - // check for invalid blocks +tl::expected> Schem::export_WESchem( + std::string_view filename, const WorldEditSchem_info &info) const noexcept { { - std::array pos; - if (this->have_invalid_block(&pos[0], &pos[1], &pos[2])) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS; - } - if (error_str != nullptr) { - *error_str = "The first invalid block is at x="; - *error_str += std::to_string(pos[0]) + ", y="; - *error_str += std::to_string(pos[1]) + ", z="; - *error_str += std::to_string(pos[2]); - } - return false; + auto res = this->pre_check(filename, ".schem"); + if (not res) { + return res; } } if (this->MC_major_ver <= SCL_gameVersion::MC12) { - if (error_flag != nullptr) { - *error_flag = ::SCL_errorFlag::EXPORT_SCHEM_MC12_NOT_SUPPORTED; - } - if (error_str != nullptr) { - *error_str = - "Exporting a schematic as 1.12 WorldEdit .schematic format " - "is not supported. Try other tools."; - } - return false; + return tl::make_unexpected(std::make_pair( + ::SCL_errorFlag::EXPORT_SCHEM_MC12_NOT_SUPPORTED, + "Exporting a schematic as 1.12 WorldEdit .schematic format " + "is not supported. Try other tools.")); } NBT::NBTWriter file; if (!file.open(filename.data())) { - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE; - } - if (error_str != nullptr) { - *error_str = "Failed to open file : "; - *error_str += filename; - } - return false; + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, + fmt::format("Failed to open file {}", filename))); } // write metadata @@ -779,11 +712,5 @@ bool Schem::export_WESchem(std::string_view filename, } // end array file.close(); - if (error_flag != nullptr) { - *error_flag = SCL_errorFlag::NO_ERROR_OCCUR; - } - if (error_str != nullptr) { - *error_str = ""; - } - return true; + return {}; } diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 17e1ff4e..90a91859 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -256,6 +256,14 @@ class Schem { tl::expected> export_litematic( std::string_view filename, const litematic_info &info) const noexcept; + tl::expected> export_structure( + std::string_view filename, + const bool is_air_structure_void) const noexcept; + + tl::expected> export_WESchem( + std::string_view filename, + const WorldEditSchem_info &info) const noexcept; + [[deprecated]] bool export_litematic( std::string_view filename, const litematic_info &info, SCL_errorFlag *const error_flag, @@ -265,19 +273,30 @@ class Schem { return res.has_value(); } - bool export_structure(std::string_view filename, - const bool is_air_structure_void = true, - SCL_errorFlag *const error_flag = nullptr, - std::string *const error_str = nullptr) const noexcept; + [[deprecated]] bool export_structure( + std::string_view filename, const bool is_air_structure_void, + SCL_errorFlag *const error_flag, + std::string *const error_str) const noexcept { + auto res = this->export_structure(filename, is_air_structure_void); + update_error_dest(res, error_flag, error_str); + return res.has_value(); + } - bool export_WESchem(std::string_view filename, - const WorldEditSchem_info &info = WorldEditSchem_info(), - SCL_errorFlag *const error_flag = nullptr, - std::string *const error_str = nullptr) const noexcept; + [[deprecated]] bool export_WESchem( + std::string_view filename, const WorldEditSchem_info &info, + SCL_errorFlag *const error_flag, + std::string *const error_str) const noexcept { + auto res = this->export_WESchem(filename, info); + update_error_dest(res, error_flag, error_str); + return res.has_value(); + } private: friend class cereal::access; + tl::expected> pre_check( + std::string_view filename, std::string_view extension) const noexcept; + template void save(archive &ar) const { ar(this->MC_major_ver); From f4aa8ac53ead3be3ca068de300d16dee77fbf105 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 17:15:01 +0800 Subject: [PATCH 0882/1123] export entity in vanilla structure Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index e04e42ef..f72bf7b7 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -598,7 +598,39 @@ Schem::export_structure(std::string_view filename, } } } - // finish writting the whole 3D array + // finish writing the whole 3D array + + if (not this->entities.size()) { + // write entities + file.writeListHead("entities", NBT::tagType::Compound, + this->entities.size()); + for (auto &entity : this->entities) { + file.writeCompound(); + { + file.writeListHead("pos", NBT::tagType::Double, 3); + for (double pos : entity->position()) { + file.writeDouble("", pos); + } + file.writeListHead("blockPos", NBT::tagType::Int, 3); + for (double pos : entity->position()) { + file.writeInt("", std::floor(pos)); + } + file.writeCompound("nbt"); + { + auto res = entity->dump(file, this->MC_data_ver); + if (not res) { + file.endCompound(); + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, + std::move(res.error()))); + } + } + file.endCompound(); + } + file.endCompound(); + } + // finish writing entities + } switch (this->MC_major_ver) { case ::SCL_gameVersion::MC12: From ac7b84f3bf1053256d3406642a062fe3b1f7a683 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 6 Aug 2024 22:58:41 +0800 Subject: [PATCH 0883/1123] export assembled maps in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.h | 21 ++++ SlopeCraftL/converted_image.cpp | 191 +++++++++++++++++++++++++++++++- SlopeCraftL/converted_image.h | 17 +++ utilities/Schem/Schem.h | 3 + utilities/Schem/entity.h | 2 + utilities/Schem/item.h | 4 + 6 files changed, 235 insertions(+), 3 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index f10bce24..144d1a39 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -263,6 +263,20 @@ struct map_data_file_give_command_options { bool after_1_20_5{false}; }; +enum class SCL_item_frame_variant : uint16_t { + common = 0, + glowing = 1, +}; +struct assembled_maps_options { + uint64_t caller_api_version{SC_VERSION_U64}; + SCL_item_frame_variant frame_variant{SCL_item_frame_variant::common}; + SCL_map_facing map_facing{SCL_map_facing::wall_north}; + bool after_1_20_5{false}; + bool fixed_frame{true}; + bool invisible_frame{true}; + int begin_index{0}; +}; + struct build_options { uint64_t caller_api_version{SC_VERSION_U64}; uint16_t max_allowed_height{256}; @@ -431,6 +445,13 @@ class converted_image { [[nodiscard]] virtual bool get_map_command( const map_data_file_give_command_options &option) const = 0; + + [[nodiscard]] virtual bool export_assembled_maps_litematic( + const char *filename, const assembled_maps_options &, + const litematic_options &) const noexcept = 0; + [[nodiscard]] virtual bool export_assembled_maps_vanilla_structure( + const char *filename, const assembled_maps_options &, + const vanilla_structure_options &) const noexcept = 0; }; class structure_3D { diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 6713d9b9..e80cfdbf 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -532,6 +532,191 @@ bool converted_image_impl::get_map_command( return true; } -// uint64_t converted_image_impl::hash() const noexcept { -// return this->converter.task_hash(); -// } \ No newline at end of file +Eigen::Matrix transform_mat_of(SCL_map_facing facing) noexcept { + switch (facing) { + case SCL_map_facing::wall_west: + return Eigen::Matrix{{0, 0}, // + {0, -1}, // c y- + {1, 0}}; // r z+ + case SCL_map_facing::wall_north: + return Eigen::Matrix{{-1, 0}, // r x- + {0, -1}, // c y- + {0, 0}}; // + case SCL_map_facing::wall_east: + return Eigen::Matrix{{0, 0}, // + {0, -1}, // c y- + {-1, 0}}; // r z- + case SCL_map_facing::wall_south: + return Eigen::Matrix{{-1, 0}, // r x- + {0, -1}, // c y- + {0, 0}}; // + case SCL_map_facing::top_south: + return Eigen::Matrix{{-1, 0}, // r x- + {0, 0}, // + {0, -1}}; // c z- + case SCL_map_facing::top_north: + return Eigen::Matrix{{1, 0}, // r x+ + {0, 0}, // + {0, 1}}; // c z+ + case SCL_map_facing::top_east: + return Eigen::Matrix{{0, -1}, // c x- + {0, 0}, // + {1, 0}}; // r z+ + case SCL_map_facing::top_west: + return Eigen::Matrix{{0, 1}, // c x+ + {0, 0}, // + {-1, 0}}; // r z- + case SCL_map_facing::bottom_north: + return Eigen::Matrix{{-1, 0}, // r x- + {0, 0}, // + {0, 1}}; // c z+ + case SCL_map_facing::bottom_south: + return Eigen::Matrix{{1, 0}, // r x+ + {0, 0}, // + {0, 1}}; // c z+ + case SCL_map_facing::bottom_east: + return Eigen::Matrix{{0, -1}, // c x- + {0, 0}, // + {-1, 0}}; // r z- + case SCL_map_facing::bottom_west: + return Eigen::Matrix{{0, 1}, // c x+ + {0, 0}, // + {1, 0}}; // r z+ + } + std::unreachable(); +} + +uint8_t rotation_of(SCL_map_facing facing) noexcept { + switch (facing) { + case SCL_map_facing::top_south: + case SCL_map_facing::bottom_north: + return 4; + case SCL_map_facing::top_north: + case SCL_map_facing::bottom_south: + return 0; + case SCL_map_facing::top_east: + case SCL_map_facing::bottom_east: + return 2; + case SCL_map_facing::top_west: + case SCL_map_facing::bottom_west: + return 6; + default: + return 0; + } +} + +libSchem::Schem converted_image_impl::assembled_maps( + const assembled_maps_options &option) const noexcept { + const auto transform_mat = transform_mat_of(option.map_facing); + const auto transform_mat_abs = transform_mat.array().abs().matrix(); + const Eigen::Vector3i offset = + (transform_mat_abs - transform_mat) * + Eigen::Vector2i{{int(this->map_rows()), int(this->map_cols())}}; + // Shape of schematic + const Eigen::Vector3i shape = [this, transform_mat_abs]() { + Eigen::Vector3i s = + transform_mat_abs * + Eigen::Vector2i{{int(this->map_rows()), int(this->map_cols())}}; + s = s.array().max(1).matrix(); + return s; + }(); + + libSchem::Schem schem; + { + std::string_view id_list[1]{std::string_view{"minecraft:air"}}; + schem.set_block_id(id_list); + schem.resize(shape[0], shape[1], shape[2]); + schem.fill(0); + } + + const libSchem::item_frame_variant variant = [&option, this]() { + if (this->game_version < SCL_gameVersion::MC17) { + return libSchem::item_frame_variant::common; + } + if (option.frame_variant == SCL_item_frame_variant::common) { + return libSchem::item_frame_variant::common; + } else { + return libSchem::item_frame_variant::glowing; + } + }(); + + for (int r = 0; r < this->map_rows(); r++) { + for (int c = 0; c < this->map_cols(); c++) { + const int map_index = option.begin_index + c + r * this->map_cols(); + const Eigen::Vector3i position = + transform_mat * Eigen::Vector2i{{r, c}} + offset; + // Check map position + for (int dim = 0; dim < 3; dim++) { + assert(position[dim] >= 0); + assert(position[dim] < shape[dim]); + } + auto map_entity = std::make_unique(); + map_entity->tile_position_ = {position[0], position[1], position[2]}; + map_entity->variant_ = variant; + map_entity->invisible_ = option.invisible_frame; + map_entity->fixed_ = option.fixed_frame; + map_entity->direction_ = + [](SCL_map_facing f) -> libSchem::hangable_facing_direction { + switch (f) { + case SCL_map_facing::wall_south: + return libSchem::hangable_facing_direction::south; + case SCL_map_facing::wall_east: + return libSchem::hangable_facing_direction::east; + case SCL_map_facing::wall_north: + return libSchem::hangable_facing_direction::north; + case SCL_map_facing::wall_west: + return libSchem::hangable_facing_direction::west; + case SCL_map_facing::top_north: + case SCL_map_facing::top_south: + case SCL_map_facing::top_east: + case SCL_map_facing::top_west: + return libSchem::hangable_facing_direction::top; + case SCL_map_facing::bottom_north: + case SCL_map_facing::bottom_south: + case SCL_map_facing::bottom_east: + case SCL_map_facing::bottom_west: + return libSchem::hangable_facing_direction::bottom; + } + return {}; + }(option.map_facing); + map_entity->item_rotation = rotation_of(option.map_facing); + { + auto map_item = std::make_unique(); + map_item->map_id = map_index; + map_entity->item = std::move(map_item); + } + + schem.entity_list().emplace_back(std::move(map_entity)); + } + } + + return schem; +} + +bool converted_image_impl::export_assembled_maps_litematic( + const char *filename, const SlopeCraft::assembled_maps_options &map_opt, + const SlopeCraft::litematic_options &export_opt) const noexcept { + auto schem = this->assembled_maps(map_opt); + libSchem::litematic_info info{}; + info.litename_utf8 = export_opt.litename_utf8; + info.regionname_utf8 = export_opt.region_name_utf8; + + auto err = schem.export_litematic(filename, info); + if (not err) { + export_opt.ui.report_error(err.error().first, err.error().second.c_str()); + return false; + } + return true; +} + +bool converted_image_impl::export_assembled_maps_vanilla_structure( + const char *filename, const SlopeCraft::assembled_maps_options &map_opt, + const SlopeCraft::vanilla_structure_options &export_opt) const noexcept { + auto schem = this->assembled_maps(map_opt); + auto err = schem.export_structure(filename, export_opt.is_air_structure_void); + if (not err) { + export_opt.ui.report_error(err.error().first, err.error().second.c_str()); + return false; + } + return true; +} \ No newline at end of file diff --git a/SlopeCraftL/converted_image.h b/SlopeCraftL/converted_image.h index de614a51..c85d201b 100644 --- a/SlopeCraftL/converted_image.h +++ b/SlopeCraftL/converted_image.h @@ -9,6 +9,7 @@ #include #include #include + #include "SlopeCraftL.h" #include "SCLDefines.h" #include "mc_block.h" @@ -79,5 +80,21 @@ class converted_image_impl : public converted_image { bool get_map_command( const map_data_file_give_command_options &option) const final; + + [[nodiscard]] libSchem::Schem assembled_maps( + const assembled_maps_options &) const noexcept; + + bool export_assembled_maps_litematic( + const char *filename, const assembled_maps_options &, + const litematic_options &) const noexcept final; + virtual bool export_assembled_maps_vanilla_structure( + const char *filename, const assembled_maps_options &, + const vanilla_structure_options &) const noexcept final; }; + +[[nodiscard]] Eigen::Matrix transform_mat_of( + SCL_map_facing) noexcept; + +[[nodiscard]] uint8_t rotation_of(SCL_map_facing) noexcept; + #endif // SLOPECRAFT_CONVERTED_IMAGE_H diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 90a91859..15a34d1f 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -232,6 +232,9 @@ class Schem { void process_mushroom_states_fast() noexcept; + auto &entity_list() noexcept { return this->entities; } + auto &entity_list() const noexcept { return this->entities; } + public: static void update_error_dest( const tl::expected> &result, diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h index 191469b6..06578e5a 100644 --- a/utilities/Schem/entity.h +++ b/utilities/Schem/entity.h @@ -75,6 +75,7 @@ class hangable : public entity { case hfd::bottom: return {0, -90}; } + return {0, 0}; } tl::expected dump( @@ -111,6 +112,7 @@ class item_frame : public hangable { case item_frame_variant::glowing: return "glow_item_frame"; } + return {}; } tl::expected dump( diff --git a/utilities/Schem/item.h b/utilities/Schem/item.h index ca53d1c6..cf684314 100644 --- a/utilities/Schem/item.h +++ b/utilities/Schem/item.h @@ -44,6 +44,10 @@ class filled_map : public item { /// The map number int map_id{0}; + std::string_view id() const noexcept override { + return "minecraft:filled_map"; + } + protected: tl::expected dump_tags( NBT::NBTWriter&, From c73bb1086d14edf48d3c2134fd1966a5479d4b99 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 10:41:20 +0800 Subject: [PATCH 0884/1123] export assembled maps in SCL Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 13 +++++++++++++ SlopeCraftL/SlopeCraftL.h | 10 ++++++---- SlopeCraftL/converted_image.cpp | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 41731ab8..f3e6e8d0 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -1302,4 +1302,17 @@ SCWind::auto_cache_report SCWind::auto_cache_3D(bool cache_all) noexcept { } return report; +} + +SlopeCraft::assembled_maps_options SCWind::current_assembled_maps_option() + const noexcept { + SlopeCraft::assembled_maps_options option; + option.frame_variant = this->ui->cb_glowing_item_frame->isChecked() + ? SCL_item_frame_variant::glowing + : SCL_item_frame_variant::common; + option.after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); + option.fixed_frame = this->ui->cb_fixed_frame->isChecked(); + option.invisible_frame = this->ui->cb_invisible_frame->isChecked(); + + return option; } \ No newline at end of file diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index 144d1a39..bebf36f8 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -41,6 +41,11 @@ This file is part of SlopeCraft. #include "SC_GlobalEnums.h" #endif +enum class SCL_item_frame_variant : uint16_t { + common = 0, + glowing = 1, +}; + namespace SlopeCraft { // using step = ::SCL_step; @@ -263,14 +268,11 @@ struct map_data_file_give_command_options { bool after_1_20_5{false}; }; -enum class SCL_item_frame_variant : uint16_t { - common = 0, - glowing = 1, -}; struct assembled_maps_options { uint64_t caller_api_version{SC_VERSION_U64}; SCL_item_frame_variant frame_variant{SCL_item_frame_variant::common}; SCL_map_facing map_facing{SCL_map_facing::wall_north}; + SCL_gameVersion mc_version{SCL_gameVersion::MC19}; bool after_1_20_5{false}; bool fixed_frame{true}; bool invisible_frame{true}; diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index e80cfdbf..af71ff5f 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -610,7 +610,7 @@ libSchem::Schem converted_image_impl::assembled_maps( const auto transform_mat = transform_mat_of(option.map_facing); const auto transform_mat_abs = transform_mat.array().abs().matrix(); const Eigen::Vector3i offset = - (transform_mat_abs - transform_mat) * + (transform_mat_abs - transform_mat) / 2 * Eigen::Vector2i{{int(this->map_rows()), int(this->map_cols())}}; // Shape of schematic const Eigen::Vector3i shape = [this, transform_mat_abs]() { @@ -621,12 +621,25 @@ libSchem::Schem converted_image_impl::assembled_maps( return s; }(); + const MCDataVersion::MCDataVersion_t data_version = [option]() { + if (option.mc_version == SCL_gameVersion::MC20) { + if (option.after_1_20_5) { + return MCDataVersion::MCDataVersion_t::Java_1_20_4; + } + return MCDataVersion::MCDataVersion_t::Java_1_20_5; + } else { + return MCDataVersion::suggested_version(option.mc_version); + } + }(); + libSchem::Schem schem; { std::string_view id_list[1]{std::string_view{"minecraft:air"}}; schem.set_block_id(id_list); schem.resize(shape[0], shape[1], shape[2]); schem.fill(0); + schem.set_MC_major_version_number(option.mc_version); + schem.set_MC_version_number(data_version); } const libSchem::item_frame_variant variant = [&option, this]() { From e60bda6caefcbb41f51eb78fadd88d799e8313e1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 11:12:56 +0800 Subject: [PATCH 0885/1123] add what's this for assembled map widgets Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.ui | 231 ++++++++++++++++++++++++++++--------------- 1 file changed, 154 insertions(+), 77 deletions(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index eb4be85b..ba1100b2 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1321,53 +1321,37 @@ - - - - 0 + + + + true - - - - MC版本≥1.20.5+ - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - 导出命令 - - - - - - - 导出地图画结构 - - - - - - - 导出地图文件 - - - - + + true + + + + + + + + 0 + 0 + + + + + + + true + + + + + + 批量获得地图物品的指令 + + @@ -1384,23 +1368,15 @@ 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 -在下面的表格里可以看到每个图像对应的文件名。 +在下面的表格里可以看到每个图像对应的文件名。 + +图像数据存储在地图数据文件中,必须先为存档导入地图数据文件,地图画结构才能生效。
true - - - - true - - - true - - - @@ -1437,27 +1413,128 @@ - - - - - 0 - 0 - - - - - - - true - - - - - - 批量获得地图物品的指令 + + + + 20 - + + + + 导出批量获得地图物品的命令(txt) + + + 导出命令 + + + + + + + 生存模式不可破坏展示框;移除它依附的方块,展示框也不会消失。 + + + 展示框不可破坏 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 1.20.5后,物品格式发生重大改变 + + + MC版本≥1.20.5+ + + + + + + + 采用荧光物品显示框 + + + 荧光物品显示框 + + + + + + + 导出包含物品展示框的投影/结构方块文件 + + + 导出组装的地图画 + + + + + + + 导出map_i.dat的地图数据文件 + + + 导出地图文件 + + + + + + + 展示框背景将不可见 + + + 展示框透明 + + + + + + + 地图画可依附于方块的侧面、顶面和底面 + + + 13 + + + 地图画方向 + + + + + + + 导出Litematica + + + 导出组装地图画的格式 + + + + 导出Litematica + + + + + 导出结构方块文件 + + + + + From 24e2a51826c9fbc2d784a4cc6730dda4ef381eba Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 14:36:54 +0800 Subject: [PATCH 0886/1123] export assembled maps in SC Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 23 +++++++--- SlopeCraft/SCWind.h | 3 ++ SlopeCraft/SCWind_slots.cpp | 87 ++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 8 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index f3e6e8d0..04b0c64e 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -150,6 +150,17 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { abort(); } } + // initialize combobox for map facing + { + const std::array key1{tr("墙面"), tr("顶面"), tr("底面")}; + const std::array key2{tr("北"), tr("南"), tr("东"), tr("西")}; + for (auto facing : magic_enum::enum_values()) { + const int idx = static_cast(facing); + const QString text = tr("%1向%2").arg(key1[idx / 4], key2[idx % 4]); + this->ui->cb_map_direction->addItem(text, QVariant::fromValue(facing)); + } + this->ui->cb_map_direction->setCurrentIndex(0); + } this->when_preset_clicked(); } @@ -293,11 +304,7 @@ SCL_gameVersion SCWind::selected_version() const noexcept { return SCL_gameVersion(idx + 12); } } - - assert(false); - abort(); - - // return SCL_gameVersion::ANCIENT; + return SCL_gameVersion::ANCIENT; } SCL_mapTypes SCWind::selected_type() const noexcept { @@ -1267,7 +1274,8 @@ bool SCWind::should_auto_cache(bool suppress_warnings) noexcept { return result; } -SCWind::auto_cache_report SCWind::auto_cache_3D(bool cache_all) noexcept { +SCWind::auto_cache_report SCWind::auto_cache_3D( + [[maybe_unused]] bool cache_all) noexcept { // const auto colortable = this->current_color_table(); // const auto build_opt = this->current_build_option(); auto_cache_report report{ @@ -1307,12 +1315,15 @@ SCWind::auto_cache_report SCWind::auto_cache_3D(bool cache_all) noexcept { SlopeCraft::assembled_maps_options SCWind::current_assembled_maps_option() const noexcept { SlopeCraft::assembled_maps_options option; + option.mc_version = this->selected_version(); option.frame_variant = this->ui->cb_glowing_item_frame->isChecked() ? SCL_item_frame_variant::glowing : SCL_item_frame_variant::common; option.after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); option.fixed_frame = this->ui->cb_fixed_frame->isChecked(); option.invisible_frame = this->ui->cb_invisible_frame->isChecked(); + option.map_facing = + this->ui->cb_map_direction->currentData().value(); return option; } \ No newline at end of file diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index f6c7b22a..de958295 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -207,6 +207,9 @@ class SCWind : public QMainWindow { int current_map_begin_seq_number() const noexcept; + SlopeCraft::assembled_maps_options current_assembled_maps_option() + const noexcept; + inline auto lang() const noexcept { return this->language; } void set_lang(::SCL_language lang) noexcept; diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 2ff38370..1466a76c 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -6,6 +6,9 @@ #include #include #include + +#include + #include "PreviewWind.h" #include "AiCvterParameterDialog.h" #include "VersionDialog.h" @@ -1052,7 +1055,7 @@ void SCWind::on_pb_export_data_command_clicked() noexcept { .converted_image), map_range.first); const QString ofilename = - QStringLiteral("%1/%2.txt") + QStringLiteral("%1/command_%2txt") .arg(dir, QFileInfo{task->filename}.baseName()); if (not command_res) { fail_count++; @@ -1083,4 +1086,84 @@ void SCWind::on_pb_export_data_command_clicked() noexcept { fail_messages); } } -void SCWind::on_pb_export_data_vanilla_structure_clicked() noexcept {} +void SCWind::on_pb_export_data_vanilla_structure_clicked() noexcept { + static QString prev_dir{""}; + const QString dir = + QFileDialog::getExistingDirectory(this, tr("设置导出位置"), prev_dir); + + if (dir.isEmpty()) { + return; + } + prev_dir = dir; + + const bool export_as_lite = + this->ui->cb_export_assembled_format->currentIndex() <= 0; + const auto converted_tasks = this->tasks.converted_tasks( + this->current_color_table(), this->current_convert_option()); + const int begin_idx = this->ui->sb_file_start_idx->value(); + + int fail_count = 0; + QString fail_messages; + auto lite_option = this->current_litematic_option(fail_messages).value(); + auto nbt_option = this->current_nbt_option(fail_messages).value(); + + this->ui->pbar_export->setValue(0); + this->ui->pbar_export->setMinimum(0); + this->ui->pbar_export->setMaximum(converted_tasks.size()); + + for (const auto [g_idx, task] : converted_tasks) { + assert(task not_eq nullptr); + assert(g_idx < this->tasks.size()); + + const auto map_range = this->tasks.map_range_of(begin_idx, g_idx); + auto option = this->current_assembled_maps_option(); + option.begin_index = map_range.first; + + const QString ofilename = + QStringLiteral("%1/maps_%2.%3") + .arg(dir, QFileInfo{task->filename}.baseName(), + export_as_lite ? "litematic" : "nbt"); + + const auto &cvted = + (task->converted_images + .at({this->current_color_table(), this->current_convert_option()}) + .converted_image); + + QString err_temp = tr("SlopeCraftL 未提供详细报错信息。"); + auto report_err_cb = [&err_temp](SCL_errorFlag e, const char *msg) { + err_temp = + tr("错误码:%1,详情:%2").arg(magic_enum::enum_name(e).data(), msg); + }; + // Set up ui callbacks; + { + SlopeCraft::ui_callbacks ui{}; + ui.wind = reinterpret_cast(&report_err_cb); + using cb_type = decltype(report_err_cb); + ui.cb_report_error = [](void *lambda, SCL_errorFlag e, const char *msg) { + (reinterpret_cast(lambda))->operator()(e, msg); + }; + lite_option.ui = ui; + nbt_option.ui = ui; + } + + bool ok; + if (export_as_lite) { + ok = cvted->export_assembled_maps_litematic( + ofilename.toLocal8Bit().data(), option, lite_option); + } else { + ok = cvted->export_assembled_maps_vanilla_structure( + ofilename.toLocal8Bit().data(), option, nbt_option); + } + if (not ok) { + fail_count++; + fail_messages.append(tr("%1 生成失败,%2\n").arg(ofilename, err_temp)); + } + + this->ui->pbar_export->setValue(this->ui->pbar_export->value() + 1); + } + if (fail_count > 0) { + QMessageBox::critical(this, tr("%1 个文件保存失败").arg(fail_count), + fail_messages); + } + this->ui->pbar_export->setValue(converted_tasks.size()); +} From 92d6dac852599f7008e698d4ca5f0c5cd4c71e79 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 14:38:57 +0800 Subject: [PATCH 0887/1123] Fix exporting entities in Schem Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 79 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index f72bf7b7..027fcb27 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -407,10 +407,8 @@ Schem::export_litematic(std::string_view filename, } } - lite.writeListHead("Entities", NBT::Compound, 0); lite.writeListHead("PendingBlockTicks", NBT::Compound, 0); lite.writeListHead("PendingFluidTiccks", NBT::Compound, 0); - lite.writeListHead("TileEntities", NBT::Compound, 0); // write 3D std::vector shrinked; @@ -426,21 +424,19 @@ Schem::export_litematic(std::string_view filename, } // progressAdd(wind, size3D[0]); - if (not this->entities.empty()) { - lite.writeListHead("Entities", NBT::tagType::Compound, - this->entities.size()); - for (auto &entity : this->entities) { - assert(entity); - lite.writeCompound(); - auto res = entity->dump(lite, this->MC_data_ver); - if (not res) { - lite.endCompound(); - return tl::make_unexpected( - std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, - std::move(res.error()))); - } + lite.writeListHead("Entities", NBT::tagType::Compound, + this->entities.size()); + for (auto &entity : this->entities) { + assert(entity); + lite.writeCompound(); + auto res = entity->dump(lite, this->MC_data_ver); + if (not res) { lite.endCompound(); + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, + std::move(res.error()))); } + lite.endCompound(); } } lite.endCompound(); // end current region @@ -519,7 +515,6 @@ Schem::export_structure(std::string_view filename, fmt::format("Failed to open file {}", filename))); } - file.writeListHead("entities", NBT::Byte, 0); file.writeListHead("size", NBT::Int, 3); { file.writeInt("This should never be shown", x_range()); @@ -600,37 +595,39 @@ Schem::export_structure(std::string_view filename, } // finish writing the whole 3D array - if (not this->entities.size()) { - // write entities - file.writeListHead("entities", NBT::tagType::Compound, - this->entities.size()); - for (auto &entity : this->entities) { - file.writeCompound(); + // write entities + file.writeListHead("entities", NBT::tagType::Compound, + this->entities.size()); + for (auto &entity : this->entities) { + file.writeCompound(); + { + file.writeListHead("pos", NBT::tagType::Double, 3); + for (double pos : entity->position()) { + file.writeDouble("", pos); + } + assert(file.isInCompound()); + file.writeListHead("blockPos", NBT::tagType::Int, 3); + for (double pos : entity->position()) { + file.writeInt("", std::floor(pos)); + } + assert(file.isInCompound()); + file.writeCompound("nbt"); { - file.writeListHead("pos", NBT::tagType::Double, 3); - for (double pos : entity->position()) { - file.writeDouble("", pos); - } - file.writeListHead("blockPos", NBT::tagType::Int, 3); - for (double pos : entity->position()) { - file.writeInt("", std::floor(pos)); - } - file.writeCompound("nbt"); - { - auto res = entity->dump(file, this->MC_data_ver); - if (not res) { - file.endCompound(); - return tl::make_unexpected( - std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, - std::move(res.error()))); - } + auto res = entity->dump(file, this->MC_data_ver); + if (not res) { + file.endCompound(); + file.close_file(); + return tl::make_unexpected( + std::make_pair(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_ENTITY, + std::move(res.error()))); } - file.endCompound(); } file.endCompound(); } - // finish writing entities + file.endCompound(); } + // finish writing entities + assert(file.isInCompound()); switch (this->MC_major_ver) { case ::SCL_gameVersion::MC12: From 00f5a8abfc8622770df95a1a09211072c8a5fd65 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 16:29:11 +0800 Subject: [PATCH 0888/1123] Fix assembled map direction Signed-off-by: ToKiNoBug --- SlopeCraftL/converted_image.cpp | 62 ++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index af71ff5f..33f7ea16 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -536,52 +536,52 @@ Eigen::Matrix transform_mat_of(SCL_map_facing facing) noexcept { switch (facing) { case SCL_map_facing::wall_west: return Eigen::Matrix{{0, 0}, // - {0, -1}, // c y- - {1, 0}}; // r z+ + {-1, 0}, // r y- + {0, 1}}; // c z+ case SCL_map_facing::wall_north: - return Eigen::Matrix{{-1, 0}, // r x- - {0, -1}, // c y- + return Eigen::Matrix{{0, -1}, // c x- + {-1, 0}, // r y- {0, 0}}; // case SCL_map_facing::wall_east: return Eigen::Matrix{{0, 0}, // - {0, -1}, // c y- - {-1, 0}}; // r z- + {-1, 0}, // r y- + {0, -1}}; // c z- case SCL_map_facing::wall_south: - return Eigen::Matrix{{-1, 0}, // r x- - {0, -1}, // c y- + return Eigen::Matrix{{0, 1}, // c x+ + {-1, 0}, // r y- {0, 0}}; // case SCL_map_facing::top_south: - return Eigen::Matrix{{-1, 0}, // r x- + return Eigen::Matrix{{0, -1}, // c x- {0, 0}, // - {0, -1}}; // c z- + {-1, 0}}; // r z- case SCL_map_facing::top_north: - return Eigen::Matrix{{1, 0}, // r x+ + return Eigen::Matrix{{0, 1}, // c x+ {0, 0}, // - {0, 1}}; // c z+ + {1, 0}}; // r z+ case SCL_map_facing::top_east: - return Eigen::Matrix{{0, -1}, // c x- + return Eigen::Matrix{{-1, 0}, // r x- {0, 0}, // - {1, 0}}; // r z+ + {0, 1}}; // c z+ case SCL_map_facing::top_west: - return Eigen::Matrix{{0, 1}, // c x+ + return Eigen::Matrix{{1, 0}, // r x+ {0, 0}, // - {-1, 0}}; // r z- + {0, -1}}; // c z- case SCL_map_facing::bottom_north: - return Eigen::Matrix{{-1, 0}, // r x- + return Eigen::Matrix{{0, -1}, // c x- {0, 0}, // - {0, 1}}; // c z+ + {1, 0}}; // r z+ case SCL_map_facing::bottom_south: - return Eigen::Matrix{{1, 0}, // r x+ - {0, 0}, // - {0, 1}}; // c z+ - case SCL_map_facing::bottom_east: - return Eigen::Matrix{{0, -1}, // c x- + return Eigen::Matrix{{0, 1}, // c x+ {0, 0}, // {-1, 0}}; // r z- + case SCL_map_facing::bottom_east: + return Eigen::Matrix{{-1, 0}, // r x- + {0, 0}, // + {0, -1}}; // c z- case SCL_map_facing::bottom_west: - return Eigen::Matrix{{0, 1}, // c x+ + return Eigen::Matrix{{1, 0}, // r x+ {0, 0}, // - {1, 0}}; // r z+ + {0, 1}}; // c z+ } std::unreachable(); } @@ -590,16 +590,16 @@ uint8_t rotation_of(SCL_map_facing facing) noexcept { switch (facing) { case SCL_map_facing::top_south: case SCL_map_facing::bottom_north: - return 4; + return 2; case SCL_map_facing::top_north: case SCL_map_facing::bottom_south: return 0; case SCL_map_facing::top_east: case SCL_map_facing::bottom_east: - return 2; + return 1; case SCL_map_facing::top_west: case SCL_map_facing::bottom_west: - return 6; + return 3; default: return 0; } @@ -611,7 +611,7 @@ libSchem::Schem converted_image_impl::assembled_maps( const auto transform_mat_abs = transform_mat.array().abs().matrix(); const Eigen::Vector3i offset = (transform_mat_abs - transform_mat) / 2 * - Eigen::Vector2i{{int(this->map_rows()), int(this->map_cols())}}; + Eigen::Vector2i{{int(this->map_rows() - 1), int(this->map_cols() - 1)}}; // Shape of schematic const Eigen::Vector3i shape = [this, transform_mat_abs]() { Eigen::Vector3i s = @@ -623,7 +623,7 @@ libSchem::Schem converted_image_impl::assembled_maps( const MCDataVersion::MCDataVersion_t data_version = [option]() { if (option.mc_version == SCL_gameVersion::MC20) { - if (option.after_1_20_5) { + if (not option.after_1_20_5) { return MCDataVersion::MCDataVersion_t::Java_1_20_4; } return MCDataVersion::MCDataVersion_t::Java_1_20_5; @@ -655,7 +655,7 @@ libSchem::Schem converted_image_impl::assembled_maps( for (int r = 0; r < this->map_rows(); r++) { for (int c = 0; c < this->map_cols(); c++) { - const int map_index = option.begin_index + c + r * this->map_cols(); + const int map_index = option.begin_index + r + c * this->map_rows(); const Eigen::Vector3i position = transform_mat * Eigen::Vector2i{{r, c}} + offset; // Check map position From 3bff24bc41a3e1c226aa3bab0f80a51ffa399019 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 16:29:32 +0800 Subject: [PATCH 0889/1123] Fix chinese text of map direction Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 04b0c64e..be8b2c29 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -156,7 +156,7 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { const std::array key2{tr("北"), tr("南"), tr("东"), tr("西")}; for (auto facing : magic_enum::enum_values()) { const int idx = static_cast(facing); - const QString text = tr("%1向%2").arg(key1[idx / 4], key2[idx % 4]); + const QString text = tr("%1,向%2").arg(key1[idx / 4], key2[idx % 4]); this->ui->cb_map_direction->addItem(text, QVariant::fromValue(facing)); } this->ui->cb_map_direction->setCurrentIndex(0); From 8eed3b74a6200ce64d1a3887f2da3995ed039f0a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 16:31:38 +0800 Subject: [PATCH 0890/1123] Set item frame to be fixed by default Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.ui | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index ba1100b2..d018f2a2 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1436,6 +1436,9 @@ 展示框不可破坏 + + true + @@ -1517,7 +1520,7 @@ - 导出Litematica + 导出组装地图画的格式 From 9a9bb85bdcf2ceaf2b95bc5b8128d86a51f78f8f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 19:46:27 +0800 Subject: [PATCH 0891/1123] suppress warning in auto version check Signed-off-by: ToKiNoBug --- utilities/VersionDialog/VersionDialog.cpp | 57 +++++++++++------------ utilities/VersionDialog/VersionDialog.h | 4 +- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/utilities/VersionDialog/VersionDialog.cpp b/utilities/VersionDialog/VersionDialog.cpp index 39073c9b..479a2fa7 100644 --- a/utilities/VersionDialog/VersionDialog.cpp +++ b/utilities/VersionDialog/VersionDialog.cpp @@ -38,8 +38,8 @@ VersionDialog::~VersionDialog() { delete this->ui; } void VersionDialog::setup_text(QString title, QString content, QString markdown_content, - QString url_download) noexcept { - this->url_download = url_download; + QString url_download_) noexcept { + this->url_download = url_download_; this->setWindowTitle(title); this->ui->label->setText(content); this->ui->tb->setMarkdown(markdown_content); @@ -71,11 +71,11 @@ uint64_t version_string_to_u64(const char *str) noexcept { #include -version_info extract_latest_version( - std::string_view json_all_releaese) noexcept(false) { +version_info extract_latest_version(std::string_view json_all_release) noexcept( + false) { using njson = nlohmann::json; - njson jo = njson::parse(json_all_releaese); + njson jo = njson::parse(json_all_release); version_info ret; @@ -90,7 +90,7 @@ version_info extract_latest_version( const uint64_t ver = version_string_to_u64(tag.data()); - if ((ver >> 48) != SC_VERSION_MAJOR_U16) { + if ((ver >> 48) not_eq SC_VERSION_MAJOR_U16) { continue; } @@ -109,7 +109,6 @@ version_info extract_latest_version( if (latest.empty()) { throw std::runtime_error( "Failed to find any release that matches current major version."); - return {}; } ret.tag_name = QString::fromStdString(latest.at("tag_name")); @@ -128,11 +127,10 @@ void version_dialog_private_fun_when_network_finished( QWidget *window, QNetworkReply *reply, bool is_manually, QString software_name) noexcept; -void VersionDialog::start_network_request(QWidget *window, - QString software_name, - const QUrl &url, - QNetworkAccessManager &manager, - bool is_manually) noexcept { +void VersionDialog::start_network_request( + [[maybe_unused]] QWidget *window, QString software_name, const QUrl &url, + QNetworkAccessManager &manager, + [[maybe_unused]] bool is_manually) noexcept { QNetworkRequest request(url); QNetworkReply *reply = manager.get(request); @@ -166,7 +164,7 @@ void version_dialog_private_fun_when_network_finished( QString data_dir = home_path + "/" + data_dir_name; QString log_file = data_dir.append("/UpdateCheckFailure.log"); { - if (!QDir(data_dir).exists()) { + if (not QDir(data_dir).exists()) { QDir{home_path}.mkpath(data_dir_name); } @@ -175,17 +173,16 @@ void version_dialog_private_fun_when_network_finished( log.write(content_qba); log.close(); } - - QMessageBox::warning( - window, QWidget::tr("获取最新版本失败"), - QWidget::tr("解析 \"%1\" " - "返回的结果时出现错误:\n\n%" - "2\n\n这不是一个致命错误,不影响软件使用。\n解析失败的信" - "息已经存储在日志文件中 (%3)。") - .arg(reply->url().toString()) - .arg(e.what()) - .arg(log_file), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}); + if (is_manually) { + QMessageBox::warning( + window, QWidget::tr("获取最新版本失败"), + QWidget::tr("解析 \"%1\" " + "返回的结果时出现错误:\n\n%" + "2\n\n这不是一个致命错误,不影响软件使用。\n解析失败的信" + "息已经存储在日志文件中 (%3)。") + .arg(reply->url().toString(), e.what(), log_file), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}); + } reply->deleteLater(); return; } @@ -212,8 +209,7 @@ void version_dialog_private_fun_when_network_finished( QMessageBox::information( window, QWidget::tr("检查更新成功"), QWidget::tr("您使用的版本 (%1) 比已发布的 (%2) 更新,可能是测试版。") - .arg(SC_VERSION_STR) - .arg(tag_name)); + .arg(SC_VERSION_STR, tag_name)); } return; } @@ -224,11 +220,10 @@ void version_dialog_private_fun_when_network_finished( vd->setAttribute(Qt::WidgetAttribute::WA_AlwaysStackOnTop, true); vd->setWindowFlag(Qt::WindowType::Window, true); - vd->setup_text(QWidget::tr("%1 已更新").arg(software_name), - QWidget::tr("最新版本为%1,当前版本为%2") - .arg(tag_name) - .arg(SC_VERSION_STR), - info.body, info.html_url); + vd->setup_text( + QWidget::tr("%1 已更新").arg(software_name), + QWidget::tr("最新版本为%1,当前版本为%2").arg(tag_name, SC_VERSION_STR), + info.body, info.html_url); vd->show(); return; diff --git a/utilities/VersionDialog/VersionDialog.h b/utilities/VersionDialog/VersionDialog.h index 823b47ca..61cefb26 100644 --- a/utilities/VersionDialog/VersionDialog.h +++ b/utilities/VersionDialog/VersionDialog.h @@ -63,7 +63,7 @@ struct version_info { uint64_t version_u64; }; -version_info extract_latest_version( - std::string_view json_all_releaese) noexcept(false); +version_info extract_latest_version(std::string_view json_all_release) noexcept( + false); #endif // SLOPECRAFT_VISUALCRAFT_VERSION_DIALOG_H \ No newline at end of file From 015365e0171d79f702b6231e1ccebedec22c41ce Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 19:56:32 +0800 Subject: [PATCH 0892/1123] Force to use tl-expected >= 1.1.0 Signed-off-by: ToKiNoBug --- cmake/required_deps/tl-expected.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/tl-expected.cmake b/cmake/required_deps/tl-expected.cmake index 6ffdf7d8..960e6262 100644 --- a/cmake/required_deps/tl-expected.cmake +++ b/cmake/required_deps/tl-expected.cmake @@ -1,4 +1,4 @@ - find_package(tl-expected QUIET) + find_package(tl-expected 1.1.0 QUIET) if (NOT tl-expected_FOUND) include(FetchContent) message(STATUS "Downloading tl-expected...") From 9617cf2b365b322712a69a519e2ec3f052486c5c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 20:38:06 +0800 Subject: [PATCH 0893/1123] update translations Signed-off-by: ToKiNoBug --- SlopeCraft/others/SlopeCraft_en_US.ts | 819 +++++++++++++++++--------- 1 file changed, 552 insertions(+), 267 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 5b40abe8..fac84a45 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -34,6 +34,34 @@ Mutation prob : + + BlockListDialog + + + 加载/删除方块列表 + Load / remove block list + + + + + + + + + + - + + + + + 确定 + OK + + + + 取消 + Cancel + + CompressEffectViewer @@ -65,32 +93,32 @@ ExportTableModel - + 原图文件名 Image file - + 图像大小 Image size - + 地图大小 Map size - + 地图序号范围 Map index range - + 第一个地图文件名 First map - + 最后一个地图文件名 Last map @@ -98,17 +126,17 @@ MaterialModel - + %1 盒 + %2 组 + %3 个 %1 shulker box(es) + %2 stack(s) + %3 - + %1 组 + %2 个 %1 stack(s) + %2 - + %1 个 %1 @@ -116,7 +144,7 @@ PoolModel - + 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. @@ -125,60 +153,85 @@ PreviewWind - + 查看材料列表 Material List - + 按组显示 Display by stacks - + 不排序 Do not sort - + 升序 Acsending - + 降序 Decsending - + + 导出为文件 + Export as file + + + + 复制到剪贴板 + Copy to clipboard + + + %1 -- 表格内容已复制到剪贴板 %1 -- Table content copied to clipboart - + 大小:%1 × %2 × %3 Size: %1 × %2 × %3 - + 体积:%1 Volume: %1 - + 方块总数:%1 Block count: %1 + + + 保存材料表 + Save material list + + + + 保存材料表失败 + Failed to save material list + + + + 无法打开文件 "%1",详细信息:%2 + Failed to open file "%1", detail: %2 + QObject - + 加载图片 %1 失败。 Failed to load image %1. - + 绘制图标时发现错误 An error occurred when drawing icon @@ -196,464 +249,592 @@ Blocklist preset - + 加载预设 Load preset - + 保存当前预设 Save as preset - + 可用方块数量: Available block count: - + 游戏版本 Game Version - + 地图画类型 Map type - + 立体地图画 3D Map - + 平板地图画 Flat Map - + 纯文件地图画 File-only Map - + 优先彩色玻璃 Use stained glass - + 优先混凝土 Use Concrete - + 优先羊毛 Use Wool - + 优先木板 Use planks - + 优先原木 Use logs - + 导入图像并转化 Load image and convert - + 原图 Original image - + 转化后 Converted image - + 删除 Delete - - + + 项目池 Task pool - + 添加 Add - + 转化算法 Convert algorithm - + 抖动 Dithering - + 转化当前图像 Convert current image - - - + + + 保存转化后图像 Save converted image - + 全部转化 Convert all - - + 导出 Export - + Litematica - - + + 结构方块文件 Vanilla structure - + 优先台阶 Use slabs - + + 全选 + Select all + + + + 全不选 + Deselect all + + + + 反选 + Invert selection + + + 显示缩略图 - + View images - + 替换 Replace - - + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - + 地图文件 Map data files - + 其他选项 Others - + 防火 Fire Proof - + 防末影人 Enderman Proof - + 连接蘑菇块 Connect mushroom blocks - + 压缩高度 Compress - + 有损压缩 Lossy Compression - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 搭桥 Glass Bridge - + 允许搭桥 Construct Glass Bridge - + layer(s) - + 搭桥间隔: Glass bridge interval: - + 投影区域名称 Region name - + 投影名称 Litematic name - + 用结构空位替代空气 Replace air with structure void - + offset - + WEOffset - - - - - - + + + + + + 0 - + 原理图名称 Name of schematic - + 依赖 mod 名称 Depend mods - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - + 垂直分割线 Vertical split line - + 水平分割线 Horizontal split line - + 大小与方块数量 Size and block count - - + + 大小: Size: - - + + 方块数量: Block count: - + 全部导出 Export all - + 预览 Preview - + 预览材料表 Material list - + 预览压缩效果 Compress effect - + 预构建三维结构 Construct 3d structure - - 地图画起始序号: - Map beginning index: + + 批量获得地图物品的指令 + /give command to get map items - + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 -在下面的表格里可以看到每个图像对应的文件名。 - 💡tips: Set the beginning index and then click "Export", then select the directory to export map data files. +在下面的表格里可以看到每个图像对应的文件名。 + +图像数据存储在地图数据文件中,必须先为存档导入地图数据文件,地图画结构才能生效。 + 💡tips: After setting map beginning index, click "Export", select path to export map data files. + +You can see filenames of each image. -Filenames of each image can be seen in the table below. +Map data are stored in map data files, assembled maps can take effect only after you must import map data files into the save. + + + + 地图画起始序号: + Map beginning index: + + + + 导出批量获得地图物品的命令(txt) + Export command to get map items + + + + 导出命令 + Export commands + + + + 生存模式不可破坏展示框;移除它依附的方块,展示框也不会消失。 + Item frams can not be removed in survivial mode; it will not disappear even the attached block is removed. + + + + 展示框不可破坏 + Fixed frame + + + + 1.20.5后,物品格式发生重大改变 + Item format is changed greatly after 1.20.5 + + + + MC版本≥1.20.5+ + MC ≥ 1.20.5 + + + + 采用荧光物品显示框 + Use glowing item frame + + + + 荧光物品显示框 + Glowing item frame + + + + 导出包含物品展示框的投影/结构方块文件 + Export the litematica / vanilla structure containing item frames + + + + 导出组装的地图画 + Export assembled maps + + + + 导出map_i.dat的地图数据文件 + Export map data files like map_i.dat + + + + 导出地图文件 + Export map data files + + + + 展示框背景将不可见 + The background of item frames will be invisible + + + + 展示框透明 + Transprant frame + + + + 地图画可依附于方块的侧面、顶面和底面 + Map can attach to a block by side, top and bottom + + + + 地图画方向 + Map direction + + + + 导出组装地图画的格式 + Format to export assembled maps + + + + 导出Litematica + Export as litematica + + + + 导出结构方块文件 + Export as structure - + + 内存使用策略 + Memory policy + + + + 缓存全部三维结构 + Cache all 3D structures + + + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ - + 加载默认预设失败 Failed to load default presets - + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -662,113 +843,74 @@ Detail information: %1 - - 设置方块列表失败 - Failed to setup blocklist - - - - 您设置的方块列表可能存在错误 - There may be errors in your blocklist - - - + 可用颜色数量:%1 Avaliable colors: %1 - + 应用预设失败 Failed to apply preset - - 转化图像失败 - Failed to convert image - - - - - 缓存失败 - Failed to save cache - - - - - 未能创建缓存文件,错误信息: -%1 - Failed to create cache directory, error info: -%1 - - - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - + 保存图像失败 Failed to save image - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - - 构建三维结构失败 - Failed to build 3d structure - - - - 构建三维结构时,出现错误。可能是因为尝试跳步。 - An error occurred when building 3d structure. Possible because you are trying to skip a necessary step. - - - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - + 方块数量:%1 Block count: %1 - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - + SlopeCraft 出现错误 An error occurred to SlopeCraft - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -777,199 +919,193 @@ Detail information: Click Ok to ignore, and click Close to exit SlopeCraft. - - + + 选择图片 Select Image - - + + 打开图像失败 Failed to open image - - + + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. Detailed information: %2 - + 请选择将被替换的图像 Please images to be replaced - + 必须先选择一个或多个图像,然后才能替换它们。 You should select one or more images, and then replace them. - + 选择预设文件 Select a preset file - + 解析预设文件失败 Failed to parse thes preset file - + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 - + 保存预设文件失败 Failed to save preset file - + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 - - - - - + + + + 未选择图像 No image selected - - - - + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - - + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - - + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - - - + 尚未构建三维结构 3d structure not built - - - + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - + + + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -978,145 +1114,294 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - + + %1 个图片导出失败 + Failed to export %1 image(s) + + + + 导出失败的图片依次为: +%1 + Following image(s) failed to export: +%1 + + + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。 SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). - + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) - + 感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量 Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software - + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. - + + 同时选中多个图片时,不显示 /give 命令。如果想预览导出的命令,请只选择一个图片。 + Can't show /give command when you selecte multiple images. To view the command, select one image only. + + + + 无法为 %1 生成命令:%2 + + Failed to generate command for %1: %2 + + + + + 无法创建/打开文件 %1:%2 + + Failed to create/open file %1: %2 + + + + + 无法写入文件 %1:%2 + + Failed to write file %1: %2 + + + + + + %1 个文件保存失败 + Failed to save %1 file(s) + + + + SlopeCraftL 未提供详细报错信息。 + SlopeCraftL doesn't give further details. + + + + 错误码:%1,详情:%2 + Error code: %1, details: %2 + + + + %1 生成失败,%2 + + Failed to generate %1, %2 + + + + + 墙面 + Wall + + + + 顶面 + Top + + + + 底面 + Bottom + + + + 北 + north + + + + 南 + south + + + + 东 + east + + + + 西 + west + + + + %1,向%2 + %1, %2 + + + + + 没有可用颜色 + No available color + + + + + 没有勾选任何颜色,无法转化图像。请至少勾选3~16种颜色。 + You didn't enable ANY COLOR, unable to convert image. Please enable at least 3~16 colors. + + + + 勾选颜色太少 + Too few colors enabled + + + + 仅仅勾选了%1种颜色,颜色过少,转化效率可能非常差。您可以点Yes继续转化,但非常建议请尽量多勾选一些颜色。 + You only enabled %1 color(s), it is so few that the conversion effect may be terrible. You can click Yes to go on, but it's strongly recommended to enable more colors. + + + + 生成命令失败: +%1 + Failed to generate command: +%1 + + + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + + 这不是严重的问题,你可以直接忽略这个警告,或者把它反馈给开发者,不影响正常使用。只是 Slopecraft 可能占用更多的内存。 +详细信息: +%1 + It's not a fatal problem, you can either ignore this warning, or report to the developer. You can feel free to use SlopeCraft with more memory cost. +Details: +%1 + + + + 获取本进程的内存占用失败 + Failed to query memory usage of this process + + + + 获取操作系统内存占用失败 + Failed to query system memory usage + + + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: From fb79b2f09f512874e0f55f362636a8b0a6d79ab7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 20:42:07 +0800 Subject: [PATCH 0894/1123] fix linux build Signed-off-by: ToKiNoBug --- SlopeCraftL/converted_image.cpp | 2 +- utilities/Schem/entity.cpp | 4 ++-- utilities/Schem/entity.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 33f7ea16..994f42ee 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -696,7 +696,7 @@ libSchem::Schem converted_image_impl::assembled_maps( { auto map_item = std::make_unique(); map_item->map_id = map_index; - map_entity->item = std::move(map_item); + map_entity->item_ = std::move(map_item); } schem.entity_list().emplace_back(std::move(map_entity)); diff --git a/utilities/Schem/entity.cpp b/utilities/Schem/entity.cpp index 60f348a3..8b97dab1 100644 --- a/utilities/Schem/entity.cpp +++ b/utilities/Schem/entity.cpp @@ -74,9 +74,9 @@ tl::expected libSchem::item_frame::dump( } bytes += destination.writeByte("ItemRotation", this->item_rotation); - if (this->item not_eq nullptr) { + if (this->item_ not_eq nullptr) { bytes += destination.writeCompound("Item"); - auto res_item = this->item->dump(destination, data_version); + auto res_item = this->item_->dump(destination, data_version); if (not res_item) { return tl::make_unexpected( fmt::format("Failed to dump item fields: {}", res_item.error())); diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h index 06578e5a..fabc1aa6 100644 --- a/utilities/Schem/entity.h +++ b/utilities/Schem/entity.h @@ -101,7 +101,7 @@ class item_frame : public hangable { int8_t item_rotation{0}; float item_drop_chance{1}; - std::unique_ptr item{nullptr}; + std::unique_ptr item_{nullptr}; item_frame_variant variant_{item_frame_variant::common}; From 3ca9e53f05c83be7967d5a9b6699b87fa61d52ba Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 7 Aug 2024 21:41:10 +0800 Subject: [PATCH 0895/1123] add EXCLUDE_FROM_ALL to 3rd deps Signed-off-by: ToKiNoBug --- cmake/optional_deps/kompute.cmake | 4 +++- cmake/required_deps/Eigen3.cmake | 4 +++- cmake/required_deps/HeuristicFlow.cmake | 4 +++- cmake/required_deps/cereal.cmake | 4 +++- cmake/required_deps/fmtlib.cmake | 1 + cmake/required_deps/magic_enum.cmake | 3 ++- cmake/required_deps/tl-expected.cmake | 4 +++- 7 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cmake/optional_deps/kompute.cmake b/cmake/optional_deps/kompute.cmake index ed119c0f..24c18f8d 100644 --- a/cmake/optional_deps/kompute.cmake +++ b/cmake/optional_deps/kompute.cmake @@ -8,7 +8,9 @@ set(KOMPUTE_OPT_USE_BUILT_IN_VULKAN_HEADER OFF) FetchContent_Declare(kompute GIT_REPOSITORY https://github.com/SlopeCraft/kompute GIT_TAG 37afc4f814eb941adb5c0c9a76fc0d8c4ebc6e53 - OVERRIDE_FIND_PACKAGE) + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL +) message(STATUS "Downaloding SlopeCraft/kompute......") FetchContent_MakeAvailable(kompute) diff --git a/cmake/required_deps/Eigen3.cmake b/cmake/required_deps/Eigen3.cmake index 585a35e5..f0f81959 100644 --- a/cmake/required_deps/Eigen3.cmake +++ b/cmake/required_deps/Eigen3.cmake @@ -11,7 +11,9 @@ include(FetchContent) FetchContent_Declare(Eigen3 GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git GIT_TAG 3.4.0 - OVERRIDE_FIND_PACKAGE) + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL +) FetchContent_MakeAvailable(Eigen3) diff --git a/cmake/required_deps/HeuristicFlow.cmake b/cmake/required_deps/HeuristicFlow.cmake index 9d23e117..47bdb998 100644 --- a/cmake/required_deps/HeuristicFlow.cmake +++ b/cmake/required_deps/HeuristicFlow.cmake @@ -4,7 +4,9 @@ include(FetchContent) FetchContent_Declare(Heu GIT_REPOSITORY https://github.com/SlopeCraft/HeuristicFlow.git GIT_TAG v1.6.4.1 - OVERRIDE_FIND_PACKAGE) + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL +) message(STATUS "Downloading HeuristicFlow") FetchContent_MakeAvailable(Heu) diff --git a/cmake/required_deps/cereal.cmake b/cmake/required_deps/cereal.cmake index cce92666..9256590e 100644 --- a/cmake/required_deps/cereal.cmake +++ b/cmake/required_deps/cereal.cmake @@ -14,7 +14,9 @@ include(FetchContent) FetchContent_Declare(cereal GIT_REPOSITORY https://github.com/USCiLab/cereal GIT_TAG v1.3.2 - OVERRIDE_FIND_PACKAGE) + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL +) message(STATUS "Configuring cereal ...") diff --git a/cmake/required_deps/fmtlib.cmake b/cmake/required_deps/fmtlib.cmake index a70cf338..37e9cdca 100644 --- a/cmake/required_deps/fmtlib.cmake +++ b/cmake/required_deps/fmtlib.cmake @@ -13,6 +13,7 @@ if (NOT ${fmt_FOUND}) GIT_REPOSITORY https://github.com/fmtlib/fmt.git GIT_TAG "10.1.1" OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL # QUIET false # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty diff --git a/cmake/required_deps/magic_enum.cmake b/cmake/required_deps/magic_enum.cmake index c72dbbaa..91d86cd0 100644 --- a/cmake/required_deps/magic_enum.cmake +++ b/cmake/required_deps/magic_enum.cmake @@ -14,8 +14,9 @@ FetchContent_Declare(magic_enum # URL https://github.com/Neargye/magic_enum/releases/download/v0.8.2/magic_enum.hpp GIT_REPOSITORY https://github.com/Neargye/magic_enum.git - GIT_TAG "v0.9.5" + GIT_TAG "v0.9.6" OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL ) message(STATUS "Downaloding magic_enum......") diff --git a/cmake/required_deps/tl-expected.cmake b/cmake/required_deps/tl-expected.cmake index 960e6262..df69d46d 100644 --- a/cmake/required_deps/tl-expected.cmake +++ b/cmake/required_deps/tl-expected.cmake @@ -5,7 +5,9 @@ FetchContent_Declare(tl-expected GIT_REPOSITORY https://github.com/TartanLlama/expected.git GIT_TAG v1.1.0 - OVERRIDE_FIND_PACKAGE) + OVERRIDE_FIND_PACKAGE + EXCLUDE_FROM_ALL + ) FetchContent_MakeAvailable(tl-expected) find_package(tl-expected CONFIG REQUIRED) endif () \ No newline at end of file From 2e2ff3e38cc9959887062013422f0a067e8a1df9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 11:57:41 +0800 Subject: [PATCH 0896/1123] fix export flat diagram of SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 2 +- utilities/FlatDiagram/FlatDiagram.cpp | 50 +++++++++++++-------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index b817d0cd..76d3ff0e 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -346,7 +346,7 @@ bool structure_3D_impl::export_flat_diagram( return false; } - img_list_rmj.emplace_back(blkp->image.transpose()); + img_list_rmj.emplace_back(blkp->image); } auto block_at_callback = [this, &img_list_rmj]( diff --git a/utilities/FlatDiagram/FlatDiagram.cpp b/utilities/FlatDiagram/FlatDiagram.cpp index e0222be0..5298ba43 100644 --- a/utilities/FlatDiagram/FlatDiagram.cpp +++ b/utilities/FlatDiagram/FlatDiagram.cpp @@ -69,7 +69,7 @@ std::string libFlatDiagram::export_flat_diagram( std::string_view png_filename, const fd_option &opt, const get_blk_image_callback_t &blk_image_at, std::span> texts) noexcept { - const int64_t rows_capacity_by_blocks = 64; + const int64_t rows_capacity_by_blocks = 16; EImgRowMajor_t buffer(rows_capacity_by_blocks * 16, opt.cols * 16); @@ -123,32 +123,30 @@ std::string libFlatDiagram::export_flat_diagram( png_set_text(png, png_info, png_txts.data(), png_txts.size()); } - for (int64_t ridx = opt.row_start; ridx < opt.row_end; - ridx += rows_capacity_by_blocks) { - const int64_t rows_this_time = - std::min(opt.row_end - ridx, rows_capacity_by_blocks); - memset(buffer.data(), 0xFF, buffer.size() * sizeof(uint32_t)); - - fd_option opt_temp = opt; - opt_temp.row_start = ridx; - opt_temp.row_end = ridx + rows_this_time; - - draw_flat_diagram_to_memory({buffer.data(), buffer.rows(), buffer.cols()}, - opt_temp, blk_image_at); - - ARGB_to_AGBR(buffer.data(), rows_this_time * 16 * opt.cols * 16); - - for (int64_t pix_r = 0; pix_r < rows_this_time * 16; pix_r++) { - // The row pointer should only be converted to const uint8_t*, but there - // is a terrible bug on libpng from brew makes this code fail to compile: - // binary interface function png_write_row is trampered to - // `void png_write_row(png_structrp png_ptr, png_bytep row)`. - // This bug doesn't exist in windows and linux, but only with libpng - // installed with homebrew. - png_write_row(png, reinterpret_cast(&buffer(pix_r, 0))); - // This is terrible because a const pointer have to be converted to - // non-constant + try { + for (int64_t ridx = opt.row_start; ridx < opt.row_end; + ridx += rows_capacity_by_blocks) { + const int64_t rows_this_time = + std::min(opt.row_end - ridx, rows_capacity_by_blocks); + buffer.fill(0xFFFFFFFF); + + fd_option opt_temp = opt; + opt_temp.row_start = ridx; + opt_temp.row_end = ridx + rows_this_time; + + draw_flat_diagram_to_memory({buffer.data(), buffer.rows(), buffer.cols()}, + opt_temp, blk_image_at); + + ARGB_to_AGBR(buffer.data(), rows_this_time * 16 * opt.cols * 16); + + for (int64_t pix_r = 0; pix_r < rows_this_time * 16; pix_r++) { + png_write_row(png, + reinterpret_cast(&buffer(pix_r, 0))); + } } + } catch (const std::exception &e) { + return fmt::format("Exception occurred while writing flat diagram: {}", + e.what()); } png_write_end(png, png_info); From c9a06204b39a0fd5107435c85e6c46839a4718d4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 11:57:56 +0800 Subject: [PATCH 0897/1123] Add todo Signed-off-by: ToKiNoBug --- utilities/StatMemory/stat_memory_src/macos.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utilities/StatMemory/stat_memory_src/macos.cpp b/utilities/StatMemory/stat_memory_src/macos.cpp index bf110e8a..61277c8e 100644 --- a/utilities/StatMemory/stat_memory_src/macos.cpp +++ b/utilities/StatMemory/stat_memory_src/macos.cpp @@ -1,10 +1,12 @@ #include "stat_memory.h" tl::expected get_system_memory_info() noexcept { +#warning "TODO: get system memory on macos" return tl::make_unexpected("Yet not implemented for macos"); } [[nodiscard]] tl::expected get_self_memory_info() noexcept { +#warning "TODO: get system memory on macos" return tl::make_unexpected("Yet not implemented for macos"); } \ No newline at end of file From 7bef54a26671fee1fa3830121a3799e11c12bf03 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 12:15:27 +0800 Subject: [PATCH 0898/1123] Add translation to MemoryPolicyDialog Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 2 +- utilities/StatMemory/CMakeLists.txt | 14 +++++ .../others/MemoryPolicyDialog_en_US.ts | 57 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 utilities/StatMemory/others/MemoryPolicyDialog_en_US.ts diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index be8b2c29..ebfcd7f3 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -20,7 +20,7 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { // create translators const char *const translator_filenames[] = { ":/i18n/SlopeCraft_en_US.qm", ":/i18n/BlockListManager_en_US.qm", - ":/i18n/VersionDialog_en_US.qm"}; + ":/i18n/VersionDialog_en_US.qm", ":/i18n/MemoryPolicyDialog_en_US.qm"}; /*this->translators.reserve(sizeof(translator_filenames) / sizeof(const char *)); */ diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 6001debd..99ae049b 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -36,3 +36,17 @@ add_library(MemoryPolicyDialog STATIC ) target_link_libraries(MemoryPolicyDialog PUBLIC Qt6::Widgets) target_link_libraries(MemoryPolicyDialog PUBLIC StatMemory) + +qt_add_lupdate(MemoryPolicyDialog + TS_FILES others/MemoryPolicyDialog_en_US.ts + OPTIONS ${SC_lupdate_flags} +) +qt_add_lrelease(MemoryPolicyDialog + TS_FILES others/MemoryPolicyDialog_en_US.ts + QM_FILES_OUTPUT_VARIABLE MemoryPolicyDialog_qm_files +) +qt_add_resources(MemoryPolicyDialog "MPD_translations" + PREFIX "/i18n" + BASE ${CMAKE_CURRENT_BINARY_DIR} + FILES ${MemoryPolicyDialog_qm_files} +) \ No newline at end of file diff --git a/utilities/StatMemory/others/MemoryPolicyDialog_en_US.ts b/utilities/StatMemory/others/MemoryPolicyDialog_en_US.ts new file mode 100644 index 00000000..22926e20 --- /dev/null +++ b/utilities/StatMemory/others/MemoryPolicyDialog_en_US.ts @@ -0,0 +1,57 @@ + + + + + MemoryPolicyDialog + + + 内存使用策略 + Memory Usage Policy + + + + Gib时自动缓存 + Gib(s) + + + + 当本进程占用> + When this process takes > + + + + 当系统剩余内存< + When system free memory < + + + + %时自动缓存 + % + + + + 提示:以上只是缓存数据的目标,不能保证内存占用一定小于设置的上限。缓存数据的实质是将构建的三维结构暂存硬盘(并释放相应内存),需要时再读取,因此必然使导出地图画变慢。 + Hint: Settings above is simply the target of caching, it's not guarented that the memory usage must be less than the assigned upper bound. Caching is to save 3d structures to disk(and release the memory), they will be read when required, leading to worse performance. + + + + 自动缓存数据以节约内存 + Enable auto caching to save memory + + + + 确定 + Ok + + + + 取消 + Cancel + + + + 恢复默认 + Reset default + + + From 496462378671907cf37081aeec8bc2cf204d29c8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 13:13:34 +0800 Subject: [PATCH 0899/1123] fix incorrect actions when types are changed Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 29 +++++++++++++++-------------- SlopeCraft/SCWind.h | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index ebfcd7f3..b72130fa 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -2,7 +2,6 @@ #include "ui_SCWind.h" #include #include -#include #include #include #include @@ -185,10 +184,11 @@ QString SCWind::cache_root_dir() const noexcept { } SlopeCraft::color_table *SCWind::current_color_table() noexcept { - auto selection = this->ui->blm->current_selection(); + auto settings = colortable_settings{this->ui->blm->current_selection(), + this->selected_type()}; { - auto find = this->color_tables.find(selection); - if (find != this->color_tables.end()) { + auto find = this->color_tables.find(settings); + if (find not_eq this->color_tables.end()) { return find->second.get(); } } @@ -212,7 +212,7 @@ SlopeCraft::color_table *SCWind::current_color_table() noexcept { return nullptr; } - auto it = this->color_tables.emplace(selection, std::move(ptr)); + auto it = this->color_tables.emplace(settings, std::move(ptr)); return it.first->second.get(); } } @@ -319,8 +319,6 @@ SCL_mapTypes SCWind::selected_type() const noexcept { if (this->ui->rb_type_fileonly->isChecked()) { return SCL_mapTypes::FileOnly; } - - assert(false); return SCL_mapTypes::Slope; // return {}; } @@ -383,8 +381,6 @@ SCL_convertAlgo SCWind::selected_algo() const noexcept { if (this->ui->rb_algo_GACvter->isChecked()) { return SCL_convertAlgo::gaCvter; } - - assert(false); return SCL_convertAlgo::RGB_Better; // return {}; } @@ -465,12 +461,15 @@ SCWind::export_type SCWind::selected_export_type() const noexcept { return export_type_list[i]; } } - assert(false); + return SCWind::export_type::litematica; // return {}; } -void SCWind::when_version_buttons_toggled() noexcept { +void SCWind::when_version_buttons_toggled(bool checked) noexcept { + if (not checked) { + return; + } this->ui->blm->when_version_updated(); this->when_blocklist_changed(); @@ -485,7 +484,10 @@ void SCWind::when_version_buttons_toggled() noexcept { this->ui->cb_mc_version_geq_1_20_5->setDisabled(fix_geq_btn); } -void SCWind::when_type_buttons_toggled() noexcept { +void SCWind::when_type_buttons_toggled(bool checked) noexcept { + if (not checked) { + return; + } this->when_blocklist_changed(); this->update_button_states(); { @@ -918,7 +920,7 @@ tl::expected SCWind::get_command( buf->append(temp); }, }; - bool after_1_20_5 = false; + bool after_1_20_5; if (this->selected_version() < SCL_gameVersion::MC20) { after_1_20_5 = true; } else if (this->selected_version() > SCL_gameVersion::MC20) { @@ -957,7 +959,6 @@ QString extension_of_export_type(SCWind::export_type et) noexcept { return "dat"; } - assert(false); return "Invalid_export_type"; } diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index de958295..4c5c3101 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -22,6 +22,35 @@ namespace Ui { class SCWind; } +struct colortable_settings { + colortable_settings() = delete; + colortable_settings(const selection& s, SCL_mapTypes t) + : selection{s}, map_type{t} {} + + colortable_settings(selection&& s, SCL_mapTypes t) + : selection{std::move(s)}, map_type{t} {} + + selection selection; + SCL_mapTypes map_type; + + [[nodiscard]] bool operator==(const colortable_settings& b) const noexcept { + if (this->selection not_eq b.selection) { + return false; + } + if (this->map_type not_eq b.map_type) { + return false; + } + return true; + } +}; + +template <> +struct std::hash { + uint64_t operator()(const colortable_settings& s) const noexcept { + return std::hash{}(s.selection) xor static_cast(s.map_type); + } +}; + SlopeCraft::progress_callbacks progress_callback(QProgressBar* bar) noexcept; SlopeCraft::const_image_reference wrap_image(const QImage& img) noexcept; @@ -80,8 +109,8 @@ class SCWind : public QMainWindow { void when_cvt_pool_selectionChanged() noexcept; void when_export_pool_selectionChanged() noexcept; - void when_version_buttons_toggled() noexcept; - void when_type_buttons_toggled() noexcept; + void when_version_buttons_toggled(bool) noexcept; + void when_type_buttons_toggled(bool) noexcept; void when_blocklist_changed() noexcept; void when_preset_clicked() noexcept; void when_export_type_toggled() noexcept; @@ -120,7 +149,8 @@ class SCWind : public QMainWindow { Ui::SCWind* ui; std::unordered_map< - selection, std::unique_ptr> + colortable_settings, + std::unique_ptr> color_tables; // SlopeCraft::Kernel* kernel; From bf5b3ca50b8243b1ae27c8b156062ca2b9d8f330 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 19:26:41 +0800 Subject: [PATCH 0900/1123] support more block list in SC Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 47 +++++++++++++++---- .../BlockListManager/BlockListManager.cpp | 20 ++++---- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index b72130fa..0952f3a8 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -43,15 +43,46 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { [this]() { return this->selected_version(); }); QDir::setCurrent(QCoreApplication::applicationDirPath()); - - this->ui->blm->add_blocklist( - QStringLiteral("%1/Blocks/FixedBlocks.zip") - .arg(QCoreApplication::applicationDirPath())); - this->ui->blm->add_blocklist( - QStringLiteral("%1/Blocks/CustomBlocks.zip") - .arg(QCoreApplication::applicationDirPath())); - + const QString blocks_dir_path = + QStringLiteral("%1/Blocks").arg(QCoreApplication::applicationDirPath()); + const QDir blocks_dir{blocks_dir_path}; + if (not blocks_dir.exists()) { + QMessageBox::critical( + this, tr("无法加载方块列表"), + tr("存储方块列表的文件夹 \"%1\" 不存在,或不是文件夹。") + .arg(blocks_dir_path) + + tr("SlopeCraft 必须退出。")); + exit(1); + } + if (not this->ui->blm->add_blocklist( + QStringLiteral("%1/%2").arg(blocks_dir_path, "FixedBlocks.zip"))) { + QMessageBox::critical( + this, tr("无法加载方块列表"), + tr("无法加载 FixedBlocks.zip ,SlopeCraft 缺乏最基础的方块列表。") + + tr("SlopeCraft 必须退出。")); + exit(1); + } + QString fail_list; + int fail_counter = 0; + for (auto file : + blocks_dir.entryInfoList({"*.zip"}, QDir::Filters{QDir::Filter::Files}, + QDir::SortFlags{QDir::SortFlag::Name})) { + if (not this->ui->blm->add_blocklist(file.absoluteFilePath())) { + fail_counter++; + fail_list.append(file.absoluteFilePath()); + fail_list.append('\n'); + } + } this->ui->blm->finish_blocklist(); + if (fail_counter > 0) { + QMessageBox::warning( + this, tr("部分方块列表加载失败"), + tr("以下 %1 " + "个方块列表文件无法被加载:\n%" + "2\n由于它们不是必需,你可以忽略此错误并继续使用。") + .arg(fail_counter) + .arg(fail_list)); + } for (auto btnp : this->version_buttons()) { connect(btnp, &QRadioButton::toggled, this, diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index faed871e..5daa54c5 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -89,7 +89,7 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { return {nullptr}; } else { QMessageBox::warning(dynamic_cast(this->parent()), - tr("解析方块列表失败"), + tr("解析方块列表成功,但出现警告"), QString::fromUtf8(warning.data())); } } @@ -112,16 +112,20 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { } bool BlockListManager::add_blocklist(QString filename) noexcept { - std::unique_ptr tmp = - this->impl_addblocklist(filename); + // Test for multiple encodings + for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { + std::unique_ptr tmp = + this->impl_addblocklist(encoding.data()); - if (!tmp) { - return false; - } + if (not tmp) { + continue; + } - this->blockslists.emplace_back(std::move(tmp)); + this->blockslists.emplace_back(std::move(tmp)); + return true; + } - return true; + return false; } void BlockListManager::finish_blocklist() noexcept { From 82d021a89e078b29c9faffa20c0861d5faf89ce0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 19:27:48 +0800 Subject: [PATCH 0901/1123] fix some clangd warnings Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 1466a76c..00d46877 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -358,7 +358,7 @@ void SCWind::on_pb_save_converted_clicked() noexcept { QMessageBox::StandardButton::No, QMessageBox::StandardButton::YesToAll, QMessageBox::StandardButton::NoToAll}); - bool replace{false}; + bool replace; switch (ret) { case QMessageBox::StandardButton::Yes: replace = true; @@ -651,7 +651,6 @@ void SCWind::on_pb_export_all_clicked() noexcept { } break; default: - assert(false); return; } } From beafb8e4d12f2ad158ff8da9fb84cececfa1eced Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 19:31:43 +0800 Subject: [PATCH 0902/1123] fix Linux build Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 4c5c3101..55727541 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -25,16 +25,16 @@ class SCWind; struct colortable_settings { colortable_settings() = delete; colortable_settings(const selection& s, SCL_mapTypes t) - : selection{s}, map_type{t} {} + : selection_{s}, map_type{t} {} colortable_settings(selection&& s, SCL_mapTypes t) - : selection{std::move(s)}, map_type{t} {} + : selection_{std::move(s)}, map_type{t} {} - selection selection; + selection selection_; SCL_mapTypes map_type; [[nodiscard]] bool operator==(const colortable_settings& b) const noexcept { - if (this->selection not_eq b.selection) { + if (this->selection_ not_eq b.selection_) { return false; } if (this->map_type not_eq b.map_type) { @@ -47,7 +47,8 @@ struct colortable_settings { template <> struct std::hash { uint64_t operator()(const colortable_settings& s) const noexcept { - return std::hash{}(s.selection) xor static_cast(s.map_type); + return std::hash{}(s.selection_) xor + static_cast(s.map_type); } }; From c41cf01ea504428b12477a2b1913e6563ee47635 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 20:00:13 +0800 Subject: [PATCH 0903/1123] implement drag and drop Signed-off-by: ToKiNoBug --- SlopeCraft/PoolModel.cpp | 27 ++++++++++++++++++++++++--- SlopeCraft/SCWind.ui | 4 ++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index f8dc1379..6366a000 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -1,9 +1,11 @@ #include "PoolModel.h" #include #include +#include #include #include #include +#include PoolModel::PoolModel(SCWind* scw) : QAbstractListModel(scw), pool{scw->tasks}, scwind{scw} { @@ -238,7 +240,7 @@ void map_indices(std::vector& pool, std::vector moved_indices, bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { - if (!this->canDropMimeData(data, action, row, column, parent)) { + if (not this->canDropMimeData(data, action, row, column, parent)) { return false; } @@ -261,9 +263,28 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, if (src_indices.size() <= 0) { return true; } + #pragma warning "TODO: Implement reshuffling here" - assert(("Reshuffing is not implemented yet", false)); - // map_indices(this->pool, src_indices, begin_row); + // Move all moved tasks into moved_tasks + std::stack moved_tasks; + const auto invalid_name = QStringLiteral("__ ## invalid __ file &* marker"); + for (int src_idx : src_indices | std::views::reverse) { + cvt_task temp; + temp.filename = invalid_name; + std::swap(temp, this->pool[src_idx]); + moved_tasks.emplace(std::move(temp)); + this->pool.erase(this->pool.begin() + src_idx); + } + assert(moved_tasks.size() == src_indices.size()); + const int insert_dest = begin_row - moved_tasks.size(); + assert(insert_dest <= this->pool.size()); + auto it_dest = this->pool.begin() + insert_dest; + while (not moved_tasks.empty()) { + cvt_task temp; + std::swap(temp, moved_tasks.top()); + moved_tasks.pop(); + it_dest = this->pool.insert(it_dest, std::move(temp)); + } } this->refresh(); diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index d018f2a2..497e4940 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -463,7 +463,7 @@ false - QAbstractItemView::DragDropMode::NoDragDrop + QAbstractItemView::DragDropMode::InternalMove Qt::DropAction::IgnoreAction @@ -475,7 +475,7 @@ Qt::TextElideMode::ElideLeft - QListView::Movement::Static + QListView::Movement::Snap QListView::Flow::TopToBottom From 07f393c2b51aaca0abb848c4d4930f3fda3dfcb9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 20:00:32 +0800 Subject: [PATCH 0904/1123] fix erasing multiple images at once Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 00d46877..5a97f8d2 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -87,8 +87,16 @@ void SCWind::on_pb_remove_image_clicked() noexcept { return; } - for (const auto &qmi : selected) { - const int idx = qmi.row(); + std::vector row; + { + row.reserve(selected.size()); + for (const auto &qmi : selected) { + row.emplace_back(qmi.row()); + } + std::sort(row.begin(), row.end(), [](int a, int b) { return a > b; }); + } + + for (const int idx : row) { this->tasks.erase(this->tasks.begin() + idx); } From 1d402db3716dd2003f1617bc7fd7c3a33d7adc8e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 20:02:17 +0800 Subject: [PATCH 0905/1123] fix linux build (disable testing of tl-expected) Signed-off-by: ToKiNoBug --- cmake/required_deps/tl-expected.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/required_deps/tl-expected.cmake b/cmake/required_deps/tl-expected.cmake index df69d46d..11326457 100644 --- a/cmake/required_deps/tl-expected.cmake +++ b/cmake/required_deps/tl-expected.cmake @@ -1,5 +1,6 @@ find_package(tl-expected 1.1.0 QUIET) if (NOT tl-expected_FOUND) + set(EXPECTED_BUILD_TESTS OFF) include(FetchContent) message(STATUS "Downloading tl-expected...") FetchContent_Declare(tl-expected From dc1403fa23492e9b75f838acd284509851e8fb51 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 21:23:26 +0800 Subject: [PATCH 0906/1123] fix drag and drop Signed-off-by: ToKiNoBug --- SlopeCraft/PoolModel.cpp | 38 +++++++++++++++++++------------------- SlopeCraft/SCWind.ui | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index 6366a000..f5ab60d0 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -162,30 +162,29 @@ QMimeData* CvtPoolModel::mimeData(const QModelIndexList& indexes) const { bool CvtPoolModel::canDropMimeData(const QMimeData* data, Qt::DropAction, int, int col, const QModelIndex& parent) const { - if (parent.isValid()) { - return false; - } - - if (col > 0) { - return false; - } - - if (!data->hasFormat(mime_data_type)) { - return true; - } + // if (parent.isValid()) { + // return false; + // } - const int bytes = data->data(mime_data_type).size(); + // if (col > 0) { + // return false; + // } - if (bytes % sizeof(int) != 0) { - return false; - } + if (data->hasFormat(mime_data_type)) { + const int bytes = data->data(mime_data_type).size(); - // disable moving multiple items, because the behavior is incorrect - if (bytes / sizeof(int) == 1) { + if (bytes % sizeof(int) not_eq 0) { + return false; + } return true; } - return false; + // // disable moving multiple items, because the behavior is incorrect + // if (bytes / sizeof(int) == 1) { + // return true; + // } + // + // return false; } template @@ -263,12 +262,13 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, if (src_indices.size() <= 0) { return true; } + std::sort(src_indices.begin(), src_indices.end(), std::greater{}); #pragma warning "TODO: Implement reshuffling here" // Move all moved tasks into moved_tasks std::stack moved_tasks; const auto invalid_name = QStringLiteral("__ ## invalid __ file &* marker"); - for (int src_idx : src_indices | std::views::reverse) { + for (int src_idx : src_indices) { cvt_task temp; temp.filename = invalid_name; std::swap(temp, this->pool[src_idx]); diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 497e4940..7c02561d 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -463,7 +463,7 @@ false - QAbstractItemView::DragDropMode::InternalMove + QAbstractItemView::DragDropMode::DragDrop Qt::DropAction::IgnoreAction From 8e5af5fbfbf079b74dc7289269ca3aec26b8a75e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 21:26:57 +0800 Subject: [PATCH 0907/1123] fix drag and drop Signed-off-by: ToKiNoBug --- SlopeCraft/PoolModel.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/SlopeCraft/PoolModel.cpp b/SlopeCraft/PoolModel.cpp index f5ab60d0..75f9cf27 100644 --- a/SlopeCraft/PoolModel.cpp +++ b/SlopeCraft/PoolModel.cpp @@ -264,13 +264,10 @@ bool CvtPoolModel::dropMimeData(const QMimeData* data, Qt::DropAction action, } std::sort(src_indices.begin(), src_indices.end(), std::greater{}); -#pragma warning "TODO: Implement reshuffling here" // Move all moved tasks into moved_tasks std::stack moved_tasks; - const auto invalid_name = QStringLiteral("__ ## invalid __ file &* marker"); for (int src_idx : src_indices) { cvt_task temp; - temp.filename = invalid_name; std::swap(temp, this->pool[src_idx]); moved_tasks.emplace(std::move(temp)); this->pool.erase(this->pool.begin() + src_idx); From b8f9a4ea446aaa8f87eb730ff4e5f755c64eb77b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 21:30:58 +0800 Subject: [PATCH 0908/1123] remove unused file Signed-off-by: ToKiNoBug --- utilities/object_pool.hpp | 778 -------------------------------------- 1 file changed, 778 deletions(-) delete mode 100644 utilities/object_pool.hpp diff --git a/utilities/object_pool.hpp b/utilities/object_pool.hpp deleted file mode 100644 index abee2d99..00000000 --- a/utilities/object_pool.hpp +++ /dev/null @@ -1,778 +0,0 @@ -// 2020/03/13 - modified by Tsung-Wei Huang -// - fixed bug in aligning memory -// -// 2020/02/02 - modified by Tsung-Wei Huang -// - new implementation motivated by Hoard -// -// 2019/07/10 - modified by Tsung-Wei Huang -// - replace raw pointer with smart pointer -// -// 2019/06/13 - created by Tsung-Wei Huang -// - implemented an object pool class - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace tf { - -#define TF_ENABLE_POOLABLE_ON_THIS \ - template friend class ObjectPool; \ - void* _object_pool_block - -// Class: ObjectPool -// -// The class implements an efficient thread-safe object pool motivated -// by the Hoard memory allocator algorithm. -// Different from the normal memory allocator, object pool allocates -// only one object at a time. -// -// Internall, we use the following variables to maintain blocks and heaps: -// X: size in byte of a item slot -// M: number of items per block -// F: emptiness threshold -// B: number of bins per local heap (bin[B-1] is the full list) -// W: number of items per bin -// K: shrinkness constant -// -// Example scenario 1: -// M = 30 -// F = 4 -// W = (30+4-1)/4 = 8 -// -// b0: 0, 1, 2, 3, 4, 5, 6, 7 -// b1: 8, 9, 10, 11, 12, 13, 14, 15 -// b2: 16, 17, 18, 19, 20, 21, 22, 23 -// b3: 24, 25, 26, 27, 28, 29 -// b4: 30 (anything equal to M) -// -// Example scenario 2: -// M = 32 -// F = 4 -// W = (32+4-1)/4 = 8 -// b0: 0, 1, 2, 3, 4, 5, 6, 7 -// b1: 8, 9, 10, 11, 12, 13, 14, 15 -// b2: 16, 17, 18, 19, 20, 21, 22, 23 -// b3: 24, 25, 26, 27, 28, 29, 30, 31 -// b4: 32 (anything equal to M) -// -template -class ObjectPool { - - // the data column must be sufficient to hold the pointer in freelist - constexpr static size_t X = (std::max)(sizeof(T*), sizeof(T)); - //constexpr static size_t X = sizeof(long double) + std::max(sizeof(T*), sizeof(T)); - //constexpr static size_t M = (S - offsetof(Block, data)) / X; - constexpr static size_t M = S / X; - constexpr static size_t F = 4; - constexpr static size_t B = F + 1; - constexpr static size_t W = (M + F - 1) / F; - constexpr static size_t K = 4; - - static_assert( - S && (!(S & (S-1))), "block size S must be a power of two" - ); - - static_assert( - M >= 128, "block size S must be larger enough to pool at least 128 objects" - ); - - struct Blocklist { - Blocklist* prev; - Blocklist* next; - }; - - struct GlobalHeap { - std::mutex mutex; - Blocklist list; - }; - - struct LocalHeap { - std::mutex mutex; - Blocklist lists[B]; - size_t u {0}; - size_t a {0}; - }; - - struct Block { - std::atomic heap; - Blocklist list_node; - size_t i; - size_t u; - T* top; - // long double padding; - char data[S]; - }; - - public: - - /** - @brief constructs an object pool from a number of anticipated threads - */ - explicit ObjectPool(unsigned = std::thread::hardware_concurrency()); - - /** - @brief destructs the object pool - */ - ~ObjectPool(); - - /** - @brief acquires a pointer to a object constructed from a given argument list - */ - template - T* animate(ArgsT&&... args); - - /** - @brief recycles a object pointed by @c ptr and destroys it - */ - void recycle(T* ptr); - - size_t num_bins_per_local_heap() const; - size_t num_objects_per_bin() const; - size_t num_objects_per_block() const; - size_t num_available_objects() const; - size_t num_allocated_objects() const; - size_t capacity() const; - size_t num_local_heaps() const; - size_t num_global_heaps() const; - size_t num_heaps() const; - - float emptiness_threshold() const; - - private: - - const size_t _lheap_mask; - - GlobalHeap _gheap; - - std::vector _lheaps; - - LocalHeap& _this_heap(); - - constexpr unsigned _next_pow2(unsigned n) const; - - template - constexpr size_t _offset_in_class(const Q P::*member) const; - - template - constexpr P* _parent_class_of(Q*, const Q P::*member); - - template - constexpr P* _parent_class_of(const Q*, const Q P::*member) const; - - constexpr Block* _block_of(Blocklist*); - constexpr Block* _block_of(const Blocklist*) const; - - size_t _bin(size_t) const; - - T* _allocate(Block*); - - void _deallocate(Block*, T*); - void _blocklist_init_head(Blocklist*); - void _blocklist_add_impl(Blocklist*, Blocklist*, Blocklist*); - void _blocklist_push_front(Blocklist*, Blocklist*); - void _blocklist_push_back(Blocklist*, Blocklist*); - void _blocklist_del_impl(Blocklist*, Blocklist*); - void _blocklist_del(Blocklist*); - void _blocklist_replace(Blocklist*, Blocklist*); - void _blocklist_move_front(Blocklist*, Blocklist*); - void _blocklist_move_back(Blocklist*, Blocklist*); - bool _blocklist_is_first(const Blocklist*, const Blocklist*); - bool _blocklist_is_last(const Blocklist*, const Blocklist*); - bool _blocklist_is_empty(const Blocklist*); - bool _blocklist_is_singular(const Blocklist*); - - template - void _for_each_block_safe(Blocklist*, C&&); - - template - void _for_each_block(Blocklist*, C&&); - -}; - -// ---------------------------------------------------------------------------- -// ObjectPool definition -// ---------------------------------------------------------------------------- - -// Constructor -template -ObjectPool::ObjectPool(unsigned t) : - //_heap_mask {(_next_pow2(t) << 1) - 1u}, - //_heap_mask { _next_pow2(t<<1) - 1u }, - //_heap_mask {(t << 1) - 1}, - _lheap_mask { _next_pow2((t+1) << 1) - 1 }, - _lheaps { _lheap_mask + 1 } { - - _blocklist_init_head(&_gheap.list); - - for(auto& h : _lheaps) { - for(size_t i=0; i -ObjectPool::~ObjectPool() { - - // clear local heaps - for(auto& h : _lheaps) { - for(size_t i=0; i -size_t ObjectPool::num_bins_per_local_heap() const { - return B; -} - -// Function: num_objects_per_bin -template -size_t ObjectPool::num_objects_per_bin() const { - return W; -} - -// Function: num_objects_per_block -template -size_t ObjectPool::num_objects_per_block() const { - return M; -} - -// Function: emptiness_threshold -template -float ObjectPool::emptiness_threshold() const { - return 1.0f/F; -} - -// Function: num_global_heaps -template -size_t ObjectPool::num_global_heaps() const { - return 1; -} - -// Function: num_lheaps -template -size_t ObjectPool::num_local_heaps() const { - return _lheaps.size(); -} - -// Function: num_heaps -template -size_t ObjectPool::num_heaps() const { - return _lheaps.size() + 1; -} - -// Function: capacity -template -size_t ObjectPool::capacity() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += M; - }; - - // local heap - for(auto& h : _lheaps) { - n += h.a; - } - - return n; -} - -// Function: num_available_objects -template -size_t ObjectPool::num_available_objects() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += (M - _block_of(p)->u); - }; - - // local heap - for(auto& h : _lheaps) { - n += (h.a - h.u); - } - return n; -} - -// Function: num_allocated_objects -template -size_t ObjectPool::num_allocated_objects() const { - - size_t n = 0; - - // global heap - for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) { - n += _block_of(p)->u; - }; - - // local heap - for(auto& h : _lheaps) { - n += h.u; - } - return n; -} - -// Function: _bin -template -size_t ObjectPool::_bin(size_t u) const { - return u == M ? F : u/W; -} - -// Function: _offset_in_class -template -template -constexpr size_t ObjectPool::_offset_in_class( - const Q P::*member) const { - return (size_t) &( reinterpret_cast(0)->*member); -} - -// C macro: parent_class_of(list_pointer, Block, list) -// C++: parent_class_of(list_pointer, &Block::list) -template -template -constexpr P* ObjectPool::_parent_class_of( - Q* ptr, const Q P::*member -) { - return (P*)( (char*)ptr - _offset_in_class(member)); -} - -// Function: _parent_class_of -template -template -constexpr P* ObjectPool::_parent_class_of( - const Q* ptr, const Q P::*member -) const { - return (P*)( (char*)ptr - _offset_in_class(member)); -} - -// Function: _block_of -template -constexpr typename ObjectPool::Block* -ObjectPool::_block_of(Blocklist* list) { - return _parent_class_of(list, &Block::list_node); -} - -// Function: _block_of -template -constexpr typename ObjectPool::Block* -ObjectPool::_block_of(const Blocklist* list) const { - return _parent_class_of(list, &Block::list_node); -} - -// Procedure: initialize a list head -template -void ObjectPool::_blocklist_init_head(Blocklist *list) { - list->next = list; - list->prev = list; -} - -// Procedure: _blocklist_add_impl -// Insert a new entry between two known consecutive entries. -// -// This is only for internal list manipulation where we know -// the prev/next entries already! -template -void ObjectPool::_blocklist_add_impl( - Blocklist *curr, Blocklist *prev, Blocklist *next -) { - next->prev = curr; - curr->next = next; - curr->prev = prev; - prev->next = curr; -} - -// list_push_front - add a new entry -// @curr: curr entry to be added -// @head: list head to add it after -// -// Insert a new entry after the specified head. -// This is good for implementing stacks. -// -template -void ObjectPool::_blocklist_push_front( - Blocklist *curr, Blocklist *head -) { - _blocklist_add_impl(curr, head, head->next); -} - -// list_add_tail - add a new entry -// @curr: curr entry to be added -// @head: list head to add it before -// -// Insert a new entry before the specified head. -// This is useful for implementing queues. -// -template -void ObjectPool::_blocklist_push_back( - Blocklist *curr, Blocklist *head -) { - _blocklist_add_impl(curr, head->prev, head); -} - -// Delete a list entry by making the prev/next entries -// point to each other. -// -// This is only for internal list manipulation where we know -// the prev/next entries already! -// -template -void ObjectPool::_blocklist_del_impl( - Blocklist * prev, Blocklist * next -) { - next->prev = prev; - prev->next = next; -} - -// _blocklist_del - deletes entry from list. -// @entry: the element to delete from the list. -// Note: list_empty() on entry does not return true after this, the entry is -// in an undefined state. -template -void ObjectPool::_blocklist_del(Blocklist *entry) { - _blocklist_del_impl(entry->prev, entry->next); - entry->next = nullptr; - entry->prev = nullptr; -} - -// list_replace - replace old entry by new one -// @old : the element to be replaced -// @curr : the new element to insert -// -// If @old was empty, it will be overwritten. -template -void ObjectPool::_blocklist_replace( - Blocklist *old, Blocklist *curr -) { - curr->next = old->next; - curr->next->prev = curr; - curr->prev = old->prev; - curr->prev->next = curr; -} - -// list_move - delete from one list and add as another's head -// @list: the entry to move -// @head: the head that will precede our entry -template -void ObjectPool::_blocklist_move_front( - Blocklist *list, Blocklist *head -) { - _blocklist_del_impl(list->prev, list->next); - _blocklist_push_front(list, head); -} - -// list_move_tail - delete from one list and add as another's tail -// @list: the entry to move -// @head: the head that will follow our entry -template -void ObjectPool::_blocklist_move_back( - Blocklist *list, Blocklist *head -) { - _blocklist_del_impl(list->prev, list->next); - _blocklist_push_back(list, head); -} - -// list_is_first - tests whether @list is the last entry in list @head -// @list: the entry to test -// @head: the head of the list -template -bool ObjectPool::_blocklist_is_first( - const Blocklist *list, const Blocklist *head -) { - return list->prev == head; -} - -// list_is_last - tests whether @list is the last entry in list @head -// @list: the entry to test -// @head: the head of the list -template -bool ObjectPool::_blocklist_is_last( - const Blocklist *list, const Blocklist *head -) { - return list->next == head; -} - -// list_empty - tests whether a list is empty -// @head: the list to test. -template -bool ObjectPool::_blocklist_is_empty(const Blocklist *head) { - return head->next == head; -} - -// list_is_singular - tests whether a list has just one entry. -// @head: the list to test. -template -bool ObjectPool::_blocklist_is_singular( - const Blocklist *head -) { - return !_blocklist_is_empty(head) && (head->next == head->prev); -} - -// Procedure: _for_each_block -template -template -void ObjectPool::_for_each_block(Blocklist* head, C&& c) { - Blocklist* p; - for(p=head->next; p!=head; p=p->next) { - c(_block_of(p)); - } -} - -// Procedure: _for_each_block_safe -// Iterate each item of a list - safe to free -template -template -void ObjectPool::_for_each_block_safe(Blocklist* head, C&& c) { - Blocklist* p; - Blocklist* t; - for(p=head->next, t=p->next; p!=head; p=t, t=p->next) { - c(_block_of(p)); - } -} - -// Function: _allocate -// allocate a spot from the block -template -T* ObjectPool::_allocate(Block* s) { - if(s->top == nullptr) { - return reinterpret_cast(s->data + s->i++ * X); - } - else { - T* retval = s->top; - s->top = *(reinterpret_cast(s->top)); - return retval; - } -} - -// Procedure: _deallocate -template -void ObjectPool::_deallocate(Block* s, T* ptr) { - *(reinterpret_cast(ptr)) = s->top; - s->top = ptr; -} - -// Function: allocate -template -template -T* ObjectPool::animate(ArgsT&&... args) { - - //std::cout << "construct a new item\n"; - - // my logically mapped heap - LocalHeap& h = _this_heap(); - - Block* s {nullptr}; - - h.mutex.lock(); - - // scan the list of superblocks from most full to least - int f = static_cast(F-1); - for(; f>=0; f--) { - if(!_blocklist_is_empty(&h.lists[f])) { - s = _block_of(h.lists[f].next); - break; - } - } - - // no superblock found - if(f == -1) { - - // check heap 0 for a superblock - _gheap.mutex.lock(); - if(!_blocklist_is_empty(&_gheap.list)) { - - s = _block_of(_gheap.list.next); - - //printf("get a superblock from global heap %lu\n", s->u); - assert(s->u < M && s->heap == nullptr); - f = static_cast(_bin(s->u + 1)); - - _blocklist_move_front(&s->list_node, &h.lists[f]); - - s->heap = &h; // must be within the global heap lock - _gheap.mutex.unlock(); - - h.u = h.u + s->u; - h.a = h.a + M; - } - // create a new block - else { - //printf("create a new superblock\n"); - _gheap.mutex.unlock(); - f = 0; - //s = static_cast(std::malloc(sizeof(Block))); - s = new Block(); - - if(s == nullptr) { - throw std::bad_alloc(); - } - - s->heap = &h; - s->i = 0; - s->u = 0; - s->top = nullptr; - - _blocklist_push_front(&s->list_node, &h.lists[f]); - - h.a = h.a + M; - } - } - - // the superblock must have at least one space - //assert(s->u < M); - //printf("%lu %lu %lu\n", h.u, h.a, s->u); - //assert(h.u < h.a); - - h.u = h.u + 1; - s->u = s->u + 1; - - // take one item from the superblock - T* mem = _allocate(s); - - int b = static_cast(_bin(s->u)); - - if(b != f) { - //printf("move superblock from list[%d] to list[%d]\n", f, b); - _blocklist_move_front(&s->list_node, &h.lists[b]); - } - - //std::cout << "s.i " << s->i << '\n' - // << "s.u " << s->u << '\n' - // << "h.u " << h.u << '\n' - // << "h.a " << h.a << '\n'; - - h.mutex.unlock(); - - //printf("allocate %p (s=%p)\n", mem, s); - - new (mem) T(std::forward(args)...); - - mem->_object_pool_block = s; - - return mem; -} - -// Function: destruct -template -void ObjectPool::recycle(T* mem) { - - //Block* s = *reinterpret_cast( - // reinterpret_cast(mem) - sizeof(Block**) - //); - - //Block* s= *(reinterpret_cast(mem) - O); // (mem) - 1 - - Block* s = static_cast(mem->_object_pool_block); - - mem->~T(); - - //printf("deallocate %p (s=%p) M=%lu W=%lu X=%lu\n", mem, s, M, W, X); - - // here we need a loop because when we lock the heap, - // other threads may have removed the superblock to another heap - bool sync = false; - - do { - LocalHeap* h = s->heap.load(std::memory_order_relaxed); - - // the block is in global heap - if(h == nullptr) { - std::lock_guard glock(_gheap.mutex); - if(s->heap == h) { - sync = true; - _deallocate(s, mem); - s->u = s->u - 1; - } - } - else { - std::lock_guard llock(h->mutex); - if(s->heap == h) { - sync = true; - // deallocate the item from the superblock - size_t f = _bin(s->u); - _deallocate(s, mem); - s->u = s->u - 1; - h->u = h->u - 1; - - size_t b = _bin(s->u); - - if(b != f) { - //printf("move superblock from list[%d] to list[%d]\n", f, b); - _blocklist_move_front(&s->list_node, &h->lists[b]); - } - - // transfer a mostly-empty superblock to global heap - if((h->u + K*M < h->a) && (h->u < ((F-1) * h->a / F))) { - for(size_t i=0; ilists[i])) { - Block* x = _block_of(h->lists[i].next); - //printf("transfer a block (x.u=%lu/x.i=%lu) to the global heap\n", x->u, x->i); - assert(h->u > x->u && h->a > M); - h->u = h->u - x->u; - h->a = h->a - M; - x->heap = nullptr; - std::lock_guard glock(_gheap.mutex); - _blocklist_move_front(&x->list_node, &_gheap.list); - break; - } - } - } - } - } - } while(!sync); - - //std::cout << "s.i " << s->i << '\n' - // << "s.u " << s->u << '\n'; -} - -// Function: _this_heap -template -typename ObjectPool::LocalHeap& -ObjectPool::_this_heap() { - // here we don't use thread local since object pool might be - // created and destroyed multiple times - //thread_local auto hv = std::hash()(std::this_thread::get_id()); - //return _lheaps[hv & _lheap_mask]; - - return _lheaps[ - std::hash()(std::this_thread::get_id()) & _lheap_mask - ]; -} - -// Function: _next_pow2 -template -constexpr unsigned ObjectPool::_next_pow2(unsigned n) const { - if(n == 0) return 1; - n--; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - n |= n >> 16; - n++; - return n; -} - -} // end namespace tf -------------------------------------------------------- From f8f3a3e558dc86c91d259f33a64beb654364a1d2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 22:02:43 +0800 Subject: [PATCH 0909/1123] support Schematic version 3 (1.20+ Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 148 +++++++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 49 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 027fcb27..806db706 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -674,71 +674,121 @@ tl::expected> Schem::export_WESchem( NBT::NBTWriter file; - if (!file.open(filename.data())) { + if (not file.open(filename.data())) { return tl::make_unexpected( std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, fmt::format("Failed to open file {}", filename))); } - // write metadata - file.writeCompound("Metadata"); - { - file.writeInt("WEOffsetX", info.WE_offset[0]); - file.writeInt("WEOffsetY", info.WE_offset[1]); - file.writeInt("WEOffsetZ", info.WE_offset[2]); - file.writeString("Name", info.schem_name_utf8.data()); - file.writeString("Author", info.author_utf8.data()); - file.writeLong("Date", info.date); - - file.writeListHead("RequiredMods", NBT::String, - info.required_mods_utf8.size()); + auto write_version = [&]() { // data version + file.writeInt("DataVersion", (int)this->MC_data_ver); + }; + auto write_palette = [&]() { + file.writeCompound("Palette"); { - for (const auto &str : info.required_mods_utf8) { - file.writeString("", str.data()); + for (int idx = 0; idx < int(block_id_list.size()); idx++) { + file.writeInt(block_id_list[idx].c_str(), idx); } - } - // finish list - } // finish compound - file.endCompound(); + } // finished palette + file.endCompound(); + }; + auto write_offset = [&]() { + file.writeIntArrayHead("Offset", 3); + { + file.writeInt("", info.offset[0]); + file.writeInt("", info.offset[1]); + file.writeInt("", info.offset[2]); + } // end array + }; + auto write_shape = [&]() { + file.writeShort("Width", x_range()); + file.writeShort("Height", y_range()); + file.writeShort("Length", z_range()); + }; - file.writeCompound("Palette"); - { - for (int idx = 0; idx < int(block_id_list.size()); idx++) { - file.writeInt(block_id_list[idx].c_str(), idx); - } - } // finished palette - file.endCompound(); + std::vector blockdata; + ::shrink_bytes_weSchem(xzy.data(), xzy.size(), block_id_list.size(), + &blockdata); + auto write_blocks = [&](const char *key) { + file.writeByteArrayHead(key, blockdata.size()); + { + const int8_t *data = reinterpret_cast(blockdata.data()); + for (int64_t idx = 0; idx < int64_t(blockdata.size()); idx++) { + file.writeByte("", data[idx]); + } + } // end array + }; + + if (this->MC_major_ver <= SCL_gameVersion::MC19) { + // write metadata + file.writeCompound("Metadata"); + { + file.writeInt("WEOffsetX", info.WE_offset[0]); + file.writeInt("WEOffsetY", info.WE_offset[1]); + file.writeInt("WEOffsetZ", info.WE_offset[2]); + file.writeString("Name", info.schem_name_utf8.data()); + file.writeString("Author", info.author_utf8.data()); + file.writeLong("Date", info.date); + + file.writeListHead("RequiredMods", NBT::String, + info.required_mods_utf8.size()); + { + for (const auto &str : info.required_mods_utf8) { + file.writeString("", str.data()); + } + } + // finish list + } // finish compound + file.endCompound(); - file.writeListHead("BlockEntities", NBT::Compound, 0); + file.writeInt("Version", 2); // schematic format version + write_version(); - file.writeInt("DataVersion", (int)this->MC_data_ver); + write_palette(); + file.writeInt("PaletteMax", block_id_list.size()); - file.writeShort("Width", x_range()); - file.writeShort("Height", y_range()); - file.writeShort("Length", z_range()); + file.writeListHead("BlockEntities", NBT::Compound, 0); - file.writeInt("Version", 2); + write_shape(); + write_offset(); + write_blocks("BlockData"); + } else { // 1.20+ + file.writeCompound("Schematic"); + { + file.writeCompound("Metadata"); + { + file.writeLong("Date", info.date); - file.writeInt("PaletteMax", block_id_list.size()); + file.writeCompound("WorldEdit"); + { + file.writeString("Version", "unknown"); + file.writeString("EditingPlatform", "enginehub:fabric"); + file.writeIntArrayHead("Origin", 3); + { + for (int i = 0; i < 3; i++) { + file.writeInt("", 0); + } + } + } + file.endCompound(); + } + file.endCompound(); // finish metadata - std::vector blockdata; - ::shrink_bytes_weSchem(xzy.data(), xzy.size(), block_id_list.size(), - &blockdata); + file.writeInt("Version", 3); // schematic format version + write_version(); + write_shape(); + write_offset(); - file.writeByteArrayHead("BlockData", blockdata.size()); - { - const int8_t *data = reinterpret_cast(blockdata.data()); - for (int64_t idx = 0; idx < int64_t(blockdata.size()); idx++) { - file.writeByte("", data[idx]); + file.writeCompound("Blocks"); + { + write_palette(); + write_blocks("Data"); + file.writeListHead("BlockEntities", NBT::tagType::Compound, 0); + } + file.endCompound(); // finish Blocks } - } // end array - - file.writeIntArrayHead("Offset", 3); - { - file.writeInt("x", info.offset[0]); - file.writeInt("y", info.offset[1]); - file.writeInt("z", info.offset[2]); - } // end array + file.endCompound(); + } file.close(); return {}; From 1a38687942392f259f4b5e127130a1ca1d557861 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 8 Aug 2024 22:03:06 +0800 Subject: [PATCH 0910/1123] promote cpack deb scripts Signed-off-by: ToKiNoBug --- cpack/deb.cmake | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cpack/deb.cmake b/cpack/deb.cmake index 751415aa..375367f4 100644 --- a/cpack/deb.cmake +++ b/cpack/deb.cmake @@ -3,15 +3,21 @@ set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE amd64) set(SlopeCraft_debian_opencl_deps) -if(${SlopeCraft_GPU_API} STREQUAL "OpenCL") +if (${SlopeCraft_GPU_API} STREQUAL "OpenCL") set(SlopeCraft_debian_opencl_deps ocl-icd-libopencl1 ) -endif() +endif () +if (${SlopeCraft_GPU_API} STREQUAL "Vulkan") + set(SlopeCraft_debian_vulkan_deps + libvulkan1) +endif () set(CPACK_DEBIAN_PACKAGE_DEPENDS - "libzip4" - "libpng16-16" + "zlib1g" + "libzip-dev" # package name like lib*-dev are much more universal in different ubuntu releases + "libboost-iostreams-dev" + "libpng-dev" "libqt6core6(>=6.2.4)" "libqt6gui6(>=6.2.4)" "libqt6widgets6(>=6.2.4)" @@ -23,6 +29,7 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libglx0" "qt6-qpa-plugins(>=6.2.4)" ${SlopeCraft_debian_opencl_deps} + ${SlopeCraft_debian_vulkan_deps} ) list(JOIN CPACK_DEBIAN_PACKAGE_DEPENDS "," CPACK_DEBIAN_PACKAGE_DEPENDS) From 73dff39513494b174c12c28c2bbb7cc92152aa29 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 01:58:51 +0800 Subject: [PATCH 0911/1123] record filename in block list manager Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BlockListManager.cpp | 3 ++- utilities/BlockListManager/BlockListManager.h | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 5daa54c5..9d85c50d 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -121,7 +121,8 @@ bool BlockListManager::add_blocklist(QString filename) noexcept { continue; } - this->blockslists.emplace_back(std::move(tmp)); + this->blockslists.emplace_back(QFileInfo{filename}.fileName(), + std::move(tmp)); return true; } diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 43d662a3..7f80735e 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -55,7 +55,8 @@ class BlockListManager : public QWidget { private: std::vector> basecolor_widgets; std::vector< - std::unique_ptr> + std::pair>> blockslists; std::function callback_get_version{nullptr}; @@ -115,6 +116,17 @@ class BlockListManager : public QWidget { [[nodiscard]] selection current_selection() const noexcept; + [[nodiscard]] std::vector< + std::pair> + get_block_lists() const noexcept { + std::vector> + ret; + for (auto &[name, list] : this->blockslists) { + ret.emplace_back(name, list.get()); + } + return ret; + } + signals: void changed(); From 06421e499d73c261a06cdf159336b3a669d99700 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 01:59:10 +0800 Subject: [PATCH 0912/1123] implement BlockListDialog Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 293 ++++++++++++++++++++++++++++++++- SlopeCraft/BlockListDialog.h | 20 ++- SlopeCraft/BlockListDialog.ui | 122 +++++++++++--- 3 files changed, 410 insertions(+), 25 deletions(-) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index 8887acba..2d915470 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -4,12 +4,303 @@ #include "BlockListDialog.h" #include "ui_BlockListDialog.h" +#include +#include "SCWind.h" -BlockListDialog::BlockListDialog(QWidget *parent) +class BLD_block_list_provider : public QAbstractListModel { + public: + const std::function>()> + available_block_lists; + + public: + explicit BLD_block_list_provider( + QWidget *parent, + std::function>()> + cb) + : QAbstractListModel{parent}, available_block_lists{std::move(cb)} {} + BLD_block_list_provider(const BLD_block_list_provider &) = delete; + + int rowCount(const QModelIndex &parent = QModelIndex()) const final { + if (parent.isValid()) { + return 0; + } + return this->available_block_lists().size(); + } + + QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const final { + if (not index.isValid()) { + return {}; + } + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; + } + const auto block_lists = this->available_block_lists(); + const int idx = index.row(); + + if (idx >= block_lists.size() or idx < 0) { + return {}; + } + if (block_lists[idx].second == nullptr) { + return tr("SlopeCraft 内部错误,方块列表的列表中出现 nullptr"); + } + return block_lists[idx].first; + } +}; + +class BLD_block_provider : public QAbstractListModel { + private: + const std::function + available_block_list; + const std::function current_lang; + + public: + explicit BLD_block_provider( + QWidget *parent, + std::function &&cb, + std::function &&lang_cb) + : QAbstractListModel{parent}, + available_block_list{std::move(cb)}, + current_lang{std::move(lang_cb)} {} + + std::vector available_blocks() + const noexcept { + auto bl = this->available_block_list(); + if (bl == nullptr) { + return {}; + } + const size_t num = bl->size(); + std::vector ret; + ret.resize(num); + [[maybe_unused]] const size_t num_ = + bl->get_blocks(ret.data(), nullptr, ret.size()); + assert(num == num_); + return ret; + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const final { + if (parent.isValid()) { + return 0; + } + auto bl = this->available_block_list(); + if (bl == nullptr) { + return 0; + } + return bl->size(); + } + QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const final { + if (not index.isValid()) { + return {}; + } + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; + } + const auto blocks = this->available_blocks(); + const int idx = index.row(); + + if (idx >= blocks.size() or idx < 0) { + return {}; + } + if (blocks[idx] == nullptr) { + return tr("SlopeCraft 内部错误,方块列表中出现 nullptr"); + } + if (this->current_lang() == SCL_language::Chinese) { + return QString::fromUtf8(blocks[idx]->getNameZH()); + } + return QString::fromUtf8(blocks[idx]->getNameEN()); + } +}; + +class BLD_block_info_provider : public QAbstractTableModel { + public: + const std::function selected_block; + + public: + explicit BLD_block_info_provider( + QWidget *parent, + std::function &&cb) + : QAbstractTableModel{parent}, selected_block{std::move(cb)} {} + + int rowCount(const QModelIndex &qmi) const final { + if (qmi.isValid()) { + return 0; + } + return 6; + } + int columnCount(const QModelIndex &qmi) const final { + if (qmi.isValid()) { + return 0; + } + return 2; + } + + static QString key_name(int index) noexcept { + const std::array keys{tr("最低版本"), tr("依附方块"), + tr("发光"), tr("末影人可搬走"), + tr("可燃"), tr("一组数量")}; + if (index < 0 or index >= keys.size()) { + return {}; + } + return keys[index]; + } + /* + * 0 -> version + * 1 -> need glass + * 2 -> do glow + * 3 -> enderman pickable + * 4 -> burnable + * 5 -> stack size + * */ + static QVariant value_of_attribute(const SlopeCraft::mc_block_interface &blk, + int index) noexcept { + auto bool_to_str = [](bool val) { + if (val) + return "Yes"; + else + return "No"; + }; + switch (index) { + case 0: { // version + const auto ver = blk.getVersion(); + if (ver < uint8_t(SCL_gameVersion::MC12)) { + return tr("远古版本"); + } + if (ver > (uint8_t)SlopeCraft::SCL_maxAvailableVersion()) { + return tr("未来版本"); + } + return QStringLiteral("1.%1").arg(int(ver)); + } + case 1: // need glass + return bool_to_str(blk.getNeedGlass()); + case 2: + return bool_to_str(blk.getDoGlow()); + case 3: + return bool_to_str(blk.getEndermanPickable()); + case 4: + return bool_to_str(blk.getBurnable()); + case 5: + return blk.getStackSize(); + } + return {}; + } + + QVariant data(const QModelIndex &qmi, int role) const noexcept final { + if (not qmi.isValid()) { + return {}; + } + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; + } + const auto current_block = this->selected_block(); + switch (qmi.column()) { + case 0: + return key_name(qmi.row()); + case 1: { + if (current_block == nullptr) { + return {}; + } + return value_of_attribute(*current_block, qmi.row()); + } + } + return {}; + } +}; + +BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) : QDialog{parent}, ui{new Ui::BlockListDialog} { this->ui->setupUi(this); + + { + auto get_block_lists = [blm]() + -> std::vector< + std::pair> { + return blm->get_block_lists(); + }; + this->block_list_provider = + new BLD_block_list_provider{this, get_block_lists}; + this->ui->lv_block_lists->setModel(this->block_list_provider); + } + { + auto get_selected_block_list = + [this]() -> const SlopeCraft::block_list_interface * { + const auto qmi = this->ui->lv_block_lists->currentIndex(); + if (not qmi.isValid()) { + return nullptr; + } + const int idx = qmi.row(); + const auto available_lists = + this->block_list_provider->available_block_lists(); + if (idx < 0 or idx >= available_lists.size()) { + return nullptr; + } + return available_lists[idx].second; + }; + auto get_lang = [parent]() -> SCL_language { return parent->lang(); }; + this->block_provider = + new BLD_block_provider{this, get_selected_block_list, get_lang}; + this->ui->lv_blocks->setModel(this->block_provider); + } + { + auto get_selected_block = + [this]() -> const SlopeCraft::mc_block_interface * { + const auto qmi = this->ui->lv_blocks->currentIndex(); + if (not qmi.isValid()) { + return nullptr; + } + const int idx = qmi.row(); + const auto available_blocks = this->block_provider->available_blocks(); + if (idx < 0 or idx >= available_blocks.size()) { + return nullptr; + } + return available_blocks[idx]; + }; + this->block_info_provider = + new BLD_block_info_provider{this, get_selected_block}; + this->ui->tv_block_props->setModel(this->block_info_provider); + } + + connect(this->ui->lv_block_lists->selectionModel(), + &QItemSelectionModel::selectionChanged, [this]() { + this->block_provider->dataChanged({}, {}, + {Qt::ItemDataRole::DisplayRole}); + }); + connect(this->ui->lv_blocks->selectionModel(), + &QItemSelectionModel::selectionChanged, [this]() { + this->block_info_provider->dataChanged( + {}, {}, {Qt::ItemDataRole::DisplayRole}); + + auto blk = this->block_info_provider->selected_block(); + this->update_info(blk); + }); + + connect(this->ui->pb_ok, &QPushButton::clicked, this, &QDialog::accept); } BlockListDialog::~BlockListDialog() { // delete this->ui; } + +void BlockListDialog::update_info( + const SlopeCraft::mc_block_interface *blk) noexcept { + if (blk == nullptr) { + this->ui->lb_image->setPixmap({}); + this->ui->le_id->clear(); + this->ui->le_id_old->clear(); + this->ui->le_name_cn->clear(); + this->ui->le_name_en->clear(); + return; + } + { + QImage img{blk->imageCols(), blk->imageRows(), QImage::Format_ARGB32}; + blk->getImage(reinterpret_cast(img.scanLine(0))); + img = img.scaledToHeight(64); + this->ui->lb_image->setPixmap(QPixmap::fromImage(img)); + } + this->ui->le_id->setText(blk->getId()); + this->ui->le_id_old->setText(blk->getIdOld()); + this->ui->le_name_cn->setText(QString::fromUtf8(blk->getNameZH())); + this->ui->le_name_en->setText(QString::fromUtf8(blk->getNameEN())); +} \ No newline at end of file diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h index 98ebbb4d..d2ed3937 100644 --- a/SlopeCraft/BlockListDialog.h +++ b/SlopeCraft/BlockListDialog.h @@ -5,8 +5,14 @@ #ifndef SLOPECRAFT_BLOCKLISTDIALOG_H #define SLOPECRAFT_BLOCKLISTDIALOG_H -#include #include +#include +#include + +#include +#include + +#include "BlockListManager.h" class BlockListDialog; @@ -14,13 +20,23 @@ namespace Ui { class BlockListDialog; } +class BLD_block_list_provider; +class BLD_block_provider; +class BLD_block_info_provider; + +class SCWind; class BlockListDialog : public QDialog { Q_OBJECT private: std::unique_ptr ui; + BLD_block_list_provider* block_list_provider{nullptr}; + BLD_block_provider* block_provider{nullptr}; + BLD_block_info_provider* block_info_provider{nullptr}; + + void update_info(const SlopeCraft::mc_block_interface*) noexcept; public: - explicit BlockListDialog(QWidget* parent); + explicit BlockListDialog(SCWind* parent, BlockListManager* blm); ~BlockListDialog(); }; diff --git a/SlopeCraft/BlockListDialog.ui b/SlopeCraft/BlockListDialog.ui index b1441e89..e523b003 100644 --- a/SlopeCraft/BlockListDialog.ui +++ b/SlopeCraft/BlockListDialog.ui @@ -6,19 +6,32 @@ 0 0 - 687 + 820 481 - 加载/删除方块列表 + 方块列表 - - - + + false + + + false + + + + + + + 0 + 0 + + + - + 0 @@ -27,29 +40,101 @@ - - - + + + 0 - + + + + 0 + 0 + + + + false + + + QFrame::Shape::StyledPanel + - + + + + + Qt::AlignmentFlag::AlignCenter - + + + true + + + 方块 id + + + + + + + true + + + 1.12 id + + + + + + + true + + + 中文名 + + + + + + + true + + + 英文名 + + + + + + + true + + + false + + + + + + + + + 0 + + + - - + 若想增加/修改方块列表,增加/删除 blocks 文件夹中的 zip 文件,然后重新启动 SlopeCraft - Qt::Horizontal + Qt::Orientation::Horizontal @@ -60,19 +145,12 @@ - + 确定 - - - - 取消 - - - From 3f4601c782681bac75a7813cffd5af1a7363d63c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 01:59:32 +0800 Subject: [PATCH 0913/1123] fix get_blocks of block list in SCL Signed-off-by: ToKiNoBug --- SlopeCraftL/mc_block.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index 6dcbe046..09f636d8 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -37,14 +37,19 @@ mc_block::mc_block() { size_t block_list::get_blocks(mc_block_interface **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) noexcept { - if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { + if (capacity_in_elements <= 0) { + return 0; + } + if (dst == nullptr and dst_basecolor == nullptr) { return 0; } size_t counter = 0; for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first.get(); - dst_basecolor[counter] = ptr.second; + if (dst) dst[counter] = ptr.first.get(); + + if (dst_basecolor) dst_basecolor[counter] = ptr.second; + counter++; if (counter >= capacity_in_elements) { return counter; @@ -56,14 +61,17 @@ size_t block_list::get_blocks(mc_block_interface **dst, uint8_t *dst_basecolor, size_t block_list::get_blocks(const mc_block_interface **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) const noexcept { - if (dst == nullptr || dst_basecolor == nullptr || capacity_in_elements <= 0) { + if (capacity_in_elements <= 0) { + return 0; + } + if (dst == nullptr and dst_basecolor == nullptr) { return 0; } size_t counter = 0; for (auto &ptr : this->m_blocks) { - dst[counter] = ptr.first.get(); - dst_basecolor[counter] = ptr.second; + if (dst) dst[counter] = ptr.first.get(); + if (dst_basecolor) dst_basecolor[counter] = ptr.second; counter++; if (counter >= capacity_in_elements) { return counter; From feadead49ab45a2744d4e636cfbd0d6a7392171a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 01:59:53 +0800 Subject: [PATCH 0914/1123] fix duplicated in loading block list Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 0952f3a8..f304929a 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -67,6 +67,9 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { for (auto file : blocks_dir.entryInfoList({"*.zip"}, QDir::Filters{QDir::Filter::Files}, QDir::SortFlags{QDir::SortFlag::Name})) { + if (file.fileName() == "FixedBlocks.zip") { + continue; + } if (not this->ui->blm->add_blocklist(file.absoluteFilePath())) { fail_counter++; fail_list.append(file.absoluteFilePath()); From 20827e60a8c2bc17d5e108caf6e56ebe6c2ff5e9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 02:00:06 +0800 Subject: [PATCH 0915/1123] pop block list dialog in SC Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 2 ++ SlopeCraft/SCWind.ui | 6 ++++++ SlopeCraft/SCWind_slots.cpp | 7 ++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 55727541..8a2bf848 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -146,6 +146,8 @@ class SCWind : public QMainWindow { void on_ac_memory_policy_triggered() noexcept; + void on_ac_blocklist_triggered() noexcept; + private: Ui::SCWind* ui; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 7c02561d..e7d617f6 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -1582,6 +1582,7 @@ + @@ -1720,6 +1721,11 @@ 缓存全部三维结构 + + + 查看方块列表 + + diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 5a97f8d2..8eaa6a93 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -14,7 +14,7 @@ #include "VersionDialog.h" #include "TransparentStrategyWind.h" #include "CompressEffectViewer.h" - +#include "BlockListDialog.h" #include "stat_memory.h" #ifdef WIN32 @@ -1174,3 +1174,8 @@ void SCWind::on_pb_export_data_vanilla_structure_clicked() noexcept { } this->ui->pbar_export->setValue(converted_tasks.size()); } + +void SCWind::on_ac_blocklist_triggered() noexcept { + auto dialog = new BlockListDialog{this, this->ui->blm}; + dialog->exec(); +} \ No newline at end of file From 1ca29394c1dea145e6c6b37532c44aa871802f31 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 10:12:18 +0800 Subject: [PATCH 0916/1123] add some 1.21 copper blocks to FixedBlocks Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 68 +++++++++++++++++- Blocks/FixedBlocks/copper_bulb.png | Bin 0 -> 242 bytes Blocks/FixedBlocks/copper_grate.png | Bin 0 -> 243 bytes Blocks/FixedBlocks/exposed_copper_bulb.png | Bin 0 -> 244 bytes Blocks/FixedBlocks/exposed_copper_grate.png | Bin 0 -> 242 bytes Blocks/FixedBlocks/oxidized_copper_bulb.png | Bin 0 -> 238 bytes Blocks/FixedBlocks/oxidized_copper_grate.png | Bin 0 -> 238 bytes Blocks/FixedBlocks/weathered_copper_bulb.png | Bin 0 -> 243 bytes Blocks/FixedBlocks/weathered_copper_grate.png | Bin 0 -> 241 bytes 9 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 Blocks/FixedBlocks/copper_bulb.png create mode 100644 Blocks/FixedBlocks/copper_grate.png create mode 100644 Blocks/FixedBlocks/exposed_copper_bulb.png create mode 100644 Blocks/FixedBlocks/exposed_copper_grate.png create mode 100644 Blocks/FixedBlocks/oxidized_copper_bulb.png create mode 100644 Blocks/FixedBlocks/oxidized_copper_grate.png create mode 100644 Blocks/FixedBlocks/weathered_copper_bulb.png create mode 100644 Blocks/FixedBlocks/weathered_copper_grate.png diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 1f4b79f5..ee1553dc 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -537,6 +537,22 @@ "icon": "waxed_cut_copper.png", "version": 17 }, + { + "baseColor": 15, + "id": "minecraft:waxed_copper_bulb", + "nameZH": "涂蜡铜灯", + "nameEN": "Waxed copper bulb", + "icon": "copper_bulb.png", + "version": 21 + }, + { + "baseColor": 15, + "id": "minecraft:waxed_copper_gate", + "nameZH": "涂蜡铜格栅", + "nameEN": "Waxed copper gate", + "icon": "copper_gate.png", + "version": 21 + }, { "baseColor": 16, "id": "minecraft:magenta_concrete", @@ -1362,6 +1378,22 @@ "icon": "mud_bricks.png", "version": 19 }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_copper_bulb", + "nameZH": "斑驳的涂蜡铜灯", + "nameEN": "Waxed exposed copper bulb", + "icon": "exposed_copper_bulb.png", + "version": 21 + }, + { + "baseColor": 44, + "id": "minecraft:waxed_exposed_copper_gate", + "nameZH": "斑驳的涂蜡铜格栅", + "nameEN": "Waxed exposed copper gate", + "icon": "exposed_copper_gate.png", + "version": 21 + }, { "baseColor": 45, "id": "minecraft:cyan_terracotta", @@ -1501,7 +1533,7 @@ "baseColor": 55, "id": "minecraft:waxed_oxidized_copper", "nameZH": "氧化的涂蜡铜块", - "nameEN": "Waxed oxided copper", + "nameEN": "Waxed oxidized copper", "icon": "waxed_oxidized_copper.png", "version": 17 }, @@ -1509,10 +1541,26 @@ "baseColor": 55, "id": "minecraft:waxed_oxidized_cut_copper", "nameZH": "氧化的涂蜡切制铜块", - "nameEN": "Waxed oxided cut copper", + "nameEN": "Waxed oxidized cut copper", "icon": "waxed_oxidized_cut_copper.png", "version": 17 }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_copper_bulb", + "nameZH": "氧化的涂蜡铜灯", + "nameEN": "Waxed oxidized copper bulb", + "icon": "oxidized_copper_bulb.png", + "version": 21 + }, + { + "baseColor": 55, + "id": "minecraft:waxed_oxidized_copper_gate", + "nameZH": "氧化的涂蜡铜格栅", + "nameEN": "Waxed oxidized copper gate", + "icon": "oxidized_copper_gate.png", + "version": 21 + }, { "baseColor": 56, "id": "minecraft:warped_planks", @@ -1547,6 +1595,22 @@ "icon": "waxed_weathered_cut_copper.png", "version": 17 }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_copper_bulb", + "nameZH": "锈蚀的涂蜡铜灯", + "nameEN": "Waxed weathered copper bulb", + "icon": "weathered_copper_bulb.png", + "version": 21 + }, + { + "baseColor": 56, + "id": "minecraft:waxed_weathered_copper_gate", + "nameZH": "锈蚀的涂蜡铜格栅", + "nameEN": "Waxed weathered copper gate", + "icon": "weathered_copper_gate.png", + "version": 21 + }, { "baseColor": 57, "id": "minecraft:warped_hyphae[axis=y]", diff --git a/Blocks/FixedBlocks/copper_bulb.png b/Blocks/FixedBlocks/copper_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..79275ba3c8bc7f76e7fbf706879172cf06b52281 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv4DbnYecY6DtvdQdN!X!mpG`^b z%cC4-1z1e*G;H(JEOwNSHx^ZyJWmd&xX07QF{I*_=$Vb2ha4o@9)ADL%h6Ra{m>yN zp|?km#Tj|;@_8VZ#vCnsm{-Q3iCaco(51sgcm6ZMBq`7Ew9~=1R?qM4Xg|JeXOb4j zM5mJ*c$z*X+go2ZS2ULZF;-1spdax)ExDvKDQaUf$n1PboFyt=akR{0J)f3*#H0l literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/copper_grate.png b/Blocks/FixedBlocks/copper_grate.png new file mode 100644 index 0000000000000000000000000000000000000000..676732423515af2711fa2a68252e2bc9c7a9bb65 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa4)6(a1=5e3a;{ZJpC}1Clj;{37&?3TU51y(u^fRe!&b5&u*jvIc=UUjv*DdM9=tgH90UiJUssAY0)9R z1;!$J?50JQ6WmT8IJ36utVe?<}5Y64P3mrQrH(#kqoxr5tM|H-@^& z?p%B9q{Zq&W7B1~ALcAwwmoly-G|5D^c;)r0 nbA@-gU*UXy-RA$a)St|^+eN%5nF-keUBuw&>gTe~DWM4fp~GMN literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/exposed_copper_bulb.png b/Blocks/FixedBlocks/exposed_copper_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..fc8ce1dcad51c27f173c77adfbe2660a38f9fce8 GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv4DbnYJ=fd3tEqfOPiEDO%oXKH zQ_2$Si^3~YLW<)9vLn1hd~NgAOuGtH+~?`y7*cUd^~^@DLk1#l5BEZ&}9ssu6{1-oD!Mv2x`&JYFA=_vo3k^{w;+ zZ$7L_TUxMzRZ6ERy3sDu%RcPvs}JQj7M`8HeCDw%jV3e3uisK0r8>SAUbJ#<^o@uO mU#~9S_@Mp34DXXWp9nj%h`O0Qh8H|eGGIHgQu&X%Q~loCIHW`U!MQ~ literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/oxidized_copper_grate.png b/Blocks/FixedBlocks/oxidized_copper_grate.png new file mode 100644 index 0000000000000000000000000000000000000000..1cb5779c715f0e28a316a7be600983a3c5df7945 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa4)6(a1=4v(=SOau=^oD?_{Hi_k9jlCcC&D zG+p~-vsTiI_C9rsd7Yo{f9csRq3QTDA#R6*?}e?CwT1YrTF!IwA8S&4J0)yuhoPuR hxkUf9ee=uyFl2`a#fJJl_zZLmgQu&X%Q~loCIHUAS(g9+ literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/weathered_copper_bulb.png b/Blocks/FixedBlocks/weathered_copper_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..6312797d2f176d66047887161670720f4a12d02e GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv4DbnYt=c}bU_(dR%JP&2<-P3% zIn!fGdc(5{-8~Ca9FrsbgFJTcvzG-b?)7wW45_%Kde)HZkb%gtkNs29UI@-P!Y8+Y zMTNcK#F`nxKf1&XR+kt=>fV?hD68{+%Ca4Q+wUJ|*VxK-i&;xKU)$YjX=RD0aMq)P zs;@3`@SC0NX?vWJtTplT=SiP=w!Zu|`)2h5-HVd(8}@`L-M4>cBD!bIr8r qFMHZ#^Ci;G?+j-&m*Ty{U)gV6Fj&~kw%`iTVGN$GelF{r5}E*2xns%z literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/weathered_copper_grate.png b/Blocks/FixedBlocks/weathered_copper_grate.png new file mode 100644 index 0000000000000000000000000000000000000000..2095213106f7554f33ea15612e52a5226f98fb78 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa4)6(a1=3a9XQr(zPgzjj+g^|} zJ*K2LJgd;%voM9RlEn!q%~%rT7tG-B>_!@p)8gsk7*cUd^^753lYt1^1N*i7GMUnI z8~N7gul1FYv~h4|u(skf-(Y?r`F6|S)9g!2mrt3SSRr)hG8=QE<9n&;( Date: Fri, 9 Aug 2024 11:19:42 +0800 Subject: [PATCH 0917/1123] support MC21 in SCL and SC Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 12 ++-- SlopeCraft/SCWind.h | 4 +- SlopeCraft/SCWind.ui | 56 +++++++++++-------- SlopeCraftL/converted_image.cpp | 2 + SlopeCraftL/image_preprocess.cpp | 2 +- .../BlockListManager/BlockListManager.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 16 ++++-- utilities/MCDataVersion/MCDataVersion.h | 1 + utilities/SC_GlobalEnums.h | 4 +- utilities/Schem/Schem.cpp | 4 +- 10 files changed, 61 insertions(+), 42 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index f304929a..409e9f8e 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -308,14 +308,15 @@ void SCWind::when_cvt_pool_selectionChanged() noexcept { { \ this->ui->rb_ver12, this->ui->rb_ver13, this->ui->rb_ver14, \ this->ui->rb_ver15, this->ui->rb_ver16, this->ui->rb_ver17, \ - this->ui->rb_ver18, this->ui->rb_ver19, this->ui->rb_ver20 \ + this->ui->rb_ver18, this->ui->rb_ver19, this->ui->rb_ver20, \ + this->ui->rb_ver21 \ } -std::array SCWind::version_buttons() noexcept { +std::array SCWind::version_buttons() noexcept { return SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST; } -std::array SCWind::version_buttons() +std::array SCWind::version_buttons() const noexcept { return SC_SLOPECRAFT_PRIVATEMACRO_VERSION_BUTTON_LIST; } @@ -842,7 +843,6 @@ void SCWind::refresh_current_cvt_display( QPixmap::fromImage(get_converted_image(*it->second.converted_image))); return; } - // #warning "TODO: Load cache here" this->ui->lb_cvted_image->setPixmap({}); } @@ -955,9 +955,7 @@ tl::expected SCWind::get_command( }, }; bool after_1_20_5; - if (this->selected_version() < SCL_gameVersion::MC20) { - after_1_20_5 = true; - } else if (this->selected_version() > SCL_gameVersion::MC20) { + if (this->selected_version() not_eq SCL_gameVersion::MC20) { after_1_20_5 = true; } else { after_1_20_5 = this->ui->cb_mc_version_geq_1_20_5->isChecked(); diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index 8a2bf848..f1b0afe8 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -181,8 +181,8 @@ class SCWind : public QMainWindow { SlopeCraft::ui_callbacks ui_callbacks() const noexcept; - std::array version_buttons() noexcept; - std::array version_buttons() const noexcept; + std::array version_buttons() noexcept; + std::array version_buttons() const noexcept; std::array type_buttons() noexcept; std::array type_buttons() const noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index e7d617f6..899713ad 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -120,20 +120,17 @@ 游戏版本 - - + + - 1.12 + 1.13 - - - - true - + + - 1.20 + 1.18 @@ -144,10 +141,13 @@ - - + + - 1.18 + 1.19 + + + false @@ -158,10 +158,10 @@ - - + + - 1.14 + 1.12 @@ -172,20 +172,30 @@ - - + + + + true + - 1.13 + 1.20 + + + true - - + + - 1.19 + 1.14 - - true + + + + + + 1.21 diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 994f42ee..5b9ab891 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -110,6 +110,7 @@ bool converted_image_impl::export_map_data( case SCL_gameVersion::MC18: case SCL_gameVersion::MC19: case SCL_gameVersion::MC20: + case SCL_gameVersion::MC21: MapFile.writeInt( "DataVersion", static_cast( @@ -158,6 +159,7 @@ bool converted_image_impl::export_map_data( case SCL_gameVersion::MC18: case SCL_gameVersion::MC19: case SCL_gameVersion::MC20: + case SCL_gameVersion::MC21: MapFile.writeListHead("banners", NBT::Compound, 0); MapFile.writeListHead("frames", NBT::Compound, 0); MapFile.writeString("dimension", "minecraft:overworld"); diff --git a/SlopeCraftL/image_preprocess.cpp b/SlopeCraftL/image_preprocess.cpp index 50f2df87..8d7bbf1f 100644 --- a/SlopeCraftL/image_preprocess.cpp +++ b/SlopeCraftL/image_preprocess.cpp @@ -93,7 +93,7 @@ SCL_EXPORT bool SCL_haveTransparentPixel(const uint32_t *ARGB32, } SCL_gameVersion SCL_EXPORT SCL_maxAvailableVersion() { - return SCL_gameVersion::MC20; + return SCL_gameVersion::MC21; } #ifndef SCL_CAPI diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 9d85c50d..6a6c8b4b 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -78,7 +78,7 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { errmsg.resize(sd_err.size); warning.resize(sd_warn.size); - if (!errmsg.empty()) { + if (not errmsg.empty()) { errmsg.append(QStringLiteral("\npwd: %1") .arg(QFileInfo{"."}.absolutePath()) .toLocal8Bit()); diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index 3c144191..af65712a 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -49,6 +49,7 @@ const char *MCDataVersion::data_version_to_string( MCDataVersion::MCDataVersion_t MCDataVersion::max_supported_version( SCL_gameVersion v) noexcept { switch (v) { + case SCL_gameVersion::ANCIENT: case SCL_gameVersion::MC12: return MCDataVersion_t::Java_1_12_2; case SCL_gameVersion::MC13: @@ -67,15 +68,17 @@ MCDataVersion::MCDataVersion_t MCDataVersion::max_supported_version( return MCDataVersion_t::Java_1_19_3; case SCL_gameVersion::MC20: return MCDataVersion_t::Java_1_20_5; - default: - abort(); - return {}; + case SCL_gameVersion::MC21: + case SCL_gameVersion::FUTURE: + return MCDataVersion_t::Java_1_21; } + abort(); } MCDataVersion::MCDataVersion_t MCDataVersion::min_supported_version( SCL_gameVersion v) noexcept { switch (v) { + case SCL_gameVersion::ANCIENT: case SCL_gameVersion::MC12: return MCDataVersion_t::Java_1_12; case SCL_gameVersion::MC13: @@ -94,10 +97,11 @@ MCDataVersion::MCDataVersion_t MCDataVersion::min_supported_version( return MCDataVersion_t::Java_1_19; case SCL_gameVersion::MC20: return MCDataVersion_t::Java_1_20; - default: - abort(); - return {}; + case SCL_gameVersion::MC21: + case SCL_gameVersion::FUTURE: + return MCDataVersion_t::Java_1_21; } + abort(); } MCDataVersion::MCDataVersion_t MCDataVersion::suggested_version( diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index abbf5198..32b68e64 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,6 +30,7 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + Java_1_21 = 3953, Java_1_20_5 = 3837, Snapshot_23w51b = 3802, Snapshot_23w51a = 3801, diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 94e0ff32..630d01bd 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -52,11 +52,13 @@ enum class SCL_gameVersion : int { MC19 = 19, /// 1.20 MC20 = 20, + /// 1.21 + MC21 = 21, /// future version FUTURE = 255 }; -constexpr SCL_gameVersion max_version = SCL_gameVersion::MC20; +constexpr SCL_gameVersion max_version = SCL_gameVersion::MC21; /// color difference formula used to match colors enum class SCL_convertAlgo : char { diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 806db706..dd51e9e7 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -456,6 +456,7 @@ Schem::export_litematic(std::string_view filename, case ::SCL_gameVersion::MC18: case ::SCL_gameVersion::MC19: case ::SCL_gameVersion::MC20: + case ::SCL_gameVersion::MC21: lite.writeInt("MinecraftDataVersion", (int)this->MC_version_number()); lite.writeInt("Version", 5); break; @@ -639,6 +640,7 @@ Schem::export_structure(std::string_view filename, case ::SCL_gameVersion::MC18: case ::SCL_gameVersion::MC19: case ::SCL_gameVersion::MC20: + case ::SCL_gameVersion::MC21: file.writeInt("MinecraftDataVersion", (int)this->MC_data_ver); break; default: @@ -646,7 +648,7 @@ Schem::export_structure(std::string_view filename, file.close(); return tl::make_unexpected(std::make_pair( SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION, - fmt::format("Unknown major game version! Only 1.12 to 1.19 is " + fmt::format("Unknown major game version! Only 1.12 to 1.21 is " "supported, but given value {}", (int)this->MC_major_ver))); } From eb4a5e40987ce38140774eaf66c6da3a195bddb3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 11:20:08 +0800 Subject: [PATCH 0918/1123] fix copper grate icon name Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index ee1553dc..df4d7c83 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -547,10 +547,10 @@ }, { "baseColor": 15, - "id": "minecraft:waxed_copper_gate", + "id": "minecraft:waxed_copper_grate", "nameZH": "涂蜡铜格栅", - "nameEN": "Waxed copper gate", - "icon": "copper_gate.png", + "nameEN": "Waxed copper grate", + "icon": "copper_grate.png", "version": 21 }, { @@ -1388,10 +1388,10 @@ }, { "baseColor": 44, - "id": "minecraft:waxed_exposed_copper_gate", + "id": "minecraft:waxed_exposed_copper_grate", "nameZH": "斑驳的涂蜡铜格栅", - "nameEN": "Waxed exposed copper gate", - "icon": "exposed_copper_gate.png", + "nameEN": "Waxed exposed copper grate", + "icon": "exposed_copper_grate.png", "version": 21 }, { @@ -1555,10 +1555,10 @@ }, { "baseColor": 55, - "id": "minecraft:waxed_oxidized_copper_gate", + "id": "minecraft:waxed_oxidized_copper_grate", "nameZH": "氧化的涂蜡铜格栅", - "nameEN": "Waxed oxidized copper gate", - "icon": "oxidized_copper_gate.png", + "nameEN": "Waxed oxidized copper grate", + "icon": "oxidized_copper_grate.png", "version": 21 }, { @@ -1605,10 +1605,10 @@ }, { "baseColor": 56, - "id": "minecraft:waxed_weathered_copper_gate", + "id": "minecraft:waxed_weathered_copper_grate", "nameZH": "锈蚀的涂蜡铜格栅", - "nameEN": "Waxed weathered copper gate", - "icon": "weathered_copper_gate.png", + "nameEN": "Waxed weathered copper grate", + "icon": "weathered_copper_grate.png", "version": 21 }, { From ea86710950792f4481173a8aade593123e932adf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 11:37:22 +0800 Subject: [PATCH 0919/1123] fix a bad error handling Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 62 ++++++++++++--------------------- 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index 73f2d5ff..e78e2acb 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -100,45 +100,41 @@ version_set parse_version_set(const nlohmann::json &jo, #define VCL_PRIVATE_MACRO_PARSE_ATTRIBUTE(key_str, key_enum) \ if (jo.contains(#key_str)) { \ if (!jo.at(#key_str).is_boolean()) { \ - *ok = false; \ - return {}; \ + return std::nullopt; \ } \ \ ret.set_attribute(VCL_block::attribute::key_enum, jo.at(#key_str)); \ } -VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { +std::optional parse_block(const nlohmann::json &jo) { if (!jo.contains("version")) { - *ok = false; - return {}; + return std::nullopt; } VCL_block ret; - ret.version_info = parse_version_set(jo.at("version"), ok); + bool ok = false; + ret.version_info = parse_version_set(jo.at("version"), &ok); - if (!ok) { - *ok = false; - return {}; + if (not ok) { + return std::nullopt; } ret.set_transparency(false); if (!jo.contains("class") || !jo.at("class").is_string()) { - *ok = false; - return {}; + return std::nullopt; } else { const std::string &str = jo.at("class"); - ret.block_class = string_to_block_class(str, ok); + ret.block_class = string_to_block_class(str, &ok); - if (!*ok) { - return {}; + if (not ok) { + return std::nullopt; } } if (jo.contains("id_replace_list")) { if (!jo.at("id_replace_list").is_array()) { - *ok = false; - return {}; + return std::nullopt; } const nlohmann::json &ja = jo.at("id_replace_list"); @@ -146,13 +142,11 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { for (size_t i = 0; i < ja.size(); i++) { const nlohmann::json &jaa = ja.at(i); if (!jaa.is_array() || jaa.size() != 2) { - *ok = false; - return {}; + return std::nullopt; } if (!jaa[0].is_number_integer() || !jaa[1].is_string()) { - *ok = false; - return {}; + return std::nullopt; } int val = jaa[0]; @@ -167,8 +161,7 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { if (jo.at("nameZH").is_string()) { ret.name_ZH = jo.at("nameZH"); } else { - *ok = false; - return {}; + return std::nullopt; } } @@ -176,8 +169,7 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { if (jo.at("nameEN").is_string()) { ret.name_EN = jo.at("nameEN"); } else { - *ok = false; - return {}; + return std::nullopt; } } @@ -185,8 +177,7 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { if (jo.at("transparent").is_boolean()) { ret.set_transparency(jo.at("transparent")); } else { - *ok = false; - return {}; + return std::nullopt; } } @@ -197,23 +188,20 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { for (size_t i = 0; i < ja.size(); i++) { if (!ja.at(i).is_string()) { - *ok = false; - return {}; + return std::nullopt; } bool _ok = true; const VCL_face_t f = string_to_face_idx(ja.at(i).get(), &_ok); if (!_ok) { - *ok = false; - return {}; + return std::nullopt; } ret.set_face_avaliablity(f, true); } } else { - *ok = false; - return {}; + return std::nullopt; } } @@ -227,8 +215,6 @@ VCL_block parse_block(const nlohmann::json &jo, bool *const ok) { VCL_PRIVATE_MACRO_PARSE_ATTRIBUTE(reproducible, reproducible); VCL_PRIVATE_MACRO_PARSE_ATTRIBUTE(rare, rare); - *ok = true; - return ret; } @@ -250,12 +236,10 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { return false; } - bool ok = true; - for (const auto &pair : jo.items()) { - VCL_block vb = parse_block(pair.value(), &ok); + auto vb = parse_block(pair.value()); - if (!ok) { + if (not vb) { std::string msg = fmt::format( "Failed to parse {}, : invalid value for block state {} : {}", filename, pair.key().c_str(), to_string(pair.value())); @@ -263,7 +247,7 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { return false; } - auto it = this->states.emplace(pair.key(), std::move(vb)); + auto it = this->states.emplace(pair.key(), std::move(vb.value())); // This statement requires that VCL_block_state_list is a friend class of // VCL_block From e8c4737da8b88ae053ab244f44ed3b8576014f27 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 12:52:43 +0800 Subject: [PATCH 0920/1123] add 1.20.6 and 1.21.1(with bugs) Signed-off-by: ToKiNoBug --- VisualCraft/vc-config-to-bin-dir.json.in | 4 ++++ VisualCraft/vc-config.json | 6 +++++- VisualCraftL/setup_zip_names.cmake | 4 ++-- cmake/required_deps/vanilla_zips.cmake | 8 +++++--- vccl/vccl-config-to-bin-dir.json.in | 4 ++++ vccl/vccl-config.json | 6 +++++- vccl/vccl.cpp | 4 ++-- 7 files changed, 27 insertions(+), 9 deletions(-) diff --git a/VisualCraft/vc-config-to-bin-dir.json.in b/VisualCraft/vc-config-to-bin-dir.json.in index d337204e..0221ff4a 100644 --- a/VisualCraft/vc-config-to-bin-dir.json.in +++ b/VisualCraft/vc-config-to-bin-dir.json.in @@ -35,6 +35,10 @@ [ 20, "@VCL_resource_20@" + ], + [ + 21, + "@VCL_resource_21@" ] ], "default_block_state_list": [ diff --git a/VisualCraft/vc-config.json b/VisualCraft/vc-config.json index d85e9927..07599109 100644 --- a/VisualCraft/vc-config.json +++ b/VisualCraft/vc-config.json @@ -34,7 +34,11 @@ ], [ 20, - "./Blocks_VCL/Vanilla_1_20_4.zip" + "./Blocks_VCL/Vanilla_1_20_6.zip" + ], + [ + 21, + "./Blocks_VCL/Vanilla_1_21_1.zip" ] ], "default_block_state_list": [ diff --git a/VisualCraftL/setup_zip_names.cmake b/VisualCraftL/setup_zip_names.cmake index 8e8ccfac..52155d77 100644 --- a/VisualCraftL/setup_zip_names.cmake +++ b/VisualCraftL/setup_zip_names.cmake @@ -1,7 +1,7 @@ set(VCL_app_files ${CMAKE_SOURCE_DIR}/VisualCraftL/VCL_blocks_fixed.json) -foreach (mcver RANGE 12 20) +foreach (mcver RANGE 12 21) set(VCL_current_var_name VCL_resource_${mcver}) if (NOT DEFINED ${VCL_current_var_name}) @@ -9,6 +9,6 @@ foreach (mcver RANGE 12 20) endif () list(APPEND VCL_app_files ${${VCL_current_var_name}}) -endforeach (mcver RANGE 12 20) +endforeach (mcver RANGE 12 21) unset(mcver) \ No newline at end of file diff --git a/cmake/required_deps/vanilla_zips.cmake b/cmake/required_deps/vanilla_zips.cmake index c7df60b9..2b942ea5 100644 --- a/cmake/required_deps/vanilla_zips.cmake +++ b/cmake/required_deps/vanilla_zips.cmake @@ -7,11 +7,13 @@ set(VCL_zip_names "Vanilla_1_17_1.zip" "Vanilla_1_18_2.zip" "Vanilla_1_19_3.zip" - "Vanilla_1_20_4.zip") + "Vanilla_1_20_6.zip" + "Vanilla_1_21_1.zip" +) #https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/Vanilla_1_20_1.zip set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") -foreach (mcver RANGE 12 20) +foreach (mcver RANGE 12 21) math(EXPR VCL_resource_idx "${mcver} - 12") # message(STATUS "VCL_resource_idx = ${VCL_resource_idx}") @@ -36,4 +38,4 @@ foreach (mcver RANGE 12 20) else () message(FATAL_ERROR "Failed to download resource pack for MC${mcver} from ${VCL_current_download_url}.") endif () -endforeach (mcver RANGE 12 20) \ No newline at end of file +endforeach (mcver RANGE 12 21) \ No newline at end of file diff --git a/vccl/vccl-config-to-bin-dir.json.in b/vccl/vccl-config-to-bin-dir.json.in index d337204e..0221ff4a 100644 --- a/vccl/vccl-config-to-bin-dir.json.in +++ b/vccl/vccl-config-to-bin-dir.json.in @@ -35,6 +35,10 @@ [ 20, "@VCL_resource_20@" + ], + [ + 21, + "@VCL_resource_21@" ] ], "default_block_state_list": [ diff --git a/vccl/vccl-config.json b/vccl/vccl-config.json index d85e9927..07599109 100644 --- a/vccl/vccl-config.json +++ b/vccl/vccl-config.json @@ -34,7 +34,11 @@ ], [ 20, - "./Blocks_VCL/Vanilla_1_20_4.zip" + "./Blocks_VCL/Vanilla_1_20_6.zip" + ], + [ + 21, + "./Blocks_VCL/Vanilla_1_21_1.zip" ] ], "default_block_state_list": [ diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 9c67526f..6f80d992 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -62,7 +62,7 @@ int main(int argc, char **argv) { int __version; app.add_option("--mcver", __version, "MC version") ->default_val(19) - ->check(CLI::Range(12, 20, "Avaliable versions")); + ->check(CLI::Range(12, 21, "Avaliable versions")); app.add_option("--layers,--layer", input.layers, "Max layers") ->default_val(1) @@ -90,7 +90,7 @@ int main(int argc, char **argv) { "conversion") ->default_val(false); app.add_flag("--show-num-color,--snc", input.show_color_num, - "Show the number of colos") + "Show the number of colors") ->default_val(false); // images From 0623ce1aa96b5fa1b7889788190e605bcf9e9404 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 13:04:51 +0800 Subject: [PATCH 0921/1123] fix bad error handling in VCL Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 8 +- VisualCraftL/ParseResourcePack.h | 14 +-- VisualCraftL/ParseResourcePack_json.cpp | 56 ++++------ VisualCraftL/ParseResourcePack_png.cpp | 142 +++++++++++------------- VisualCraftL/TokiVC.cpp | 19 ++-- VisualCraftL/VisualCraftL.cpp | 12 +- 6 files changed, 109 insertions(+), 142 deletions(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index e78e2acb..7ce0bade 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -192,13 +192,13 @@ std::optional parse_block(const nlohmann::json &jo) { } bool _ok = true; - const VCL_face_t f = - string_to_face_idx(ja.at(i).get(), &_ok); - if (!_ok) { + const std::optional f = + string_to_face_idx(ja.at(i).get()); + if (not f) { return std::nullopt; } - ret.set_face_avaliablity(f, true); + ret.set_face_avaliablity(f.value(), true); } } else { return std::nullopt; diff --git a/VisualCraftL/ParseResourcePack.h b/VisualCraftL/ParseResourcePack.h index fefe97df..8e136266 100644 --- a/VisualCraftL/ParseResourcePack.h +++ b/VisualCraftL/ParseResourcePack.h @@ -427,8 +427,8 @@ class model { } // namespace block_model -std::array compute_mean_color( - const block_model::EImgRowMajor_t &img, bool *const ok = nullptr) noexcept; +std::optional> compute_mean_color( + const block_model::EImgRowMajor_t &img) noexcept; bool compose_image_background_half_transparent( block_model::EImgRowMajor_t &frontend_and_dest, @@ -558,8 +558,8 @@ bool parse_block_state( } // namespace resource_json -block_model::face_idx string_to_face_idx(std::string_view str, - bool *const _ok) noexcept; +std::optional string_to_face_idx( + std::string_view str) noexcept; const char *face_idx_to_string(block_model::face_idx) noexcept; struct model_with_rotation { @@ -614,14 +614,14 @@ class VCL_resource_pack { bool add_textures(const zipped_folder &resourece_pack_root, const bool on_conflict_replace_old = true) noexcept; - bool add_block_models(const zipped_folder &resourece_pack_root, + bool add_block_models(const zipped_folder &resource_pack_root, const bool on_conflict_replace_old = true) noexcept; bool add_block_states(const zipped_folder &resourece_pack_root, const bool on_conflict_replace_old = true) noexcept; - const Eigen::Array - *find_texture(std::string_view path, bool override_only) const noexcept; + const Eigen::Array * + find_texture(std::string_view path, bool override_only) const noexcept; bool override_required_textures(VCL_biome_t biome, bool replace_transparent_with_black, diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index 0dbe2f9e..733207e7 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -163,8 +163,6 @@ bool resource_json::multipart_pair::match(const state_list &sl) const noexcept { } else { return counter >= when_or.components.size(); } - - return false; } model_pass_t block_states_variant::block_model_name( @@ -471,7 +469,6 @@ std::vector parse_multipart_apply(const njson &apply) noexcept( return ret; } throw std::runtime_error("Invalid value for \"apply\" in a multipart."); - return {}; } std::variant @@ -638,43 +635,31 @@ struct block_model_json_temp { bool is_inherited{false}; }; -block_model::face_idx string_to_face_idx(std::string_view str, - bool *const _ok) noexcept { - block_model::face_idx res = block_model::face_idx::face_down; - bool ok = false; +std::optional string_to_face_idx( + std::string_view str) noexcept { if (str == "up") { - res = block_model::face_idx::face_up; - ok = true; + return block_model::face_idx::face_up; } if (str == "down") { - res = block_model::face_idx::face_down; - ok = true; + return block_model::face_idx::face_down; } if (str == "bottom") { - res = block_model::face_idx::face_down; - ok = true; + return block_model::face_idx::face_down; } if (str == "north") { - res = block_model::face_idx::face_north; - ok = true; + return block_model::face_idx::face_north; } if (str == "south") { - res = block_model::face_idx::face_south; - ok = true; + return block_model::face_idx::face_south; } if (str == "east") { - res = block_model::face_idx::face_east; - ok = true; + return block_model::face_idx::face_east; } if (str == "west") { - res = block_model::face_idx::face_west; - ok = true; + return block_model::face_idx::face_west; } - if (_ok != nullptr) { - *_ok = ok; - } - return res; + return std::nullopt; } const char *face_idx_to_string(block_model::face_idx f) noexcept { @@ -809,9 +794,8 @@ bool parse_single_model_json(const char *const json_beg, face_json_temp f; block_model::face_idx fidx; { - bool _ok; - fidx = string_to_face_idx(temp.key(), &_ok); - if (!_ok) { + auto fidx_opt = string_to_face_idx(temp.key()); + if (not fidx_opt) { std::string msg = fmt::format( "Error while parsing block model json : invalid key {} " "doesn't refer to any face.", @@ -819,6 +803,7 @@ bool parse_single_model_json(const char *const json_beg, ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } + fidx = fidx_opt.value(); } const njson &curface = temp.value(); @@ -847,18 +832,15 @@ bool parse_single_model_json(const char *const json_beg, } if (!cullface_temp.empty()) { - bool ok; - const block_model::face_idx cullface_fidx = - string_to_face_idx(cullface_temp, &ok); + auto cullface_fidx = string_to_face_idx(cullface_temp); - if (!ok) { + if (not cullface_fidx) { std::string msg = fmt::format("Invalid value for cullface : {}", cullface_temp); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } - - f.cullface_face = cullface_fidx; + f.cullface_face = cullface_fidx.value(); f.have_cullface = true; } } @@ -1046,12 +1028,12 @@ bool inherit_recrusively(std::string_view childname, } bool resource_pack::add_block_models( - const zipped_folder &resourece_pack_root, + const zipped_folder &resource_pack_root, const bool on_conflict_replace_old) noexcept { - const std::unordered_map *files = nullptr; + const std::unordered_map *files; // find assets/minecraft/models/block { - const zipped_folder *temp = resourece_pack_root.subfolder("assets"); + const zipped_folder *temp = resource_pack_root.subfolder("assets"); if (temp == nullptr) return false; temp = temp->subfolder("minecraft"); if (temp == nullptr) return false; diff --git a/VisualCraftL/ParseResourcePack_png.cpp b/VisualCraftL/ParseResourcePack_png.cpp index 51d02e25..8cbd4cc5 100644 --- a/VisualCraftL/ParseResourcePack_png.cpp +++ b/VisualCraftL/ParseResourcePack_png.cpp @@ -99,49 +99,48 @@ bool parse_png( if (bit_depth > 8) { png_set_strip_16(png); } - if (bit_depth < 8) - png_set_expand(png); + if (bit_depth < 8) png_set_expand(png); switch (color_type) { - case PNG_COLOR_TYPE_GRAY: // fixed - png_set_gray_to_rgb(png); - add_alpha = true; - // cout << "PNG_COLOR_TYPE_GRAY"; - break; - case PNG_COLOR_TYPE_PALETTE: // fixed - - png_set_palette_to_rgb(png); - png_set_bgr(png); - { - int num_trans = 0; - png_get_tRNS(png, info, NULL, &num_trans, NULL); - if (num_trans <= 0) { - add_alpha = true; + case PNG_COLOR_TYPE_GRAY: // fixed + png_set_gray_to_rgb(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_GRAY"; + break; + case PNG_COLOR_TYPE_PALETTE: // fixed + + png_set_palette_to_rgb(png); + png_set_bgr(png); + { + int num_trans = 0; + png_get_tRNS(png, info, NULL, &num_trans, NULL); + if (num_trans <= 0) { + add_alpha = true; + } + // cout << "num_trans = " << num_trans << endl; } - // cout << "num_trans = " << num_trans << endl; - } - // cout << "PNG_COLOR_TYPE_PALETTE"; - break; - case PNG_COLOR_TYPE_RGB: // fixed - png_set_bgr(png); - add_alpha = true; - // cout << "PNG_COLOR_TYPE_RGB"; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: // fixed - png_set_bgr(png); - // cout << "PNG_COLOR_TYPE_RGB_ALPHA"; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: // fixed - png_set_gray_to_rgb(png); - // png_set_swap_alpha(png); - // cout << "PNG_COLOR_TYPE_GRAY_ALPHA"; - break; - default: - png_destroy_read_struct(&png, &info, &info_end); - std::string msg = fmt::format("Unknown color type {}", color_type); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; + // cout << "PNG_COLOR_TYPE_PALETTE"; + break; + case PNG_COLOR_TYPE_RGB: // fixed + png_set_bgr(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_RGB"; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: // fixed + png_set_bgr(png); + // cout << "PNG_COLOR_TYPE_RGB_ALPHA"; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: // fixed + png_set_gray_to_rgb(png); + // png_set_swap_alpha(png); + // cout << "PNG_COLOR_TYPE_GRAY_ALPHA"; + break; + default: + png_destroy_read_struct(&png, &info, &info_end); + std::string msg = fmt::format("Unknown color type {}", color_type); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; } // cout << ")\n"; // #warning here @@ -157,7 +156,7 @@ bool parse_png( png_read_image(png, row_ptrs.data()); - if (add_alpha) { // add alpha manually + if (add_alpha) { // add alpha manually for (int r = 0; r < int(height); r++) { uint8_t *const data = reinterpret_cast(&(*img)(r, 0)); for (int pixel_idx = img->cols() - 1; pixel_idx > 0; pixel_idx--) { @@ -185,8 +184,7 @@ resize_image_nearest(const Eigen::Array result(0, 0); - if (rows <= 0 || cols <= 0 || src.size() <= 0) - return result; + if (rows <= 0 || cols <= 0 || src.size() <= 0) return result; result.resize(rows, cols); result.setZero(); @@ -211,8 +209,7 @@ resize_image_nearest( int rows, int cols) noexcept { Eigen::Array result(0, 0); - if (rows <= 0 || cols <= 0 || src_block.size() <= 0) - return result; + if (rows <= 0 || cols <= 0 || src_block.size() <= 0) return result; result.resize(rows, cols); result.setZero(); @@ -253,7 +250,6 @@ bool resource_pack::add_colormaps(const zipped_folder &rpr) noexcept { bool resource_pack::add_textures(const zipped_folder &rpr, const bool conflict_conver_old) noexcept { - const zipped_folder *const assets = rpr.subfolder("assets"); if (assets == nullptr) { ::VCL_report(VCL_report_type_t::error, @@ -312,8 +308,7 @@ bool resource_pack::add_textures_direct( std::array buffer; for (const auto &file : pngs) { - if (!file.first.ends_with(".png")) - continue; + if (!file.first.ends_with(".png")) continue; const bool is_dynamic = pngs.contains(file.first + ".mcmeta"); @@ -350,10 +345,10 @@ bool resource_pack::add_textures_direct( const bool success = parse_png(file.second.data(), file.second.file_size(), &img); if (!success || img.size() <= 0) { - std::string msg = - fmt::format("Failed to parse png file {} in {}. Png parsing will " - "continue but this warning may cause further errors.", - file.first, buffer.data()); + std::string msg = fmt::format( + "Failed to parse png file {} in {}. Png parsing will " + "continue but this warning may cause further errors.", + file.first, buffer.data()); ::VCL_report(VCL_report_type_t::warning, msg.c_str()); continue; } @@ -433,10 +428,10 @@ bool resource_pack::add_colormap(const zipped_folder &resourece_pack_root, } if (ptr == nullptr || !ptr->files.contains(filename.data())) { - std::string msg = - fmt::format("Failed to find \"assets/minecraft/textures/colormap/{}\". " - "File doesn\'t exist.", - filename); + std::string msg = fmt::format( + "Failed to find \"assets/minecraft/textures/colormap/{}\". " + "File doesn\'t exist.", + filename); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -455,10 +450,10 @@ bool resource_pack::add_colormap(const zipped_folder &resourece_pack_root, } if (img.rows() != 256 || img.cols() != 256) { - std::string msg = - fmt::format("Failed to parse assets/minecraft/textures/colormap/{}. " - "The rows({}) and cols({}) mismatch with (256,256).", - filename, img.rows(), img.cols()); + std::string msg = fmt::format( + "Failed to parse assets/minecraft/textures/colormap/{}. " + "The rows({}) and cols({}) mismatch with (256,256).", + filename, img.rows(), img.cols()); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -488,15 +483,10 @@ resource_pack::find_texture(std::string_view path, return nullptr; } -std::array -compute_mean_color(const block_model::EImgRowMajor_t &img, - bool *const ok) noexcept { +std::optional> compute_mean_color( + const block_model::EImgRowMajor_t &img) noexcept { if (img.size() <= 0) { - if (ok != nullptr) { - *ok = false; - } - - return {0, 0, 0}; + return std::nullopt; } std::array val{0, 0, 0}; @@ -515,11 +505,6 @@ compute_mean_color(const block_model::EImgRowMajor_t &img, val[i] /= img.size(); ret[i] = val[i] & 0xFF; } - - if (ok != nullptr) { - *ok = true; - } - return ret; } @@ -544,19 +529,16 @@ bool compose_image_background_half_transparent( return true; } -std::array -compose_image_and_mean(const block_model::EImgRowMajor_t &front, - const block_model::EImgRowMajor_t &back, - bool *const ok) noexcept { +std::array compose_image_and_mean( + const block_model::EImgRowMajor_t &front, + const block_model::EImgRowMajor_t &back, bool *const ok) noexcept { if (front.rows() != back.rows() || front.cols() != back.cols()) { - if (ok != nullptr) - *ok = false; + if (ok != nullptr) *ok = false; return {}; } if (front.size() <= 0) { - if (ok != nullptr) - *ok = false; + if (ok != nullptr) *ok = false; return {}; } diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 2a87d52a..0db8dbff 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -23,7 +23,6 @@ This file is part of SlopeCraft. #include "TokiVC.h" #include "VCL_internal.h" -#include #include #include #include @@ -137,13 +136,14 @@ bool add_color_non_transparent( const std::vector &bs_nontransparent, mutlihash_color_blocks &map_color_blocks) noexcept { for (VCL_block *blkp : bs_nontransparent) { - bool ok = true; - auto ret = compute_mean_color(blkp->project_image_on_exposed_face, &ok); - if (!ok) { + auto ret = compute_mean_color(blkp->project_image_on_exposed_face); + if (not ret) { return false; } + auto mean_color = ret.value(); - map_color_blocks.emplace(ARGB32(ret[0], ret[1], ret[2]), blkp); + map_color_blocks.emplace( + ARGB32(mean_color[0], mean_color[1], mean_color[2]), blkp); // temp_rgb_rowmajor.emplace_back(ret); // LUT_bcitb.emplace_back(blkp); @@ -209,19 +209,18 @@ bool add_color_trans_to_trans_recurs( min_alpha = std::min(min_alpha, getA(front(i))); } - // if multiple transparent block composed a non transparent image, then the + // if multiple transparent block composed a non-transparent image, then the // recursion terminate. if (min_alpha >= 255) { - bool ok = true; - std::array mean = compute_mean_color(front, &ok); + auto mean_opt = compute_mean_color(front); - if (!ok) { + if (not mean_opt) { VCL_report(VCL_report_type_t::error, "Function add_color_trans_to_trans_recurs failed to " "compute mean color.\n"); return false; } - + auto &mean = mean_opt.value(); map_color_blocks.emplace(ARGB32(mean[0], mean[1], mean[2]), accumulate_blocks); // LUT_bcitb.emplace_back(accumulate_blocks); diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 09da1306..02213b69 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -677,13 +677,13 @@ VCL_EXPORT_FUN size_t VCL_get_blocks_from_block_state_list_match_const( size_t write_counter = 0; const bool can_write = - (array_of_const_VCL_block != nullptr) && (array_capcity > 0); + (array_of_const_VCL_block not_eq nullptr) and (array_capcity > 0); for (const auto &pair : bsl->block_states()) { if (pair.second.match(version, f)) { available_block_counter++; - if (can_write && (write_counter < array_capcity)) { + if (can_write and (write_counter < array_capcity)) { array_of_const_VCL_block[write_counter] = &pair.second; write_counter++; } @@ -712,7 +712,11 @@ VCL_EXPORT_FUN const char *VCL_face_t_to_str(VCL_face_t f) { } VCL_EXPORT_FUN VCL_face_t VCL_str_to_face_t(const char *str, bool *ok) { - return string_to_face_idx(str, ok); + auto res = string_to_face_idx(str); + if (ok not_eq nullptr) { + *ok = res.has_value(); + } + return res.value_or(VCL_face_t::face_up); } VCL_EXPORT_FUN bool VCL_get_block_attribute(const VCL_block *b, @@ -858,7 +862,7 @@ VCL_EXPORT_FUN bool VCL_compute_projection_image(const VCL_model *md, return false; } - auto img = mdptr->projection_image(face); + [[maybe_unused]] auto img = mdptr->projection_image(face); Eigen::Map map(img_buffer_argb32, 16, 16); From 1ac948e56bd357e92a2e77e67b849d0e97032bc9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 13:19:38 +0800 Subject: [PATCH 0922/1123] fix VCL to parse 1.21.1 Signed-off-by: ToKiNoBug --- VisualCraftL/ParseResourcePack_json.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index 733207e7..ce9178b9 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -1152,7 +1152,14 @@ bool resource_pack::add_block_models( ele.faces[faceidx].uv_end[0] = tface.uv[2]; ele.faces[faceidx].uv_end[1] = tface.uv[3]; + // try to find the image in texture/block auto imgptr = this->find_texture(tface.texture, false); + if (imgptr == nullptr) { // try to resolve the name of this texture + auto it = tmodel.second.textures.find(tface.texture); + if (it not_eq tmodel.second.textures.end()) { + imgptr = this->find_texture(it->second, false); + } + } if (imgptr == nullptr) { if (tface.texture.starts_with('#') && tmodel.second.is_inherited) { @@ -1161,7 +1168,7 @@ bool resource_pack::add_block_models( continue; } std::string msg = fmt::format( - "Undefined reference to texture {}, required by " + "Undefined reference to texture \"{}\", required by " "model {} but no such image.\nThe textures are : \n", tface.texture, tmodel.first); for (const auto &pair : tmodel.second.textures) { From bed79be5c3bfd07bac8399309acee17f5013a592 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 13:22:06 +0800 Subject: [PATCH 0923/1123] add radio button for 1.21 Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 3 ++ VisualCraft/VCWind.ui | 80 ++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 7c2dc127..b24ff011 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -139,6 +139,9 @@ SCL_gameVersion VCWind::current_selected_version() const noexcept { if (ui->rdb_version_20->isChecked()) { return SCL_gameVersion::MC20; } + if (ui->rdb_version_21->isChecked()) { + return SCL_gameVersion::MC21; + } abort(); } diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 7152960b..ed62b423 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -3,14 +3,14 @@ VCWind - Qt::NonModal + Qt::WindowModality::NonModal 0 0 1057 - 479 + 490 @@ -29,7 +29,7 @@ 0 - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTop|Qt::AlignmentFlag::AlignTrailing @@ -43,16 +43,16 @@
- QTabWidget::North + QTabWidget::TabPosition::North - QTabWidget::Rounded + QTabWidget::TabShape::Rounded 0 - Qt::ElideNone + Qt::TextElideMode::ElideNone @@ -62,7 +62,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -112,7 +112,7 @@ 1.19 - true + false @@ -142,6 +142,16 @@ 1.20 + + true + + + + + + + 1.21 + @@ -195,10 +205,10 @@ true - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection @@ -207,13 +217,13 @@ - QListView::Snap + QListView::Movement::Snap - QListView::Batched + QListView::LayoutMode::Batched - QListView::ListMode + QListView::ViewMode::ListMode true @@ -252,19 +262,19 @@ - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QListView::Snap + QListView::Movement::Snap - QListView::Batched + QListView::LayoutMode::Batched - QListView::ListMode + QListView::ViewMode::ListMode true @@ -307,7 +317,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -381,7 +391,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -447,8 +457,8 @@ 0 0 - 98 - 28 + 885 + 305 @@ -468,7 +478,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -481,7 +491,7 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel @@ -588,13 +598,13 @@ true - QAbstractItemView::DropOnly + QAbstractItemView::DragDropMode::DropOnly - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QListView::Static + QListView::Movement::Static false @@ -613,7 +623,7 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel @@ -663,7 +673,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -839,7 +849,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1011,7 +1021,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1102,10 +1112,10 @@ - QAbstractItemView::SingleSelection + QAbstractItemView::SelectionMode::SingleSelection - QAbstractItemView::SelectItems + QAbstractItemView::SelectionBehavior::SelectItems true @@ -1132,7 +1142,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1191,7 +1201,7 @@ 0 0 1057 - 22 + 33 From b9a59617e16d81da039d6a32437b64e1275d161c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 13:23:06 +0800 Subject: [PATCH 0924/1123] add vccl test for 1.21 Signed-off-by: ToKiNoBug --- vccl/add_test_vccl.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vccl/add_test_vccl.cmake b/vccl/add_test_vccl.cmake index 208c7ef9..82de7436 100644 --- a/vccl/add_test_vccl.cmake +++ b/vccl/add_test_vccl.cmake @@ -42,7 +42,7 @@ endif () # set(dither "true" "false") foreach (_layers RANGE 1 3 1) - foreach (_ver RANGE 12 20) + foreach (_ver RANGE 12 21) set(VCL_current_var_name VCL_resource_${mcver}) set(zip_file ${VCL_current_var_name}) @@ -71,7 +71,7 @@ foreach (_layers RANGE 1 3 1) endforeach (_dither ${dither}) endforeach (_algo ${algos}) endforeach (_face ${list_faces}) - endforeach (_ver RANGE 12 20) + endforeach (_ver RANGE 12 21) endforeach (_layers RANGE 1 3 1) From 86415cb21665d1020e945a3a78ce04b5860e6b6f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 14:31:04 +0800 Subject: [PATCH 0925/1123] add copper stuffs to VCl block list Signed-off-by: ToKiNoBug --- VisualCraftL/VCL_blocks_fixed.json | 164 +++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 21 deletions(-) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 5a75b08b..76d937f4 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -250,6 +250,13 @@ "nameZH": "干草块", "version": "all" }, + "minecraft:crafting_table": { + "class": "crafted", + "nameEN": "Crafting table", + "nameZH": "工作台", + "version": "all", + "burnable": true + }, "minecraft:coarse_dirt": { "class": "desert", "endermanPickable": true, @@ -293,7 +300,7 @@ "minecraft:stained_glass[color=black]" ] ], - "nameEN": "Blakc glass", + "nameEN": "Black glass", "nameZH": "黑色染色玻璃", "transparent": true, "version": "all" @@ -532,7 +539,7 @@ "minecraft:leaves[variant=birch,check_decay=false,decayable=false]" ] ], - "nameEN": "Brich leaves", + "nameEN": "Birch leaves", "nameZH": "白桦树叶", "version": "all", "is_foliage": true @@ -1069,50 +1076,153 @@ "class": "ore", "nameEN": "Waxed copper", "nameZH": "涂蜡铜块", - "version": 17, - "rare": true + "version": 17 }, "minecraft:waxed_cut_copper": { "class": "ore", "nameEN": "Waxed cut copper", "nameZH": "涂蜡切制铜块", - "version": 17, - "rare": true + "version": 17 }, "minecraft:waxed_exposed_copper": { "class": "ore", "nameEN": "Waxed exposed copper", "nameZH": "涂蜡斑驳铜块", - "version": 17, - "rare": true + "version": 17 }, "minecraft:waxed_exposed_cut_copper": { "class": "ore", "nameEN": "Waxed exposed cut copper", "nameZH": "涂蜡切制斑驳铜块", - "version": 17, - "rare": true + "version": 17 + }, + "minecraft:waxed_weathered_copper": { + "class": "ore", + "nameEN": "Waxed weathered copper", + "nameZH": "涂蜡生锈铜块", + "version": 17 + }, + "minecraft:waxed_weathered_cut_copper": { + "class": "ore", + "nameEN": "Waxed weathered cut copper", + "nameZH": "涂蜡切制生锈铜块", + "version": 17 }, "minecraft:waxed_oxidized_copper": { "class": "ore", - "nameEN": "Waxed oxided copper", + "nameEN": "Waxed oxidized copper", "nameZH": "涂蜡氧化铜块", - "version": 17, - "rare": true + "version": 17 }, "minecraft:waxed_oxidized_cut_copper": { "class": "ore", - "nameEN": "Waxed oxided cut copper", + "nameEN": "Waxed oxidized cut copper", "nameZH": "涂蜡切制氧化铜块", - "version": 17, - "rare": true + "version": 17 }, - "minecraft:waxed_weathered_copper": { + "minecraft:waxed_chiseled_copper": { "class": "ore", - "nameEN": "Waxed weathered copper", - "nameZH": "涂蜡生锈铜块", - "version": 17, - "rare": true + "nameEN": "Waxed chiseled copper", + "nameZH": "涂蜡雕纹铜块", + "version": 21 + }, + "minecraft:waxed_exposed_chiseled_copper": { + "class": "ore", + "nameEN": "Waxed exposed chiseled copper", + "nameZH": "涂蜡斑驳雕纹铜块", + "version": 21 + }, + "minecraft:waxed_weathered_chiseled_copper": { + "class": "ore", + "nameEN": "Waxed weathered chiseled copper", + "nameZH": "涂蜡生锈雕纹铜块", + "version": 21 + }, + "minecraft:waxed_oxidized_chiseled_copper": { + "class": "ore", + "nameEN": "Waxed oxidized chiseled copper", + "nameZH": "涂蜡氧化雕纹铜块", + "version": 21 + }, + "minecraft:waxed_copper_grate": { + "class": "ore", + "nameEN": "Waxed copper grate", + "nameZH": "涂蜡铜格栅", + "version": 21, + "transparent": true + }, + "minecraft:waxed_exposed_copper_grate": { + "class": "ore", + "nameEN": "Waxed exposed copper grate", + "nameZH": "涂蜡斑驳铜格栅", + "version": 21, + "transparent": true + }, + "minecraft:waxed_weathered_copper_grate": { + "class": "ore", + "nameEN": "Waxed weathered copper grate", + "nameZH": "涂蜡生锈铜格栅", + "version": 21, + "transparent": true + }, + "minecraft:waxed_oxidized_copper_grate": { + "class": "ore", + "nameEN": "Waxed oxidized copper grate", + "nameZH": "涂蜡氧化铜格栅", + "version": 21, + "transparent": true + }, + "minecraft:waxed_copper_bulb[lit=false,powered=false]": { + "class": "ore", + "nameEN": "Waxed copper bulb", + "nameZH": "涂蜡铜灯", + "version": 21 + }, + "minecraft:waxed_copper_bulb[lit=true,powered=false]": { + "class": "ore", + "nameEN": "Waxed copper bulb(lit)", + "nameZH": "涂蜡铜灯(点亮)", + "version": 21, + "isGlowing": true + }, + "minecraft:waxed_exposed_copper_bulb[lit=false,powered=false]": { + "class": "ore", + "nameEN": "Waxed exposed copper bulb", + "nameZH": "涂蜡斑驳铜灯", + "version": 21 + }, + "minecraft:waxed_exposed_copper_bulb[lit=true,powered=false]": { + "class": "ore", + "nameEN": "Waxed exposed copper bulb(lit)", + "nameZH": "涂蜡斑驳铜灯(点亮)", + "version": 21, + "isGlowing": true + }, + "minecraft:waxed_weathered_copper_bulb[lit=false,powered=false]": { + "class": "ore", + "nameEN": "Waxed weathered copper bulb", + "nameZH": "涂蜡生锈铜灯", + "version": 21 + }, + "minecraft:waxed_weathered_copper_bulb[lit=true,powered=false]": { + "class": "ore", + "nameEN": "Waxed weathered copper bulb(lit)", + "nameZH": "涂蜡生锈铜灯(点亮)", + "version": 21, + "isGlowing": true + }, + "minecraft:waxed_oxidized_copper_bulb[lit=false,powered=false]": { + "class": "ore", + "nameEN": "Waxed oxidized copper bulb", + "nameZH": "涂蜡氧化铜灯", + "version": 21 + }, + "minecraft:waxed_oxidized_copper_bulb[lit=true,powered=false]": { + "class": "ore", + "nameEN": "Waxed oxidized copper bulb(lit)", + "nameZH": "涂蜡氧化铜灯(点亮)", + "version": 21, + "isGlowing": true }, "minecraft:gilded_blackstone": { "class": "ore", @@ -1892,6 +2002,18 @@ "version": 17, "reproducible": false }, + "minecraft:tuff_bricks": { + "class": "stone", + "nameEN": "Tuff bricks", + "nameZH": "凝灰岩砖", + "version": 21 + }, + "minecraft:chiseled_tuff_bricks": { + "class": "stone", + "nameEN": "Chiseled tuff bricks", + "nameZH": "雕纹凝灰岩砖", + "version": 21 + }, "minecraft:calcite": { "class": "stone", "nameEN": "Calcite", From 65ea33e465e4cf2e1e8cf0cc4b014a39bb4e56ab Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 14:33:01 +0800 Subject: [PATCH 0926/1123] fix linux build Signed-off-by: ToKiNoBug --- VisualCraftL/ParseResourcePack.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/VisualCraftL/ParseResourcePack.h b/VisualCraftL/ParseResourcePack.h index 8e136266..5555ca38 100644 --- a/VisualCraftL/ParseResourcePack.h +++ b/VisualCraftL/ParseResourcePack.h @@ -23,13 +23,14 @@ This file is part of SlopeCraft. #ifndef SLOPECRAFT_VISUALCRAFTL_PARSERESOURCEPACK_H #define SLOPECRAFT_VISUALCRAFTL_PARSERESOURCEPACK_H -#include - -#include #include #include #include #include +#include + +#include +#include #include "Resource_tree.h" #include "VisualCraftL.h" From c62cbfc62d719e93cd3eab779501a0a64dcdd076 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 15:19:22 +0800 Subject: [PATCH 0927/1123] add smiting table, cartography table, fletching table, lodestone, composter, note block, 3 furnaces, 2 bee hives Signed-off-by: ToKiNoBug --- VisualCraftL/VCL_blocks_fixed.json | 262 +++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 76d937f4..67a003bc 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -257,6 +257,226 @@ "version": "all", "burnable": true }, + "minecraft:cartography_table": { + "class": "crafted", + "nameEN": "Cartography table", + "nameZH": "制图台", + "version": 14, + "burnable": true + }, + "minecraft:fletching_table": { + "class": "crafted", + "nameEN": "Fletching table", + "nameZH": "制箭台", + "version": 14, + "burnable": true + }, + "minecraft:smithing_table": { + "class": "crafted", + "nameEN": "Smithing table", + "nameZH": "锻造台", + "version": 14, + "burnable": true + }, + "minecraft:lodestone": { + "class": "crafted", + "nameEN": "Lodestone", + "nameZH": "磁石", + "version": 16, + "rare": true + }, + "minecraft:composter[level=0]": { + "class": "crafted", + "nameEN": "Composter", + "nameZH": "堆肥桶", + "version": 14, + "burnable": true + }, + "minecraft:note_block[note=0,powered=false]": { + "class": "crafted", + "nameEN": "Note block", + "nameZH": "音符盒", + "version": 14, + "burnable": true + }, + "minecraft:loom[facing=north]": { + "class": "crafted", + "nameEN": "Loom(north)", + "nameZH": "织布机(向北)", + "version": 14, + "burnable": true + }, + "minecraft:loom[facing=east]": { + "class": "crafted", + "nameEN": "Loom(east)", + "nameZH": "织布机(向东)", + "version": 14, + "burnable": true, + "faces": [ + "east", + "north" + ] + }, + "minecraft:loom[facing=south]": { + "class": "crafted", + "nameEN": "Loom(south)", + "nameZH": "织布机(向南)", + "version": 14, + "burnable": true, + "faces": [ + "south" + ] + }, + "minecraft:loom[facing=west]": { + "class": "crafted", + "nameEN": "Loom(west)", + "nameZH": "织布机(向西)", + "version": 14, + "burnable": true, + "faces": [ + "west" + ] + }, + "minecraft:smoker[facing=north,lit=false]": { + "class": "crafted", + "nameEN": "Smoker(north)", + "nameZH": "烟熏炉(向北)", + "version": 14 + }, + "minecraft:smoker[facing=east,lit=false]": { + "class": "crafted", + "nameEN": "Smoker(east)", + "nameZH": "烟熏炉(向东)", + "version": 14, + "faces": [ + "east", + "north" + ] + }, + "minecraft:smoker[facing=south,lit=false]": { + "class": "crafted", + "nameEN": "Smoker(south)", + "nameZH": "烟熏炉(向南)", + "version": 14, + "faces": [ + "south" + ] + }, + "minecraft:smoker[facing=west,lit=false]": { + "class": "crafted", + "nameEN": "Smoker(west)", + "nameZH": "烟熏炉(向西)", + "version": 14, + "faces": [ + "west" + ] + }, + "minecraft:furnace[facing=north,lit=false]": { + "class": "crafted", + "nameEN": "Furnace(north)", + "nameZH": "熔炉(向北)", + "version": "all" + }, + "minecraft:furnace[facing=east,lit=false]": { + "class": "crafted", + "nameEN": "Furnace(east)", + "nameZH": "熔炉(向东)", + "version": "all", + "faces": [ + "east", + "north" + ] + }, + "minecraft:furnace[facing=south,lit=false]": { + "class": "crafted", + "nameEN": "Furnace(south)", + "nameZH": "熔炉(向南)", + "version": "all", + "faces": [ + "south" + ] + }, + "minecraft:furnace[facing=west,lit=false]": { + "class": "crafted", + "nameEN": "Furnace(west)", + "nameZH": "熔炉(向西)", + "version": "all", + "faces": [ + "west" + ] + }, + "minecraft:blast_furnace[facing=north,lit=false]": { + "class": "crafted", + "nameEN": "Blast furnace(north)", + "nameZH": "高炉(向北)", + "version": 14 + }, + "minecraft:blast_furnace[facing=east,lit=false]": { + "class": "crafted", + "nameEN": "Blast furnace(east)", + "nameZH": "高炉(向东)", + "version": 14, + "faces": [ + "east", + "north" + ] + }, + "minecraft:blast_furnace[facing=south,lit=false]": { + "class": "crafted", + "nameEN": "Blast furnace(south)", + "nameZH": "高炉(向南)", + "version": 14, + "faces": [ + "south" + ] + }, + "minecraft:blast_furnace[facing=west,lit=false]": { + "class": "crafted", + "nameEN": "Blast furnace(west)", + "nameZH": "高炉(向西)", + "version": 14, + "faces": [ + "west" + ] + }, + "minecraft:beehive[facing=north,honey_level=0]": { + "class": "crafted", + "nameEN": "Bee hive(north)", + "nameZH": "蜂箱(向北)", + "version": 14, + "burnable": true + }, + "minecraft:beehive[facing=east,honey_level=0]": { + "class": "crafted", + "nameEN": "Bee hive(east)", + "nameZH": "蜂箱(向东)", + "version": 14, + "burnable": true, + "faces": [ + "east", + "north" + ] + }, + "minecraft:beehive[facing=south,honey_level=0]": { + "class": "crafted", + "nameEN": "Bee hive(south)", + "nameZH": "蜂箱(向南)", + "version": 14, + "burnable": true, + "faces": [ + "south" + ] + }, + "minecraft:beehive[facing=west,honey_level=0]": { + "class": "crafted", + "nameEN": "Bee hive(west)", + "nameZH": "蜂箱(向西)", + "version": 14, + "burnable": true, + "faces": [ + "west" + ] + }, "minecraft:coarse_dirt": { "class": "desert", "endermanPickable": true, @@ -855,6 +1075,48 @@ "version": 19, "rare": true }, + "minecraft:bee_nest[facing=north,honey_level=0]": { + "class": "natural", + "nameEN": "Bee nest(north)", + "nameZH": "蜂巢(向北)", + "version": 14, + "burnable": true, + "reproducible": false + }, + "minecraft:bee_nest[facing=east,honey_level=0]": { + "class": "natural", + "nameEN": "Bee nest(east)", + "nameZH": "蜂巢(向东)", + "version": 14, + "burnable": true, + "faces": [ + "east", + "north" + ], + "reproducible": false + }, + "minecraft:bee_nest[facing=south,honey_level=0]": { + "class": "natural", + "nameEN": "Bee nest(south)", + "nameZH": "蜂巢(向南)", + "version": 14, + "burnable": true, + "faces": [ + "south" + ], + "reproducible": false + }, + "minecraft:bee_nest[facing=west,honey_level=0]": { + "class": "natural", + "nameEN": "Bee nest(west)", + "nameZH": "蜂巢(向西)", + "version": 14, + "burnable": true, + "faces": [ + "west" + ], + "reproducible": false + }, "minecraft:crimson_nylium": { "class": "nether", "endermanPickable": true, From ed1fcb1c92fe9f3ff603608fa00e25012c418f76 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 15:41:43 +0800 Subject: [PATCH 0928/1123] add crafter Signed-off-by: ToKiNoBug --- VisualCraftL/VCL_blocks_fixed.json | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index 67a003bc..dc45574d 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -477,6 +477,119 @@ "west" ] }, + "minecraft:crafter[crafting=false,triggered=false,orientation=up_north]": { + "class": "crafted", + "nameEN": "Crafter(up north)", + "nameZH": "合成器(正面向上,顶面向北)", + "version": 21, + "faces": [ + "up", + "down", + "north", + "south" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=up_west]": { + "class": "crafted", + "nameEN": "Crafter(up west)", + "nameZH": "合成器(正面向上,顶面向西)", + "version": 21, + "faces": [ + "north", + "south", + "east", + "west" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=up_south]": { + "class": "crafted", + "nameEN": "Crafter(up south)", + "nameZH": "合成器(正面向上,顶面向南)", + "version": 21, + "faces": [ + "north", + "south" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=up_east]": { + "class": "crafted", + "nameEN": "Crafter(up east)", + "nameZH": "合成器(正面向上,顶面向东)", + "version": 21, + "faces": [ + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=south_up]": { + "class": "crafted", + "nameEN": "Crafter(south up)", + "nameZH": "合成器(正面向南,顶面向上)", + "version": 21, + "faces": [ + "up", + "down", + "north" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=east_up]": { + "class": "crafted", + "nameEN": "Crafter(east up)", + "nameZH": "合成器(正面向东,顶面向上)", + "version": 21, + "faces": [ + "east", + "west" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=north_up]": { + "class": "crafted", + "nameEN": "Crafter(north up)", + "nameZH": "合成器(正面向北,顶面向上)", + "version": 21, + "faces": [ + "south" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=west_up]": { + "class": "crafted", + "nameEN": "Crafter(west up)", + "nameZH": "合成器(正面向西,顶面向上)", + "version": 21, + "faces": [] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=down_south]": { + "class": "crafted", + "nameEN": "Crafter(down south)", + "nameZH": "合成器(正面向下,顶面向南)", + "version": 21, + "faces": [ + "up", + "down" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=down_east]": { + "class": "crafted", + "nameEN": "Crafter(down east)", + "nameZH": "合成器(正面向下,顶面向东)", + "version": 21, + "faces": [ + "east", + "west" + ] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=down_north]": { + "class": "crafted", + "nameEN": "Crafter(down north)", + "nameZH": "合成器(正面向下,顶面向北)", + "version": 21, + "faces": [] + }, + "minecraft:crafter[crafting=false,triggered=false,orientation=down_west]": { + "class": "crafted", + "nameEN": "Crafter(down west)", + "nameZH": "合成器(正面向下,顶面向西)", + "version": 21, + "faces": [] + }, "minecraft:coarse_dirt": { "class": "desert", "endermanPickable": true, From cc14c25f33cc313cbc85a18dfd592df456ca1220 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 15:57:34 +0800 Subject: [PATCH 0929/1123] try to fix windows-msvc build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 16 +++++++++++++++- cmake/required_deps/libnbt++.cmake | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index adc62ed7..9477d8f5 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -94,13 +94,27 @@ jobs: tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared + - name: Install libnbt++ + shell: cmd + run: | + cd 3rdParty + git clone https://github.com/PrismLauncher/libnbtplusplus + cd libnbtplusplus + git checkout 23b955121b8217c1c348a9ed2483167a6f3ff4ad + mkdir build ../libnbt++ + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="C:/vcpkg/installed/x64-windows" -DCMAKE_INSTALL_PREFIX:PATH=../libnbt++ -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DNBT_BUILD_SHARED=OFF -DNBT_USE_ZLIB=OFF -DNBT_BUILD_TESTS=OFF + cmake --build ./build --parallel + cmake --install ./build + cd .. + tree /f libnbt++ + - name: CMake configure shell: cmd run: | mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc - name: CMake build shell: cmd diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 60439d03..c0a089eb 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -2,6 +2,14 @@ cmake_minimum_required(VERSION 3.29) find_package(ZLIB REQUIRED) +find_package(libnbt++) + +if (libnbt++_FOUND) + message(STATUS "Found installed libnbt++") + return() +endif () + +message(STATUS "Failed to find libnbt++, cloning...") set(NBT_BUILD_SHARED OFF CACHE BOOL "") set(NBT_BUILD_TESTS OFF CACHE BOOL "") FetchContent_Declare(libnbt++ From d49fb0849ac8763f8a2a8fb5fc7ea01871fb5237 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:08:40 +0800 Subject: [PATCH 0930/1123] try to fix windows-msvc build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 9477d8f5..a39641a1 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -94,7 +94,7 @@ jobs: tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - - name: Install libnbt++ + - name: Configure libnbt++ shell: cmd run: | cd 3rdParty @@ -103,6 +103,12 @@ jobs: git checkout 23b955121b8217c1c348a9ed2483167a6f3ff4ad mkdir build ../libnbt++ "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="C:/vcpkg/installed/x64-windows" -DCMAKE_INSTALL_PREFIX:PATH=../libnbt++ -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DNBT_BUILD_SHARED=OFF -DNBT_USE_ZLIB=OFF -DNBT_BUILD_TESTS=OFF + + + - name: Build and install libnbt++ + shell: cmd + run: | + cd 3rdParty/libnbtplusplus cmake --build ./build --parallel cmake --install ./build cd .. From 3d7d51eac399f8383af5ffbf59b716802e444f92 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:19:48 +0800 Subject: [PATCH 0931/1123] try to fix windows-msvc build Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 38 ++++++++++++++--------------- cmake/required_deps/libnbt++.cmake | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a39641a1..c5f55a41 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -94,25 +94,25 @@ jobs: tree /f bin/Qt6.5.0-msvc-shared # Qt installation dir: bin/Qt6.5.0-msvc-shared - - name: Configure libnbt++ - shell: cmd - run: | - cd 3rdParty - git clone https://github.com/PrismLauncher/libnbtplusplus - cd libnbtplusplus - git checkout 23b955121b8217c1c348a9ed2483167a6f3ff4ad - mkdir build ../libnbt++ - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="C:/vcpkg/installed/x64-windows" -DCMAKE_INSTALL_PREFIX:PATH=../libnbt++ -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DNBT_BUILD_SHARED=OFF -DNBT_USE_ZLIB=OFF -DNBT_BUILD_TESTS=OFF - - - - name: Build and install libnbt++ - shell: cmd - run: | - cd 3rdParty/libnbtplusplus - cmake --build ./build --parallel - cmake --install ./build - cd .. - tree /f libnbt++ + # - name: Configure libnbt++ + # shell: cmd + # run: | + # cd 3rdParty + # git clone https://github.com/PrismLauncher/libnbtplusplus + # cd libnbtplusplus + # git checkout 23b955121b8217c1c348a9ed2483167a6f3ff4ad + # mkdir build ../libnbt++ + # "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="C:/vcpkg/installed/x64-windows" -DCMAKE_INSTALL_PREFIX:PATH=../libnbt++ -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DNBT_BUILD_SHARED=OFF -DNBT_USE_ZLIB=OFF -DNBT_BUILD_TESTS=OFF + # + # + # - name: Build and install libnbt++ + # shell: cmd + # run: | + # cd 3rdParty/libnbtplusplus + # cmake --build ./build --parallel + # cmake --install ./build + # cd .. + # tree /f libnbt++ - name: CMake configure shell: cmd diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index c0a089eb..5bd810d0 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -22,4 +22,4 @@ FetchContent_MakeAvailable(libnbt++) find_package(libnbt++ REQUIRED) target_link_libraries(nbt++ ZLIB::ZLIB) -target_compile_features(nbt++ PUBLIC cxx_std_23) \ No newline at end of file +target_compile_features(nbt++ PUBLIC cxx_std_20) \ No newline at end of file From 881fa9292f111074688e24ee47d08714d9fb903e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:28:07 +0800 Subject: [PATCH 0932/1123] try to fix windows-msvc build Signed-off-by: ToKiNoBug --- cmake/required_deps/libnbt++.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 5bd810d0..9dfca1a1 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -22,4 +22,7 @@ FetchContent_MakeAvailable(libnbt++) find_package(libnbt++ REQUIRED) target_link_libraries(nbt++ ZLIB::ZLIB) -target_compile_features(nbt++ PUBLIC cxx_std_20) \ No newline at end of file +target_compile_features(nbt++ PUBLIC cxx_std_20) +if (${MSVC}) + target_compile_options(nbt++ PRIVATE /std:c++20) +endif () \ No newline at end of file From 2b655328e15977c3cb0743bfc893afa43e6bd311 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:31:54 +0800 Subject: [PATCH 0933/1123] try to fix linux build Signed-off-by: ToKiNoBug --- utilities/sNBT_formatter/sNBT_formatter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utilities/sNBT_formatter/sNBT_formatter.cpp b/utilities/sNBT_formatter/sNBT_formatter.cpp index 7d792776..e003c816 100644 --- a/utilities/sNBT_formatter/sNBT_formatter.cpp +++ b/utilities/sNBT_formatter/sNBT_formatter.cpp @@ -90,7 +90,9 @@ void sNBT::sNBT_format_visitor::visit(const nbt::tag_compound &c) { } this->os << "{"; size_t idx = 0; - for (auto &[key, val] : c) { + for (const auto &pair : c) { + const auto &key = pair.first; + const auto &val = pair.second; if (key.contains(':')) { this->os << '\"' << key << '\"' << ':'; } else { From ffbb8591b83f2e8082153dcd6518e53381ab64e1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:41:17 +0800 Subject: [PATCH 0934/1123] try to fix mac and linux ci Signed-off-by: ToKiNoBug --- utilities/sNBT_formatter/sNBT_formatter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/sNBT_formatter/sNBT_formatter.cpp b/utilities/sNBT_formatter/sNBT_formatter.cpp index e003c816..7d9b0e39 100644 --- a/utilities/sNBT_formatter/sNBT_formatter.cpp +++ b/utilities/sNBT_formatter/sNBT_formatter.cpp @@ -93,7 +93,7 @@ void sNBT::sNBT_format_visitor::visit(const nbt::tag_compound &c) { for (const auto &pair : c) { const auto &key = pair.first; const auto &val = pair.second; - if (key.contains(':')) { + if (key.find(':') not_eq key.npos) { this->os << '\"' << key << '\"' << ':'; } else { this->os << key << ':'; From 0bfb1a24281407311329da55b9217895d810c61c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 16:58:16 +0800 Subject: [PATCH 0935/1123] fix bee nest and bee hive version Signed-off-by: ToKiNoBug --- VisualCraftL/VCL_blocks_fixed.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index dc45574d..a1724c27 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -443,14 +443,14 @@ "class": "crafted", "nameEN": "Bee hive(north)", "nameZH": "蜂箱(向北)", - "version": 14, + "version": 15, "burnable": true }, "minecraft:beehive[facing=east,honey_level=0]": { "class": "crafted", "nameEN": "Bee hive(east)", "nameZH": "蜂箱(向东)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "east", @@ -461,7 +461,7 @@ "class": "crafted", "nameEN": "Bee hive(south)", "nameZH": "蜂箱(向南)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "south" @@ -471,7 +471,7 @@ "class": "crafted", "nameEN": "Bee hive(west)", "nameZH": "蜂箱(向西)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "west" @@ -1192,7 +1192,7 @@ "class": "natural", "nameEN": "Bee nest(north)", "nameZH": "蜂巢(向北)", - "version": 14, + "version": 15, "burnable": true, "reproducible": false }, @@ -1200,7 +1200,7 @@ "class": "natural", "nameEN": "Bee nest(east)", "nameZH": "蜂巢(向东)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "east", @@ -1212,7 +1212,7 @@ "class": "natural", "nameEN": "Bee nest(south)", "nameZH": "蜂巢(向南)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "south" @@ -1223,7 +1223,7 @@ "class": "natural", "nameEN": "Bee nest(west)", "nameZH": "蜂巢(向西)", - "version": 14, + "version": 15, "burnable": true, "faces": [ "west" From 7d13c1c23d9e8329e64db5d255e67809df6cb52a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 17:58:47 +0800 Subject: [PATCH 0936/1123] support Java 1.21.1 and 1.20.6 Signed-off-by: ToKiNoBug --- utilities/MCDataVersion/MCDataVersion.cpp | 4 ++-- utilities/MCDataVersion/MCDataVersion.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index af65712a..6d1d7b1d 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -67,10 +67,10 @@ MCDataVersion::MCDataVersion_t MCDataVersion::max_supported_version( case SCL_gameVersion::MC19: return MCDataVersion_t::Java_1_19_3; case SCL_gameVersion::MC20: - return MCDataVersion_t::Java_1_20_5; + return MCDataVersion_t::Java_1_20_6; case SCL_gameVersion::MC21: case SCL_gameVersion::FUTURE: - return MCDataVersion_t::Java_1_21; + return MCDataVersion_t::Java_1_21_1; } abort(); } diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index 32b68e64..eb4f5f98 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,7 +30,22 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + Java_1_21_1 = 3955, + Java_1_21_1__rc1 = 3954, Java_1_21 = 3953, + Java_1_21__rc1 = 3952, + Java_1_21__pre4 = 3951, + Java_1_21__pre3 = 3950, + Java_1_21__pre2 = 3949, + Java_1_21__pre1 = 3948, + Snapshot_24w21b = 3947, + Snapshot_24w21a = 3946, + Snapshot_24w20a = 3944, + Snapshot_24w19b = 3942, + Snapshot_24w19a = 3941, + Snapshot_24w18a = 3940, + Java_1_20_6 = 3839, + Java_1_20_6__rc1 = 3838, Java_1_20_5 = 3837, Snapshot_23w51b = 3802, Snapshot_23w51a = 3801, From c5d6a650ca0271e989ece1a612dcc4b019d3c207 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 9 Aug 2024 22:00:39 +0800 Subject: [PATCH 0937/1123] add some quark blocks as a new SCL block list Signed-off-by: ToKiNoBug --- Blocks/QuarkModBlocks/ancient_leaves.png | Bin 0 -> 644 bytes Blocks/QuarkModBlocks/ancient_planks.png | Bin 0 -> 445 bytes Blocks/QuarkModBlocks/ancient_planks_slab.png | Bin 0 -> 220 bytes Blocks/QuarkModBlocks/azalea_planks.png | Bin 0 -> 440 bytes Blocks/QuarkModBlocks/azalea_planks_slab.png | Bin 0 -> 212 bytes Blocks/QuarkModBlocks/black_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/blaze_lantern.png | Bin 0 -> 296 bytes Blocks/QuarkModBlocks/block_list.json | 313 ++++++++++++++++++ Blocks/QuarkModBlocks/blossom_planks.png | Bin 0 -> 412 bytes Blocks/QuarkModBlocks/blossom_planks_slab.png | Bin 0 -> 213 bytes Blocks/QuarkModBlocks/blue_blossom_leaves.png | Bin 0 -> 433 bytes Blocks/QuarkModBlocks/blue_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/brown_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/cactus_block.png | Bin 0 -> 291 bytes Blocks/QuarkModBlocks/chorus_fruit_block.png | Bin 0 -> 435 bytes Blocks/QuarkModBlocks/cyan_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/duskbound_block.png | Bin 0 -> 216 bytes Blocks/QuarkModBlocks/green_shingles_slab.png | Bin 0 -> 253 bytes Blocks/QuarkModBlocks/iron_plate.png | Bin 0 -> 370 bytes .../lavender_blossom_leaves.png | Bin 0 -> 479 bytes .../light_blue_shingles_slab.png | Bin 0 -> 191 bytes .../light_gray_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/lime_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/limestone.png | Bin 0 -> 428 bytes .../QuarkModBlocks/magenta_shingles_slab.png | Bin 0 -> 259 bytes Blocks/QuarkModBlocks/midori_block.png | Bin 0 -> 446 bytes Blocks/QuarkModBlocks/myalite.png | Bin 0 -> 226 bytes .../QuarkModBlocks/orange_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/permafrost.png | Bin 0 -> 243 bytes Blocks/QuarkModBlocks/pink_shingles_slab.png | Bin 0 -> 254 bytes .../QuarkModBlocks/purple_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/raw_copper_bricks.png | Bin 0 -> 260 bytes .../QuarkModBlocks/raw_gold_bricks_slab.png | Bin 0 -> 202 bytes Blocks/QuarkModBlocks/red_blossom_leaves.png | Bin 0 -> 452 bytes Blocks/QuarkModBlocks/red_shingles_slab.png | Bin 0 -> 254 bytes Blocks/QuarkModBlocks/shale.png | Bin 0 -> 454 bytes Blocks/QuarkModBlocks/shingles_slab.png | Bin 0 -> 245 bytes Blocks/QuarkModBlocks/stick_block_top.png | Bin 0 -> 262 bytes Blocks/QuarkModBlocks/sugar_cane_block.png | Bin 0 -> 263 bytes Blocks/QuarkModBlocks/white_shingles_slab.png | Bin 0 -> 254 bytes .../QuarkModBlocks/yellow_blossom_leaves.png | Bin 0 -> 316 bytes .../QuarkModBlocks/yellow_shingles_slab.png | Bin 0 -> 263 bytes SlopeCraftL/CMakeLists.txt | 12 +- 43 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 Blocks/QuarkModBlocks/ancient_leaves.png create mode 100644 Blocks/QuarkModBlocks/ancient_planks.png create mode 100644 Blocks/QuarkModBlocks/ancient_planks_slab.png create mode 100644 Blocks/QuarkModBlocks/azalea_planks.png create mode 100644 Blocks/QuarkModBlocks/azalea_planks_slab.png create mode 100644 Blocks/QuarkModBlocks/black_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/blaze_lantern.png create mode 100644 Blocks/QuarkModBlocks/block_list.json create mode 100644 Blocks/QuarkModBlocks/blossom_planks.png create mode 100644 Blocks/QuarkModBlocks/blossom_planks_slab.png create mode 100644 Blocks/QuarkModBlocks/blue_blossom_leaves.png create mode 100644 Blocks/QuarkModBlocks/blue_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/brown_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/cactus_block.png create mode 100644 Blocks/QuarkModBlocks/chorus_fruit_block.png create mode 100644 Blocks/QuarkModBlocks/cyan_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/duskbound_block.png create mode 100644 Blocks/QuarkModBlocks/green_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/iron_plate.png create mode 100644 Blocks/QuarkModBlocks/lavender_blossom_leaves.png create mode 100644 Blocks/QuarkModBlocks/light_blue_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/light_gray_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/lime_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/limestone.png create mode 100644 Blocks/QuarkModBlocks/magenta_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/midori_block.png create mode 100644 Blocks/QuarkModBlocks/myalite.png create mode 100644 Blocks/QuarkModBlocks/orange_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/permafrost.png create mode 100644 Blocks/QuarkModBlocks/pink_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/purple_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/raw_copper_bricks.png create mode 100644 Blocks/QuarkModBlocks/raw_gold_bricks_slab.png create mode 100644 Blocks/QuarkModBlocks/red_blossom_leaves.png create mode 100644 Blocks/QuarkModBlocks/red_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/shale.png create mode 100644 Blocks/QuarkModBlocks/shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/stick_block_top.png create mode 100644 Blocks/QuarkModBlocks/sugar_cane_block.png create mode 100644 Blocks/QuarkModBlocks/white_shingles_slab.png create mode 100644 Blocks/QuarkModBlocks/yellow_blossom_leaves.png create mode 100644 Blocks/QuarkModBlocks/yellow_shingles_slab.png diff --git a/Blocks/QuarkModBlocks/ancient_leaves.png b/Blocks/QuarkModBlocks/ancient_leaves.png new file mode 100644 index 0000000000000000000000000000000000000000..9f4c7b0230040d0fc90a81c4f5d7cd0d0e49ada2 GIT binary patch literal 644 zcmV-~0(s(?`Fc|<^5mm);a+Vz{Q6pm87Pf6soFAl+ zpOmnnALXt9?AAKio^R-0=a}q7jb_3ll{rum)w81>tXw2qNh8Mj(FOmPMz8v)L({5X zO)HJQH1}Si&Crf&0qHt&xNnJc9cf8fG?_L|x{heNNYaS$iVbE)+%pu~6P>v(EizR9 zOiRiVn5I#0sy8Z}J;3sI3V@jrm+->zbI!lml5&7+R;GN+Z+=gUXu(d6bp}Giwrw$6N((?X z*T-e95ot*|z)2c0)>hN>D?c(g-AvoI&~Xpcd%1D4i&tMDYMzuh+_&WQqQ6~wz^qKk zEjAb*YpbPyUKR3#lAWl*2s9d=pOjwZKh0j2w^L+uef}$3o9uOt0T>@^E1mnm)+PXJ et7-1#zVa7L)j({2{<|;$0000g#Dy#Ww)^)_Ts;sTc2R5>CUlaLU}oAN*F}5BN$uT)oI9Dh z=bMwrS}U8b;pTG8D0Re42&-p%R{L@(@2?9YYpnomx(0x5S#mwTW;czwxg7hCw69vb zHULB`Q;44ajUtt3@XHqU=7sL!P8*-c}Ts;6#h&qGHar4GQ` zy-2E_wlW^thUUj_1KB)h67Zqp$mWv-h@PMSO6c`rb~j+4rTx=2oMfOS)I|MbWxbrjY9 n7aut0Ak6zIkB~|DFKB%OG^$lLyLS_`00000NkvXXu0mjf6CchW literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/ancient_planks_slab.png b/Blocks/QuarkModBlocks/ancient_planks_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..d451a33cef25917db03ea8791aa34e25878476c3 GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!bbwEY>&>&5U)_GPbKCC4i`PAV z`|{WS_y7O@|Ni|ukZk%d7YkIzSrX(I4CI0VL$H5^5J<4VBeIx*fm;}a85w5HkpKz? zdAc};NK8F?;vi!K0}qqox(ko~3I8r<{M<8-|F6j1>`mp><{4U!WODuH zkz8$(9PR#o+Z)~6wyMz_TQY@MFD=Mpn2`QvqKVw?I>ybytoxo_Pe}rr&fw|l=d#Wz Gp$Pz%P*+_5 literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/azalea_planks.png b/Blocks/QuarkModBlocks/azalea_planks.png new file mode 100644 index 0000000000000000000000000000000000000000..2a514ce0980f9f06946afe3ef87bf0e634e9e6bb GIT binary patch literal 440 zcmV;p0Z0CcP)055Qd)<2O>zU79ntOVFZC|0_jrv&lq>9LVi~IwC>yprx1w{0)Y_NSa2-kMaQA$ zF2!ordxxEA4(4NL-iP>xIm(xANno1MT2a^0>4F!907PC8qs)}Z~x+=dI>qi40K0Qh)00${bM5Pt-~nlS+4 zk66>qi$9Xx-QTtoGi0$m@b$|@XJbE?N^#;T=9cW|ubWoSFQvhWXKD>jJXAy;seX-8 z8geHdCn+=&^|~r-Ne6VhM!tSHoHf02cz$}-x?XF29EZ}L$e^$B)71z57cc(AW_R|% zc3($*`rYp9&Z){J@&TwI58F>~>eIpgBS7%MPRPFhxNcRW`XFVH)}EgNr?i&+{`0L} zEDscOOUeR*T~i;ZFVg=b-|p*prh-XN*T*%dpi8O41FBoSP|R&K6crSo!?5OD_xA`4 iQor|kq)gQRY5W7g#Rp790f9UK0000&#^#tG6YcyOO>CSW02B z?abLBjg6lF|Nnozb}v6r4M$0kUoemh0u1+>_eKK6I14-?iy0WWg+Z8+Vb&Z8prD_p zi(`ny)T3usG9G3SIO6cOc=kVQz72s=Cma|*{yaF}>5WGn>mn6F1(tSYMh_vDTX)yK z&CBlYoSPth+|A2jg2p5PjYsngFRZ^WjoIX$N)`d@O1TaS?83{1OP)z BO&|aO literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/black_shingles_slab.png b/Blocks/QuarkModBlocks/black_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..c2548a45defc93286ad0aa2f88ae3012721df399 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>$>7U$WK+sFQ)MB*-rq$o>DHVe|ea`+*{y1s;*b3=G`DAk4@xYmNj^(8bfm zF+^hO(Vm062Mlw%iJ!0Ng7OfR%5 pB~Hw;Kauw@;hpmu*~@op7()Y?*RNZo{RC(pgQu&X%Q~loCIEJ(OQZk* literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/blaze_lantern.png b/Blocks/QuarkModBlocks/blaze_lantern.png new file mode 100644 index 0000000000000000000000000000000000000000..320d37ff29854c52a19c7fd0e89bd3b2be5e3914 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>Q2!~Oqb@BerF|6dLL&6+O+rU7Ro0ZiDSxl%r+k#39&KCy zMfp_ovPX&KF1K&Lc-q>$qe)dyc#c*%&wmWR0Z%^FQJD z>vPsAle)k{0@v|r`JeeeqY?p97tkrAQ)Xv|bg&9S>Ow8nDdV*OTT`Ti=+ph;7g8H; zO=nYALGb!sQrTcAQuXdIdP#MIcDhIWdpIXW zK??`X7X}}CoUw3LUK3yLZt6R?8h_sX;D7OH<&`49emq^YolocC;avO#unD41|4yHO zc-_RIZ&AW#z0R(&`k-OZ-f1pF+PnC6zu^6Fq?a^f0mZJZ58M~+{}K1&sjlf@+SR?e z=Nz<4j;`Ci&`U9h8|h)0DkHCJBW%{|-1_~RN6WmQ4hO=T@w%JuTIb3NCzJFilo+$w7fvN);haJ%W^wB0$U zRd1{4-1KmocI8&UhS%G)t~{M*m~nF2?$eucPx$Ye_^wR5*=wQ!z`!KotH?5V}f-)J~a|{D3YF71}Akpa_A0dzakc+9i{7g@Q}$ zyTLl=yWrFV2WFGFXyu5}DbN$bOrpwb|F7=H$g$&GJ@&HkM}d zpr#9p92ONd=LS+RzK~~aB(>6_#3ya6%gB=`#g$I5ZYNTZwAWGF@_?|Y=;P@PyTwF3 z-aX^u@(iEvCCb+?NRr)RqMV{lpV<-VMq5nHXAa=AHW!#kYV|*R%lFYMm9yU*9u8{S bDJSw5$AEy9ZZzCN00000NkvXXu0mjf@IlN` literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/blue_shingles_slab.png b/Blocks/QuarkModBlocks/blue_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..447422ca6f3184e9fdff5a313d966ae7a1f65251 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>!mfM@Tds#;t zYqQL70(Y)*K0-po^!A zV~E7mqdf{-ZPx=4= literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/brown_shingles_slab.png b/Blocks/QuarkModBlocks/brown_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..11fb3fd75c9578f9e72f941e68d99803e4765c73 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>Bx!N zYRLx}tN#E0KlM)CB%mx?NswPKko*5X!{+@<_5(#Y3p^r=85p>QL70(Y)*K0-po^!A zV~E7mqdlBl2Mjn^zHj*dzsOvT^(FhF6CD=a&%<|=Y*5{q|5BP0;`V literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/cactus_block.png b/Blocks/QuarkModBlocks/cactus_block.png new file mode 100644 index 0000000000000000000000000000000000000000..cb67278f1de4916285c261c52919d671e5e92091 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHVEbxddW?Nn{1`wE}!XT(@j$U%w`H)r!Ieb3^+Vg-`7BO_^cT(&Qf9qg`HVA5^R6 znXl-Ss$dx*b<*!>E>Ks$r;B4qMI7rvMZQA@5^NXN$1f9ja$Y4Z_poJ|h?50_n020$ z#UU0U0gWRz!drw{uA2yZyG`r+er0L=wWr4=gDTjzs3}AnW~J!)tofi?#w63bXifsF z!K(+$S1;T8N>s?fp!&`o9*MNKKW6`_a=m(N&&4mY!5;4~@jkF)t$#nSFLb}7L|2ob h>4pZihk}NW`9Erya2$#Vo(OargQu&X%Q~loCIII_X(<2z literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/chorus_fruit_block.png b/Blocks/QuarkModBlocks/chorus_fruit_block.png new file mode 100644 index 0000000000000000000000000000000000000000..7aa41ab735b829eea3145a36fa863feecf52f99f GIT binary patch literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJXMsm#F#`kNVGw3Kp1&dmD9DoT z=KOuWUeSCdQbWKHgd1+8-SwLBSKwh?ccBV^aid{;g zO=6;TV!TaUjAe9;c}$F1OteXKgkeO4K}5KIc$i*TuwHP8Zb*Q3K%iEjpSquyikFwN zm%Dlh=#+V8&T?Wqs3SOYR+x z0YT=^v~I@xD)8^#etxTeM(85WHyQWrUd=vSW}eR$f7g85(}^E4ZW~`?J0&$mwA1_1 z0oEq#xd&PWWGooO8_bqH-B|df_wgn{om~MbslQka5B@K$FIdpHHRI8O)*0T7Ua58^ zi14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>~+NB{r-fA_5eu|Qe2k|4ieAou@&hRyqz><5Z)7I;J!Gca%qgD@k*tT_@uK^IRK z#}J9BM|&=E9thxIKCg1O{%O|I4=NXbV&dp4o zl94nyJ#kW?cb$WE_KPV8m4V7CJY5_^D&klV9^^gbz{7GNc7EleHItc?7IkdD%s53r z<14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>DHVe|ea`+*{y1s;*b3=G`DAk4@xYmNj^(Am?) zF+^hO(VmOE4Gug`nh*YIbI(&-&V8fb&Wp>!u6cfsB!jbfxE oO;CMXdMY(n&A}OV3Oqc6z?F4`!0H$$BeV+lyi*mQ!c<)n6sydAW zi;cb8ZXSBiixNNvVD02|I(^=6stTZK8WEuk*7KG#SG=g3);UMEi9VmtF-GTH-L!Sn z5}XUBaWFQOs4Ce@dohI!06m!!bNR;pHGyoR&zPohphfC7{AJqMbeR{WWyOy3OsO*d z8#~5GWWV3Pb>Xy(E{$!vEi3Q+GQCv@;UAaYd*>Y4s`^T4x81}Tt+y#5TSUC~^QQUE zY?n)yc~P=AZ@H`2rt79%CTp3hD&Ils``JU+Jy_OtkC+0#om7U$?=Q>X2RWtrd^`TU Qy#N3J07*qoM6N<$f{;e0;Q#;t literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/lavender_blossom_leaves.png b/Blocks/QuarkModBlocks/lavender_blossom_leaves.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ce4286100bd8e7eaf89df72c688bcf9cffd980 GIT binary patch literal 479 zcmV<50U-W~P)Px$nMp)JR5*=oQ?GBrKotIN!H`*&rNfX+E;Mrs9y3RJ0s#VtnA(!nwj`(`rY4#o zCWb&9!8KWsOPFkKK_a`R8Gpi(H?iI2QF!Kh@80*lUtghBP5{vFO(=;{!oMX^O417{ z4pwAhxDEUU4g3ZP0MII@Y+GQy>!4d(;?} zzd_yF67yZh23P9O7W_JUw6W%tUPv%y^0NB92?2ogLgFo&to)8RSkX9c9`wq=TIDtg zH%pR4DQT6HIqd@jkK?8t^1yHGlSwZmlhJ@ViAlmUTN2)HxwK>J>-Q!ky>M^kM*&*p zG>)5lb1_3sqLj+I0Uwxo;J#xd03i6o!_681;7Ug%QA*Q~C4$}%*|tFa@*Hcu!En?T zyyX)<5LY@P+ZHfjwFt#%7F+P!=R5d1)glxXb7@tlctP9BSgV|>)l*9h{AtEipcbL9 zQeNu~zAx@^_Vt9}sBL{M_sW8~#lebN?iI3avG3$T<&Bu{gTIt(zbqaTR9+`n!15oAMn9N+ickHV2sDhr)78&qol`;+08$r0{{R30 literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/light_gray_shingles_slab.png b/Blocks/QuarkModBlocks/light_gray_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..dcbb63e521b7d088e2e7618d9e3aafd493175b42 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>O>_%)r1c48n{Iv*t(u1zkK{ z9780g9__ivc_4s;S-l#w9W?ik(8}eV q(}eo#|0M4D%)i_|#b)XDsCyn~nCFJ?QdR<*$KdJe=d#Wzp$PzV!&6@X literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/lime_shingles_slab.png b/Blocks/QuarkModBlocks/lime_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..3fab8113a8c39d7b9276377d94f9ced4f9483475 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>%^3p=2lu% zw>wXm?Dqfv|5-7vpMbJ#B|(0{K<@wl44d~a*$))qEbxddW?XcdEqkYP+8WPi3lpFq!{j&Pcq^dJ3I|cmQ5WA3J&V~PskUK41{Rd+D zAF$$OqTSd@F3y%6t0Ux@m$nU$$Mv{i^Z0PB5!}hh9qn%E0;mAu3>UJKJPP>bSMdcf W?FZY(_*04i000014Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>gQ(=0S{9$q+>w+Z<_!p|G7N0Qd%2+ym t!|$nI46J|V`xotgerYCu__>Ac{98;|j4!-PaRD00;OXk;vd$@?2>|RDQtto& literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/midori_block.png b/Blocks/QuarkModBlocks/midori_block.png new file mode 100644 index 0000000000000000000000000000000000000000..c82dd91baf970d17b0a7a1abf36b8a95549304a6 GIT binary patch literal 446 zcmV;v0YUzWP)w4V3zh16bl0t$Nsdnszhr{I z4@izq_J1=A&8BG2)%j4mokbZ8UnRVa$FjPtUDC=vrXAzaK$`8Y;KSqXjg&>H!NXG` zVP$Py8d*cq`6ay?tWrGZ+NpD^_ZNK>(COnqzzwrF4)!(%E!bGBGyRRcn5)^DDF;?& z!T$9~Ha6QT0rACIK7D~(Ml6nN84aw4fi$Zm_<2>4Di6%!fXZ7t9aS4}_VEk{&KOF9 zz&xJAGtYDU;qFB literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/myalite.png b/Blocks/QuarkModBlocks/myalite.png new file mode 100644 index 0000000000000000000000000000000000000000..4fe95e8991e864224cca0cb296cea58aea0d5d90 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UAI14-?iy0XBj({-ZRBb+Kpx_iw z7sn8Zsip@vb}}0ZFdX=}uq4skoJst_d;414Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>=G|ARM876r<(l?3?(1G)eIGi=_!WIs@Zv%n*=n1O*?7=#%aX3dcR3c7f@ zIEF|}J=$}Tw;_OsiGRiK^*PzepB^!NDsEwjk^dOX5ZY?1@!`geQ%15AvYt=(i1pnv prQ+Lhe`mXTi|@{9%S*yfOMB!n&wguWdJp5W$o<=t8O*Tzq*K7#sjE;G0EHAgP~@uzt_oeq;9;Zk~H^N!ABl* z%l-3f7B35EF*|%>*)vYH^8K5Hj-PcsE?uytwCYNS)X8O*PTPw9dK`DNk9j8k`pRp` lqW1I4O)7;xsV2UZ{;y~*bBDRMTo>pB22WQ%mvv4FO#rh+Tv`AC literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/pink_shingles_slab.png b/Blocks/QuarkModBlocks/pink_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..d178a598a0ca7ec33bb9a7bac053b265bcea23e8 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>Gk&9 znv}3HEadXcdEq p%e#59ef1>kYP+8WPernRFq!f(M_ezfHU^r<;OXk;vd$@?2>=TYPB{Po literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/purple_shingles_slab.png b/Blocks/QuarkModBlocks/purple_shingles_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..8d8ad9b7aa6d89bca2e5b4b7ddc5a14d36dd0788 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>jbi~Iloe_Y7vWk6ZBk|4ieAou@&hRyqz><5Z)7I;J!Gca%qgD@k*tT_@uK^IRK z#}J9BM|&8#4j6DSCr|qO|Fm~5`zHR7iNYV7o`>%!QBd8O<(Q(FeXQL>_*9sD;&V~Q p%Wl7wm+zg~{L*~7c;KgJ+*V(ivzB}>(*T;s;OXk;vd$@?2>|)#Pm%xt literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/raw_copper_bricks.png b/Blocks/QuarkModBlocks/raw_copper_bricks.png new file mode 100644 index 0000000000000000000000000000000000000000..b0677e194425aecba12d63c2b2fc903f0de4703c GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!L4Z$)tN*SUR%OYNQyZ&hWco+h z6{fq+=*g@v3SUv4v@6r+T6Of?aQhZt>sRdszgJB8|Nno#f1x7CppqcJU?3M6Fg#F> zl?2Lh7I;J!Gca%qgD@k*tT_@u!8lJB#}J9jM^7ANJmkQ`ykW{b&z$3_|8swCW~f?a zXaCAy@M8FPw`8rAE~l@bo+W*1ve0jzlW*MoL%8?6=WHxy$p4sihjV4#M7^`Du3?j0 o*4Z$3d8-Nrc4oX^=lR|;Ufqp{Czk!(L!eCzp00i_>zopr0B6l*hX4Qo literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/raw_gold_bricks_slab.png b/Blocks/QuarkModBlocks/raw_gold_bricks_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..5f30894b209c47b730b57ca047b7b93c605584c8 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!Xn;?M>#tXO|G&@ue#G$I5~-6t zGV5~H{{R1fP~@c)Pyu^MkY6y63j_>O-pp=5AEak7 zarx-!jl52bBCP>C?(g`2gkM@(eZnV|AJ4Xb6ffAM6wnkaP?~V1%%RcoYeShr)kUVf rH`SjEo-R`|Q{T;^cu9QHM^QV8b`90LOPbaK&1CR&^>bP0l+XkKy|PEP literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/red_blossom_leaves.png b/Blocks/QuarkModBlocks/red_blossom_leaves.png new file mode 100644 index 0000000000000000000000000000000000000000..0eddbb6aeebf8f2e2f072c81c5518360bc92b8f8 GIT binary patch literal 452 zcmV;#0XzPQP)Px$en~_@R5*=oQ$0(=P!v7S-_apehafaVX))lGp@@@%hG3`6u7PB6%+jGhpp#pq z=;Eey7TUCQ5u{)mDdvA%hk743uer-h-o5ACk8>X=i3k94$D_gz2>(|20cEyJ%RxXK zBQ1o7pfXsGDwkW~;kL4hsbkaHKRe~vrbP{Qrr11A(KD9%D z(@94UIgG73S!TP$85t}|IEl=xNo2ofX-)Fwjz^j8)+BEPP!dr(>D1=JLoWP)%)O~e z#12z7lLP>ibUdmX0Du~eRpAGef9`O1eSvLR;pDi5)w)7|wqG)C`A7~#jmBzQR$%aO zGgnWq9~%7qyMvT-xS114Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>V|dhcSi(f8MrXqEATD q&Xo_TiCcE4F$546(h|z5@=bG^i@-@H?VWq(%wHSbKR#7ekz0Iukr{|a z&o5QdPAvYNPpy-s7Tt{=swmA29?uvahu-b5cA^qGV_ro6SuX1k;kw(kn47Eqz#U)X zah=6a0nnm^>0(t&5QVcWcW#T1iM_wR8MV43ZS1x?Yqb(Ld^~|GtT(x{r2rtg(T4^B z2~Z^SK-K%=;?yO|o&q2TATj_z@Il|ozugn0=n5QQtAqZ{(Ay@^3A{)}H8BgGO_3B7 z5&14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>kZns>Y3{0d|RFT f?=p3h-ifmxJNn{1`Nn{1`)dPG&TzA}eSb4^#|AN)jEhaSw6ic@%6s%RqS}K#VP%dquMA|&r zn8_kxoxVqRvLa5 zg*BVl#9qF8ndISl?YFeWwzpL`zcX*2wfWie77_1NaVw@oq%`d_+05>=yDXFK>bu;P zj$12tXCK(wU8*dx@sQJjgNAIc<9nXh6r214Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>EUyo)9mx^KMYa~oqA${%A&=d6_;aAT^g4)z4*}Q$iB}k^fiI literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/yellow_blossom_leaves.png b/Blocks/QuarkModBlocks/yellow_blossom_leaves.png new file mode 100644 index 0000000000000000000000000000000000000000..01ada507bbfd05c08895b1657a730099ae7e2d0c GIT binary patch literal 316 zcmV-C0mJ@@P)Px#_DMuRR5*=wQ^660APh_?HgM(ew+jBu*n~qHHsOp#&;*aXau3|NAo4*&b`y4k zXw4=fawRb>!Q@_Af*nyz&tS;mwZ_HPxU{&|Y+8b?ae0v-@k(M>l8#JkHbDSjPG+zJ zXg{KupiOQIfFnK?M-u#tp24>L_qr>CwPr8E>mex(jNK0iyzM{N$Hn7ns0c8Vpa@rX z629-)+RVNy-NlG-3ecKc+Z2PyT7r#p(^-Ur(YBGKYi*576A~ayB8kgRKsVumaYt@2 z5&`C!am_$5`V2=pOD8$K&*yXZuSWzT*6N#m_C3B*p8ePG+)1OIJduBhXr$NT>diy| O000014Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>FMGaA~E%7&u!iY10LqT9XIP!CW$TSVm)!*b=vtIcJ1? Date: Fri, 9 Aug 2024 22:22:43 +0800 Subject: [PATCH 0938/1123] fix quark blocks Signed-off-by: ToKiNoBug --- Blocks/QuarkModBlocks/block_list.json | 148 ++++++++++++------ Blocks/QuarkModBlocks/jasper.png | Bin 0 -> 444 bytes .../QuarkModBlocks/orange_blossom_leaves.png | Bin 0 -> 424 bytes .../QuarkModBlocks/raw_iron_bricks_slab.png | Bin 0 -> 208 bytes 4 files changed, 97 insertions(+), 51 deletions(-) create mode 100644 Blocks/QuarkModBlocks/jasper.png create mode 100644 Blocks/QuarkModBlocks/orange_blossom_leaves.png create mode 100644 Blocks/QuarkModBlocks/raw_iron_bricks_slab.png diff --git a/Blocks/QuarkModBlocks/block_list.json b/Blocks/QuarkModBlocks/block_list.json index 897e98e5..4389fbdc 100644 --- a/Blocks/QuarkModBlocks/block_list.json +++ b/Blocks/QuarkModBlocks/block_list.json @@ -4,14 +4,16 @@ "id": "quark:shale", "nameZH": "页岩", "nameEN": "Shale", - "icon": "shale.png" + "icon": "shale.png", + "version": 18 }, { "baseColor": 6, "id": "quark:iron_plate", "nameZH": "铁板块", "nameEN": "Iron plate", - "icon": "iron_plate.png" + "icon": "iron_plate.png", + "version": 18 }, { "baseColor": 7, @@ -19,57 +21,65 @@ "nameZH": "Ashen 树叶", "nameEN": "Ashen leaves", "burnable": true, - "icon": "ancient_leaves.png" + "icon": "ancient_leaves.png", + "version": 19 }, { "baseColor": 11, "id": "quark:limestone", "nameZH": "石灰石", "nameEN": "Lime stone", - "icon": "limestone.png" + "icon": "limestone.png", + "version": 18 }, { "baseColor": 13, "id": "quark:stick_block", "nameZH": "木棍堆", "nameEN": "Stick block", - "icon": "stick_block_top.png" + "icon": "stick_block_top.png", + "version": 14 }, { "baseColor": 15, "id": "quark:shingles_slab[type=bottom]", "nameZH": "陶瓦砖瓦台阶", "nameEN": "Shingles slab", - "icon": "shingles_slab.png" + "icon": "shingles_slab.png", + "version": 14 }, { "baseColor": 15, "id": "quark:raw_copper_bricks_slab", "nameZH": "生铜块台阶", "nameEN": "Raw copper bricks slab", - "icon": "raw_copper_bricks.png" + "icon": "raw_copper_bricks.png", + "version": 19 }, { "baseColor": 16, "id": "quark:duskbound_block", "nameZH": "黯缚块", - "nameEN": "Dusk bound block", - "icon": "duskbound_block.png" + "nameEN": "Duskbound block", + "icon": "duskbound_block.png", + "version": 14 }, { "baseColor": 17, "id": "quark:permafrost", "nameZH": "永冻石", "nameEN": "Perma frost", - "icon": "permafrost.png" + "icon": "permafrost.png", + "version": 18 }, { "baseColor": 17, "id": "quark:blue_blossom_leaves[persistent=true]", "nameZH": "雪霜花树叶", - "nameEN": "Blue blossom leaves", + "nameEN": "Frosty trumpet leaves", "burnable": true, - "icon": "blue_blossom_leaves.png" + "icon": "blue_blossom_leaves.png", + "version": 20 }, { "baseColor": 18, @@ -77,22 +87,25 @@ "nameZH": "烈焰灯", "nameEN": "Blaze lantern", "isGlowing": true, - "icon": "blaze_lantern.png" + "icon": "blaze_lantern.png", + "version": 14 }, { "baseColor": 18, "id": "quark:yellow_blossom_leaves[persistent=true]", "nameZH": "阳光花树叶", - "nameEN": "Yellow blossom leaves", + "nameEN": "Sunny trumpet leaves", "burnable": true, - "icon": "yellow_blossom_leaves.png" + "icon": "yellow_blossom_leaves.png", + "version": 20 }, { "baseColor": 19, "id": "quark:midori_block", "nameZH": "绿块", "nameEN": "Midori block", - "icon": "midori_block.png" + "icon": "midori_block.png", + "version": 14 }, { "baseColor": 19, @@ -100,7 +113,8 @@ "nameZH": "杜鹃木板", "nameEN": "Azalea planks", "burnable": true, - "icon": "azalea_planks.png" + "icon": "azalea_planks.png", + "version": 18 }, { "baseColor": 19, @@ -108,74 +122,84 @@ "nameZH": "杜鹃木台阶", "nameEN": "Azalea plank slab", "burnable": true, - "icon": "azalea_planks_slab.png" + "icon": "azalea_planks_slab.png", + "version": 18 }, { "baseColor": 19, "id": "quark:sugar_cane_block", "nameZH": "甘蔗捆", "nameEN": "Sugar cane block", - "icon": "sugar_cane_block.png" + "icon": "sugar_cane_block.png", + "version": 14 }, { "baseColor": 20, "id": "quark:lavender_blossom_leaves[persistent=true]", "nameZH": "幽静花树叶", - "nameEN": "Lavender blossom leaves", + "nameEN": "Serene trumpet leaves", "burnable": true, - "icon": "lavender_blossom_leaves.png" + "icon": "lavender_blossom_leaves.png", + "version": 20 }, { "baseColor": 24, "id": "quark:myalite", "nameZH": "幻境石", "nameEN": "Myalite", - "icon": "myalite.png" + "icon": "myalite.png", + "version": 18 }, { "baseColor": 24, "id": "quark:chorus_fruit_block", "nameZH": "紫颂果块", "nameEN": "Chorus fruit block", - "icon": "chorus_fruit_block.png" + "icon": "chorus_fruit_block.png", + "version": 16 }, { "baseColor": 27, "id": "quark:cactus_block", "nameZH": "仙人掌块", "nameEN": "Cactus block", - "icon": "cactus_block.png" + "icon": "cactus_block.png", + "version": 14 }, { "baseColor": 28, "id": "quark:blossom_planks", "nameZH": "花木板", - "nameEN": "Blossom planks", + "nameEN": "Trumpet planks", "burnable": true, - "icon": "blossom_planks.png" + "icon": "blossom_planks.png", + "version": 20 }, { "baseColor": 28, "id": "quark:blossom_planks_slab", "nameZH": "花木台阶", - "nameEN": "Blossom plank slab", + "nameEN": "Trumpet plank slab", "burnable": true, - "icon": "blossom_planks_slab.png" + "icon": "blossom_planks_slab.png", + "version": 20 }, { "baseColor": 28, "id": "quark:red_blossom_leaves[persistent=true]", "nameZH": "火热花树叶", - "nameEN": "Red blossom leaves", + "nameEN": "Fiery trumpet leaves", "burnable": true, - "icon": "red_blossom_leaves.png" + "icon": "red_blossom_leaves.png", + "version": 20 }, { "baseColor": 30, "id": "quark:raw_gold_bricks_slab", "nameZH": "生金块台阶", "nameEN": "Raw gold bricks slab", - "icon": "raw_gold_bricks_slab.png" + "icon": "raw_gold_bricks_slab.png", + "version": 19 }, { "baseColor": 36, @@ -183,7 +207,8 @@ "nameZH": "Ashen 木板", "nameEN": "Ashen planks", "burnable": true, - "icon": "ancient_planks.png" + "icon": "ancient_planks.png", + "version": 19 }, { "baseColor": 36, @@ -191,123 +216,144 @@ "nameZH": "Ashen 木台阶", "nameEN": "Ashen plank slab", "burnable": true, - "icon": "ancient_planks_slab.png" + "icon": "ancient_planks_slab.png", + "version": 19 }, { "baseColor": 36, "id": "quark:white_shingles_slab[type=bottom]", "nameZH": "白色陶瓦砖瓦台阶", "nameEN": "White shingles slab", - "icon": "white_shingles_slab.png" + "icon": "white_shingles_slab.png", + "version": 14 }, { "baseColor": 37, "id": "quark:orange_shingles_slab[type=bottom]", "nameZH": "橙色陶瓦砖瓦台阶", "nameEN": "Orange shingles slab", - "icon": "orange_shingles_slab.png" + "icon": "orange_shingles_slab.png", + "version": 14 }, { "baseColor": 37, "id": "quark:orange_blossom_leaves[persistent=true]", "nameZH": "温暖花树叶", - "nameEN": "Orange blossom leaves", - "burnable": true + "nameEN": "Warm trumpet leaves", + "burnable": true, + "icon": "orange_blossom_leaves.png", + "version": 20 }, { "baseColor": 38, "id": "quark:magenta_shingles_slab[type=bottom]", "nameZH": "品红色陶瓦砖瓦台阶", "nameEN": "Magenta shingles slab", - "icon": "magenta_shingles_slab.png" + "icon": "magenta_shingles_slab.png", + "version": 14 }, { "baseColor": 39, "id": "quark:light_blue_shingles_slab[type=bottom]", "nameZH": "浅蓝色陶瓦砖瓦台阶", "nameEN": "Light blue shingles slab", - "icon": "light_blue_shingles_slab.png" + "icon": "light_blue_shingles_slab.png", + "version": 14 }, { "baseColor": 40, "id": "quark:yellow_shingles_slab[type=bottom]", "nameZH": "黄色陶瓦砖瓦台阶", "nameEN": "Yellow shingles slab", - "icon": "yellow_shingles_slab.png" + "icon": "yellow_shingles_slab.png", + "version": 14 }, { "baseColor": 41, "id": "quark:pink_shingles_slab[type=bottom]", "nameZH": "粉色陶瓦砖瓦台阶", "nameEN": "Pink shingles slab", - "icon": "pink_shingles_slab.png" + "icon": "pink_shingles_slab.png", + "version": 14 }, { "baseColor": 42, "id": "quark:lime_shingles_slab[type=bottom]", "nameZH": "黄绿色陶瓦砖瓦台阶", "nameEN": "Lime shingles slab", - "icon": "lime_shingles_slab.png" + "icon": "lime_shingles_slab.png", + "version": 14 }, { "baseColor": 45, "id": "quark:cyan_shingles_slab[type=bottom]", "nameZH": "青色陶瓦砖瓦台阶", "nameEN": "Cyan shingles slab", - "icon": "cyan_shingles_slab.png" + "icon": "cyan_shingles_slab.png", + "version": 14 }, { "baseColor": 46, "id": "quark:purple_shingles_slab[type=bottom]", "nameZH": "紫色陶瓦砖瓦台阶", "nameEN": "Purple shingles slab", - "icon": "purple_shingles_slab.png" + "icon": "purple_shingles_slab.png", + "version": 14 }, { "baseColor": 47, "id": "quark:blue_shingles_slab[type=bottom]", "nameZH": "蓝色陶瓦砖瓦台阶", "nameEN": "Blue shingles slab", - "icon": "blue_shingles_slab.png" + "icon": "blue_shingles_slab.png", + "version": 14 }, { "baseColor": 49, "id": "quark:Green_shingles_slab[type=bottom]", "nameZH": "绿色陶瓦砖瓦台阶", "nameEN": "Green shingles slab", - "icon": "green_shingles_slab.png" + "icon": "green_shingles_slab.png", + "version": 14 }, { "baseColor": 48, "id": "quark:brown_shingles_slab[type=bottom]", "nameZH": "棕色陶瓦砖瓦台阶", "nameEN": "Brown shingles slab", - "icon": "brown_shingles_slab.png" + "icon": "brown_shingles_slab.png", + "version": 14 }, { "baseColor": 50, "id": "quark:jasper", "nameZH": "碧玉石", - "nameEN": "Jasper" + "nameEN": "Jasper", + "icon": "jasper.png", + "version": 18 }, { "baseColor": 50, "id": "quark:red_shingles_slab[type=bottom]", "nameZH": "红色陶瓦砖瓦台阶", "nameEN": "Red shingles slab", - "icon": "red_shingles_slab.png" + "icon": "red_shingles_slab.png", + "version": 14 }, { "baseColor": 51, "id": "quark:black_shingles_slab[type=bottom]", "nameZH": "黑色陶瓦砖瓦台阶", "nameEN": "Black shingles slab", - "icon": "black_shingles_slab.png" + "icon": "black_shingles_slab.png", + "version": 14 }, { "baseColor": 60, "id": "quark:raw_iron_bricks_slab", "nameZH": "生铁块台阶", - "nameEN": "Raw iron bricks slab" + "nameEN": "Raw iron bricks slab", + "icon": "raw_iron_bricks_slab.png", + "version": 19 } ] \ No newline at end of file diff --git a/Blocks/QuarkModBlocks/jasper.png b/Blocks/QuarkModBlocks/jasper.png new file mode 100644 index 0000000000000000000000000000000000000000..8bb195a1a01dce7685f95077cb8fb555f84e6514 GIT binary patch literal 444 zcmV;t0YmfHfA+l`%Tw0buVdI=$&a#_AME1Q_ryWt9edIw-$GS{(lr|Df)_;dSo zpzmX^v2*v2FVu^jo04(8)93wF_&z0@&!#G7wGaN``R&y{?}n>muUub37+S1s6i}5h zhIs4lA77YCy_=GeR+W^?7=yG1DX@HPD=M=x18KGwJ0~fZSNo)1?A*ii8ws<$=oy)* z=v?TPG()o)#*Lk`;8QLWKrh16t!(p>d9;-+P)RF{fFbk^chqL<6&>5Y_Mi0000Px$Vo5|nR5*=wQ=v}8KoEV40*7mYsz6dKoT$1cSOf-FyUB@SsuA}AD@ZP|93toz7*fZN%;5f|8?8 zUdGJJm<9k?72LH8*!2>#lT#cOuSQ7hdI^u&_o|iE@moYD6HYwPo zpj2s6&;!(6+lY`hbz1_cZA3ky2Fp9PlM7Dg$=<9Q%&PE3^zkH}%gCyr+&-Yd(|O`W z&daz@R@;bDQNWr+is;IoM9&+xHe_Fug0+o$mJb406`anKo-QJC=Q4(S)3Zndp=}`v z02m#3yt)Pen6WdR%lPrt;_~JeyLN%Y literal 0 HcmV?d00001 diff --git a/Blocks/QuarkModBlocks/raw_iron_bricks_slab.png b/Blocks/QuarkModBlocks/raw_iron_bricks_slab.png new file mode 100644 index 0000000000000000000000000000000000000000..79ecd817135b0a0b18a5cb9cfc0ef9cb08acfd50 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!M1W6-YfX}UT9A2PNyv@$lh^l^ zzdW(=-@Oz6|Nn1lb=?9~!%-6C7YyWr0K>iJy^%mM&H|6fVg?3oVGw3ym^DWNDCp(s z;us=v`RIv_ybTNj%p1MG2>sTtS(wHY^Gj}DU%gYZsdj7O%Gix14*4q?Qjb2HG4<4} wsdE#=4n*w??AX}xaZSTSwkJvs9ZnBedA?}bzl*g!4>Xm*)78&qol`;+0DSOGV*mgE literal 0 HcmV?d00001 From 5a2fbec29087e287b023d62c5ce0296a30933dbf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 11:08:39 +0800 Subject: [PATCH 0939/1123] implement block list name prefix Signed-off-by: ToKiNoBug --- SlopeCraftL/SlopeCraftL.cpp | 83 +++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index e61dcdec..c03e71b1 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -155,6 +155,45 @@ struct zip_deleter { } }; +struct block_list_metainfo { + std::string prefix_ZH; + std::string prefix_EN; + std::vector required_mods; +}; + +tl::expected parse_meta_info( + std::function(const char *filename, + std::vector &dest)> + extract_file, + std::vector &buffer) noexcept { + using njson = nlohmann::json; + // parse meta data + auto res = extract_file("metainfo.json", buffer); + if (res) { + block_list_metainfo ret; + try { + njson jo = njson::parse(buffer, nullptr, true, true); + auto &prefix = jo.at("name prefix"); + ret.prefix_ZH = prefix.at("ZH"); + ret.prefix_EN = prefix.at("EN"); + auto &mods = jo.at("required mods"); + ret.required_mods.reserve(mods.size()); + for (size_t i = 0; i < mods.size(); i++) { + std::string mod_name = mods[i]; + ret.required_mods.emplace_back(std::move(mod_name)); + } + + } catch (const std::exception &e) { + return tl::make_unexpected( + fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); + } + + return ret; + } + return tl::make_unexpected( + fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); +} + std::tuple, std::string> impl_create_block_list_from_zip(const char *zip_path) noexcept { std::string warnings{}; @@ -220,19 +259,37 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { }; std::vector buffer; + + block_list *bl = new block_list; + + using njson = nlohmann::json; + block_list_metainfo meta_info; + { + const char metainfo_name[] = "metainfo.json"; + const int64_t index = + zip_name_locate(archive.get(), metainfo_name, ZIP_FL_UNCHANGED); + if (index >= 0) { + // metainfo.json exists in the archive + auto mi_res = parse_meta_info(extract_file, buffer); + if (not mi_res) { + fmt::format_to( + std::back_inserter(warnings), + "metainfo.json exist in the archive, but failed to parse it: {}\n", + mi_res.error()); + } + meta_info = std::move(mi_res).value_or(block_list_metainfo{}); + } + } + // parse json array of blocks { auto err = extract_file("block_list.json", buffer); if (!err) { return {tl::make_unexpected(err.error()), warnings}; } } - - block_list *bl = new block_list; - - using njson = nlohmann::json; try { njson jo = njson::parse(buffer, nullptr, true, true); - if (!jo.is_array()) { + if (not jo.is_array()) { return {tl::make_unexpected( fmt::format("Json should contain an array directly")), warnings}; @@ -240,8 +297,18 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { // parse blocks for (size_t idx = 0; idx < jo.size(); idx++) { - auto [version, block] = parse_block(jo[idx]); - bl->blocks().emplace(std::make_unique(block), version); + try { + auto [version, block] = parse_block(jo[idx]); + + block.nameZH = meta_info.prefix_ZH + block.nameZH; + block.nameEN = meta_info.prefix_EN + block.nameEN; + + bl->blocks().emplace(std::make_unique(block), version); + } catch (const std::exception &e) { + return {tl::make_unexpected(fmt::format( + "Failed to parse block at index {}:\n{}", idx, e.what())), + warnings}; + } } } catch (const std::exception &e) { @@ -255,7 +322,7 @@ impl_create_block_list_from_zip(const char *zip_path) noexcept { for (auto &pair : bl->blocks()) { { auto err = extract_file(pair.first->imageFilename.c_str(), buffer); - if (!err) { + if (not err) { warnings += fmt::format("{}, required by {}", err.error(), pair.first->id); continue; From 9e22d71f7e121b50d19ba0153fb842c7b391092f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 11:09:08 +0800 Subject: [PATCH 0940/1123] add metainfo for QuarkModBlocks Signed-off-by: ToKiNoBug --- Blocks/QuarkModBlocks/metainfo.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Blocks/QuarkModBlocks/metainfo.json diff --git a/Blocks/QuarkModBlocks/metainfo.json b/Blocks/QuarkModBlocks/metainfo.json new file mode 100644 index 00000000..70baca78 --- /dev/null +++ b/Blocks/QuarkModBlocks/metainfo.json @@ -0,0 +1,9 @@ +{ + "name prefix": { + "ZH": "[夸克]", + "EN": "[Quark]" + }, + "required mods": [ + "Quark" + ] +} \ No newline at end of file From f8d328fac9d8e1ab80f0a6ac0fdbfcc9ee831b98 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 12:10:42 +0800 Subject: [PATCH 0941/1123] allow removing blocklists Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 2 +- utilities/BlockListManager/BaseColor.cpp | 65 +++++++++++++++---- utilities/BlockListManager/BaseColor.h | 13 +++- utilities/BlockListManager/Block.h | 2 +- .../BlockListManager/BlockListManager.cpp | 41 +++++++++++- utilities/BlockListManager/BlockListManager.h | 7 +- 6 files changed, 112 insertions(+), 18 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 8eaa6a93..c3880a6f 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -961,7 +961,7 @@ void SCWind::on_ac_test_blocklist_triggered() noexcept { basecolor++) { const auto bcwp = this->ui->blm->basecolorwidget_at(basecolor); for (const auto &bwp : bcwp->block_widgets()) { - blks.emplace_back(bwp->attachted_block()); + blks.emplace_back(bwp->attached_block()); basecolors.emplace_back(basecolor); } } diff --git a/utilities/BlockListManager/BaseColor.cpp b/utilities/BlockListManager/BaseColor.cpp index 038a27f2..12a207ca 100644 --- a/utilities/BlockListManager/BaseColor.cpp +++ b/utilities/BlockListManager/BaseColor.cpp @@ -30,6 +30,7 @@ constexpr int basecolor_cols = 3; static_assert(basecolor_cols >= 1); void BaseColorWidget::add_block(SlopeCraft::mc_block_interface* ab) noexcept { + this->place_holders.clear(); BlockWidget* bw = new BlockWidget(this, ab); const int idx = this->blocks.size(); @@ -47,27 +48,67 @@ void BaseColorWidget::add_block(SlopeCraft::mc_block_interface* ab) noexcept { void BaseColorWidget::add_placeholders() noexcept { if (this->blocks.size() <= 0) { + this->place_holders.clear(); return; } if (this->blocks.size() < basecolor_cols) { + this->place_holders.clear(); for (int i = this->blocks.size(); i < basecolor_cols; i++) { - QLabel* lb = new QLabel("", this); + auto lb = new QLabel("", this); // lb->setFrameShape(QLabel::Shape::Box); dynamic_cast(this->ui->layout_blocks)->addWidget(lb, 0, i); + this->place_holders.emplace_back(lb); } return; } if (this->blocks.size() % basecolor_cols == 0) { - return; + this->place_holders.clear(); } - /* - const int max_row = this->blocks.size() / basecolor_cols; +} - dynamic_cast(this->ui->layout_blocks) - ->addWidget(new QLabel("", this), max_row, basecolor_cols - 1); - */ +void BaseColorWidget::re_arrange_blocks() noexcept { + this->place_holders.clear(); + auto layout = dynamic_cast(this->ui->layout_blocks); + for (auto& bw : this->blocks) { + assert(layout->indexOf(bw) >= 0); + layout->removeWidget(bw); + } + + constexpr int cols = basecolor_cols; + for (size_t idx = 0; idx < this->blocks.size(); idx++) { + const int col = idx % cols; + const int row = idx / cols; + layout->addWidget(this->blocks[idx], row, col); + } + this->finish_blocks(); +} + +tl::expected BaseColorWidget::remove_blocks( + const std::function& + remove_this_block) noexcept { + size_t remove_counter = 0; + for (auto it = this->blocks.begin(); it not_eq this->blocks.end();) { + const bool remove_current = remove_this_block((*it)->attached_block()); + if (not remove_current) { + ++it; + continue; + } + if (this->blocks.size() <= 1) { + return tl::make_unexpected( + tr("无法删除方块 %1,基色 %2 只拥有 " + "%3个方块,若继续删除,则该基色将没有方块,SlopeCraft 可能崩溃。") + .arg((*it)->text()) + .arg(int(this->basecolor), this->blocks.size())); + } + + (*it)->deleteLater(); + it = this->blocks.erase(it); + remove_counter++; + } + this->re_arrange_blocks(); + return remove_counter; } constexpr inline bool should_be_disabled( @@ -95,8 +136,7 @@ void BaseColorWidget::finish_blocks() noexcept { for (int idx = 0; idx < (int)this->blocks.size(); idx++) { this->blocks[idx]->setDisabled(should_be_disabled( - idx, - (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(), + idx, (SCL_gameVersion)this->blocks[idx]->attached_block()->getVersion(), this->blocks.size(), v)); } } @@ -129,8 +169,7 @@ void BaseColorWidget::when_version_updated(SCL_gameVersion v) noexcept { for (int idx = 0; idx < int(this->blocks.size()); idx++) { this->blocks[idx]->setDisabled(should_be_disabled( - idx, - (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(), + idx, (SCL_gameVersion)this->blocks[idx]->attached_block()->getVersion(), this->blocks.size(), v)); } if (this->basecolor == 0) { // basecolor 0 (air) must be selected @@ -164,7 +203,7 @@ int BaseColorWidget::prefered_block_idx(int checked_idx, score = 0; const SCL_gameVersion blk_ver = - (SCL_gameVersion)this->blocks[idx]->attachted_block()->getVersion(); + (SCL_gameVersion)this->blocks[idx]->attached_block()->getVersion(); if (blk_ver <= ver) { score = 100; @@ -200,7 +239,7 @@ void BaseColorWidget::select_by_callback(const select_callback_t& fun) { std::vector blks; blks.reserve(this->blocks.size()); for (auto bw : this->blocks) { - blks.emplace_back(bw->attachted_block()); + blks.emplace_back(bw->attached_block()); } const int output = fun(blks); diff --git a/utilities/BlockListManager/BaseColor.h b/utilities/BlockListManager/BaseColor.h index 20e4321e..5c0a0581 100644 --- a/utilities/BlockListManager/BaseColor.h +++ b/utilities/BlockListManager/BaseColor.h @@ -4,6 +4,9 @@ #include #include #include +#include + +#include class BaseColorWidget; @@ -20,6 +23,7 @@ class BaseColorWidget : public QGroupBox { std::unique_ptr ui; const uint8_t basecolor{255}; std::vector blocks; + std::vector> place_holders; public: explicit BaseColorWidget(QWidget* parent, uint8_t _basecolor); @@ -29,6 +33,11 @@ class BaseColorWidget : public QGroupBox { void add_block(SlopeCraft::mc_block_interface* ab) noexcept; + // return the num of removed blocks + tl::expected remove_blocks( + const std::function& + remove_this_block) noexcept; + void finish_blocks() noexcept; void select_block_soft(int idx) noexcept; @@ -40,7 +49,7 @@ class BaseColorWidget : public QGroupBox { bool is_enabled() const noexcept; const SlopeCraft::mc_block_interface* selected_block() const noexcept { - return this->blocks[this->selected_idx()]->attachted_block(); + return this->blocks[this->selected_idx()]->attached_block(); } void update_lang(SCL_language lang) noexcept; @@ -59,6 +68,8 @@ class BaseColorWidget : public QGroupBox { private: void add_placeholders() noexcept; + void re_arrange_blocks() noexcept; + void select_block_direct(int idx) noexcept; int prefered_block_idx(int checked_idx, SCL_gameVersion ver) const noexcept; diff --git a/utilities/BlockListManager/Block.h b/utilities/BlockListManager/Block.h index 189de5d5..2f0dda8a 100644 --- a/utilities/BlockListManager/Block.h +++ b/utilities/BlockListManager/Block.h @@ -15,7 +15,7 @@ class BlockWidget : public QRadioButton { explicit BlockWidget(QWidget* parent, SlopeCraft::mc_block_interface* _blk); ~BlockWidget() = default; - auto attachted_block() const noexcept { return this->block; } + auto attached_block() const noexcept { return this->block; } void update_lang(SCL_language lang) noexcept; }; diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 6a6c8b4b..ec7ef275 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -135,6 +135,45 @@ void BlockListManager::finish_blocklist() noexcept { } } +tl::expected BlockListManager::remove_blocklist( + QString blocklist_name) noexcept { + const SlopeCraft::block_list_interface *bl = nullptr; + auto it_removed = this->blockslists.end(); + { + QString loaded_names; + for (auto it = this->blockslists.begin(); it not_eq this->blockslists.end(); + ++it) { + auto &name = it->first; + loaded_names.append(name); + loaded_names.push_back(","); + if (name == blocklist_name) { + bl = it->second.get(); + it_removed = it; + break; + } + } + if (bl == nullptr) { + return tl::make_unexpected( + tr("无法删除方块列表 \"%1\",没有加载同名的方块列表。已加载:%2") + .arg(blocklist_name, loaded_names)); + } + } + size_t removed_counter = 0; + for (auto &bcw : this->basecolor_widgets) { + auto res = bcw->remove_blocks( + [bl](const SlopeCraft::mc_block_interface *blk) -> bool { + return bl->contains(blk); + }); + if (not res) { + return tl::make_unexpected(std::move(res.error())); + } + removed_counter += res.value(); + } + this->blockslists.erase(it_removed); + + return removed_counter; +} + void BlockListManager::when_version_updated() noexcept { for (auto &bcw : this->basecolor_widgets) { bcw->when_version_updated(this->callback_get_version()); @@ -177,7 +216,7 @@ bool BlockListManager::loadPreset(const blockListPreset &preset) noexcept { auto &bws = bcw->block_widgets(); int matched_idx = -1; for (int idx = 0; idx < (int)bws.size(); idx++) { - if (QString::fromLatin1(bws[idx]->attachted_block()->getId()) == + if (QString::fromLatin1(bws[idx]->attached_block()->getId()) == preset.values[bc].second) { matched_idx = idx; break; diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index 7f80735e..d31fc9d0 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -1,11 +1,13 @@ #ifndef SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H #define SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H +#include +#include + #include #include #include #include "BaseColor.h" -#include struct basecolorOption { uint8_t baseColor{0xFF}; @@ -68,6 +70,9 @@ class BlockListManager : public QWidget { bool add_blocklist(QString filename) noexcept; + tl::expected remove_blocklist( + QString blocklist_name) noexcept; + void finish_blocklist() noexcept; void set_version_callback( From 63dbb15d723933d8672c15fc62d6b1d5e793c661 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 13:10:57 +0800 Subject: [PATCH 0942/1123] implement removing block lists Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 58 +++++++++++- SlopeCraft/BlockListDialog.h | 7 ++ SlopeCraft/BlockListDialog.ui | 93 ++++++++++--------- .../BlockListManager/BlockListManager.cpp | 13 ++- 4 files changed, 124 insertions(+), 47 deletions(-) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index 2d915470..aa1660fb 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -2,9 +2,11 @@ // Created by Joseph on 2024/4/9. // +#include +#include +#include #include "BlockListDialog.h" #include "ui_BlockListDialog.h" -#include #include "SCWind.h" class BLD_block_list_provider : public QAbstractListModel { @@ -210,7 +212,7 @@ class BLD_block_info_provider : public QAbstractTableModel { }; BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) - : QDialog{parent}, ui{new Ui::BlockListDialog} { + : QDialog{parent}, ui{new Ui::BlockListDialog}, block_list_manager{blm} { this->ui->setupUi(this); { @@ -303,4 +305,56 @@ void BlockListDialog::update_info( this->ui->le_id_old->setText(blk->getIdOld()); this->ui->le_name_cn->setText(QString::fromUtf8(blk->getNameZH())); this->ui->le_name_en->setText(QString::fromUtf8(blk->getNameEN())); +} + +void BlockListDialog::on_pb_add_block_list_clicked() noexcept { + const auto files = QFileDialog::getOpenFileNames(this, tr("选择方块列表"), + this->prev_dir, "*.zip"); + if (files.empty()) { + return; + } + this->prev_dir = QFileInfo{files.first()}.absoluteDir().path(); + + for (auto &file : files) { + this->block_list_manager->add_blocklist(file); + } + this->block_list_provider->dataChanged({}, {}); +} + +void BlockListDialog::on_pb_remove_block_list_clicked() noexcept { + const auto selected_indices = + this->ui->lv_block_lists->selectionModel()->selectedIndexes(); + std::vector names; + for (auto &qmi : selected_indices) { + if (not qmi.isValid()) { + continue; + } + names.emplace_back( + this->block_list_provider->available_block_lists()[qmi.row()].first); + } + + int num_lists = 0; + size_t remove_counter = 0; + for (auto &name : names) { + if (name == "FixedBlocks.zip") { + QMessageBox::warning(this, tr("不能删除基础方块列表"), + tr("FixedBlocks.zip 是基础方块列表,不允许移除。")); + continue; + } + auto res = this->block_list_manager->remove_blocklist(name); + if (not res) { + QMessageBox::warning(this, tr("删除方块列表 %1 失败").arg(name), + res.error()); + } else { + remove_counter += res.value(); + num_lists++; + } + } + if (num_lists > 0) { + QMessageBox::information(this, tr("删除方块列表成功"), + tr("删除了 %1 个方块列表,移除了 %2 个方块") + .arg(num_lists) + .arg(remove_counter)); + } + this->block_list_provider->dataChanged({}, {}); } \ No newline at end of file diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h index d2ed3937..a055996c 100644 --- a/SlopeCraft/BlockListDialog.h +++ b/SlopeCraft/BlockListDialog.h @@ -32,12 +32,19 @@ class BlockListDialog : public QDialog { BLD_block_list_provider* block_list_provider{nullptr}; BLD_block_provider* block_provider{nullptr}; BLD_block_info_provider* block_info_provider{nullptr}; + QString prev_dir; + + BlockListManager* const block_list_manager; void update_info(const SlopeCraft::mc_block_interface*) noexcept; public: explicit BlockListDialog(SCWind* parent, BlockListManager* blm); ~BlockListDialog(); + + private slots: + void on_pb_add_block_list_clicked() noexcept; + void on_pb_remove_block_list_clicked() noexcept; }; #endif // SLOPECRAFT_BLOCKLISTDIALOG_H diff --git a/SlopeCraft/BlockListDialog.ui b/SlopeCraft/BlockListDialog.ui index e523b003..31aa5107 100644 --- a/SlopeCraft/BlockListDialog.ui +++ b/SlopeCraft/BlockListDialog.ui @@ -19,18 +19,49 @@ false - - - - - - 0 - 0 - + + + + + 0 - + + + + 添加方块列表 + + + + + + + 删除方块列表 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 确定 + + + + - + @@ -40,7 +71,7 @@ - + 0 @@ -119,39 +150,15 @@ - - - - 0 + + + + + 0 + 0 + - - - - 若想增加/修改方块列表,增加/删除 blocks 文件夹中的 zip 文件,然后重新启动 SlopeCraft - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - 确定 - - - - + diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index ec7ef275..6e9ddfd4 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -112,6 +112,16 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { } bool BlockListManager::add_blocklist(QString filename) noexcept { + const QString name = QFileInfo{filename}.fileName(); + for (auto &[bl_name, _] : this->blockslists) { + if (bl_name == name) { + QMessageBox::warning( + this, tr("无法加载方块列表"), + tr("名为 %1 的方块列表已经加载,不允许加载同名的方块列表。") + .arg(bl_name)); + return false; + } + } // Test for multiple encodings for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { std::unique_ptr tmp = @@ -121,8 +131,7 @@ bool BlockListManager::add_blocklist(QString filename) noexcept { continue; } - this->blockslists.emplace_back(QFileInfo{filename}.fileName(), - std::move(tmp)); + this->blockslists.emplace_back(name, std::move(tmp)); return true; } From c39194df74fdfedc92ab537604f2e02e3794f6a0 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:00:13 +0800 Subject: [PATCH 0943/1123] fix a typo Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index dd51e9e7..41b49e1d 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -383,7 +383,6 @@ Schem::export_litematic(std::string_view filename, { std::string pure_block_id; pure_block_id.reserve(1024); - memset(pure_block_id.data(), 0, pure_block_id.capacity()); std::vector> properties; properties.reserve(64); @@ -408,7 +407,7 @@ Schem::export_litematic(std::string_view filename, } lite.writeListHead("PendingBlockTicks", NBT::Compound, 0); - lite.writeListHead("PendingFluidTiccks", NBT::Compound, 0); + lite.writeListHead("PendingFluidTicks", NBT::Compound, 0); // write 3D std::vector shrinked; From 145d35790848c7641b600a468496c944a4bf97ad Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:02:16 +0800 Subject: [PATCH 0944/1123] use new libSchem api Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index 76d3ff0e..abe50c0c 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -224,13 +224,10 @@ bool structure_3D_impl::export_litematica( info.regionname_utf8 = option.region_name_utf8; { - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool ok = - this->schem.export_litematic(filename, info, &flag, &error_string); + auto res = this->schem.export_litematic(filename, info); - if (!ok) { - option.ui.report_error(flag, error_string.c_str()); + if (not res) { + option.ui.report_error(res.error().first, res.error().second.c_str()); return false; } } @@ -245,13 +242,9 @@ bool structure_3D_impl::export_vanilla_structure( option.ui.report_working_status(workStatus::writingMetaInfo); option.progressbar.set_range(0, 100 + schem.size(), 0); - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool success = schem.export_structure( - filename, option.is_air_structure_void, &flag, &error_string); - - if (!success) { - option.ui.report_error(flag, error_string.c_str()); + auto res = schem.export_structure(filename, option.is_air_structure_void); + if (not res) { + option.ui.report_error(res.error().first, res.error().second.c_str()); return false; } @@ -279,13 +272,9 @@ bool structure_3D_impl::export_WE_schem( option.progressbar.set_range(0, 100, 5); - errorFlag flag = errorFlag::NO_ERROR_OCCUR; - std::string error_string; - const bool success = - schem.export_WESchem(filename, info, &flag, &error_string); - - if (!success) { - option.ui.report_error(flag, error_string.c_str()); + auto res = schem.export_WESchem(filename, info); + if (not res) { + option.ui.report_error(res.error().first, res.error().second.c_str()); return false; } From 8675b565fb96c6a033baef6e3a242b0952987f9f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:15:20 +0800 Subject: [PATCH 0945/1123] load only vanilla block lists by default Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 8 +++++--- SlopeCraft/BlockListDialog.h | 1 - SlopeCraft/SCWind.cpp | 15 +++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index aa1660fb..6deae02b 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -308,16 +308,18 @@ void BlockListDialog::update_info( } void BlockListDialog::on_pb_add_block_list_clicked() noexcept { - const auto files = QFileDialog::getOpenFileNames(this, tr("选择方块列表"), - this->prev_dir, "*.zip"); + const auto files = QFileDialog::getOpenFileNames( + this, tr("选择方块列表"), + QStringLiteral("%1/Blocks").arg(QCoreApplication::applicationDirPath()), + "*.zip"); if (files.empty()) { return; } - this->prev_dir = QFileInfo{files.first()}.absoluteDir().path(); for (auto &file : files) { this->block_list_manager->add_blocklist(file); } + this->block_list_manager->finish_blocklist(); this->block_list_provider->dataChanged({}, {}); } diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h index a055996c..37db0e45 100644 --- a/SlopeCraft/BlockListDialog.h +++ b/SlopeCraft/BlockListDialog.h @@ -32,7 +32,6 @@ class BlockListDialog : public QDialog { BLD_block_list_provider* block_list_provider{nullptr}; BLD_block_provider* block_provider{nullptr}; BLD_block_info_provider* block_info_provider{nullptr}; - QString prev_dir; BlockListManager* const block_list_manager; diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 409e9f8e..317a06d2 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -62,17 +62,16 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { tr("SlopeCraft 必须退出。")); exit(1); } + QString default_loaded[] = {"CustomBlocks.zip"}; QString fail_list; int fail_counter = 0; - for (auto file : - blocks_dir.entryInfoList({"*.zip"}, QDir::Filters{QDir::Filter::Files}, - QDir::SortFlags{QDir::SortFlag::Name})) { - if (file.fileName() == "FixedBlocks.zip") { - continue; - } - if (not this->ui->blm->add_blocklist(file.absoluteFilePath())) { + for (auto file : default_loaded) { + assert(file not_eq "FixedBlocks.zip"); + const QString abs_name = + QStringLiteral("%1/%2").arg(blocks_dir_path, file); + if (not this->ui->blm->add_blocklist(abs_name)) { fail_counter++; - fail_list.append(file.absoluteFilePath()); + fail_list.append(abs_name); fail_list.append('\n'); } } From 6e0278f0adda1765b2e961f8d4b43311e60c3807 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:30:50 +0800 Subject: [PATCH 0946/1123] ignore if no block lists are assigned to be removed Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index 6deae02b..9b5508c3 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -326,6 +326,9 @@ void BlockListDialog::on_pb_add_block_list_clicked() noexcept { void BlockListDialog::on_pb_remove_block_list_clicked() noexcept { const auto selected_indices = this->ui->lv_block_lists->selectionModel()->selectedIndexes(); + if (selected_indices.empty()) { + return; + } std::vector names; for (auto &qmi : selected_indices) { if (not qmi.isValid()) { From b41b9a5ee23dc27f15285101e51a41d9db1894b6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:31:08 +0800 Subject: [PATCH 0947/1123] fix MapViewer Signed-off-by: ToKiNoBug --- MapViewer/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index d855cb63..0bc806a1 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -61,6 +61,7 @@ target_link_libraries(MapViewer Qt6::Widgets OpenMP::OpenMP_CXX Eigen3::Eigen) +target_compile_features(MapViewer PRIVATE cxx_std_23) set_target_properties(MapViewer PROPERTIES VERSION ${PROJECT_VERSION} From efb371e039212da3c788803913769fdc98372939 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:31:20 +0800 Subject: [PATCH 0948/1123] fix SlopeCraft installation on mac Signed-off-by: ToKiNoBug --- SlopeCraft/install.cmake | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/SlopeCraft/install.cmake b/SlopeCraft/install.cmake index 59d1911f..4c8deffa 100644 --- a/SlopeCraft/install.cmake +++ b/SlopeCraft/install.cmake @@ -1,14 +1,3 @@ - -#file(GLOB SlopeCraft_install_jsons -# "${CMAKE_SOURCE_DIR}/Blocks/*.json" -# "${CMAKE_SOURCE_DIR}/Blocks/*.md") -# -#file(GLOB SlopeCraft_install_png_fixedblocks -# "${CMAKE_SOURCE_DIR}/Blocks/FixedBlocks/*.png") -# -#file(GLOB SlopeCraft_install_png_customblocks -# "${CMAKE_SOURCE_DIR}/Blocks/CustomBlocks/*.png") - file(GLOB SlopeCraft_block_list_archives "${CMAKE_BINARY_DIR}/SCL_block_lists/*.zip") @@ -44,7 +33,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") # Install all block list archives install(FILES ${SlopeCraft_install_presets} DESTINATION SlopeCraft.app/Contents/MacOS/Blocks) - file(COPY ${SlopeCraft_install_png_customblocks} + file(COPY ${SlopeCraft_block_list_archives} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/SlopeCraft.app/Contents/MacOS/Blocks/) # Install presets From 41e4f2722cefe64326f423426055c338fd3d4d1f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:31:42 +0800 Subject: [PATCH 0949/1123] add missing id attributes to Quark mod blocks Signed-off-by: ToKiNoBug --- Blocks/QuarkModBlocks/block_list.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Blocks/QuarkModBlocks/block_list.json b/Blocks/QuarkModBlocks/block_list.json index 4389fbdc..aadb8db9 100644 --- a/Blocks/QuarkModBlocks/block_list.json +++ b/Blocks/QuarkModBlocks/block_list.json @@ -50,7 +50,7 @@ }, { "baseColor": 15, - "id": "quark:raw_copper_bricks_slab", + "id": "quark:raw_copper_bricks_slab[type=bottom]", "nameZH": "生铜块台阶", "nameEN": "Raw copper bricks slab", "icon": "raw_copper_bricks.png", @@ -118,7 +118,7 @@ }, { "baseColor": 19, - "id": "quark:azalea_planks_slab", + "id": "quark:azalea_planks_slab[type=bottom]", "nameZH": "杜鹃木台阶", "nameEN": "Azalea plank slab", "burnable": true, @@ -177,7 +177,7 @@ }, { "baseColor": 28, - "id": "quark:blossom_planks_slab", + "id": "quark:blossom_planks_slab[type=bottom]", "nameZH": "花木台阶", "nameEN": "Trumpet plank slab", "burnable": true, @@ -195,7 +195,7 @@ }, { "baseColor": 30, - "id": "quark:raw_gold_bricks_slab", + "id": "quark:raw_gold_bricks_slab[type=bottom]", "nameZH": "生金块台阶", "nameEN": "Raw gold bricks slab", "icon": "raw_gold_bricks_slab.png", @@ -350,7 +350,7 @@ }, { "baseColor": 60, - "id": "quark:raw_iron_bricks_slab", + "id": "quark:raw_iron_bricks_slab[type=bottom]", "nameZH": "生铁块台阶", "nameEN": "Raw iron bricks slab", "icon": "raw_iron_bricks_slab.png", From 596834f5d3c7c91c270a027af91781e4c549bb70 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 14:45:05 +0800 Subject: [PATCH 0950/1123] add conspicuous button to manage block list Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 3 +++ SlopeCraft/SCWind.ui | 30 ++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 317a06d2..fa828723 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -195,6 +195,9 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { } this->when_preset_clicked(); + + connect(this->ui->pb_manage_block_list, &QPushButton::clicked, this, + &SCWind::on_ac_blocklist_triggered); } SCWind::~SCWind() { diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 899713ad..93ec5e3a 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -24,7 +24,7 @@ 地图画配置 - + @@ -235,6 +235,32 @@ + + + + 管理方块列表 + + + + + + + + 0 + 0 + + + + 默认只加载原版方块,点击上方按钮可加载其他方块列表。 + + + Qt::TextFormat::AutoText + + + true + + + @@ -330,7 +356,7 @@ 0 0 - 622 + 750 653 From 4aad0c6414f29ea62bf4bdb631310e2f4b1f8e1f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 20:49:32 +0800 Subject: [PATCH 0951/1123] update translations Signed-off-by: ToKiNoBug --- SlopeCraft/others/SlopeCraft_en_US.ts | 667 +++++++++++------- .../others/BlockListManager_en_US.ts | 36 +- 2 files changed, 441 insertions(+), 262 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index fac84a45..6b83dcbe 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -34,32 +34,136 @@ Mutation prob : + + BLD_block_info_provider + + + 最低版本 + Minimum version + + + + 依附方块 + Attached block + + + + 发光 + Glowing + + + + 末影人可搬走 + Enderman pickable + + + + 可燃 + Burnable + + + + 一组数量 + Stack size + + + + 远古版本 + Very old + + + + 未来版本 + Future + + + + BLD_block_list_provider + + + SlopeCraft 内部错误,方块列表的列表中出现 nullptr + SlopeCraft internal error, nullptr found in list of blocklist + + + + BLD_block_provider + + + SlopeCraft 内部错误,方块列表中出现 nullptr + SlopeCraft internal error, nullptr found in list of blocklist + + BlockListDialog - 加载/删除方块列表 - Load / remove block list + 方块列表 + Block list - - + - + + 添加方块列表 + Add block list - - - - + + 删除方块列表 + Remove block list - + 确定 OK - - 取消 - Cancel + + 方块 id + Block id + + + + 1.12 id + id in 1.12 + + + + 中文名 + Chinese name + + + + 英文名 + English name + + + + 选择方块列表 + Select block list + + + + 不能删除基础方块列表 + Can not remove fundamental block list + + + + FixedBlocks.zip 是基础方块列表,不允许移除。 + FixedBlocks.zip is the fundamental block list, not allowed to remove. + + + + 删除方块列表 %1 失败 + Failed to deleta block list %1 + + + + 删除方块列表成功 + Removed block list + + + + 删除了 %1 个方块列表,移除了 %2 个方块 + Removed %1 block list(s) and %2 block(s) @@ -144,7 +248,7 @@ PoolModel - + 被绘制的图标尺寸应当是 32*32,但实际上是%1*%2。这属于 SlopeCraft 内部错误,请向开发者反馈。SlopeCraft 必须崩溃。 The size of icon to be drawn should be 32*32, but actually it is %1*%2. This is a SlopeCraft internal error, please report to developer. SlopeCraft mush crash. @@ -231,7 +335,7 @@ Failed to load image %1. - + 绘制图标时发现错误 An error occurred when drawing icon @@ -255,7 +359,7 @@ - + 保存当前预设 Save as preset @@ -270,352 +374,362 @@ Game Version - + 地图画类型 Map type - + 立体地图画 3D Map - + 平板地图画 Flat Map - + 纯文件地图画 File-only Map - + 优先彩色玻璃 Use stained glass - + 优先混凝土 Use Concrete - + 优先羊毛 Use Wool - + 优先木板 Use planks - + 优先原木 Use logs - + 导入图像并转化 Load image and convert - + 原图 Original image - + 转化后 Converted image - + 删除 Delete - - + + 项目池 Task pool - + 添加 Add - + 转化算法 Convert algorithm - + 抖动 Dithering - + 转化当前图像 Convert current image - - - + + + 保存转化后图像 Save converted image - + 全部转化 Convert all - + 导出 Export - + Litematica - - + + 结构方块文件 Vanilla structure - + + 管理方块列表 + Manage block lists + + + + 默认只加载原版方块,点击上方按钮可加载其他方块列表。 + Only vanilla blocks are loaded by default, click button above to load other block lists. + + + 优先台阶 Use slabs - + 全选 Select all - + 全不选 Deselect all - + 反选 Invert selection - + 显示缩略图 View images - + 替换 Replace - - + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - + 地图文件 Map data files - + 其他选项 Others - + 防火 Fire Proof - + 防末影人 Enderman Proof - + 连接蘑菇块 Connect mushroom blocks - + 压缩高度 Compress - + 有损压缩 Lossy Compression - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 搭桥 Glass Bridge - + 允许搭桥 Construct Glass Bridge - + layer(s) - + 搭桥间隔: Glass bridge interval: - + 投影区域名称 Region name - + 投影名称 Litematic name - + 用结构空位替代空气 Replace air with structure void - + offset - + WEOffset - - - - - - + + + + + + 0 - + 原理图名称 Name of schematic - + 依赖 mod 名称 Depend mods - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - + 垂直分割线 Vertical split line - + 水平分割线 Horizontal split line - + 大小与方块数量 Size and block count - - + + 大小: Size: - - + + 方块数量: Block count: - + 全部导出 Export all - + 预览 Preview - + 预览材料表 Material list - + 预览压缩效果 Compress effect - + 预构建三维结构 Construct 3d structure - + 批量获得地图物品的指令 /give command to get map items - + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 在下面的表格里可以看到每个图像对应的文件名。 @@ -628,213 +742,218 @@ You can see filenames of each image. Map data are stored in map data files, assembled maps can take effect only after you must import map data files into the save. - + 地图画起始序号: Map beginning index: - + 导出批量获得地图物品的命令(txt) Export command to get map items - + 导出命令 Export commands - + 生存模式不可破坏展示框;移除它依附的方块,展示框也不会消失。 Item frams can not be removed in survivial mode; it will not disappear even the attached block is removed. - + 展示框不可破坏 Fixed frame - + 1.20.5后,物品格式发生重大改变 Item format is changed greatly after 1.20.5 - + MC版本≥1.20.5+ MC ≥ 1.20.5 - + 采用荧光物品显示框 Use glowing item frame - + 荧光物品显示框 Glowing item frame - + 导出包含物品展示框的投影/结构方块文件 Export the litematica / vanilla structure containing item frames - + 导出组装的地图画 Export assembled maps - + 导出map_i.dat的地图数据文件 Export map data files like map_i.dat - + 导出地图文件 Export map data files - + 展示框背景将不可见 The background of item frames will be invisible - + 展示框透明 Transprant frame - + 地图画可依附于方块的侧面、顶面和底面 Map can attach to a block by side, top and bottom - + 地图画方向 Map direction - + 导出组装地图画的格式 Format to export assembled maps - + 导出Litematica Export as litematica - + 导出结构方块文件 Export as structure - + 内存使用策略 Memory policy - + 缓存全部三维结构 Cache all 3D structures - + + 查看方块列表 + View block lists + + + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ - + 加载默认预设失败 Failed to load default presets - + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -843,74 +962,74 @@ Detail information: %1 - + 可用颜色数量:%1 Avaliable colors: %1 - + 应用预设失败 Failed to apply preset - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - + 保存图像失败 Failed to save image - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - + 方块数量:%1 Block count: %1 - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - + SlopeCraft 出现错误 An error occurred to SlopeCraft - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -920,192 +1039,192 @@ Click Ok to ignore, and click Close to exit SlopeCraft. - + 选择图片 Select Image - + 打开图像失败 Failed to open image - + 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 Failed to open image %1. Possible reason: the image is too large. Detailed information: %2 - + 请选择将被替换的图像 Please images to be replaced - + 必须先选择一个或多个图像,然后才能替换它们。 You should select one or more images, and then replace them. - + 选择预设文件 Select a preset file - + 解析预设文件失败 Failed to parse thes preset file - + 预设文件%1存在错误:%2 The preset file "%1" is invalid. Detail: %2 - + 保存预设文件失败 Failed to save preset file - + 无法生成预设文件%1,错误信息:%2 Failed to generate preset file "%1", detail: %2 - - - - + + + + 未选择图像 No image selected - - - + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - + 尚未构建三维结构 3d structure not built - + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - - - + + + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - + 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 @@ -1114,244 +1233,280 @@ Click Ignore to skip this image, and Cancel to cancel. Click Yes to replace them, or No to cancel. - + %1 个图片导出失败 Failed to export %1 image(s) - + 导出失败的图片依次为: %1 Following image(s) failed to export: %1 - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。 SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). - + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) - + 感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量 Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software - + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. - + 同时选中多个图片时,不显示 /give 命令。如果想预览导出的命令,请只选择一个图片。 Can't show /give command when you selecte multiple images. To view the command, select one image only. - + 无法为 %1 生成命令:%2 Failed to generate command for %1: %2 - + 无法创建/打开文件 %1:%2 Failed to create/open file %1: %2 - + 无法写入文件 %1:%2 Failed to write file %1: %2 - - + + %1 个文件保存失败 Failed to save %1 file(s) - + SlopeCraftL 未提供详细报错信息。 SlopeCraftL doesn't give further details. - + 错误码:%1,详情:%2 Error code: %1, details: %2 - + %1 生成失败,%2 Failed to generate %1, %2 - + + + 无法加载方块列表 + Failed to load block list + + + + 存储方块列表的文件夹 "%1" 不存在,或不是文件夹。 + Directory of block list zips \"%1\" doesn't exist or is not a directory. + + + + + SlopeCraft 必须退出。 + SlopeCraft must exit. + + + + 无法加载 FixedBlocks.zip ,SlopeCraft 缺乏最基础的方块列表。 + Failed to load FixedBlocks.zip, fundamental blocks are missing for SlopeCraft. + + + + 部分方块列表加载失败 + Some block lists failed to be loaded + + + + 以下 %1 个方块列表文件无法被加载: +%2 +由于它们不是必需,你可以忽略此错误并继续使用。 + Failed to load %1 following block list(s): +%2 +Since they are not essential, you can ignore this error and go on. + + + 墙面 Wall - + 顶面 Top - + 底面 Bottom - + north - + south - + east - + 西 west - + %1,向%2 %1, %2 - - + + 没有可用颜色 No available color - - + + 没有勾选任何颜色,无法转化图像。请至少勾选3~16种颜色。 You didn't enable ANY COLOR, unable to convert image. Please enable at least 3~16 colors. - + 勾选颜色太少 Too few colors enabled - + 仅仅勾选了%1种颜色,颜色过少,转化效率可能非常差。您可以点Yes继续转化,但非常建议请尽量多勾选一些颜色。 You only enabled %1 color(s), it is so few that the conversion effect may be terrible. You can click Yes to go on, but it's strongly recommended to enable more colors. - + 生成命令失败: %1 Failed to generate command: %1 - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 这不是严重的问题,你可以直接忽略这个警告,或者把它反馈给开发者,不影响正常使用。只是 Slopecraft 可能占用更多的内存。 详细信息: %1 @@ -1360,48 +1515,48 @@ Details: %1 - + 获取本进程的内存占用失败 Failed to query memory usage of this process - + 获取操作系统内存占用失败 Failed to query system memory usage - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index 365bfc54..9d48eb00 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -8,29 +8,53 @@ 启用 Enable + + + 无法删除方块 %1,基色 %2 只拥有 %3个方块,若继续删除,则该基色将没有方块,SlopeCraft 可能崩溃。 + Failed to remove %1: base color %2 has only %3 block now, if you continue to delete, there will not be any block for this base color, and SlopeCraft will possible crash. + BlockListManager - - + 解析方块列表失败 Failed to parse block list - - + + 解析方块列表成功,但出现警告 + Block list parsed with warnings + + + + 无法加载方块列表 + Failed to parse block list + + + + 名为 %1 的方块列表已经加载,不允许加载同名的方块列表。 + Block list named %1 was already loaded, and it's not allowed to load multiple block list with identity name. + + + + 无法删除方块列表 "%1",没有加载同名的方块列表。已加载:%2 + Failed to load block list \"%1\", no block list for such name. Loaded: %2 + + + + 加载预设错误 Failed to load preset - + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors - + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id From 771351fd794c6c74aff094b1826a16b5ef996b8a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 21:00:59 +0800 Subject: [PATCH 0952/1123] update version number Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5d0c9a9..f4d6cd91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.2.2) +set(SlopeCraft_version 5.3.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 146a275aa7cddca9716b1383ec6402142297814f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 22:19:44 +0800 Subject: [PATCH 0953/1123] fix translation in block list dialog Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 315 ++++++++++++++------------------- SlopeCraft/BlockListDialog.h | 67 ++++++- 2 files changed, 200 insertions(+), 182 deletions(-) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index 9b5508c3..5331be94 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -9,207 +9,164 @@ #include "ui_BlockListDialog.h" #include "SCWind.h" -class BLD_block_list_provider : public QAbstractListModel { - public: - const std::function>()> - available_block_lists; - - public: - explicit BLD_block_list_provider( - QWidget *parent, - std::function>()> - cb) - : QAbstractListModel{parent}, available_block_lists{std::move(cb)} {} - BLD_block_list_provider(const BLD_block_list_provider &) = delete; - - int rowCount(const QModelIndex &parent = QModelIndex()) const final { - if (parent.isValid()) { - return 0; - } - return this->available_block_lists().size(); +int BLD_block_list_provider::rowCount(const QModelIndex &parent) const { + if (parent.isValid()) { + return 0; } + return this->available_block_lists().size(); +} - QVariant data(const QModelIndex &index, - int role = Qt::DisplayRole) const final { - if (not index.isValid()) { - return {}; - } - if (role not_eq Qt::ItemDataRole::DisplayRole) { - return {}; - } - const auto block_lists = this->available_block_lists(); - const int idx = index.row(); - - if (idx >= block_lists.size() or idx < 0) { - return {}; - } - if (block_lists[idx].second == nullptr) { - return tr("SlopeCraft 内部错误,方块列表的列表中出现 nullptr"); - } - return block_lists[idx].first; +QVariant BLD_block_list_provider::data(const QModelIndex &index, + int role) const { + if (not index.isValid()) { + return {}; } -}; - -class BLD_block_provider : public QAbstractListModel { - private: - const std::function - available_block_list; - const std::function current_lang; - - public: - explicit BLD_block_provider( - QWidget *parent, - std::function &&cb, - std::function &&lang_cb) - : QAbstractListModel{parent}, - available_block_list{std::move(cb)}, - current_lang{std::move(lang_cb)} {} - - std::vector available_blocks() - const noexcept { - auto bl = this->available_block_list(); - if (bl == nullptr) { - return {}; - } - const size_t num = bl->size(); - std::vector ret; - ret.resize(num); - [[maybe_unused]] const size_t num_ = - bl->get_blocks(ret.data(), nullptr, ret.size()); - assert(num == num_); - return ret; + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; } + const auto block_lists = this->available_block_lists(); + const int idx = index.row(); - int rowCount(const QModelIndex &parent = QModelIndex()) const final { - if (parent.isValid()) { - return 0; - } - auto bl = this->available_block_list(); - if (bl == nullptr) { - return 0; - } - return bl->size(); + if (idx >= block_lists.size() or idx < 0) { + return {}; } - QVariant data(const QModelIndex &index, - int role = Qt::DisplayRole) const final { - if (not index.isValid()) { - return {}; - } - if (role not_eq Qt::ItemDataRole::DisplayRole) { - return {}; - } - const auto blocks = this->available_blocks(); - const int idx = index.row(); + if (block_lists[idx].second == nullptr) { + return tr("SlopeCraft 内部错误,方块列表的列表中出现 nullptr"); + } + return block_lists[idx].first; +} - if (idx >= blocks.size() or idx < 0) { - return {}; - } - if (blocks[idx] == nullptr) { - return tr("SlopeCraft 内部错误,方块列表中出现 nullptr"); - } - if (this->current_lang() == SCL_language::Chinese) { - return QString::fromUtf8(blocks[idx]->getNameZH()); - } - return QString::fromUtf8(blocks[idx]->getNameEN()); +std::vector +BLD_block_provider::available_blocks() const noexcept { + auto bl = this->available_block_list(); + if (bl == nullptr) { + return {}; } -}; + const size_t num = bl->size(); + std::vector ret; + ret.resize(num); + [[maybe_unused]] const size_t num_ = + bl->get_blocks(ret.data(), nullptr, ret.size()); + assert(num == num_); + return ret; +} -class BLD_block_info_provider : public QAbstractTableModel { - public: - const std::function selected_block; +int BLD_block_provider::rowCount(const QModelIndex &parent) const { + if (parent.isValid()) { + return 0; + } + auto bl = this->available_block_list(); + if (bl == nullptr) { + return 0; + } + return bl->size(); +} +QVariant BLD_block_provider::data(const QModelIndex &index, int role) const { + if (not index.isValid()) { + return {}; + } + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; + } + const auto blocks = this->available_blocks(); + const int idx = index.row(); - public: - explicit BLD_block_info_provider( - QWidget *parent, - std::function &&cb) - : QAbstractTableModel{parent}, selected_block{std::move(cb)} {} + if (idx >= blocks.size() or idx < 0) { + return {}; + } + if (blocks[idx] == nullptr) { + return tr("SlopeCraft 内部错误,方块列表中出现 nullptr"); + } + if (this->current_lang() == SCL_language::Chinese) { + return QString::fromUtf8(blocks[idx]->getNameZH()); + } + return QString::fromUtf8(blocks[idx]->getNameEN()); +} - int rowCount(const QModelIndex &qmi) const final { - if (qmi.isValid()) { - return 0; - } - return 6; +int BLD_block_info_provider::rowCount(const QModelIndex &qmi) const { + if (qmi.isValid()) { + return 0; } - int columnCount(const QModelIndex &qmi) const final { - if (qmi.isValid()) { - return 0; - } - return 2; + return 6; +} +int BLD_block_info_provider::columnCount(const QModelIndex &qmi) const { + if (qmi.isValid()) { + return 0; } + return 2; +} - static QString key_name(int index) noexcept { - const std::array keys{tr("最低版本"), tr("依附方块"), - tr("发光"), tr("末影人可搬走"), - tr("可燃"), tr("一组数量")}; - if (index < 0 or index >= keys.size()) { - return {}; - } - return keys[index]; +QString BLD_block_info_provider::key_name(int index) noexcept { + const std::array keys{tr("最低版本"), tr("依附方块"), + tr("发光"), tr("末影人可搬走"), + tr("可燃"), tr("一组数量")}; + if (index < 0 or index >= keys.size()) { + return {}; } - /* - * 0 -> version - * 1 -> need glass - * 2 -> do glow - * 3 -> enderman pickable - * 4 -> burnable - * 5 -> stack size - * */ - static QVariant value_of_attribute(const SlopeCraft::mc_block_interface &blk, - int index) noexcept { - auto bool_to_str = [](bool val) { - if (val) - return "Yes"; - else - return "No"; - }; - switch (index) { - case 0: { // version - const auto ver = blk.getVersion(); - if (ver < uint8_t(SCL_gameVersion::MC12)) { - return tr("远古版本"); - } - if (ver > (uint8_t)SlopeCraft::SCL_maxAvailableVersion()) { - return tr("未来版本"); - } - return QStringLiteral("1.%1").arg(int(ver)); + return keys[index]; +} +/* + * 0 -> version + * 1 -> need glass + * 2 -> do glow + * 3 -> enderman pickable + * 4 -> burnable + * 5 -> stack size + * */ +QVariant BLD_block_info_provider::value_of_attribute( + const SlopeCraft::mc_block_interface &blk, int index) noexcept { + auto bool_to_str = [](bool val) { + if (val) + return "Yes"; + else + return "No"; + }; + switch (index) { + case 0: { // version + const auto ver = blk.getVersion(); + if (ver < uint8_t(SCL_gameVersion::MC12)) { + return tr("远古版本"); } - case 1: // need glass - return bool_to_str(blk.getNeedGlass()); - case 2: - return bool_to_str(blk.getDoGlow()); - case 3: - return bool_to_str(blk.getEndermanPickable()); - case 4: - return bool_to_str(blk.getBurnable()); - case 5: - return blk.getStackSize(); + if (ver > (uint8_t)SlopeCraft::SCL_maxAvailableVersion()) { + return tr("未来版本"); + } + return QStringLiteral("1.%1").arg(int(ver)); } - return {}; + case 1: // need glass + return bool_to_str(blk.getNeedGlass()); + case 2: + return bool_to_str(blk.getDoGlow()); + case 3: + return bool_to_str(blk.getEndermanPickable()); + case 4: + return bool_to_str(blk.getBurnable()); + case 5: + return blk.getStackSize(); } + return {}; +} - QVariant data(const QModelIndex &qmi, int role) const noexcept final { - if (not qmi.isValid()) { - return {}; - } - if (role not_eq Qt::ItemDataRole::DisplayRole) { - return {}; - } - const auto current_block = this->selected_block(); - switch (qmi.column()) { - case 0: - return key_name(qmi.row()); - case 1: { - if (current_block == nullptr) { - return {}; - } - return value_of_attribute(*current_block, qmi.row()); +QVariant BLD_block_info_provider::data(const QModelIndex &qmi, + int role) const noexcept { + if (not qmi.isValid()) { + return {}; + } + if (role not_eq Qt::ItemDataRole::DisplayRole) { + return {}; + } + const auto current_block = this->selected_block(); + switch (qmi.column()) { + case 0: + return key_name(qmi.row()); + case 1: { + if (current_block == nullptr) { + return {}; } + return value_of_attribute(*current_block, qmi.row()); } - return {}; } -}; + return {}; +} BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) : QDialog{parent}, ui{new Ui::BlockListDialog}, block_list_manager{blm} { diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h index 37db0e45..96b44daf 100644 --- a/SlopeCraft/BlockListDialog.h +++ b/SlopeCraft/BlockListDialog.h @@ -20,9 +20,70 @@ namespace Ui { class BlockListDialog; } -class BLD_block_list_provider; -class BLD_block_provider; -class BLD_block_info_provider; +class BLD_block_list_provider : public QAbstractListModel { + Q_OBJECT + public: + const std::function>()> + available_block_lists; + + public: + explicit BLD_block_list_provider( + QWidget* parent, + std::function>()> + cb) + : QAbstractListModel{parent}, available_block_lists{std::move(cb)} {} + BLD_block_list_provider(const BLD_block_list_provider&) = delete; + + int rowCount(const QModelIndex& parent = QModelIndex()) const final; + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const final; +}; +class BLD_block_provider : public QAbstractListModel { + Q_OBJECT + private: + const std::function + available_block_list; + const std::function current_lang; + + public: + explicit BLD_block_provider( + QWidget* parent, + std::function&& cb, + std::function&& lang_cb) + : QAbstractListModel{parent}, + available_block_list{std::move(cb)}, + current_lang{std::move(lang_cb)} {} + + std::vector available_blocks() + const noexcept; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; +}; + +class BLD_block_info_provider : public QAbstractTableModel { + Q_OBJECT + public: + const std::function selected_block; + + public: + explicit BLD_block_info_provider( + QWidget* parent, + std::function&& cb) + : QAbstractTableModel{parent}, selected_block{std::move(cb)} {} + + int rowCount(const QModelIndex& qmi) const final; + + int columnCount(const QModelIndex& qmi) const final; + + static QString key_name(int index) noexcept; + static QVariant value_of_attribute(const SlopeCraft::mc_block_interface& blk, + int index) noexcept; + + QVariant data(const QModelIndex& qmi, int role) const noexcept final; +}; class SCWind; class BlockListDialog : public QDialog { From 3027f818e97c00fd53304aad519a817e481502b7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 10 Aug 2024 22:24:35 +0800 Subject: [PATCH 0954/1123] use unique_ptr in block list manager Signed-off-by: ToKiNoBug --- SlopeCraft/BlockListDialog.cpp | 18 +++++++++--------- SlopeCraft/BlockListDialog.h | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/SlopeCraft/BlockListDialog.cpp b/SlopeCraft/BlockListDialog.cpp index 5331be94..87415872 100644 --- a/SlopeCraft/BlockListDialog.cpp +++ b/SlopeCraft/BlockListDialog.cpp @@ -178,9 +178,9 @@ BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) std::pair> { return blm->get_block_lists(); }; - this->block_list_provider = - new BLD_block_list_provider{this, get_block_lists}; - this->ui->lv_block_lists->setModel(this->block_list_provider); + this->block_list_provider.reset( + new BLD_block_list_provider{this, get_block_lists}); + this->ui->lv_block_lists->setModel(this->block_list_provider.get()); } { auto get_selected_block_list = @@ -198,9 +198,9 @@ BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) return available_lists[idx].second; }; auto get_lang = [parent]() -> SCL_language { return parent->lang(); }; - this->block_provider = - new BLD_block_provider{this, get_selected_block_list, get_lang}; - this->ui->lv_blocks->setModel(this->block_provider); + this->block_provider.reset( + new BLD_block_provider{this, get_selected_block_list, get_lang}); + this->ui->lv_blocks->setModel(this->block_provider.get()); } { auto get_selected_block = @@ -216,9 +216,9 @@ BlockListDialog::BlockListDialog(SCWind *parent, BlockListManager *blm) } return available_blocks[idx]; }; - this->block_info_provider = - new BLD_block_info_provider{this, get_selected_block}; - this->ui->tv_block_props->setModel(this->block_info_provider); + this->block_info_provider.reset( + new BLD_block_info_provider{this, get_selected_block}); + this->ui->tv_block_props->setModel(this->block_info_provider.get()); } connect(this->ui->lv_block_lists->selectionModel(), diff --git a/SlopeCraft/BlockListDialog.h b/SlopeCraft/BlockListDialog.h index 96b44daf..1c3beca3 100644 --- a/SlopeCraft/BlockListDialog.h +++ b/SlopeCraft/BlockListDialog.h @@ -90,9 +90,9 @@ class BlockListDialog : public QDialog { Q_OBJECT private: std::unique_ptr ui; - BLD_block_list_provider* block_list_provider{nullptr}; - BLD_block_provider* block_provider{nullptr}; - BLD_block_info_provider* block_info_provider{nullptr}; + std::unique_ptr block_list_provider{nullptr}; + std::unique_ptr block_provider{nullptr}; + std::unique_ptr block_info_provider{nullptr}; BlockListManager* const block_list_manager; From 1f7e56611ecfd24b930e2013f0884aa8a2cb7719 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 11 Aug 2024 00:11:18 +0800 Subject: [PATCH 0955/1123] skip path encoding problem(partly Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 3 +-- utilities/BlockListManager/BlockListManager.cpp | 4 ++-- utilities/BlockListManager/BlockListManager.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index fa828723..37e0f50b 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -43,8 +43,7 @@ SCWind::SCWind(QWidget *parent) : QMainWindow(parent), ui(new Ui::SCWind) { [this]() { return this->selected_version(); }); QDir::setCurrent(QCoreApplication::applicationDirPath()); - const QString blocks_dir_path = - QStringLiteral("%1/Blocks").arg(QCoreApplication::applicationDirPath()); + const QString blocks_dir_path = QStringLiteral("./Blocks"); const QDir blocks_dir{blocks_dir_path}; if (not blocks_dir.exists()) { QMessageBox::critical( diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 6e9ddfd4..65f31feb 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -63,7 +63,7 @@ uint64_t std::hash::operator()(const selection &s) const noexcept { // } std::unique_ptr -BlockListManager::impl_addblocklist(const QString &filename) noexcept { +BlockListManager::impl_addblocklist(const char *filename) noexcept { std::string errmsg; errmsg.resize(8192); auto sd_err = SlopeCraft::string_deliver::from_string(errmsg); @@ -73,7 +73,7 @@ BlockListManager::impl_addblocklist(const QString &filename) noexcept { SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::block_list_interface *bli = - SlopeCraft::SCL_create_block_list(filename.toLocal8Bit().data(), option); + SlopeCraft::SCL_create_block_list(filename, option); errmsg.resize(sd_err.size); warning.resize(sd_warn.size); diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index d31fc9d0..bb837441 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -137,7 +137,7 @@ class BlockListManager : public QWidget { private: std::unique_ptr - impl_addblocklist(const QString &filename) noexcept; + impl_addblocklist(const char *filename) noexcept; }; #endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H From 9f0880c39482561ad2ae9d0674568dc036dee5e9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 11 Aug 2024 21:52:06 +0800 Subject: [PATCH 0956/1123] SCL supports loading block list from buffer Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 + SlopeCraftL/SlopeCraftL.cpp | 361 +++--------------------------------- SlopeCraftL/SlopeCraftL.h | 3 + SlopeCraftL/block_list.cpp | 313 +++++++++++++++++++++++++++++++ SlopeCraftL/blocklist.h | 60 ++++++ SlopeCraftL/mc_block.cpp | 14 ++ SlopeCraftL/mc_block.h | 29 --- 7 files changed, 422 insertions(+), 360 deletions(-) create mode 100644 SlopeCraftL/block_list.cpp create mode 100644 SlopeCraftL/blocklist.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 70073eae..dd198faf 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -59,6 +59,8 @@ set(SlopeCraft_SCL_sources #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} + block_list.cpp + blocklist.h ) # add this definations to both targets diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index c03e71b1..47d1e58b 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -28,339 +28,12 @@ This file is part of SlopeCraft. #include "SlopeCraftL.h" #include "mc_block.h" +#include "blocklist.h" #include "string_deliver.h" #include "color_table.h" using namespace SlopeCraft; -// mc_block_interface *mc_block_interface::create() { return new mc_block; } - -void mc_block_interface::clear() noexcept { - setBurnable(false); - setDoGlow(false); - setEndermanPickable(false); - setId("minecraft:air"); - setIdOld(""); - setNeedGlass(false); - setVersion(0); - setNameZH(""); - setNameEN(""); - // setWallUseable(false); -} - -using namespace SlopeCraft; - -std::pair parse_block(const nlohmann::json &jo) noexcept( - false) { - mc_block ret; - const int basecolor = jo.at("baseColor"); - if (basecolor < 0 || basecolor >= 64) { - throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; - } - - ret.id = jo.at("id"); - ret.nameZH = jo.at("nameZH"); - ret.nameEN = jo.at("nameEN"); - ret.imageFilename = jo.at("icon"); - ret.version = jo.at("version"); - if (jo.contains("idOld")) { - ret.idOld = jo.at("idOld"); - } else { - ret.idOld = ret.id; - } - - if (jo.contains("endermanPickable")) { - ret.endermanPickable = jo.at("endermanPickable"); - } - - if (jo.contains("isGlowing")) { - ret.doGlow = jo.at("isGlowing"); - } - - if (jo.contains("burnable")) { - ret.burnable = jo.at("burnable"); - } - - if (jo.contains("needGlass")) { - ret.needGlass = jo.at("needGlass"); - } - if (jo.contains("stackSize")) { - const int val = jo.at("stackSize"); - if (val <= 0 or val > 64) { - throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; - } - ret.stackSize = val; - } - - return {basecolor, ret}; -} - -// block_list_interface *impl_createBlockList(const char *filename, -// const blockListOption &option, -// std::string &errmsg) noexcept { -// errmsg.reserve(4096); -// errmsg.clear(); -// -// block_list *bl = new block_list; -// using njson = nlohmann::json; -// try { -// std::ifstream ifs(filename); -// njson jo = njson::parse(ifs, nullptr, true, true); -// -// njson::array_t arr; -// if (jo.contains("FixedBlocks")) { -// arr = std::move(jo.at("FixedBlocks")); -// } else { -// arr = std::move(jo.at("CustomBlocks")); -// } -// -// // parse blocks -// for (size_t idx = 0; idx < arr.size(); idx++) { -// auto temp = parse_block(arr[idx], option.image_dir); -// -// auto ptr = new mc_block; -// *ptr = std::move(temp.second); -// bl->blocks().emplace(ptr, temp.first); -// } -// -// } catch (std::exception &e) { -// delete bl; -// errmsg += fmt::format( -// "Exception occured when parsing blocklist json: \"{}\"\n", e.what()); -// return nullptr; -// } -// -// // load images -// for (auto &pair : bl->blocks()) { -// pair.first->image.resize(16, 16); -// if (!option.callback_load_image(pair.first->getImageFilename(), -// pair.first->image.data())) { -// errmsg += fmt::format( -// "Failed to load image \"{}\", this error will be ignored.\n", -// pair.first->getImageFilename()); -// continue; -// } -// pair.first->image.transposeInPlace(); -// } -// -// return bl; -// } - -struct zip_deleter { - void operator()(zip_t *archive) const noexcept { - if (archive == nullptr) { - return; - } - zip_close(archive); - } -}; - -struct block_list_metainfo { - std::string prefix_ZH; - std::string prefix_EN; - std::vector required_mods; -}; - -tl::expected parse_meta_info( - std::function(const char *filename, - std::vector &dest)> - extract_file, - std::vector &buffer) noexcept { - using njson = nlohmann::json; - // parse meta data - auto res = extract_file("metainfo.json", buffer); - if (res) { - block_list_metainfo ret; - try { - njson jo = njson::parse(buffer, nullptr, true, true); - auto &prefix = jo.at("name prefix"); - ret.prefix_ZH = prefix.at("ZH"); - ret.prefix_EN = prefix.at("EN"); - auto &mods = jo.at("required mods"); - ret.required_mods.reserve(mods.size()); - for (size_t i = 0; i < mods.size(); i++) { - std::string mod_name = mods[i]; - ret.required_mods.emplace_back(std::move(mod_name)); - } - - } catch (const std::exception &e) { - return tl::make_unexpected( - fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); - } - - return ret; - } - return tl::make_unexpected( - fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); -} - -std::tuple, std::string> -impl_create_block_list_from_zip(const char *zip_path) noexcept { - std::string warnings{}; - int error_code = ZIP_ER_OK; - std::unique_ptr archive{ - zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; - if (archive == nullptr) { - return {tl::make_unexpected(fmt::format( - "Failed to open archive \"{}\" with libzip error code {}", - zip_path, error_code)), - warnings}; - } - if (error_code != ZIP_ER_OK) { - auto ret = tl::make_unexpected(fmt::format( - "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", - zip_path, zip_strerror(archive.get()), error_code)); - return {ret, warnings}; - } - - auto extract_file = - [zip_path, &archive]( - const char *filename, - std::vector &dest) -> tl::expected { - dest.clear(); - - int error_code = ZIP_ER_OK; - const int64_t index_i = - zip_name_locate(archive.get(), filename, ZIP_FL_UNCHANGED); - if (index_i < 0) { - return tl::make_unexpected(fmt::format( - "File \"{}\" doesn't exist in archive \"{}\"", filename, zip_path)); - } - const uint64_t index = uint64_t(index_i); - - zip_stat_t stat; - error_code = zip_stat_index(archive.get(), index, ZIP_FL_UNCHANGED, &stat); - if (error_code != ZIP_ER_OK) { - return tl::make_unexpected(fmt::format( - "Failed to get size of file \"{}\" in archive \"{}\" : \"{}\", " - "error code = {}", - filename, zip_path, zip_strerror(archive.get()), error_code)); - } - - const uint64_t file_size = stat.size; - dest.resize(file_size); - - auto file = zip_fopen(archive.get(), filename, ZIP_FL_UNCHANGED); - if (file == nullptr) { - return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive \"{}\" : \"{}\" ", - filename, zip_path, zip_strerror(archive.get()))); - } - - const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); - if (read_bytes != int64_t(file_size)) { - return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive \"{}\", expected " - "{} bytes, but extracted {} bytes : \"{}\" ", - filename, zip_path, file_size, read_bytes, - zip_strerror(archive.get()))); - } - return {}; - }; - - std::vector buffer; - - block_list *bl = new block_list; - - using njson = nlohmann::json; - block_list_metainfo meta_info; - { - const char metainfo_name[] = "metainfo.json"; - const int64_t index = - zip_name_locate(archive.get(), metainfo_name, ZIP_FL_UNCHANGED); - if (index >= 0) { - // metainfo.json exists in the archive - auto mi_res = parse_meta_info(extract_file, buffer); - if (not mi_res) { - fmt::format_to( - std::back_inserter(warnings), - "metainfo.json exist in the archive, but failed to parse it: {}\n", - mi_res.error()); - } - meta_info = std::move(mi_res).value_or(block_list_metainfo{}); - } - } - // parse json array of blocks - { - auto err = extract_file("block_list.json", buffer); - if (!err) { - return {tl::make_unexpected(err.error()), warnings}; - } - } - try { - njson jo = njson::parse(buffer, nullptr, true, true); - if (not jo.is_array()) { - return {tl::make_unexpected( - fmt::format("Json should contain an array directly")), - warnings}; - } - - // parse blocks - for (size_t idx = 0; idx < jo.size(); idx++) { - try { - auto [version, block] = parse_block(jo[idx]); - - block.nameZH = meta_info.prefix_ZH + block.nameZH; - block.nameEN = meta_info.prefix_EN + block.nameEN; - - bl->blocks().emplace(std::make_unique(block), version); - } catch (const std::exception &e) { - return {tl::make_unexpected(fmt::format( - "Failed to parse block at index {}:\n{}", idx, e.what())), - warnings}; - } - } - - } catch (const std::exception &e) { - delete bl; - return {tl::make_unexpected( - fmt::format("nlohmann json exception : {}", e.what())), - warnings}; - } - // load images - std::vector buf_pixel; - for (auto &pair : bl->blocks()) { - { - auto err = extract_file(pair.first->imageFilename.c_str(), buffer); - if (not err) { - warnings += - fmt::format("{}, required by {}", err.error(), pair.first->id); - continue; - } - } - - pair.first->image.resize(16, 16); - { - auto [result, warns] = parse_png_into_argb32(buffer, buf_pixel); - warnings += warns; - - if (!result) { - fmt::format_to(std::back_insert_iterator{warnings}, - "Failed to load image \"{}\" because \"{}\"\n", - pair.first->getImageFilename(), result.error()); - // for (uint8_t byte : buffer) { - // printf("%02X ", int(byte)); - // } - // printf("\n"); - continue; - } - auto image_size = result.value(); - if (image_size.rows != 16 || image_size.cols != 16) { - fmt::format_to(std::back_insert_iterator{warnings}, - "{} has invalid shape, expected 16x16, but found {} " - "rows x {} cols.\n", - pair.first->getImageFilename(), image_size.rows, - image_size.cols); - continue; - } - } - assert(buf_pixel.size() == 16 * 16); - memcpy(pair.first->image.data(), buf_pixel.data(), 256 * sizeof(uint32_t)); - } - - return {bl, warnings}; -} - extern "C" { SCL_EXPORT const float *SCL_get_rgb_basic_colorset_source() { @@ -372,15 +45,41 @@ SCL_EXPORT void SCL_destroy_block(mc_block_interface *b) { delete b; } SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option) { - auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); + auto [res, warnings] = create_block_list_from_file(zip_filename); + + SlopeCraft::write_to_sd(option.warnings, warnings); + if (not res) { + SlopeCraft::write_to_sd(option.error, res.error()); + return nullptr; + } + + auto bl = new block_list{std::move(res.value())}; + assert(bl not_eq nullptr); + return bl; +} + +SCL_EXPORT block_list_interface *SCL_create_block_list_from_buffer( + const void *buffer, size_t buffer_bytes, + const block_list_create_info &option) { + if (buffer == nullptr or buffer_bytes <= 0) { + SlopeCraft::write_to_sd( + option.error, + "SCL_create_block_list_from_buffer met invalid value, either buffer is " + "nullptr or buffer size is 0"); + return nullptr; + } + auto [res, warnings] = create_block_list_from_buffer( + {reinterpret_cast(buffer), buffer_bytes}); SlopeCraft::write_to_sd(option.warnings, warnings); - if (!res) { + if (not res) { SlopeCraft::write_to_sd(option.error, res.error()); return nullptr; } - return res.value(); + auto bl = new block_list{std::move(res.value())}; + assert(bl not_eq nullptr); + return bl; } SCL_EXPORT void SCL_destroy_block_list(block_list_interface *bli) { diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index bebf36f8..c15266c2 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -513,6 +513,9 @@ struct block_list_create_info { [[nodiscard]] SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option); +[[nodiscard]] SCL_EXPORT block_list_interface * +SCL_create_block_list_from_buffer(const void *buffer, size_t buffer_bytes, + const block_list_create_info &option); SCL_EXPORT void SCL_destroy_block_list(block_list_interface *); SCL_EXPORT void SCL_preprocessImage( diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp new file mode 100644 index 00000000..de559901 --- /dev/null +++ b/SlopeCraftL/block_list.cpp @@ -0,0 +1,313 @@ +/* +Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + +SlopeCraft is free software: you can redistribute it and/or modify + it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + + SlopeCraft 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 +General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include +#include +#include +#include +#include + +#include "SlopeCraftL.h" +#include "mc_block.h" +#include "blocklist.h" +#include "string_deliver.h" +#include "color_table.h" + +using namespace SlopeCraft; + +// mc_block_interface *mc_block_interface::create() { return new mc_block; } + +std::pair parse_block(const nlohmann::json &jo) noexcept( + false) { + mc_block ret; + const int basecolor = jo.at("baseColor"); + if (basecolor < 0 || basecolor >= 64) { + throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; + } + + ret.id = jo.at("id"); + ret.nameZH = jo.at("nameZH"); + ret.nameEN = jo.at("nameEN"); + ret.imageFilename = jo.at("icon"); + ret.version = jo.at("version"); + if (jo.contains("idOld")) { + ret.idOld = jo.at("idOld"); + } else { + ret.idOld = ret.id; + } + + if (jo.contains("endermanPickable")) { + ret.endermanPickable = jo.at("endermanPickable"); + } + + if (jo.contains("isGlowing")) { + ret.doGlow = jo.at("isGlowing"); + } + + if (jo.contains("burnable")) { + ret.burnable = jo.at("burnable"); + } + + if (jo.contains("needGlass")) { + ret.needGlass = jo.at("needGlass"); + } + if (jo.contains("stackSize")) { + const int val = jo.at("stackSize"); + if (val <= 0 or val > 64) { + throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; + } + ret.stackSize = val; + } + + return {basecolor, ret}; +} + +struct zip_deleter { + void operator()(zip_t *archive) const noexcept { + if (archive == nullptr) { + return; + } + zip_close(archive); + } +}; + +tl::expected parse_meta_info( + std::function(const char *filename, + std::vector &dest)> + extract_file, + std::vector &buffer) noexcept { + using njson = nlohmann::json; + // parse meta data + auto res = extract_file("metainfo.json", buffer); + if (res) { + block_list_metainfo ret; + try { + njson jo = njson::parse(buffer, nullptr, true, true); + auto &prefix = jo.at("name prefix"); + ret.prefix_ZH = prefix.at("ZH"); + ret.prefix_EN = prefix.at("EN"); + auto &mods = jo.at("required mods"); + ret.required_mods.reserve(mods.size()); + for (size_t i = 0; i < mods.size(); i++) { + std::string mod_name = mods[i]; + ret.required_mods.emplace_back(std::move(mod_name)); + } + + } catch (const std::exception &e) { + return tl::make_unexpected( + fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); + } + + return ret; + } + return tl::make_unexpected( + fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); +} + +block_list_create_result parse_block_list(zip_t *archive) noexcept { + std::string warnings{}; + assert(archive not_eq nullptr); + + auto extract_file = + [archive](const char *filename, + std::vector &dest) -> tl::expected { + dest.clear(); + + int error_code = ZIP_ER_OK; + const int64_t index_i = + zip_name_locate(archive, filename, ZIP_FL_UNCHANGED); + if (index_i < 0) { + return tl::make_unexpected( + fmt::format("File \"{}\" doesn't exist in archive", filename)); + } + const uint64_t index = uint64_t(index_i); + + zip_stat_t stat; + error_code = zip_stat_index(archive, index, ZIP_FL_UNCHANGED, &stat); + if (error_code != ZIP_ER_OK) { + return tl::make_unexpected( + fmt::format("Failed to get size of file \"{}\" in archive: \"{}\", " + "error code = {}", + filename, zip_strerror(archive), error_code)); + } + + const uint64_t file_size = stat.size; + dest.resize(file_size); + + auto file = zip_fopen(archive, filename, ZIP_FL_UNCHANGED); + if (file == nullptr) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive : \"{}\" ", + filename, zip_strerror(archive))); + } + + const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); + if (read_bytes != int64_t(file_size)) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive, expected " + "{} bytes, but extracted {} bytes : \"{}\" ", + filename, file_size, read_bytes, zip_strerror(archive))); + } + return {}; + }; + + std::vector buffer; + + block_list bl{}; + + using njson = nlohmann::json; + block_list_metainfo meta_info; + { + const char metainfo_name[] = "metainfo.json"; + const int64_t index = + zip_name_locate(archive, metainfo_name, ZIP_FL_UNCHANGED); + if (index >= 0) { + // metainfo.json exists in the archive + auto mi_res = parse_meta_info(extract_file, buffer); + if (not mi_res) { + fmt::format_to(std::back_inserter(warnings), + "metainfo.json exist in the archive, but failed to " + "parse it: {}\n", + mi_res.error()); + } + meta_info = std::move(mi_res).value_or(block_list_metainfo{}); + } + } + // parse json array of blocks + { + auto err = extract_file("block_list.json", buffer); + if (!err) { + return {tl::make_unexpected(err.error()), warnings}; + } + } + try { + njson jo = njson::parse(buffer, nullptr, true, true); + if (not jo.is_array()) { + return {tl::make_unexpected( + fmt::format("Json should contain an array directly")), + warnings}; + } + + // parse blocks + for (size_t idx = 0; idx < jo.size(); idx++) { + try { + auto [version, block] = parse_block(jo[idx]); + + block.nameZH = meta_info.prefix_ZH + block.nameZH; + block.nameEN = meta_info.prefix_EN + block.nameEN; + + bl.blocks().emplace(std::make_unique(block), version); + } catch (const std::exception &e) { + return {tl::make_unexpected(fmt::format( + "Failed to parse block at index {}:\n{}", idx, e.what())), + warnings}; + } + } + + } catch (const std::exception &e) { + return {tl::make_unexpected( + fmt::format("nlohmann json exception : {}", e.what())), + warnings}; + } + // load images + std::vector buf_pixel; + for (auto &pair : bl.blocks()) { + { + auto err = extract_file(pair.first->imageFilename.c_str(), buffer); + if (not err) { + warnings += + fmt::format("{}, required by {}", err.error(), pair.first->id); + continue; + } + } + + pair.first->image.resize(16, 16); + { + auto [result, warns] = parse_png_into_argb32(buffer, buf_pixel); + warnings += warns; + + if (!result) { + fmt::format_to(std::back_insert_iterator{warnings}, + "Failed to load image \"{}\" because \"{}\"\n", + pair.first->getImageFilename(), result.error()); + // for (uint8_t byte : buffer) { + // printf("%02X ", int(byte)); + // } + // printf("\n"); + continue; + } + auto image_size = result.value(); + if (image_size.rows != 16 || image_size.cols != 16) { + fmt::format_to(std::back_insert_iterator{warnings}, + "{} has invalid shape, expected 16x16, but found {} " + "rows x {} cols.\n", + pair.first->getImageFilename(), image_size.rows, + image_size.cols); + continue; + } + } + assert(buf_pixel.size() == 16 * 16); + memcpy(pair.first->image.data(), buf_pixel.data(), 256 * sizeof(uint32_t)); + } + + return block_list_create_result{.result{std::move(bl)}, .warnings{warnings}}; +} + +block_list_create_result create_block_list_from_file( + const char *zip_path) noexcept { + std::string warnings{}; + int error_code = ZIP_ER_OK; + std::unique_ptr archive{ + zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; + if (error_code not_eq ZIP_ER_OK or archive == nullptr) { + auto ret = tl::make_unexpected(fmt::format( + "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", + zip_path, zip_strerror(archive.get()), error_code)); + return {ret, warnings}; + } + + return parse_block_list(archive.get()); +} + +block_list_create_result create_block_list_from_buffer( + std::span buffer) noexcept { + zip_error_t err; + zip_source_t *const source = + zip_source_buffer_create(buffer.data(), buffer.size_bytes(), 0, &err); + if (source == nullptr) { + return {tl::make_unexpected(fmt::format("Failed to create zip_source_t: {}", + zip_error_strerror(&err))), + {}}; + } + + std::unique_ptr archive{ + zip_open_from_source(source, ZIP_RDONLY | ZIP_CHECKCONS, &err)}; + if (archive == nullptr) { + zip_source_free(source); + return {tl::make_unexpected(fmt::format("Failed to open zip: {}", + zip_error_strerror(&err))), + {}}; + } + + return parse_block_list(archive.get()); +} \ No newline at end of file diff --git a/SlopeCraftL/blocklist.h b/SlopeCraftL/blocklist.h new file mode 100644 index 00000000..be7915af --- /dev/null +++ b/SlopeCraftL/blocklist.h @@ -0,0 +1,60 @@ +// +// Created by Joseph on 2024/8/11. +// + +#ifndef SLOPECRAFT_BLOCKLIST_H +#define SLOPECRAFT_BLOCKLIST_H + +#include +#include + +#include "mc_block.h" + +struct block_list_metainfo { + std::string prefix_ZH; + std::string prefix_EN; + std::vector required_mods; +}; + +class block_list : public ::SlopeCraft::block_list_interface { + private: + std::map, uint8_t> m_blocks; + + public: + block_list() = default; + block_list(block_list &&) = default; + ~block_list(); + + public: + size_t size() const noexcept override { return m_blocks.size(); } + size_t get_blocks(mc_block_interface **dst, uint8_t *, + size_t capacity_in_elements) noexcept override; + + size_t get_blocks(const mc_block_interface **dst, uint8_t *, + size_t capacity_in_elements) const noexcept override; + + bool contains(const mc_block_interface *cp) const noexcept override { + const mc_block *ptr = dynamic_cast(cp); + return this->m_blocks.contains( + reinterpret_cast &>(ptr)); + } + + public: + const auto &blocks() const noexcept { return this->m_blocks; } + auto &blocks() noexcept { return this->m_blocks; } + + void clear() noexcept; +}; + +struct block_list_create_result { + tl::expected result; + std::string warnings; +}; + +[[nodiscard]] block_list_create_result create_block_list_from_file( + const char *zip_filename) noexcept; + +[[nodiscard]] block_list_create_result create_block_list_from_buffer( + std::span) noexcept; + +#endif // SLOPECRAFT_BLOCKLIST_H diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index 09f636d8..72691c76 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -21,6 +21,7 @@ This file is part of SlopeCraft. */ #include "mc_block.h" +#include "blocklist.h" mc_block::mc_block() { // id = ""; @@ -35,6 +36,19 @@ mc_block::mc_block() { // wallUseable=true; } +void mc_block_interface::clear() noexcept { + setBurnable(false); + setDoGlow(false); + setEndermanPickable(false); + setId("minecraft:air"); + setIdOld(""); + setNeedGlass(false); + setVersion(0); + setNameZH(""); + setNameEN(""); + // setWallUseable(false); +} + size_t block_list::get_blocks(mc_block_interface **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) noexcept { if (capacity_in_elements <= 0) { diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index 51b94f29..eaca2aab 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -129,33 +129,4 @@ class mc_block : public ::SlopeCraft::mc_block_interface { // mc_block& operator =(const mc_block &); }; -class block_list : public ::SlopeCraft::block_list_interface { - private: - std::map, uint8_t> m_blocks; - - public: - block_list() = default; - ~block_list(); - - public: - size_t size() const noexcept override { return m_blocks.size(); } - size_t get_blocks(mc_block_interface **dst, uint8_t *, - size_t capacity_in_elements) noexcept override; - - size_t get_blocks(const mc_block_interface **dst, uint8_t *, - size_t capacity_in_elements) const noexcept override; - - bool contains(const mc_block_interface *cp) const noexcept override { - const mc_block *ptr = dynamic_cast(cp); - return this->m_blocks.contains( - reinterpret_cast &>(ptr)); - } - - public: - const auto &blocks() const noexcept { return this->m_blocks; } - auto &blocks() noexcept { return this->m_blocks; } - - void clear() noexcept; -}; - #endif // SIMPLEBLOCK_H From 40692653036042e86fb0d127657e654b22ae6b50 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 11 Aug 2024 22:04:19 +0800 Subject: [PATCH 0957/1123] SC loads block lists from buffer Signed-off-by: ToKiNoBug --- .../BlockListManager/BlockListManager.cpp | 33 ++++++++++++------- utilities/BlockListManager/BlockListManager.h | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 65f31feb..50463f69 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -63,7 +63,7 @@ uint64_t std::hash::operator()(const selection &s) const noexcept { // } std::unique_ptr -BlockListManager::impl_addblocklist(const char *filename) noexcept { +BlockListManager::impl_addblocklist(const QByteArray &file_content) noexcept { std::string errmsg; errmsg.resize(8192); auto sd_err = SlopeCraft::string_deliver::from_string(errmsg); @@ -73,7 +73,8 @@ BlockListManager::impl_addblocklist(const char *filename) noexcept { SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::block_list_interface *bli = - SlopeCraft::SCL_create_block_list(filename, option); + SlopeCraft::SCL_create_block_list_from_buffer( + file_content.data(), file_content.size(), option); errmsg.resize(sd_err.size); warning.resize(sd_warn.size); @@ -122,20 +123,30 @@ bool BlockListManager::add_blocklist(QString filename) noexcept { return false; } } - // Test for multiple encodings - for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { - std::unique_ptr tmp = - this->impl_addblocklist(encoding.data()); - if (not tmp) { - continue; + QByteArray buffer; + { + QFile file{filename}; + if (not file.open(QFile::OpenModeFlag::ReadOnly | + QFile::OpenModeFlag::ExistingOnly)) { + QMessageBox::warning( + this, tr("无法加载方块列表"), + tr("无法打开文件 \"%1\":%2").arg(filename, file.errorString())); + return false; } + buffer = file.readAll(); + } + + // Test for multiple encodings + std::unique_ptr tmp = + this->impl_addblocklist(buffer); - this->blockslists.emplace_back(name, std::move(tmp)); - return true; + if (not tmp) { + return false; } - return false; + this->blockslists.emplace_back(name, std::move(tmp)); + return true; } void BlockListManager::finish_blocklist() noexcept { diff --git a/utilities/BlockListManager/BlockListManager.h b/utilities/BlockListManager/BlockListManager.h index bb837441..471cb9c3 100644 --- a/utilities/BlockListManager/BlockListManager.h +++ b/utilities/BlockListManager/BlockListManager.h @@ -137,7 +137,7 @@ class BlockListManager : public QWidget { private: std::unique_ptr - impl_addblocklist(const char *filename) noexcept; + impl_addblocklist(const QByteArray &file_content) noexcept; }; #endif // SLOPECRAFT_UTILITIES_BLOCKLISTMANAGER_BLOCKLISTMANAGER_H From d98d855eb7ca060d31b5cd9b31c3eb69a1990bb3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 13 Aug 2024 13:03:09 +0800 Subject: [PATCH 0958/1123] fix corner cases Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index 37e0f50b..b06c66bb 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -374,8 +374,18 @@ std::optional SCWind::selected_cvt_task_idx() const noexcept { if (sel.size() <= 0) { return std::nullopt; } + auto front = sel.front(); + if (not front.isValid()) { + return std::nullopt; + } - return sel.front().row(); + const int idx = front.row(); + if (idx < 0 or idx >= this->tasks.size()) { + // In some corner cases this is true + // Return nullopt so that we don't return a invalid index + return std::nullopt; + } + return idx; } std::vector SCWind::selected_export_task_list() const noexcept { From 2a86f0192f484e3bac1b039a4351cd1b7e22b0dd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 15 Aug 2024 14:54:47 +0800 Subject: [PATCH 0959/1123] show map shape of image Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 10 +- SlopeCraft/SCWind.ui | 258 ++++++++++++++++++++++-------------------- 2 files changed, 143 insertions(+), 125 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index b06c66bb..d48ca666 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -833,9 +833,10 @@ QImage get_converted_image(const SlopeCraft::converted_image &cvted) noexcept { void SCWind::refresh_current_cvt_display( std::optional selected_idx) noexcept { - if (!selected_idx.has_value()) { + if (not selected_idx.has_value()) { this->ui->lb_raw_image->setPixmap({}); this->ui->lb_cvted_image->setPixmap({}); + this->ui->lb_map_shape->setText(""); return; } @@ -843,6 +844,13 @@ void SCWind::refresh_current_cvt_display( this->ui->lb_raw_image->setPixmap( QPixmap::fromImage(this->tasks[idx].original_image)); + { + auto shape = this->tasks[idx].original_image.size(); + const int map_rows = std::ceil(shape.height() / 128.0f); + const int map_cols = std::ceil(shape.width() / 128.0f); + this->ui->lb_map_shape->setText( + tr("%1行,%2列").arg(map_rows).arg(map_cols)); + } auto &task = this->tasks[selected_idx.value()]; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 93ec5e3a..7553ce54 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -370,107 +370,21 @@ 导入图像并转化 - - - - - - 500 - 400 - - - - QTabWidget::TabPosition::North - - - QTabWidget::TabShape::Rounded - - - 0 - - - Qt::TextElideMode::ElideLeft - - - false - - - false - - - false + + + + + + 0 + 0 + - - - 原图 - - - - - - - 0 - 0 - - - - true - - - QFrame::Shape::NoFrame - - - 1 - - - - - - false - - - - - - - - 转化后 - - - - - - - 0 - 0 - - - - true - - - QFrame::Shape::NoFrame - - - 1 - - - - - - - - - - - - - - 0 + + 全部转化 - + 0 @@ -585,6 +499,32 @@ + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + 保存转化后图像 + + + @@ -659,43 +599,113 @@ - - - - - 0 - 0 - - + + - 保存转化后图像 + + + + Qt::AlignmentFlag::AlignCenter - - - - Qt::Orientation::Vertical + + + + 0 - + + + + + - 20 - 40 + 500 + 400 - - - - - - - 0 - 0 - + + QTabWidget::TabPosition::North - - 全部转化 + + QTabWidget::TabShape::Rounded + + + 0 + + + Qt::TextElideMode::ElideLeft + + + false + + + false + + + false + + + 原图 + + + + + + + 0 + 0 + + + + true + + + QFrame::Shape::NoFrame + + + 1 + + + + + + false + + + + + + + + 转化后 + + + + + + + 0 + 0 + + + + true + + + QFrame::Shape::NoFrame + + + 1 + + + + + + + + From c5b21ba2926314dac6b5000bd6fca0d8e0287faa Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 16 Aug 2024 15:41:39 +0800 Subject: [PATCH 0960/1123] fix SCL for 1.12 Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 2 +- utilities/ProcessBlockId/process_block_id.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index ff45c4e3..3ab6f226 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -145,7 +145,7 @@ std::vector color_table_impl::block_id_list( dest.emplace_back("minecraft:air"); } for (auto &blk : this->blocks) { - dest.emplace_back(blk.id); + dest.emplace_back(blk.idForVersion(this->mc_version_)); } return dest; } diff --git a/utilities/ProcessBlockId/process_block_id.h b/utilities/ProcessBlockId/process_block_id.h index 17540e1b..568ff9d1 100644 --- a/utilities/ProcessBlockId/process_block_id.h +++ b/utilities/ProcessBlockId/process_block_id.h @@ -1,11 +1,12 @@ #ifndef SLOPECRAFT_UTILITIES_PROCESS_BLOCK_ID_PROCESS_BLOCK_ID_H #define SLOPECRAFT_UTILITIES_PROCESS_BLOCK_ID_PROCESS_BLOCK_ID_H +#include #include #include #include #include -#include +#include namespace blkid { From 3a3166a22fe5e1a462b88ec79f352fb25ece82ce Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 17 Aug 2024 01:54:09 +0800 Subject: [PATCH 0961/1123] VCL support parse zip from buffer Signed-off-by: ToKiNoBug --- VisualCraftL/Resource_tree.cpp | 121 +++++++++++++++--------- VisualCraftL/Resource_tree.h | 30 ++++-- VisualCraftL/VisualCraftL.cpp | 107 +++++++++++++++------ VisualCraftL/VisualCraftL.h | 12 ++- VisualCraftL/others/VisualCraftL.def.in | 1 + 5 files changed, 184 insertions(+), 87 deletions(-) diff --git a/VisualCraftL/Resource_tree.cpp b/VisualCraftL/Resource_tree.cpp index 78b2a682..991fb2b4 100644 --- a/VisualCraftL/Resource_tree.cpp +++ b/VisualCraftL/Resource_tree.cpp @@ -23,8 +23,9 @@ This file is part of SlopeCraft. #include "Resource_tree.h" #include - +#include #include +#include #include "VCL_internal.h" @@ -49,48 +50,11 @@ auto split_by_slash(std::string_view str) noexcept { return result; } -zipped_folder zipped_folder::from_zip(std::string_view zipname, - bool *const ok) noexcept { +std::optional zipped_folder::from_zip(std::string_view zipname, + zip_t *zip) noexcept { zipped_folder result; - if (true) { - std::filesystem::path path = (const char8_t *)(zipname).data(); - if (zipname.empty()) { - if (ok) - *ok = false; - std::string msg = - fmt::format("The filename \"{}\" of zip is empty.", zipname); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return result; - } - - if (!std::filesystem::is_regular_file(path)) { - if (ok) - *ok = false; - std::string msg = fmt::format( - "The filename \"{}\" does not refer to a regular file.", zipname); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return result; - } - - if (path.extension() != ".zip") { - if (ok) - *ok = false; - std::string msg = fmt::format( - "The filename \"{}\" extension name is not .zip", zipname); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return result; - } - } - int errorcode; - zip_t *const zip = zip_open(zipname.data(), ZIP_RDONLY, &errorcode); - - if (zip == NULL) { - if (ok) - *ok = false; - std::string msg = fmt::format( - "Failed to open zip file : {}, error code = {}", zipname, errorcode); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return result; + if (zip == nullptr) { + return std::nullopt; } const int64_t entry_num = zip_get_num_entries(zip, ZIP_FL_UNCHANGED); @@ -124,8 +88,6 @@ zipped_folder zipped_folder::from_zip(std::string_view zipname, destfile->__data.resize(stat.size); zip_file_t *const zfile = zip_fopen_index(zip, entry_idx, ZIP_FL_UNCHANGED); if (zfile == NULL) { - if (ok) - *ok = false; std::string msg = fmt::format( "Failed to open file in zip. index : {}, file name : {}\n", entry_idx, ::zip_get_name(zip, entry_idx, ZIP_FL_ENC_GUESS)); @@ -136,12 +98,77 @@ zipped_folder zipped_folder::from_zip(std::string_view zipname, zip_fread(zfile, destfile->__data.data(), stat.size); } - if (ok) - *ok = true; - return result; } +std::optional zipped_folder::from_zip( + std::string_view zipname, + const std::span zip_content) noexcept { + zip_error_t err; + zip_source_t *source = zip_source_buffer_create( + zip_content.data(), zip_content.size_bytes(), 0, &err); + if (source == nullptr) { + ::VCL_report(VCL_report_type_t::error, + fmt::format("{} may be a broken zip: {}", zipname, + zip_error_strerror(&err)) + .c_str()); + return std::nullopt; + } + + zip_t *archive = zip_open_from_source(source, ZIP_RDONLY, &err); + if (archive == nullptr) { + ::VCL_report(VCL_report_type_t::error, + fmt::format("{} may be a broken zip: {}", zipname, + zip_error_strerror(&err)) + .c_str()); + zip_source_free(source); + return std::nullopt; + } + auto content = from_zip(zipname, archive); + zip_close(archive); + return std::move(content); +} + +std::optional zipped_folder::from_zip( + std::string_view zipname) noexcept { + if (true) { + std::filesystem::path path = (const char8_t *)(zipname).data(); + if (zipname.empty()) { + std::string msg = + fmt::format("The filename \"{}\" of zip is empty.", zipname); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return std::nullopt; + } + + if (!std::filesystem::is_regular_file(path)) { + std::string msg = fmt::format( + "The filename \"{}\" does not refer to a regular file.", zipname); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return std::nullopt; + } + + if (path.extension() != ".zip") { + std::string msg = fmt::format( + "The filename \"{}\" extension name is not .zip", zipname); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return std::nullopt; + } + } + int errorcode; + zip_t *const zip = zip_open(zipname.data(), ZIP_RDONLY, &errorcode); + + if (zip == NULL) { + std::string msg = fmt::format( + "Failed to open zip file : {}, error code = {}", zipname, errorcode); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return std::nullopt; + } + + auto content = from_zip(zipname, zip); + zip_close(zip); + return std::move(content); +} + void zipped_folder::merge_from_base(const zipped_folder &source_base) noexcept { for (const auto &it : source_base.files) { auto find = this->files.find(it.first); diff --git a/VisualCraftL/Resource_tree.h b/VisualCraftL/Resource_tree.h index de15f294..b14dde60 100644 --- a/VisualCraftL/Resource_tree.h +++ b/VisualCraftL/Resource_tree.h @@ -27,17 +27,20 @@ This file is part of SlopeCraft. #include #include #include - -#include +#include +#include +#include +// forward declaration for zip and zip_t defined in zip.h +struct zip; class zipped_file; class zipped_folder; class zipped_file { -private: + private: std::vector __data; -public: + public: friend class zipped_folder; inline int64_t file_size() const noexcept { return __data.size(); } @@ -49,7 +52,7 @@ class zipped_file { }; class zipped_folder { -public: + public: std::unordered_map subfolders; std::unordered_map files; @@ -70,8 +73,8 @@ class zipped_folder { } } - inline const zipped_folder * - subfolder(std::string_view fdname) const noexcept { + inline const zipped_folder *subfolder( + std::string_view fdname) const noexcept { auto it = subfolders.find(std::string(fdname)); if (it == subfolders.end()) { return nullptr; @@ -86,8 +89,15 @@ class zipped_folder { void merge_from_base(zipped_folder &&source_base) noexcept; - static zipped_folder from_zip(std::string_view zipname, - bool *const ok = nullptr) noexcept; + static std::optional from_zip(std::string_view zipname, + zip *archive) noexcept; + + static std::optional from_zip( + std::string_view zipname) noexcept; + + static std::optional from_zip( + std::string_view zipname, + const std::span zip_content) noexcept; }; -#endif // SLOPECRAFT_VISUALCRAFTL_RESOURCE_TREE_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFTL_RESOURCE_TREE_H \ No newline at end of file diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 02213b69..d37a24ea 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -44,35 +44,8 @@ VCL_EXPORT_FUN void VCL_destroy_kernel(VCL_Kernel *const ptr) { } } -VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( - const int zip_file_count, const char *const *const zip_file_names) { - if (zip_file_count <= 0) { - return nullptr; - } - - bool ok = true; - zipped_folder zf = zipped_folder::from_zip(zip_file_names[0], &ok); - - if (!ok) { - std::string msg = fmt::format("Failed to parse {}\n", zip_file_names[0]); - - VCL_report(VCL_report_type_t::error, msg.c_str(), true); - return nullptr; - } - - for (int zfidx = 1; zfidx < zip_file_count; zfidx++) { - zipped_folder z = zipped_folder::from_zip(zip_file_names[zfidx], &ok); - - if (!ok) { - std::string msg = - fmt::format("Failed to parse {}\n", zip_file_names[zfidx]); - VCL_report(VCL_report_type_t::error, msg.c_str(), true); - return nullptr; - } - - zf.merge_from_base(std::move(z)); - } - +VCL_resource_pack *zip_folder_to_resource_pack( + const zipped_folder &zf) noexcept { VCL_resource_pack *const rp = new VCL_resource_pack; if (!rp->add_colormaps(zf)) { @@ -117,6 +90,82 @@ VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( return rp; } +VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( + const int zip_file_count, const char *const *const zip_file_names) { + if (zip_file_count <= 0) { + return nullptr; + } + auto parse_zip = [](const char *filename) noexcept { + std::optional zf_opt = zipped_folder::from_zip(filename); + + if (not zf_opt) { + std::string msg = fmt::format("Failed to parse {}\n", filename); + VCL_report(VCL_report_type_t::error, msg.c_str(), true); + } + return zf_opt; + }; + + zipped_folder zf; + { + std::optional zf_opt = parse_zip(zip_file_names[0]); + + if (not zf_opt) { + return nullptr; + } + zf = std::move(zf_opt.value()); + } + + for (int zfidx = 1; zfidx < zip_file_count; zfidx++) { + std::optional zf_opt = parse_zip(zip_file_names[0]); + if (not zf_opt) { + return nullptr; + } + + zf.merge_from_base(std::move(zf_opt.value())); + } + + return zip_folder_to_resource_pack(zf); +} + +[[nodiscard]] VCL_EXPORT_FUN VCL_resource_pack * +VCL_create_resource_pack_from_buffers(const size_t zip_count, + const VCL_read_only_buffer *file_contents, + const char *const *const zip_file_names) { + if (zip_count <= 0) { + return nullptr; + } + zipped_folder zf; + { + auto zf_opt = zipped_folder::from_zip( + zip_file_names[0], + {reinterpret_cast(file_contents[0].data), + file_contents[0].size}); + if (not zf_opt) { + VCL_report(VCL_report_type_t::error, + fmt::format("Failed to parse {}\n", zip_file_names[0]).c_str(), + true); + return nullptr; + } + zf = std::move(zf_opt.value()); + } + for (size_t idx = 1; idx < zip_count; idx++) { + auto zf_opt = zipped_folder::from_zip( + zip_file_names[idx], + {reinterpret_cast(file_contents[idx].data), + file_contents[idx].size}); + if (not zf_opt) { + VCL_report( + VCL_report_type_t::error, + fmt::format("Failed to parse {}\n", zip_file_names[idx]).c_str(), + true); + return nullptr; + } + zf.merge_from_base(std::move(zf_opt.value())); + } + + return zip_folder_to_resource_pack(zf); +} + VCL_EXPORT_FUN void VCL_destroy_resource_pack(VCL_resource_pack *const ptr) { if (ptr != nullptr) { delete ptr; diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index 0e5eb35f..3c7ca0f1 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -183,6 +183,11 @@ struct VCL_string_deliver { size_t capacity{0}; }; +struct VCL_read_only_buffer { + const void *data{nullptr}; + size_t size{0}; +}; + class VCL_Kernel; class VCL_resource_pack; class VCL_block_state_list; @@ -297,7 +302,12 @@ VCL_EXPORT_FUN void VCL_destroy_kernel(VCL_Kernel *const ptr); // create and destroy resource pack [[nodiscard]] VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( const int zip_file_count, const char *const *const zip_file_names); -VCL_EXPORT_FUN void VCL_destroy_resource_pack(VCL_resource_pack *const ptr); +[[nodiscard]] VCL_EXPORT_FUN VCL_resource_pack * +VCL_create_resource_pack_from_buffers(const size_t zip_count, + const VCL_read_only_buffer *file_contents, + const char *const *const zip_file_names); +VCL_EXPORT_FUN +void VCL_destroy_resource_pack(VCL_resource_pack *const ptr); // create and destroy block state list [[nodiscard]] VCL_EXPORT_FUN VCL_block_state_list *VCL_create_block_state_list( diff --git a/VisualCraftL/others/VisualCraftL.def.in b/VisualCraftL/others/VisualCraftL.def.in index 3c31f2ba..58101a32 100644 --- a/VisualCraftL/others/VisualCraftL.def.in +++ b/VisualCraftL/others/VisualCraftL.def.in @@ -2,6 +2,7 @@ EXPORTS VCL_create_kernel VCL_destroy_kernel VCL_create_resource_pack +VCL_create_resource_pack_from_buffers VCL_destroy_resource_pack VCL_create_block_state_list VCL_destroy_block_state_list From f603d7ae150f340a808a0882bab2cbc9d0e79153 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 17 Aug 2024 02:10:34 +0800 Subject: [PATCH 0962/1123] VC create resource pack from buffer Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index b24ff011..76999465 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -242,12 +242,33 @@ VCL_resource_pack *VCWind::create_resource_pack( rpfiles_qba.reserve(opt.zips.size()); std::vector rpfiles_charp; rpfiles_charp.reserve(opt.zips.size()); + + std::vector rp_contents; + std::vector rp_buffer_references; + for (auto &qstr : opt.zips) { rpfiles_qba.emplace_back(qstr.toUtf8()); rpfiles_charp.emplace_back(rpfiles_qba.back().data()); - } - - return VCL_create_resource_pack(rpfiles_charp.size(), rpfiles_charp.data()); + QFile file{qstr}; + if (not file.open(QIODevice::OpenModeFlag::ReadOnly | + QIODevice::OpenModeFlag::ExistingOnly)) { + QMessageBox::critical(nullptr, tr("无法读取文件 %1").arg(qstr), + file.errorString()); + return nullptr; + } + rp_contents.emplace_back(file.readAll()); + const auto &content = rp_contents.back(); + rp_buffer_references.emplace_back(content.data(), content.size()); + file.close(); + } + assert(rpfiles_qba.size() == rpfiles_charp.size()); + assert(rpfiles_charp.size() == rp_contents.size()); + assert(rp_contents.size() == rp_buffer_references.size()); + + return VCL_create_resource_pack_from_buffers( + rp_contents.size(), rp_buffer_references.data(), rpfiles_charp.data()); + // return VCL_create_resource_pack(rpfiles_charp.size(), + // rpfiles_charp.data()); } // utilitiy functions From e22ee5c437451cd11e7e442d09187ee40c0d7bd6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 19 Aug 2024 17:15:25 +0800 Subject: [PATCH 0963/1123] fix windows CI with gcc Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c5f55a41..c74f9141 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -229,7 +229,9 @@ jobs: echo "env:path = $env:path" mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected magic-enum + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected + + # magic-enum - name: Install OpenCL with vcpkg From a1e1df97f9a56307e56056110e166360557eb2b8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 19 Aug 2024 17:18:04 +0800 Subject: [PATCH 0964/1123] fix windows CI with gcc Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c74f9141..9625df12 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -229,9 +229,9 @@ jobs: echo "env:path = $env:path" mkdir C:\vcpkg\downloads curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected - - # magic-enum + cd C:/vcpkg + git pull + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected magic-enum - name: Install OpenCL with vcpkg From 60ff2c2a84c474a2c70b4ad7fcd099831ad43655 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 16 Sep 2024 18:14:38 +0800 Subject: [PATCH 0965/1123] make version_set a standalone lib Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 1 + VisualCraftL/BlockStateList.h | 53 +--------------------- VisualCraftL/CMakeLists.txt | 4 +- utilities/CMakeLists.txt | 1 + utilities/version_set/CMakeLists.txt | 3 ++ utilities/version_set/version_set.hpp | 64 +++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 53 deletions(-) create mode 100644 utilities/version_set/CMakeLists.txt create mode 100644 utilities/version_set/version_set.hpp diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index dd198faf..18ca9af7 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -93,6 +93,7 @@ set(SlopeCraft_SCL_link_libs FlatDiagram libpng_reader sNBT-formatter + version_set ZLIB::ZLIB OpenMP::OpenMP_CXX diff --git a/VisualCraftL/BlockStateList.h b/VisualCraftL/BlockStateList.h index ba00aec2..07ff3ae1 100644 --- a/VisualCraftL/BlockStateList.h +++ b/VisualCraftL/BlockStateList.h @@ -31,60 +31,9 @@ This file is part of SlopeCraft. #include #include +#include "version_set.hpp" #include "VisualCraftL.h" -constexpr inline size_t major_version_to_idx(SCL_gameVersion v) noexcept { - switch (v) { - case SCL_gameVersion::FUTURE: - return 31; - - default: - return size_t(v); - } -} - -class version_set { - private: - std::bitset<32> set{0}; - - public: - version_set() = default; - - explicit version_set(uint32_t val) : set(val) {} - - static version_set all() noexcept { - version_set ret(~uint32_t(0)); - return ret; - } - - inline bool match(SCL_gameVersion v) const noexcept { - return set[major_version_to_idx(v)]; - } - - inline auto operator[](SCL_gameVersion v) noexcept { - return set[major_version_to_idx(v)]; - } - - inline auto operator[](SCL_gameVersion v) const noexcept { - return set[major_version_to_idx(v)]; - } - - inline uint64_t to_u32() const noexcept { return set.to_ulong(); } - - inline bool operator==(const version_set &vs) const noexcept { - return this->to_u32() == vs.to_u32(); - } - - SCL_gameVersion introduced_version() const noexcept { - for (size_t i = 0; i < 32; i++) { - if (this->set[i]) { - return SCL_gameVersion(i); - } - } - return SCL_gameVersion::FUTURE; - } -}; - class VCL_block_state_list; class VCL_block { diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 0476a16d..08afc56f 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -97,13 +97,15 @@ target_include_directories(VisualCraftL_static PUBLIC set(VCL_link_libs ColorManip + version_set libzip::zip ZLIB::ZLIB PNG::PNG ${VCL_libzip_additions} Schem fmt::fmt - ProcessBlockId) + ProcessBlockId +) target_link_libraries(VisualCraftL PRIVATE $) target_link_libraries(VisualCraftL_static PUBLIC ${VCL_link_libs}) diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 56d378b9..83f78a0b 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(MCDataVersion) +add_subdirectory(version_set) add_subdirectory(GPUWrapper) add_subdirectory(ColorManip) add_subdirectory(ProcessBlockId) diff --git a/utilities/version_set/CMakeLists.txt b/utilities/version_set/CMakeLists.txt new file mode 100644 index 00000000..acbcc4b4 --- /dev/null +++ b/utilities/version_set/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(version_set INTERFACE) +target_sources(version_set INTERFACE version_set.hpp) +target_include_directories(version_set INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/utilities/version_set/version_set.hpp b/utilities/version_set/version_set.hpp new file mode 100644 index 00000000..3043ac25 --- /dev/null +++ b/utilities/version_set/version_set.hpp @@ -0,0 +1,64 @@ +// +// Created by Joseph on 2024/9/15. +// + +#ifndef SLOPECRAFT_VERSION_SET_H +#define SLOPECRAFT_VERSION_SET_H + +#include +#include +#include "SC_GlobalEnums.h" + +constexpr inline size_t major_version_to_idx(SCL_gameVersion v) noexcept { + switch (v) { + case SCL_gameVersion::FUTURE: + return 31; + + default: + return size_t(v); + } +} + +class version_set { + private: + std::bitset<32> set{0}; + + public: + version_set() = default; + + explicit version_set(uint32_t val) : set(val) {} + + static version_set all() noexcept { + version_set ret(~uint32_t(0)); + return ret; + } + + inline bool match(SCL_gameVersion v) const noexcept { + return set[major_version_to_idx(v)]; + } + + inline auto operator[](SCL_gameVersion v) noexcept { + return set[major_version_to_idx(v)]; + } + + inline auto operator[](SCL_gameVersion v) const noexcept { + return set[major_version_to_idx(v)]; + } + + inline uint64_t to_u32() const noexcept { return set.to_ulong(); } + + inline bool operator==(const version_set &vs) const noexcept { + return this->to_u32() == vs.to_u32(); + } + + SCL_gameVersion introduced_version() const noexcept { + for (size_t i = 0; i < 32; i++) { + if (this->set[i]) { + return SCL_gameVersion(i); + } + } + return SCL_gameVersion::FUTURE; + } +}; + +#endif // SLOPECRAFT_VERSION_SET_H From 1b3a69226da28bed741dee497b0d06a06d49acda Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 16 Sep 2024 19:33:23 +0800 Subject: [PATCH 0966/1123] add new attribute "needStone" for SCL Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 80 ++++++++++++++++++++++++------ SlopeCraftL/SlopeCraftL.h | 3 ++ SlopeCraftL/block_list.cpp | 25 ++++++++++ SlopeCraftL/mc_block.cpp | 4 ++ SlopeCraftL/mc_block.h | 19 +++++-- SlopeCraftL/structure_3D.cpp | 10 +++- utilities/Schem/entity.h | 1 + 7 files changed, 119 insertions(+), 23 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index df4d7c83..ec70ae78 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -286,7 +286,10 @@ "nameEN": "White glass", "icon": "white_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=white]" + "idOld": "minecraft:stained_glass[color=white]", + "needStone": [ + 12 + ] }, { "baseColor": 8, @@ -457,7 +460,10 @@ "nameEN": "Orange glass", "icon": "orange_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=orange]" + "idOld": "minecraft:stained_glass[color=orange]", + "needStone": [ + 12 + ] }, { "baseColor": 15, @@ -578,7 +584,10 @@ "nameEN": "Magenta glass", "icon": "magenta_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=magenta]" + "idOld": "minecraft:stained_glass[color=magenta]", + "needStone": [ + 12 + ] }, { "baseColor": 16, @@ -613,7 +622,10 @@ "nameEN": "Light blue glass", "icon": "light_blue_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=light_blue]" + "idOld": "minecraft:stained_glass[color=light_blue]", + "needStone": [ + 12 + ] }, { "baseColor": 18, @@ -640,7 +652,10 @@ "nameEN": "yellow glass", "icon": "yellow_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=yellow]" + "idOld": "minecraft:stained_glass[color=yellow]", + "needStone": [ + 12 + ] }, { "baseColor": 18, @@ -675,7 +690,10 @@ "nameEN": "Lime glass", "icon": "lime_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=lime]" + "idOld": "minecraft:stained_glass[color=lime]", + "needStone": [ + 12 + ] }, { "baseColor": 20, @@ -702,7 +720,10 @@ "nameEN": "Pink glass", "icon": "pink_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=pink]" + "idOld": "minecraft:stained_glass[color=pink]", + "needStone": [ + 12 + ] }, { "baseColor": 20, @@ -739,7 +760,10 @@ "nameEN": "Gray glass", "icon": "gray_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=gray]" + "idOld": "minecraft:stained_glass[color=gray]", + "needStone": [ + 12 + ] }, { "baseColor": 21, @@ -775,7 +799,10 @@ "nameEN": "Light gray glass", "icon": "light_gray_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=silver]" + "idOld": "minecraft:stained_glass[color=silver]", + "needStone": [ + 12 + ] }, { "baseColor": 23, @@ -803,7 +830,10 @@ "nameEN": "Cyan glass", "icon": "cyan_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=cyan]" + "idOld": "minecraft:stained_glass[color=cyan]", + "needStone": [ + 12 + ] }, { "baseColor": 23, @@ -848,7 +878,10 @@ "nameEN": "Purple glass", "icon": "purple_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=purple]" + "idOld": "minecraft:stained_glass[color=purple]", + "needStone": [ + 12 + ] }, { "baseColor": 24, @@ -884,7 +917,10 @@ "nameEN": "Blue glass", "icon": "blue_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=blue]" + "idOld": "minecraft:stained_glass[color=blue]", + "needStone": [ + 12 + ] }, { "baseColor": 26, @@ -912,7 +948,10 @@ "nameEN": "Brown glass", "icon": "brown_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=brown]" + "idOld": "minecraft:stained_glass[color=brown]", + "needStone": [ + 12 + ] }, { "baseColor": 26, @@ -966,7 +1005,10 @@ "nameEN": "Green glass", "icon": "green_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=green]" + "idOld": "minecraft:stained_glass[color=green]", + "needStone": [ + 12 + ] }, { "baseColor": 27, @@ -1002,7 +1044,10 @@ "nameEN": "Red glass", "icon": "red_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=red]" + "idOld": "minecraft:stained_glass[color=red]", + "needStone": [ + 12 + ] }, { "baseColor": 28, @@ -1075,7 +1120,10 @@ "nameEN": "Blakc glass", "icon": "black_stained_glass.png", "version": 0, - "idOld": "minecraft:stained_glass[color=black]" + "idOld": "minecraft:stained_glass[color=black]", + "needStone": [ + 12 + ] }, { "baseColor": 29, diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index c15266c2..c97154dc 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -173,6 +173,9 @@ class mc_block_interface { virtual void clear() noexcept; virtual const char *idForVersion(SCL_gameVersion ver) const noexcept = 0; + + virtual bool getNeedStone(SCL_gameVersion v) const noexcept = 0; + virtual void setNeedStone(SCL_gameVersion v, bool) noexcept = 0; }; class block_list_interface { diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp index de559901..f1ea8369 100644 --- a/SlopeCraftL/block_list.cpp +++ b/SlopeCraftL/block_list.cpp @@ -78,6 +78,31 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( } ret.stackSize = val; } + if (jo.contains("needStone")) { + auto &need_stone = jo.at("needStone"); + if (need_stone.is_boolean()) { + ret.needStone = version_set::all(); + } else if (need_stone.is_array()) { + for (auto ver : need_stone) { + if (not ver.is_number_integer()) { + throw std::runtime_error{ + fmt::format("needStone must be boolean or array of versions, but " + "found non-integer element in array")}; + } + const int ver_int = ver; + if (ver_int < static_cast(SCL_gameVersion::MC12) or + ver_int > static_cast(SCL_maxAvailableVersion())) { + throw std::runtime_error{fmt::format( + "Found invalid version {} in version list of needStone", + ver_int)}; + } + ret.needStone[static_cast(ver_int)] = true; + } + } else { + throw std::runtime_error{ + fmt::format("needStone must be boolean or array of versions")}; + } + } return {basecolor, ret}; } diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index 72691c76..ce2d8eeb 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -46,6 +46,10 @@ void mc_block_interface::clear() noexcept { setVersion(0); setNameZH(""); setNameEN(""); + for (auto ver = static_cast(SCL_gameVersion::MC12); + ver <= static_cast(SCL_maxAvailableVersion()); ver++) { + this->setNeedStone(static_cast(ver), false); + } // setWallUseable(false); } diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index eaca2aab..2301ec20 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -23,8 +23,6 @@ This file is part of SlopeCraft. #ifndef SIMPLEBLOCK_H #define SIMPLEBLOCK_H -#include "SCLDefines.h" -using namespace SlopeCraft; #include #include #include @@ -32,6 +30,10 @@ using namespace SlopeCraft; #include #include +#include "SCLDefines.h" +using namespace SlopeCraft; +#include + typedef std::vector stringList; class mc_block : public ::SlopeCraft::mc_block_interface { @@ -39,12 +41,13 @@ class mc_block : public ::SlopeCraft::mc_block_interface { mc_block(); ~mc_block(){}; std::string id{}; - uint8_t version{0}; std::string idOld{}; std::string nameZH{}; std::string nameEN{}; std::string imageFilename{}; Eigen::Array image; + version_set needStone{0}; + uint8_t version{0}; bool needGlass{false}; bool doGlow{false}; bool endermanPickable{false}; @@ -76,6 +79,9 @@ class mc_block : public ::SlopeCraft::mc_block_interface { memcpy(dest_row_major, this->image.data(), this->image.size() * sizeof(uint32_t)); } + bool getNeedStone(SCL_gameVersion v) const noexcept override { + return this->needStone[v]; + } void setId(const char *_id) noexcept override { id = _id; }; void setVersion(unsigned char _ver) noexcept override { version = _ver; }; @@ -91,9 +97,12 @@ class mc_block : public ::SlopeCraft::mc_block_interface { void setStackSize(uint8_t stack_size) noexcept override { this->stackSize = std::max(stack_size, 1); } + void setNeedStone(SCL_gameVersion v, bool ns) noexcept override { + this->needStone[v] = ns; + } - void setNameZH(const char *__nzh) noexcept override { this->nameZH = __nzh; } - void setNameEN(const char *__nen) noexcept override { this->nameEN = __nen; } + void setNameZH(const char *nzh) noexcept override { this->nameZH = nzh; } + void setNameEN(const char *nzh) noexcept override { this->nameEN = nzh; } void setImage(const uint32_t *src, bool is_row_major) noexcept override { if (is_row_major) { Eigen::Map> map(src, 16, 16); diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index abe50c0c..bbc16fbc 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -123,8 +123,14 @@ std::optional structure_3D_impl::create( const int x = c + 1; const int y = low_map(r + 1, c); const int z = r + 1; - if (y >= 1 && table.blocks[base_color(r + 1, c)].needGlass) { - ret.schem(x, y - 1, z) = 0 + 1; + if (y >= 1) { + auto &blk = table.blocks[base_color(r + 1, c)]; + if (blk.needGlass) { + ret.schem(x, y - 1, z) = 0 + 1; + } + if (blk.needStone[table.mc_version_]) { + ret.schem(x, y - 1, z) = 11 + 1; + } } const bool fire_proof = fixed_opt.fire_proof && table.blocks[base_color(r + 1, c)].burnable; diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h index fabc1aa6..5ad4b7af 100644 --- a/utilities/Schem/entity.h +++ b/utilities/Schem/entity.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include From 1d249bc6cb566f395b136bfd3ed37a01deca63cc Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 16 Sep 2024 19:39:39 +0800 Subject: [PATCH 0967/1123] replace stone instead of glass for pressure plates Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index ec70ae78..71ddc3f4 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -176,7 +176,7 @@ "nameEN": "Iron pressure plate", "icon": "heavy_weighted_pressure_plate.png", "version": 0, - "needGlass": true, + "needStone": true, "wallUseable": false }, { @@ -1205,7 +1205,7 @@ "nameEN": "Gold pressure plate", "icon": "light_weighted_pressure_plate.png", "version": 0, - "needGlass": true + "needStone": true }, { "baseColor": 30, From f1542f5b98edb3e537f6bf37b51e2ed696f02f22 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 16 Sep 2024 23:13:03 +0800 Subject: [PATCH 0968/1123] add slicing and copy to libSchem Signed-off-by: ToKiNoBug --- SlopeCraftL/converted_image.cpp | 2 +- utilities/Schem/CMakeLists.txt | 5 ++ utilities/Schem/Schem.cpp | 138 +++++++++++++++++++++++++++----- utilities/Schem/Schem.h | 38 ++++++++- utilities/Schem/entity.h | 16 ++++ utilities/Schem/item.h | 6 ++ 6 files changed, 184 insertions(+), 21 deletions(-) diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 5b9ab891..00f90e14 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -734,4 +734,4 @@ bool converted_image_impl::export_assembled_maps_vanilla_structure( return false; } return true; -} \ No newline at end of file +} diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 0951543d..fb9cded2 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -20,6 +20,8 @@ find_package(cereal REQUIRED) find_package(fmt REQUIRED) find_package(magic_enum REQUIRED) +find_package(Boost) + # target_compile_options(Schem BEFORE PUBLIC -std=c++17) target_link_libraries(Schem PUBLIC NBTWriter @@ -29,6 +31,9 @@ target_link_libraries(Schem PUBLIC magic_enum::magic_enum NBTWriter ) +if (TARGET Boost::multi_array) + target_link_libraries(Schem PUBLIC Boost::multi_array) +endif () target_compile_features(Schem PUBLIC cxx_std_23) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 41b49e1d..10343863 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -20,15 +20,17 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "Schem.h" - +#include +#include #include - +#include #include #include #include #include +#include "Schem.h" + #include "../NBTWriter/NBTWriter.h" #include "bit_shrink.h" @@ -138,7 +140,105 @@ bool Schem::have_invalid_block( return false; } -enum class __mushroom_type : uint8_t { +Schem Schem::slice_no_check(std::span, 3> + xyz_index_range) const noexcept { + Schem ret; + ret.block_id_list = this->block_id_list; + ret.MC_major_ver = this->MC_major_ver; + ret.MC_data_ver = this->MC_data_ver; + + ret.entities.reserve(this->entities.size()); + Eigen::Array3d pos_min, pos_max; + for (size_t dim = 0; dim < 3; dim++) { + pos_min[dim] = xyz_index_range[dim].first; + pos_max[dim] = xyz_index_range[dim].second; + } + { + Eigen::array start, extent; + start[0] = xyz_index_range[0].first; + start[1] = xyz_index_range[2].first; + start[2] = xyz_index_range[1].first; + extent[0] = xyz_index_range[0].second - xyz_index_range[0].first; + extent[1] = xyz_index_range[2].second - xyz_index_range[2].first; + extent[2] = xyz_index_range[1].second - xyz_index_range[1].first; + ret.xzy = this->xzy.slice(start, extent); + } + + for (auto &entity : this->entities) { + const auto pos_std = entity->position(); + const Eigen::Array3d pos{pos_std[0], pos_std[1], pos_std[2]}; + if ((pos >= pos_min and pos < pos_max).all()) { + ret.entities.emplace_back(entity->clone()); + } + } + + return ret; +} + +tl::expected, 3>, std::string> +Schem::split_by_block_size( + std::span x_block_length, + std::span y_block_length, + std::span z_block_length) const noexcept { + // check input block length and compute index ranges + std::array>, 3> xyz_block_index_pairs; + { + std::array, 3> xyz_block_len{ + x_block_length, y_block_length, z_block_length}; + std::array block_len_sum{0, 0, 0}; + std::array shape{this->x_range(), this->y_range(), + this->z_range()}; + for (size_t dim = 0; dim < 3; dim++) { + int64_t cur_block_start_index = 0; + for (auto [blk_idx, block_len] : + xyz_block_len[dim] | std::views::enumerate) { + if (block_len <= 0) { + return tl::make_unexpected(fmt::format( + "Found non-positive block length in dim = {}, block index = {}", + dim, blk_idx)); + } + block_len_sum[dim] += block_len; + const int64_t cur_block_end_index = + static_cast(block_len_sum[dim]); + assert(cur_block_end_index > cur_block_start_index); + xyz_block_index_pairs[dim].emplace_back(cur_block_start_index, + cur_block_end_index); + cur_block_start_index = cur_block_end_index; + } + if (block_len_sum[dim] not_eq shape[dim]) { + return tl::make_unexpected(fmt::format( + "The sum of block length of dim {} is {}, which is not identical " + "to shape on this dim({}), ", + dim, block_len_sum[dim], shape[dim])); + } + } + } + + boost::multi_array, 3> ret{ + boost::extents[xyz_block_index_pairs[0].size()] + [xyz_block_index_pairs[1].size()] + [xyz_block_index_pairs[2].size()]}; + + for (auto [x_idx, x_range] : + xyz_block_index_pairs[0] | std::views::enumerate) { + for (auto [y_idx, y_range] : + xyz_block_index_pairs[1] | std::views::enumerate) { + for (auto [z_idx, z_range] : + xyz_block_index_pairs[2] | std::views::enumerate) { + const Eigen::Array offset{x_range.first, y_range.first, + z_range.first}; + auto &dest = ret[x_idx][y_idx][z_idx]; + dest.offset = offset; + dest.content = + this->slice_no_check(std::array, 3>{ + x_range, y_range, z_range}); + } + } + } + return ret; +} + +enum class mushroom_type : uint8_t { not_mushroom = 0, red_mushroom = 1, brown_mushroom = 2, @@ -192,7 +292,7 @@ void Schem::process_mushroom_states() noexcept { u6_to_ele_stem[u6] = this->block_id_list.size() - 1; } } - std::vector<__mushroom_type> is_mushroom_LUT; + std::vector is_mushroom_LUT; is_mushroom_LUT.resize(this->block_id_list.size()); for (int blockidx = 0; blockidx < int(this->block_id_list.size()); @@ -200,18 +300,18 @@ void Schem::process_mushroom_states() noexcept { const auto &block_id = this->block_id_list[blockidx]; const auto pure_id = ::to_pure_block_id(block_id); if (pure_id == id_red) { - is_mushroom_LUT[blockidx] = __mushroom_type::red_mushroom; + is_mushroom_LUT[blockidx] = mushroom_type::red_mushroom; continue; } if (pure_id == id_brown) { - is_mushroom_LUT[blockidx] = __mushroom_type::brown_mushroom; + is_mushroom_LUT[blockidx] = mushroom_type::brown_mushroom; continue; } if (pure_id == id_stem) { - is_mushroom_LUT[blockidx] = __mushroom_type::mushroom_stem; + is_mushroom_LUT[blockidx] = mushroom_type::mushroom_stem; continue; } - is_mushroom_LUT[blockidx] = __mushroom_type::not_mushroom; + is_mushroom_LUT[blockidx] = mushroom_type::not_mushroom; } // fix the correct state @@ -219,9 +319,9 @@ void Schem::process_mushroom_states() noexcept { for (int64_t z = 0; z < z_range(); z++) { for (int64_t x = 0; x < x_range(); x++) { // if current block is not mushroom, continue - const __mushroom_type current_mushroom_type = + const mushroom_type current_mushroom_type = is_mushroom_LUT[this->operator()(x, y, z)]; - if (current_mushroom_type == __mushroom_type::not_mushroom) { + if (current_mushroom_type == mushroom_type::not_mushroom) { continue; } @@ -229,42 +329,42 @@ void Schem::process_mushroom_states() noexcept { // match the correct side if (x + 1 < x_range()) { const ele_t ele_of_side = this->operator()(x + 1, y, z); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.east() = false; } } if (x - 1 >= 0) { const ele_t ele_of_side = this->operator()(x - 1, y, z); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.west() = false; } } if (y + 1 < y_range()) { const ele_t ele_of_side = this->operator()(x, y + 1, z); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.up() = false; } } if (y - 1 >= 0) { const ele_t ele_of_side = this->operator()(x, y - 1, z); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.down() = false; } } if (z + 1 < z_range()) { const ele_t ele_of_side = this->operator()(x, y, z + 1); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.south() = false; } } if (z - 1 >= 0) { const ele_t ele_of_side = this->operator()(x, y, z - 1); - if (is_mushroom_LUT[ele_of_side] != __mushroom_type::not_mushroom) { + if (is_mushroom_LUT[ele_of_side] != mushroom_type::not_mushroom) { side.north() = false; } } @@ -272,10 +372,10 @@ void Schem::process_mushroom_states() noexcept { // write in the correct value of ele_t ele_t corrected_ele = invalid_ele_t; switch (current_mushroom_type) { - case __mushroom_type::brown_mushroom: + case mushroom_type::brown_mushroom: corrected_ele = u6_to_ele_brown[side.u6()]; break; - case __mushroom_type::red_mushroom: + case mushroom_type::red_mushroom: corrected_ele = u6_to_ele_red[side.u6()]; break; default: diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 15a34d1f..0ff688aa 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -27,6 +27,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ This file is part of SlopeCraft. #include #include +#include + #include "SC_GlobalEnums.h" #include "entity.h" @@ -86,13 +89,29 @@ class Schem { public: Schem() { xzy.resize(0, 0, 0); } - Schem(const Schem &) = delete; + Schem(const Schem &src) noexcept + : block_id_list{src.block_id_list}, + MC_major_ver{src.MC_major_ver}, + MC_data_ver{src.MC_data_ver}, + xzy{src.xzy} { + this->entities.reserve(src.entities.size()); + for (auto &entity : src.entities) { + this->entities.emplace_back(entity->clone()); + } + } Schem(Schem &&) = default; Schem(int64_t x, int64_t y, int64_t z) { xzy.resize(x, y, z); xzy.setZero(); } + Schem &operator=(Schem &&src) = default; + Schem &operator=(const Schem &src) noexcept { + Schem temp{src}; + std::swap(*this, temp); + return *this; + } + std::string check_size() const noexcept; static std::string check_size(int64_t x, int64_t y, int64_t z) noexcept; @@ -235,6 +254,23 @@ class Schem { auto &entity_list() noexcept { return this->entities; } auto &entity_list() const noexcept { return this->entities; } + template + struct schem_slice { + Eigen::Array offset; + T content; + }; + + [[nodiscard]] tl::expected, 3>, + std::string> + split_by_block_size(std::span x_block_length, + std::span y_block_length, + std::span z_block_length) const noexcept; + + protected: + [[nodiscard]] Schem slice_no_check( + std::span, 3> xyz_index_range) + const noexcept; + public: static void update_error_dest( const tl::expected> &result, diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h index 5ad4b7af..3bb18fd7 100644 --- a/utilities/Schem/entity.h +++ b/utilities/Schem/entity.h @@ -36,6 +36,8 @@ class entity { virtual tl::expected dump( NBT::NBTWriter& destination, MCDataVersion::MCDataVersion_t data_version) const noexcept; + + virtual std::unique_ptr clone() const noexcept = 0; }; enum class hangable_facing_direction : int8_t { @@ -106,6 +108,16 @@ class item_frame : public hangable { item_frame_variant variant_{item_frame_variant::common}; + explicit item_frame() = default; + + explicit item_frame(const item_frame& src) + : fixed_{src.fixed_}, + invisible_{src.invisible_}, + item_rotation{src.item_rotation}, + item_drop_chance{src.item_drop_chance}, + variant_{src.variant_}, + item_{src.item_->clone()} {} + std::string_view id() const noexcept override { switch (this->variant_) { case item_frame_variant::common: @@ -119,6 +131,10 @@ class item_frame : public hangable { tl::expected dump( NBT::NBTWriter& destination, MCDataVersion::MCDataVersion_t data_version) const noexcept override; + + std::unique_ptr clone() const noexcept override { + return std::make_unique(*this); + } }; } // namespace libSchem diff --git a/utilities/Schem/item.h b/utilities/Schem/item.h index cf684314..7a5aef64 100644 --- a/utilities/Schem/item.h +++ b/utilities/Schem/item.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,8 @@ class item { NBT::NBTWriter&, MCDataVersion::MCDataVersion_t data_version) const noexcept; + [[nodiscard]] virtual std::unique_ptr clone() const noexcept = 0; + protected: virtual tl::expected dump_basic_fields( NBT::NBTWriter&, @@ -47,6 +50,9 @@ class filled_map : public item { std::string_view id() const noexcept override { return "minecraft:filled_map"; } + std::unique_ptr clone() const noexcept override { + return std::make_unique(*this); + } protected: tl::expected dump_tags( From 4a4ceb23afb5ccbddf59e4cacf1b91d65c2ed204 Mon Sep 17 00:00:00 2001 From: RealRoller233 <13257601+a1d123e2r@user.noreply.gitee.com> Date: Mon, 16 Dec 2024 20:17:19 +0800 Subject: [PATCH 0969/1123] FIX linux.cpp entity.h BlockListManager.cpp CMakeList to enable build --- CMakeLists.txt | 5 +++-- utilities/BlockListManager/BlockListManager.cpp | 7 +++++-- utilities/Schem/entity.h | 1 + utilities/StatMemory/stat_memory_src/linux.cpp | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4d6cd91..1637a062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ set(SlopeCraft_version 5.3.0) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) @@ -156,4 +157,4 @@ add_subdirectory(vccl) # install and pack ----------------------------------------------------------- include(cmake/install.cmake) -include(cpack/make-packs.cmake) \ No newline at end of file +include(cpack/make-packs.cmake) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 65f31feb..28efea67 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -32,20 +32,23 @@ void BlockListManager::setup_basecolors() noexcept { } } + uint64_t std::hash::operator()(const selection &s) const noexcept { boost::uuids::detail::md5 hash; for (auto &id : s.ids) { hash.process_bytes(id.data(), id.size()); } - uint32_t dig[4]{}; + unsigned char dig[16] = {}; // 修改为 unsigned char 类型,大小为 16 hash.get_digest(dig); + uint64_t fold = 0; for (size_t i = 0; i < 2; i++) { const uint64_t cur = (uint64_t(dig[2 * i]) << 32) | (uint64_t(dig[2 * i + 1])); fold ^= cur; } + return fold; } @@ -344,4 +347,4 @@ const std::string_view basecolor_names[64] = {"00 None", "60 RawIron", "61 GlowLichen", "Unknown", - "Unknown"}; \ No newline at end of file + "Unknown"}; diff --git a/utilities/Schem/entity.h b/utilities/Schem/entity.h index fabc1aa6..b7c44a1c 100644 --- a/utilities/Schem/entity.h +++ b/utilities/Schem/entity.h @@ -14,6 +14,7 @@ #include #include #include "item.h" +#include namespace NBT { template diff --git a/utilities/StatMemory/stat_memory_src/linux.cpp b/utilities/StatMemory/stat_memory_src/linux.cpp index 4625ef9f..ca71fa41 100644 --- a/utilities/StatMemory/stat_memory_src/linux.cpp +++ b/utilities/StatMemory/stat_memory_src/linux.cpp @@ -10,6 +10,7 @@ #include #include +#include tl::expected, std::string> parse_linux_file( const char* filename, @@ -148,4 +149,4 @@ get_self_memory_info() noexcept { return tl::make_unexpected( fmt::format("Failed to parse field VmSize from {}", file)); -} \ No newline at end of file +} From b197d3dd6b16bc1bd330b38c0c3f6d243cc893d7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 17 Dec 2024 13:29:07 +0800 Subject: [PATCH 0970/1123] fix linux build Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BlockListManager.cpp | 2 +- utilities/StatMemory/stat_memory_src/linux.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 50463f69..cd52642b 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -39,7 +39,7 @@ uint64_t std::hash::operator()(const selection &s) const noexcept { } uint32_t dig[4]{}; - hash.get_digest(dig); + hash.get_digest(reinterpret_cast(dig)); uint64_t fold = 0; for (size_t i = 0; i < 2; i++) { const uint64_t cur = diff --git a/utilities/StatMemory/stat_memory_src/linux.cpp b/utilities/StatMemory/stat_memory_src/linux.cpp index 4625ef9f..4e6026fc 100644 --- a/utilities/StatMemory/stat_memory_src/linux.cpp +++ b/utilities/StatMemory/stat_memory_src/linux.cpp @@ -11,6 +11,8 @@ #include +#include + tl::expected, std::string> parse_linux_file( const char* filename, const std::function& skip_this_line = {}) noexcept { From a4a9e9bea64244e2fd37255e675c6b6fc03eccf2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 11 Aug 2024 21:52:06 +0800 Subject: [PATCH 0971/1123] SCL supports loading block list from buffer Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 + SlopeCraftL/SlopeCraftL.cpp | 361 +++--------------------------------- SlopeCraftL/SlopeCraftL.h | 3 + SlopeCraftL/block_list.cpp | 313 +++++++++++++++++++++++++++++++ SlopeCraftL/blocklist.h | 60 ++++++ SlopeCraftL/mc_block.cpp | 14 ++ SlopeCraftL/mc_block.h | 29 --- 7 files changed, 422 insertions(+), 360 deletions(-) create mode 100644 SlopeCraftL/block_list.cpp create mode 100644 SlopeCraftL/blocklist.h diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 70073eae..dd198faf 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -59,6 +59,8 @@ set(SlopeCraft_SCL_sources #${SlopeCraft_SCL_internal_headers} ${SlopeCraft_SCL_windows_rc_files} + block_list.cpp + blocklist.h ) # add this definations to both targets diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index c03e71b1..47d1e58b 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -28,339 +28,12 @@ This file is part of SlopeCraft. #include "SlopeCraftL.h" #include "mc_block.h" +#include "blocklist.h" #include "string_deliver.h" #include "color_table.h" using namespace SlopeCraft; -// mc_block_interface *mc_block_interface::create() { return new mc_block; } - -void mc_block_interface::clear() noexcept { - setBurnable(false); - setDoGlow(false); - setEndermanPickable(false); - setId("minecraft:air"); - setIdOld(""); - setNeedGlass(false); - setVersion(0); - setNameZH(""); - setNameEN(""); - // setWallUseable(false); -} - -using namespace SlopeCraft; - -std::pair parse_block(const nlohmann::json &jo) noexcept( - false) { - mc_block ret; - const int basecolor = jo.at("baseColor"); - if (basecolor < 0 || basecolor >= 64) { - throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; - } - - ret.id = jo.at("id"); - ret.nameZH = jo.at("nameZH"); - ret.nameEN = jo.at("nameEN"); - ret.imageFilename = jo.at("icon"); - ret.version = jo.at("version"); - if (jo.contains("idOld")) { - ret.idOld = jo.at("idOld"); - } else { - ret.idOld = ret.id; - } - - if (jo.contains("endermanPickable")) { - ret.endermanPickable = jo.at("endermanPickable"); - } - - if (jo.contains("isGlowing")) { - ret.doGlow = jo.at("isGlowing"); - } - - if (jo.contains("burnable")) { - ret.burnable = jo.at("burnable"); - } - - if (jo.contains("needGlass")) { - ret.needGlass = jo.at("needGlass"); - } - if (jo.contains("stackSize")) { - const int val = jo.at("stackSize"); - if (val <= 0 or val > 64) { - throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; - } - ret.stackSize = val; - } - - return {basecolor, ret}; -} - -// block_list_interface *impl_createBlockList(const char *filename, -// const blockListOption &option, -// std::string &errmsg) noexcept { -// errmsg.reserve(4096); -// errmsg.clear(); -// -// block_list *bl = new block_list; -// using njson = nlohmann::json; -// try { -// std::ifstream ifs(filename); -// njson jo = njson::parse(ifs, nullptr, true, true); -// -// njson::array_t arr; -// if (jo.contains("FixedBlocks")) { -// arr = std::move(jo.at("FixedBlocks")); -// } else { -// arr = std::move(jo.at("CustomBlocks")); -// } -// -// // parse blocks -// for (size_t idx = 0; idx < arr.size(); idx++) { -// auto temp = parse_block(arr[idx], option.image_dir); -// -// auto ptr = new mc_block; -// *ptr = std::move(temp.second); -// bl->blocks().emplace(ptr, temp.first); -// } -// -// } catch (std::exception &e) { -// delete bl; -// errmsg += fmt::format( -// "Exception occured when parsing blocklist json: \"{}\"\n", e.what()); -// return nullptr; -// } -// -// // load images -// for (auto &pair : bl->blocks()) { -// pair.first->image.resize(16, 16); -// if (!option.callback_load_image(pair.first->getImageFilename(), -// pair.first->image.data())) { -// errmsg += fmt::format( -// "Failed to load image \"{}\", this error will be ignored.\n", -// pair.first->getImageFilename()); -// continue; -// } -// pair.first->image.transposeInPlace(); -// } -// -// return bl; -// } - -struct zip_deleter { - void operator()(zip_t *archive) const noexcept { - if (archive == nullptr) { - return; - } - zip_close(archive); - } -}; - -struct block_list_metainfo { - std::string prefix_ZH; - std::string prefix_EN; - std::vector required_mods; -}; - -tl::expected parse_meta_info( - std::function(const char *filename, - std::vector &dest)> - extract_file, - std::vector &buffer) noexcept { - using njson = nlohmann::json; - // parse meta data - auto res = extract_file("metainfo.json", buffer); - if (res) { - block_list_metainfo ret; - try { - njson jo = njson::parse(buffer, nullptr, true, true); - auto &prefix = jo.at("name prefix"); - ret.prefix_ZH = prefix.at("ZH"); - ret.prefix_EN = prefix.at("EN"); - auto &mods = jo.at("required mods"); - ret.required_mods.reserve(mods.size()); - for (size_t i = 0; i < mods.size(); i++) { - std::string mod_name = mods[i]; - ret.required_mods.emplace_back(std::move(mod_name)); - } - - } catch (const std::exception &e) { - return tl::make_unexpected( - fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); - } - - return ret; - } - return tl::make_unexpected( - fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); -} - -std::tuple, std::string> -impl_create_block_list_from_zip(const char *zip_path) noexcept { - std::string warnings{}; - int error_code = ZIP_ER_OK; - std::unique_ptr archive{ - zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; - if (archive == nullptr) { - return {tl::make_unexpected(fmt::format( - "Failed to open archive \"{}\" with libzip error code {}", - zip_path, error_code)), - warnings}; - } - if (error_code != ZIP_ER_OK) { - auto ret = tl::make_unexpected(fmt::format( - "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", - zip_path, zip_strerror(archive.get()), error_code)); - return {ret, warnings}; - } - - auto extract_file = - [zip_path, &archive]( - const char *filename, - std::vector &dest) -> tl::expected { - dest.clear(); - - int error_code = ZIP_ER_OK; - const int64_t index_i = - zip_name_locate(archive.get(), filename, ZIP_FL_UNCHANGED); - if (index_i < 0) { - return tl::make_unexpected(fmt::format( - "File \"{}\" doesn't exist in archive \"{}\"", filename, zip_path)); - } - const uint64_t index = uint64_t(index_i); - - zip_stat_t stat; - error_code = zip_stat_index(archive.get(), index, ZIP_FL_UNCHANGED, &stat); - if (error_code != ZIP_ER_OK) { - return tl::make_unexpected(fmt::format( - "Failed to get size of file \"{}\" in archive \"{}\" : \"{}\", " - "error code = {}", - filename, zip_path, zip_strerror(archive.get()), error_code)); - } - - const uint64_t file_size = stat.size; - dest.resize(file_size); - - auto file = zip_fopen(archive.get(), filename, ZIP_FL_UNCHANGED); - if (file == nullptr) { - return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive \"{}\" : \"{}\" ", - filename, zip_path, zip_strerror(archive.get()))); - } - - const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); - if (read_bytes != int64_t(file_size)) { - return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive \"{}\", expected " - "{} bytes, but extracted {} bytes : \"{}\" ", - filename, zip_path, file_size, read_bytes, - zip_strerror(archive.get()))); - } - return {}; - }; - - std::vector buffer; - - block_list *bl = new block_list; - - using njson = nlohmann::json; - block_list_metainfo meta_info; - { - const char metainfo_name[] = "metainfo.json"; - const int64_t index = - zip_name_locate(archive.get(), metainfo_name, ZIP_FL_UNCHANGED); - if (index >= 0) { - // metainfo.json exists in the archive - auto mi_res = parse_meta_info(extract_file, buffer); - if (not mi_res) { - fmt::format_to( - std::back_inserter(warnings), - "metainfo.json exist in the archive, but failed to parse it: {}\n", - mi_res.error()); - } - meta_info = std::move(mi_res).value_or(block_list_metainfo{}); - } - } - // parse json array of blocks - { - auto err = extract_file("block_list.json", buffer); - if (!err) { - return {tl::make_unexpected(err.error()), warnings}; - } - } - try { - njson jo = njson::parse(buffer, nullptr, true, true); - if (not jo.is_array()) { - return {tl::make_unexpected( - fmt::format("Json should contain an array directly")), - warnings}; - } - - // parse blocks - for (size_t idx = 0; idx < jo.size(); idx++) { - try { - auto [version, block] = parse_block(jo[idx]); - - block.nameZH = meta_info.prefix_ZH + block.nameZH; - block.nameEN = meta_info.prefix_EN + block.nameEN; - - bl->blocks().emplace(std::make_unique(block), version); - } catch (const std::exception &e) { - return {tl::make_unexpected(fmt::format( - "Failed to parse block at index {}:\n{}", idx, e.what())), - warnings}; - } - } - - } catch (const std::exception &e) { - delete bl; - return {tl::make_unexpected( - fmt::format("nlohmann json exception : {}", e.what())), - warnings}; - } - // load images - std::vector buf_pixel; - for (auto &pair : bl->blocks()) { - { - auto err = extract_file(pair.first->imageFilename.c_str(), buffer); - if (not err) { - warnings += - fmt::format("{}, required by {}", err.error(), pair.first->id); - continue; - } - } - - pair.first->image.resize(16, 16); - { - auto [result, warns] = parse_png_into_argb32(buffer, buf_pixel); - warnings += warns; - - if (!result) { - fmt::format_to(std::back_insert_iterator{warnings}, - "Failed to load image \"{}\" because \"{}\"\n", - pair.first->getImageFilename(), result.error()); - // for (uint8_t byte : buffer) { - // printf("%02X ", int(byte)); - // } - // printf("\n"); - continue; - } - auto image_size = result.value(); - if (image_size.rows != 16 || image_size.cols != 16) { - fmt::format_to(std::back_insert_iterator{warnings}, - "{} has invalid shape, expected 16x16, but found {} " - "rows x {} cols.\n", - pair.first->getImageFilename(), image_size.rows, - image_size.cols); - continue; - } - } - assert(buf_pixel.size() == 16 * 16); - memcpy(pair.first->image.data(), buf_pixel.data(), 256 * sizeof(uint32_t)); - } - - return {bl, warnings}; -} - extern "C" { SCL_EXPORT const float *SCL_get_rgb_basic_colorset_source() { @@ -372,15 +45,41 @@ SCL_EXPORT void SCL_destroy_block(mc_block_interface *b) { delete b; } SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option) { - auto [res, warnings] = impl_create_block_list_from_zip(zip_filename); + auto [res, warnings] = create_block_list_from_file(zip_filename); + + SlopeCraft::write_to_sd(option.warnings, warnings); + if (not res) { + SlopeCraft::write_to_sd(option.error, res.error()); + return nullptr; + } + + auto bl = new block_list{std::move(res.value())}; + assert(bl not_eq nullptr); + return bl; +} + +SCL_EXPORT block_list_interface *SCL_create_block_list_from_buffer( + const void *buffer, size_t buffer_bytes, + const block_list_create_info &option) { + if (buffer == nullptr or buffer_bytes <= 0) { + SlopeCraft::write_to_sd( + option.error, + "SCL_create_block_list_from_buffer met invalid value, either buffer is " + "nullptr or buffer size is 0"); + return nullptr; + } + auto [res, warnings] = create_block_list_from_buffer( + {reinterpret_cast(buffer), buffer_bytes}); SlopeCraft::write_to_sd(option.warnings, warnings); - if (!res) { + if (not res) { SlopeCraft::write_to_sd(option.error, res.error()); return nullptr; } - return res.value(); + auto bl = new block_list{std::move(res.value())}; + assert(bl not_eq nullptr); + return bl; } SCL_EXPORT void SCL_destroy_block_list(block_list_interface *bli) { diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index bebf36f8..c15266c2 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -513,6 +513,9 @@ struct block_list_create_info { [[nodiscard]] SCL_EXPORT block_list_interface *SCL_create_block_list( const char *zip_filename, const block_list_create_info &option); +[[nodiscard]] SCL_EXPORT block_list_interface * +SCL_create_block_list_from_buffer(const void *buffer, size_t buffer_bytes, + const block_list_create_info &option); SCL_EXPORT void SCL_destroy_block_list(block_list_interface *); SCL_EXPORT void SCL_preprocessImage( diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp new file mode 100644 index 00000000..de559901 --- /dev/null +++ b/SlopeCraftL/block_list.cpp @@ -0,0 +1,313 @@ +/* +Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + +SlopeCraft is free software: you can redistribute it and/or modify + it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + + SlopeCraft 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 +General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include +#include +#include +#include +#include + +#include "SlopeCraftL.h" +#include "mc_block.h" +#include "blocklist.h" +#include "string_deliver.h" +#include "color_table.h" + +using namespace SlopeCraft; + +// mc_block_interface *mc_block_interface::create() { return new mc_block; } + +std::pair parse_block(const nlohmann::json &jo) noexcept( + false) { + mc_block ret; + const int basecolor = jo.at("baseColor"); + if (basecolor < 0 || basecolor >= 64) { + throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; + } + + ret.id = jo.at("id"); + ret.nameZH = jo.at("nameZH"); + ret.nameEN = jo.at("nameEN"); + ret.imageFilename = jo.at("icon"); + ret.version = jo.at("version"); + if (jo.contains("idOld")) { + ret.idOld = jo.at("idOld"); + } else { + ret.idOld = ret.id; + } + + if (jo.contains("endermanPickable")) { + ret.endermanPickable = jo.at("endermanPickable"); + } + + if (jo.contains("isGlowing")) { + ret.doGlow = jo.at("isGlowing"); + } + + if (jo.contains("burnable")) { + ret.burnable = jo.at("burnable"); + } + + if (jo.contains("needGlass")) { + ret.needGlass = jo.at("needGlass"); + } + if (jo.contains("stackSize")) { + const int val = jo.at("stackSize"); + if (val <= 0 or val > 64) { + throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; + } + ret.stackSize = val; + } + + return {basecolor, ret}; +} + +struct zip_deleter { + void operator()(zip_t *archive) const noexcept { + if (archive == nullptr) { + return; + } + zip_close(archive); + } +}; + +tl::expected parse_meta_info( + std::function(const char *filename, + std::vector &dest)> + extract_file, + std::vector &buffer) noexcept { + using njson = nlohmann::json; + // parse meta data + auto res = extract_file("metainfo.json", buffer); + if (res) { + block_list_metainfo ret; + try { + njson jo = njson::parse(buffer, nullptr, true, true); + auto &prefix = jo.at("name prefix"); + ret.prefix_ZH = prefix.at("ZH"); + ret.prefix_EN = prefix.at("EN"); + auto &mods = jo.at("required mods"); + ret.required_mods.reserve(mods.size()); + for (size_t i = 0; i < mods.size(); i++) { + std::string mod_name = mods[i]; + ret.required_mods.emplace_back(std::move(mod_name)); + } + + } catch (const std::exception &e) { + return tl::make_unexpected( + fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); + } + + return ret; + } + return tl::make_unexpected( + fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); +} + +block_list_create_result parse_block_list(zip_t *archive) noexcept { + std::string warnings{}; + assert(archive not_eq nullptr); + + auto extract_file = + [archive](const char *filename, + std::vector &dest) -> tl::expected { + dest.clear(); + + int error_code = ZIP_ER_OK; + const int64_t index_i = + zip_name_locate(archive, filename, ZIP_FL_UNCHANGED); + if (index_i < 0) { + return tl::make_unexpected( + fmt::format("File \"{}\" doesn't exist in archive", filename)); + } + const uint64_t index = uint64_t(index_i); + + zip_stat_t stat; + error_code = zip_stat_index(archive, index, ZIP_FL_UNCHANGED, &stat); + if (error_code != ZIP_ER_OK) { + return tl::make_unexpected( + fmt::format("Failed to get size of file \"{}\" in archive: \"{}\", " + "error code = {}", + filename, zip_strerror(archive), error_code)); + } + + const uint64_t file_size = stat.size; + dest.resize(file_size); + + auto file = zip_fopen(archive, filename, ZIP_FL_UNCHANGED); + if (file == nullptr) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive : \"{}\" ", + filename, zip_strerror(archive))); + } + + const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); + if (read_bytes != int64_t(file_size)) { + return tl::make_unexpected( + fmt::format("Failed to extract \"{}\" from archive, expected " + "{} bytes, but extracted {} bytes : \"{}\" ", + filename, file_size, read_bytes, zip_strerror(archive))); + } + return {}; + }; + + std::vector buffer; + + block_list bl{}; + + using njson = nlohmann::json; + block_list_metainfo meta_info; + { + const char metainfo_name[] = "metainfo.json"; + const int64_t index = + zip_name_locate(archive, metainfo_name, ZIP_FL_UNCHANGED); + if (index >= 0) { + // metainfo.json exists in the archive + auto mi_res = parse_meta_info(extract_file, buffer); + if (not mi_res) { + fmt::format_to(std::back_inserter(warnings), + "metainfo.json exist in the archive, but failed to " + "parse it: {}\n", + mi_res.error()); + } + meta_info = std::move(mi_res).value_or(block_list_metainfo{}); + } + } + // parse json array of blocks + { + auto err = extract_file("block_list.json", buffer); + if (!err) { + return {tl::make_unexpected(err.error()), warnings}; + } + } + try { + njson jo = njson::parse(buffer, nullptr, true, true); + if (not jo.is_array()) { + return {tl::make_unexpected( + fmt::format("Json should contain an array directly")), + warnings}; + } + + // parse blocks + for (size_t idx = 0; idx < jo.size(); idx++) { + try { + auto [version, block] = parse_block(jo[idx]); + + block.nameZH = meta_info.prefix_ZH + block.nameZH; + block.nameEN = meta_info.prefix_EN + block.nameEN; + + bl.blocks().emplace(std::make_unique(block), version); + } catch (const std::exception &e) { + return {tl::make_unexpected(fmt::format( + "Failed to parse block at index {}:\n{}", idx, e.what())), + warnings}; + } + } + + } catch (const std::exception &e) { + return {tl::make_unexpected( + fmt::format("nlohmann json exception : {}", e.what())), + warnings}; + } + // load images + std::vector buf_pixel; + for (auto &pair : bl.blocks()) { + { + auto err = extract_file(pair.first->imageFilename.c_str(), buffer); + if (not err) { + warnings += + fmt::format("{}, required by {}", err.error(), pair.first->id); + continue; + } + } + + pair.first->image.resize(16, 16); + { + auto [result, warns] = parse_png_into_argb32(buffer, buf_pixel); + warnings += warns; + + if (!result) { + fmt::format_to(std::back_insert_iterator{warnings}, + "Failed to load image \"{}\" because \"{}\"\n", + pair.first->getImageFilename(), result.error()); + // for (uint8_t byte : buffer) { + // printf("%02X ", int(byte)); + // } + // printf("\n"); + continue; + } + auto image_size = result.value(); + if (image_size.rows != 16 || image_size.cols != 16) { + fmt::format_to(std::back_insert_iterator{warnings}, + "{} has invalid shape, expected 16x16, but found {} " + "rows x {} cols.\n", + pair.first->getImageFilename(), image_size.rows, + image_size.cols); + continue; + } + } + assert(buf_pixel.size() == 16 * 16); + memcpy(pair.first->image.data(), buf_pixel.data(), 256 * sizeof(uint32_t)); + } + + return block_list_create_result{.result{std::move(bl)}, .warnings{warnings}}; +} + +block_list_create_result create_block_list_from_file( + const char *zip_path) noexcept { + std::string warnings{}; + int error_code = ZIP_ER_OK; + std::unique_ptr archive{ + zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; + if (error_code not_eq ZIP_ER_OK or archive == nullptr) { + auto ret = tl::make_unexpected(fmt::format( + "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", + zip_path, zip_strerror(archive.get()), error_code)); + return {ret, warnings}; + } + + return parse_block_list(archive.get()); +} + +block_list_create_result create_block_list_from_buffer( + std::span buffer) noexcept { + zip_error_t err; + zip_source_t *const source = + zip_source_buffer_create(buffer.data(), buffer.size_bytes(), 0, &err); + if (source == nullptr) { + return {tl::make_unexpected(fmt::format("Failed to create zip_source_t: {}", + zip_error_strerror(&err))), + {}}; + } + + std::unique_ptr archive{ + zip_open_from_source(source, ZIP_RDONLY | ZIP_CHECKCONS, &err)}; + if (archive == nullptr) { + zip_source_free(source); + return {tl::make_unexpected(fmt::format("Failed to open zip: {}", + zip_error_strerror(&err))), + {}}; + } + + return parse_block_list(archive.get()); +} \ No newline at end of file diff --git a/SlopeCraftL/blocklist.h b/SlopeCraftL/blocklist.h new file mode 100644 index 00000000..be7915af --- /dev/null +++ b/SlopeCraftL/blocklist.h @@ -0,0 +1,60 @@ +// +// Created by Joseph on 2024/8/11. +// + +#ifndef SLOPECRAFT_BLOCKLIST_H +#define SLOPECRAFT_BLOCKLIST_H + +#include +#include + +#include "mc_block.h" + +struct block_list_metainfo { + std::string prefix_ZH; + std::string prefix_EN; + std::vector required_mods; +}; + +class block_list : public ::SlopeCraft::block_list_interface { + private: + std::map, uint8_t> m_blocks; + + public: + block_list() = default; + block_list(block_list &&) = default; + ~block_list(); + + public: + size_t size() const noexcept override { return m_blocks.size(); } + size_t get_blocks(mc_block_interface **dst, uint8_t *, + size_t capacity_in_elements) noexcept override; + + size_t get_blocks(const mc_block_interface **dst, uint8_t *, + size_t capacity_in_elements) const noexcept override; + + bool contains(const mc_block_interface *cp) const noexcept override { + const mc_block *ptr = dynamic_cast(cp); + return this->m_blocks.contains( + reinterpret_cast &>(ptr)); + } + + public: + const auto &blocks() const noexcept { return this->m_blocks; } + auto &blocks() noexcept { return this->m_blocks; } + + void clear() noexcept; +}; + +struct block_list_create_result { + tl::expected result; + std::string warnings; +}; + +[[nodiscard]] block_list_create_result create_block_list_from_file( + const char *zip_filename) noexcept; + +[[nodiscard]] block_list_create_result create_block_list_from_buffer( + std::span) noexcept; + +#endif // SLOPECRAFT_BLOCKLIST_H diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index 09f636d8..72691c76 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -21,6 +21,7 @@ This file is part of SlopeCraft. */ #include "mc_block.h" +#include "blocklist.h" mc_block::mc_block() { // id = ""; @@ -35,6 +36,19 @@ mc_block::mc_block() { // wallUseable=true; } +void mc_block_interface::clear() noexcept { + setBurnable(false); + setDoGlow(false); + setEndermanPickable(false); + setId("minecraft:air"); + setIdOld(""); + setNeedGlass(false); + setVersion(0); + setNameZH(""); + setNameEN(""); + // setWallUseable(false); +} + size_t block_list::get_blocks(mc_block_interface **dst, uint8_t *dst_basecolor, size_t capacity_in_elements) noexcept { if (capacity_in_elements <= 0) { diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index 51b94f29..eaca2aab 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -129,33 +129,4 @@ class mc_block : public ::SlopeCraft::mc_block_interface { // mc_block& operator =(const mc_block &); }; -class block_list : public ::SlopeCraft::block_list_interface { - private: - std::map, uint8_t> m_blocks; - - public: - block_list() = default; - ~block_list(); - - public: - size_t size() const noexcept override { return m_blocks.size(); } - size_t get_blocks(mc_block_interface **dst, uint8_t *, - size_t capacity_in_elements) noexcept override; - - size_t get_blocks(const mc_block_interface **dst, uint8_t *, - size_t capacity_in_elements) const noexcept override; - - bool contains(const mc_block_interface *cp) const noexcept override { - const mc_block *ptr = dynamic_cast(cp); - return this->m_blocks.contains( - reinterpret_cast &>(ptr)); - } - - public: - const auto &blocks() const noexcept { return this->m_blocks; } - auto &blocks() noexcept { return this->m_blocks; } - - void clear() noexcept; -}; - #endif // SIMPLEBLOCK_H From 8a888e8e89bc9f4d45a859125da83ce87ead9f5f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 17 Dec 2024 14:02:09 +0800 Subject: [PATCH 0972/1123] add git attributes Signed-off-by: ToKiNoBug --- .gitattribute => .gitattributes | 2 ++ 1 file changed, 2 insertions(+) rename .gitattribute => .gitattributes (84%) diff --git a/.gitattribute b/.gitattributes similarity index 84% rename from .gitattribute rename to .gitattributes index 2e0ce43b..688db333 100644 --- a/.gitattribute +++ b/.gitattributes @@ -1,3 +1,5 @@ +*.zip filter=lfs diff=lfs merge=lfs -text + * text=crlf *.bat text eol=crlf *.sh text eol=lf From 9b982d5bba8201c0d9b140b7ea71e32d9917a6d2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 22 Dec 2024 17:06:24 +0800 Subject: [PATCH 0973/1123] fix windows-clang19-msvc build Signed-off-by: ToKiNoBug --- cmake/required_deps/HeuristicFlow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/HeuristicFlow.cmake b/cmake/required_deps/HeuristicFlow.cmake index 47bdb998..5b0fcd08 100644 --- a/cmake/required_deps/HeuristicFlow.cmake +++ b/cmake/required_deps/HeuristicFlow.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare(Heu GIT_REPOSITORY https://github.com/SlopeCraft/HeuristicFlow.git - GIT_TAG v1.6.4.1 + GIT_TAG v1.6.4.3 OVERRIDE_FIND_PACKAGE EXCLUDE_FROM_ALL ) From bd8ea502ad8eadb74404a0e9f4a3c5f2c49ddc54 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 22 Dec 2024 17:11:44 +0800 Subject: [PATCH 0974/1123] fix a warning in TokiVC Signed-off-by: ToKiNoBug --- VisualCraftL/ParseResourcePack_json.cpp | 2536 +++++++++++------------ VisualCraftL/TokiVC_export_test.cpp | 11 +- 2 files changed, 1278 insertions(+), 1269 deletions(-) diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index ce9178b9..301cfa45 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -1,1268 +1,1268 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include -#include -#include -#include - -#include -#include "ParseResourcePack.h" -#include "VCL_internal.h" - -using namespace resource_json; - -using njson = nlohmann::json; - -size_t resource_json::state_list::num_1() const noexcept { - size_t counter = 0; - for (const auto &s : *this) { - if (s.value.empty()) { - counter++; - } - } - return counter; -} - -bool resource_json::state_list::euqals( - const state_list &another) const noexcept { - if (this->size() <= 0) return true; - if (this->size() != another.size()) return false; - int match_num = 0; - for (const state &sa : *this) { - for (const state &sb : another) { - if ((sa.key == sb.key) && (sa.value == sb.value)) { - match_num++; - } - } - } - - if (match_num < int(this->size())) { - return false; - } else { - return true; - } -} - -bool resource_json::state_list::contains( - const state_list &another) const noexcept { - if (another.size() > this->size()) { - return false; - } - - for (const state &s_json : another) { - bool is_current_state_matched = false; - for (const state &s_block : *this) { - if (s_json.key != s_block.key) { - continue; - } - - if (s_block.value == s_json.value) { - is_current_state_matched = true; - break; - } - } - if (!is_current_state_matched) { - return false; - } - } - - return true; -} - -bool resource_json::criteria_list_and::match( - const state_list &sl) const noexcept { - const auto &cl = *this; - int match_num = 0; - for (const criteria &c : cl) { - std::string_view key = c.key; - - const char *value = nullptr; - for (const state &s : sl) { - if (s.key == key) { - value = s.value.data(); - break; - } - } - // if value is not set, it is not considered as match - if (value == nullptr) { - break; - } - - if (c.match(value)) { - match_num++; - } - } - - if (match_num < int(cl.size())) { - return false; - } - return true; -} - -bool resource_json::match_criteria_list(const criteria_list_and &cl, - const state_list &sl) noexcept { - return cl.match(sl); -} - -bool resource_json::multipart_pair::match(const state_list &sl) const noexcept { - const resource_json::criteria *when = - std::get_if(&this->criteria_variant); - if (when != nullptr) { - std::string_view key = when->key; - const char *slvalue = nullptr; - for (const state &s : sl) { - if (s.key == key) { - slvalue = s.value.data(); - break; - } - } - // if sl don't have a value for the key of criteria, it is considered as - // mismatch - if (slvalue == nullptr) { - return false; - } - - return when->match(slvalue); - } - - if (std::get_if(&this->criteria_variant) != nullptr) { - return true; - } - - const auto &when_or = std::get(this->criteria_variant); - - size_t counter = 0; - for (const criteria_list_and &cl : when_or.components) { - if (cl.match(sl)) { - counter++; - } - } - - if (when_or.is_or) { - return counter > 0; - } else { - return counter >= when_or.components.size(); - } -} - -model_pass_t block_states_variant::block_model_name( - const state_list &sl_blk) const noexcept { - model_pass_t res; - res.model_name = nullptr; - for (const auto &pair : this->LUT) { - if (sl_blk.contains(pair.first)) { - res = model_pass_t(pair.second); - return res; - } - } - - return res; -} - -void block_states_variant::sort() noexcept { - std::sort(LUT.begin(), LUT.end(), - [](const std::pair &a, - const std::pair &b) -> bool { - const size_t a_1 = a.first.num_1(); - const size_t b_1 = b.first.num_1(); - if (a_1 != b_1) { - return a_1 < b_1; - } - return a.first.size() > b.first.size(); - }); -} - -std::vector block_state_multipart::block_model_names( - const state_list &sl) const noexcept { - std::vector res; - - for (const multipart_pair &pair : this->pairs) { - if (pair.match(sl)) { - for (const auto &ms : pair.apply_blockmodel) { - res.emplace_back(model_pass_t(ms)); - } - } - // res.emplace_back(model_pass_t(pair.apply_blockmodel)); - } - - return res; -} - -struct parse_bs_buffer { - std::vector> attributes; -}; - -bool parse_block_state_variant(const njson::object_t &obj, - block_states_variant *const dest_variant); - -bool parse_block_state_multipart(const njson::object_t &obj, - block_state_multipart *const dest_variant); - -bool resource_json::parse_block_state( - const char *const json_str_beg, const char *const json_str_end, - std::variant *dest, - bool *const is_dest_variant) noexcept { - njson::object_t obj; - try { - obj = njson::parse(json_str_beg, json_str_end); - } catch (...) { - std::string msg = "nlohmann json failed to parse json string : "; - msg.append(json_str_beg, json_str_end); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - const bool has_variant = - obj.contains("variants") && obj.at("variants").is_object(); - const bool has_multipart = - obj.contains("multipart") && obj.at("multipart").is_array(); - - if (has_variant == has_multipart) { - std::string msg = fmt::format( - "Function parse_block_state failed to parse json : " - "has_variant = {}, has_multipart = {}.", - has_variant, has_multipart); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (has_variant) { - if (is_dest_variant != nullptr) *is_dest_variant = true; - - block_states_variant variant; - const bool ok = parse_block_state_variant(obj, &variant); - *dest = std::move(variant); - return ok; - } - - if (has_multipart) { - // parsing multipart is not supported yet. - if (is_dest_variant != nullptr) *is_dest_variant = false; - - block_state_multipart multipart; - const bool ok = parse_block_state_multipart(obj, &multipart); - *dest = std::move(multipart); - return ok; - // return parse_block_state_multipart(obj, dest_multipart); - } - // unreachable - return false; -} - -bool parse_block_state_list(std::string_view str, state_list *const sl, - parse_bs_buffer &buffer) noexcept { - sl->clear(); - if (str.size() <= 1) return true; - - if (str == "normal") { - return true; - } - - if (str == "all") { - return true; - } - - if (str == "map") { - return true; - } - - if (!blkid::process_state_list({str.data(), str.data() + str.size()}, - &buffer.attributes, nullptr)) { - std::string msg = fmt::format( - " Function parse_block_state_list failed to parse block state " - "list : {}", - str); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - sl->reserve(buffer.attributes.size()); - - for (const auto &pair : buffer.attributes) { - state strpair; - strpair.key.assign(pair.first.begin(), pair.first.end()); - strpair.value.assign(pair.second.begin(), pair.second.end()); - - sl->emplace_back(strpair); - } - - return true; -} - -bool parse_block_state_list(std::string_view str, - state_list *const sl) noexcept { - parse_bs_buffer buffer; - - return parse_block_state_list(str, sl, buffer); -} - -model_store_t json_to_model(const njson &obj) noexcept { - model_store_t res; - - res.model_name = obj.at("model"); - - if (obj.contains("x") && obj.at("x").is_number()) { - const int val = obj.at("x"); - - if (!block_model::is_0_90_180_270(val)) { - std::string msg; - msg = fmt::format( - "Invalid x rotation value : {}. Invalid values : 0, 90, 180, 270.", - val); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return {}; - } - - res.x = block_model::int_to_face_rot(val); - } - - if (obj.contains("y") && obj.at("y").is_number()) { - const int val = obj.at("y"); - if (!block_model::is_0_90_180_270(val)) { - std::string msg; - msg = fmt::format( - "Invalid y rotation value : {}. Invalid values : 0, 90, 180, 270.", - val); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return {}; - } - res.y = block_model::int_to_face_rot(val); - } - - if (obj.contains("uvlock") && obj.at("uvlock").is_boolean()) { - res.uvlock = obj.at("uvlock"); - } - - return res; -} - -bool parse_block_state_variant(const njson::object_t &obj, - block_states_variant *const dest) { - const njson &variants = obj.at("variants"); - - dest->LUT.clear(); - dest->LUT.reserve(variants.size()); - - for (auto pair : variants.items()) { - if (!pair.value().is_structured()) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : " - "value for key \"{}\" is not an object or array.", - pair.key()); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (pair.value().is_array() && pair.value().size() <= 0) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : " - "value for key \"{}\" is an empty array.", - pair.key().data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - const njson &obj = - (pair.value().is_object()) ? (pair.value()) : (pair.value().at(0)); - - if ((!obj.contains("model")) || (!obj.at("model").is_string())) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : no " - "valid value for key \"model\""); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - std::pair p; - - parse_bs_buffer buffer; - - if (!parse_block_state_list(pair.key(), &p.first, buffer)) { - std::string msg = - fmt::format("Failed to parse block state list : {}", pair.key()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - p.second = json_to_model(obj); - - dest->LUT.emplace_back(p); - } - - dest->sort(); - - return true; -} - -void parse_single_criteria_split(std::string_view key, std::string_view values, - criteria *const cr) noexcept { - cr->key = key; - cr->values.clear(); - - size_t current_value_beg_idx = 0; - - for (size_t idx = 0;; idx++) { - if (values.size() <= idx || values[idx] == '\0' || values[idx] == '|') { - cr->values.emplace_back( - values.substr(current_value_beg_idx, idx - current_value_beg_idx)); - current_value_beg_idx = idx + 1; - } - - if (values.size() <= idx || values[idx] == '\0') { - break; - } - } -} - -model_store_t parse_single_apply(const njson &single_obj) noexcept(false) { - model_store_t ms; - - ms.model_name = single_obj.at("model"); - if (single_obj.contains("x")) { - ms.x = block_model::int_to_face_rot(single_obj.at("x")); - } - if (single_obj.contains("y")) { - ms.y = block_model::int_to_face_rot(single_obj.at("y")); - } - if (single_obj.contains("uvlock")) { - ms.uvlock = single_obj.at("uvlock"); - } - - return ms; -} - -std::vector parse_multipart_apply(const njson &apply) noexcept( - false) { - std::vector ret; - - if (apply.is_object()) { - ret.emplace_back(parse_single_apply(apply)); - return ret; - } - - if (apply.is_array()) { - for (size_t i = 0; i < apply.size(); i++) { - ret.emplace_back(parse_single_apply(apply.at(i))); - } - return ret; - } - throw std::runtime_error("Invalid value for \"apply\" in a multipart."); -} - -std::variant -parse_multipart_when(const njson &when) noexcept(false) { - const bool is_or = when.contains("OR"); - const bool is_and = when.contains("AND"); - if (is_or || is_and) { - const njson &list_or_and = (is_or) ? (when.at("OR")) : (when.at("AND")); - criteria_list_or_and when_or_and; - - when_or_and.components.reserve(list_or_and.size()); - when_or_and.is_or = is_or; - - for (size_t idx = 0; idx < list_or_and.size(); idx++) { - criteria_list_and and_list; - - for (auto it = list_or_and[idx].begin(); it != list_or_and[idx].end(); - ++it) { - criteria cr; - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - - } else { - parse_single_criteria_split(it.key(), it.value().get(), - &cr); - } - // const std::string &v_str = ; - and_list.emplace_back(std::move(cr)); - } - - when_or_and.components.emplace_back(std::move(and_list)); - } - - return when_or_and; - } - - if (when.size() == 1) { - criteria cr; - - auto it = when.begin(); - - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - } else { - parse_single_criteria_split(it.key(), it.value().get(), &cr); - } - - return cr; - } - criteria_list_and and_list; - - for (auto it = when.begin(); it != when.end(); ++it) { - criteria cr; - - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - } else { - parse_single_criteria_split(it.key(), it.value().get(), &cr); - } - and_list.emplace_back(std::move(cr)); - } - - criteria_list_or_and when_or; - when_or.components.emplace_back(std::move(and_list)); - - return when_or; -} - -bool parse_block_state_multipart(const njson::object_t &obj, - block_state_multipart *const dest) { - const njson &multiparts = obj.at("multipart"); - - if (!multiparts.is_array()) { - std::string msg = fmt::format("Fatal error : multipart must be an array."); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - dest->pairs.clear(); - - for (size_t i = 0; i < multiparts.size(); i++) { - const njson &part = multiparts[i]; - - multipart_pair mpp; - - // parse apply - try { - const njson &apply = part.at("apply"); - mpp.apply_blockmodel = parse_multipart_apply(apply); - } catch (const std::exception &err) { - std::string msg = fmt::format( - "An error occurred when parsing the value of apply. Details : {}", - err.what()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - // parse when - if (!part.contains("when")) { - mpp.criteria_variant = criteria_all_pass(); - dest->pairs.emplace_back(std::move(mpp)); - continue; - } - - try { - const njson &when = part.at("when"); - - mpp.criteria_variant = parse_multipart_when(when); - - } catch (const std::exception &err) { - std::string msg = fmt::format( - "\nFatal error : failed to parse \"when\" for a multipart blockstate " - "file. Details : {}\n", - err.what()); - return false; - } - - dest->pairs.emplace_back(std::move(mpp)); - /* - if (!part.is_object()) { - printf("\nFatal error : multipart must an array of objects.\n"); - return false; - } - - if (!part.contains("apply") || !part.contains("when")) { - printf("\nFatal error : element in multipart must contains \"apply\" - and " - "\"when\"\n"); - return false; - } - - if (!apply.contains("model") || !apply.at("model").is_string()) { - printf("\nFatal error : multipart should apply a model.\n"); - return false; - } - */ - } - - return true; -} - -struct face_json_temp { - std::string texture{""}; - std::array uv{0, 0, 16, 16}; - block_model::face_idx cullface_face; - bool have_cullface{false}; - bool is_hidden{true}; ///< note that by default, is_hidden is true. -}; - -struct element_json_temp { - std::array from; - std::array to; - std::array faces; -}; - -struct block_model_json_temp { - std::string parent{""}; - std::map textures; - std::vector elements; - bool is_inherited{false}; -}; - -std::optional string_to_face_idx( - std::string_view str) noexcept { - if (str == "up") { - return block_model::face_idx::face_up; - } - if (str == "down") { - return block_model::face_idx::face_down; - } - if (str == "bottom") { - return block_model::face_idx::face_down; - } - if (str == "north") { - return block_model::face_idx::face_north; - } - if (str == "south") { - return block_model::face_idx::face_south; - } - if (str == "east") { - return block_model::face_idx::face_east; - } - if (str == "west") { - return block_model::face_idx::face_west; - } - - return std::nullopt; -} - -const char *face_idx_to_string(block_model::face_idx f) noexcept { - switch (f) { - case block_model::face_idx::face_up: - return "up"; - case block_model::face_idx::face_down: - return "down"; - case block_model::face_idx::face_north: - return "north"; - case block_model::face_idx::face_south: - return "south"; - case block_model::face_idx::face_east: - return "east"; - case block_model::face_idx::face_west: - return "west"; - } - - return nullptr; -} - -bool parse_single_model_json(const char *const json_beg, - const char *const json_end, - block_model_json_temp *const dest) { - dest->textures.clear(); - dest->elements.clear(); - // disable exceptions, and ignore comments. - njson obj = njson::parse(json_beg, json_end, nullptr, false, true); - if (obj.is_null()) { - // this may be unsafe but just keep it currently. - std::string msg = "Failed to parse block model json : "; - msg.append(json_beg, json_end); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (obj.contains("parent") && obj.at("parent").is_string()) { - std::string p_str = obj.at("parent"); - if (p_str.starts_with("minecraft:")) { - dest->parent = p_str.substr(sizeof("minecraft:") / sizeof(char) - 1); - } else { - dest->parent = p_str; - } - } - - if (obj.contains("textures") && obj.at("textures").is_object()) { - const njson &textures = obj.at("textures"); - // dest->textures.reserve(textures.size()); - for (auto temp : textures.items()) { - if (!temp.value().is_string()) { - continue; - } - - auto it = dest->textures.emplace(temp.key(), temp.value()); - - if (it.first->second.starts_with("block/") || - it.first->second.starts_with("blocks/")) { - it.first->second = "minecraft:" + it.first->second; - } - } - } - // finished textures - - if (obj.contains("elements") && obj.at("elements").is_array()) { - const njson::array_t &elearr = obj.at("elements"); - - dest->elements.reserve(obj.size()); - for (const auto &e : elearr) { - if (!e.is_object()) { - return false; - } - - element_json_temp ele; - if (!e.contains("from") || !e.at("from").is_array()) { - ::VCL_report(VCL_report_type_t::error, - "\"from\" doesn't exist, or is not an array."); - return false; - } - // from - { - const njson::array_t &arr_from = e.at("from"); - if (arr_from.size() != 3 || !arr_from.front().is_number()) { - ::VCL_report(VCL_report_type_t::error, "size of \"from\" is not 3"); - return false; - } - - for (int idx = 0; idx < 3; idx++) { - if (!arr_from[idx].is_number()) { - ::VCL_report( - VCL_report_type_t::error, - "one or more element in array \"from\" is not number."); - return false; - } - ele.from[idx] = arr_from[idx]; - } - } - if (!e.contains("to") || !e.at("to").is_array()) { - ::VCL_report(VCL_report_type_t::error, - "\"to\" doesn't exist, or is not an array."); - return false; - } - // to - { - const njson::array_t &arr_to = e.at("to"); - if (arr_to.size() != 3) { - ::VCL_report(VCL_report_type_t::error, "size of \"to\" is not 3."); - return false; - } - - for (int idx = 0; idx < 3; idx++) { - if (!arr_to[idx].is_number()) { - ::VCL_report(VCL_report_type_t::error, - "one or more element in array \"to\" is not number."); - return false; - } - ele.to[idx] = arr_to[idx]; - } - } - - // faces - { - if (!e.contains("faces") || !e.at("faces").is_object()) { - ::VCL_report(VCL_report_type_t::error, - "\"faces\" doesn't exist, or is not an object."); - return false; - } - - const njson &faces = e.at("faces"); - for (auto temp : faces.items()) { - // if the face is not object, skip current face. - if (!temp.value().is_object()) continue; - face_json_temp f; - block_model::face_idx fidx; - { - auto fidx_opt = string_to_face_idx(temp.key()); - if (not fidx_opt) { - std::string msg = fmt::format( - "Error while parsing block model json : invalid key {} " - "doesn't refer to any face.", - temp.key()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - fidx = fidx_opt.value(); - } - - const njson &curface = temp.value(); - - if (!curface.contains("texture") || - !curface.at("texture").is_string()) { - ::VCL_report( - VCL_report_type_t::error, - "Error while parsing block model json : face do not have " - "texture."); - return false; - } - - f.texture = curface.at("texture"); - if (f.texture.starts_with("block/")) { - f.texture = ("minecraft:") + f.texture; - } - // finished texture - - // cullface - { - std::string cullface_temp(""); - if (curface.contains("cullface") && - curface.at("cullface").is_string()) { - cullface_temp = curface.at("cullface"); - } - - if (!cullface_temp.empty()) { - auto cullface_fidx = string_to_face_idx(cullface_temp); - - if (not cullface_fidx) { - std::string msg = fmt::format("Invalid value for cullface : {}", - cullface_temp); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - f.cullface_face = cullface_fidx.value(); - f.have_cullface = true; - } - } - // finished cullface - - // uv - if (curface.contains("uv") && curface.at("uv").is_array()) { - const njson::array_t &uvarr = curface.at("uv"); - - if (uvarr.size() != 4) { - ::VCL_report(VCL_report_type_t::error, - "Invalid value for uv array : the size must be 4."); - return false; - } - - for (int idx = 0; idx < 4; idx++) { - if (!uvarr.at(idx).is_number()) { - ::VCL_report(VCL_report_type_t::error, - "Invalid value for uv array : the value must be " - "numbers."); - return false; - } - f.uv[idx] = uvarr[idx]; - } - } - // finished uv - - f.is_hidden = false; - // finished is_hidden - - // write in this face - ele.faces[int(fidx)] = f; - } - } - // finished all faces - - dest->elements.emplace_back(ele); - } - } - - return true; -} - -const char *dereference_texture_name( - std::map::iterator it, - std::map &text) noexcept { - if (it == text.end()) { - return nullptr; - } - - if (!it->second.starts_with('#')) { - return it->second.data(); - } - - // here it->second must be a # reference. - - auto next_it = text.find(it->second.data() + 1); - - // This line is added as a patch, to fix error when parsing 1.19.3 data packs. - // I'm not sure whether models that triggered this can be parsed correctly, it - // is only introduced to prevent endless recursion, so that errors can be - // reported - if (next_it == it) { - // found a self-reference value - return nullptr; - } - - const char *const ret = dereference_texture_name(next_it, text); - - if (ret != nullptr) { - // found a non-reference value - it->second = ret; - return ret; - } else { - // it->second is the the farest reference and no further link - return it->second.data(); - } -} - -void dereference_texture_name( - std::map &text) noexcept { - for (auto it = text.begin(); it != text.end(); ++it) { - if (!it->second.starts_with('#')) continue; - dereference_texture_name(it, text); - } -} - -void dereference_model(block_model_json_temp &model) { - // dereference_texture_name(model.textures); - - for (auto &ele : model.elements) { - for (auto &face : ele.faces) { - if (face.is_hidden) continue; - if (face.texture.starts_with('#')) { - auto it = model.textures.find(face.texture.data() + 1); - - if (it == model.textures.end()) { - continue; - } - face.texture = it->second; - } - } - // finished current face - } - // finished current element -} - -bool model_json_inherit_new(block_model_json_temp &child, - block_model_json_temp &parent, const bool) { - if (child.parent.empty()) { - ::VCL_report(VCL_report_type_t::error, "child has no parent."); - return false; - } - - parent.is_inherited = true; - - // child.textures.reserve(child.textures.size() + parent.textures.size()); - // merge textures - for (const auto &pt : parent.textures) { - if (!child.textures.contains(pt.first)) { - child.textures.emplace(pt.first, pt.second); - } - } - - dereference_texture_name(child.textures); - - // if child have a parent, and child doesn't define its own element, child - // inherit parent's elements. - if (child.elements.size() <= 0) { - child.elements = parent.elements; - } - - dereference_model(child); - - // parent - child.parent = parent.parent; - return true; -} - -bool inherit_recrusively(std::string_view childname, - block_model_json_temp &child, - std::unordered_map - &temp_models) noexcept { - if (child.parent.empty()) return true; - - // #warning This function is not finished yet. I hope to inherit from the - // root, which measn to find the root and inherit from root to leaf - - // find parent till the root - auto it = temp_models.find(child.parent); - - if (it == temp_models.end()) { - std::string msg = fmt::format( - "Failed to inherit. Undefined reference to model {}, " - "required by {}.", - child.parent.data(), childname.data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (!it->second.parent.empty()) { - // find root - const bool success = - inherit_recrusively(it->first, it->second, temp_models); - if (!success) { - return false; - } - } - /* - printf("\ninhering : parent : %s, child : %s,\n", child.parent.data(), - childname.data()); - */ - const bool success = model_json_inherit_new(child, it->second, false); - - // dereference_texture_name(child.textures); - - if (!success) { - std::string msg = fmt::format("Failed to inherit. Child : {}, parent : {}.", - childname.data(), child.parent.data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - return true; -} - -bool resource_pack::add_block_models( - const zipped_folder &resource_pack_root, - const bool on_conflict_replace_old) noexcept { - const std::unordered_map *files; - // find assets/minecraft/models/block - { - const zipped_folder *temp = resource_pack_root.subfolder("assets"); - if (temp == nullptr) return false; - temp = temp->subfolder("minecraft"); - if (temp == nullptr) return false; - temp = temp->subfolder("models"); - if (temp == nullptr) return false; - temp = temp->subfolder("block"); - if (temp == nullptr) return false; - - files = &temp->files; - } - - // the name of model is : block/ - std::unordered_map temp_models; - - temp_models.reserve(files->size()); - - std::array buffer; - - for (const auto &file : *files) { - if (!file.first.ends_with(".json")) continue; - buffer.fill('\0'); - std::strcpy(buffer.data(), "block/"); - { - const int end = file.first.find_last_of('.'); - char *const dest = buffer.data() + std::strlen(buffer.data()); - for (int idx = 0; idx < end; idx++) { - dest[idx] = file.first[idx]; - } - } - - block_model_json_temp bmjt; - - const bool ok = parse_single_model_json( - (const char *)file.second.data(), - (const char *)file.second.data() + file.second.file_size(), &bmjt); - - if (!ok) { - std::string msg = fmt::format( - "Failed to parse assets/minecraft/models/block/{}.", file.first); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - temp_models.emplace(buffer.data(), bmjt); - } - // parsed all jsons - /* - printf("Loaded %i model jsons.\n", int(temp_models.size())); - - for (const auto &file : temp_models) { - printf("%s, ", file.first.data()); - } - printf("\n\n"); - - */ - - // inherit - for (auto &model : temp_models) { - const bool ok = inherit_recrusively(model.first, model.second, temp_models); - if (!ok) { - model.second.parent = "INVALID"; - std::string msg = fmt::format( - "Failed to inherit model {}. This model will be " - "skipped, but it may cause further errors.", - model.first); - ::VCL_report(VCL_report_type_t::warning, msg.c_str()); - // #warning following line should be commented. - // return false; - continue; - } - - dereference_texture_name(model.second.textures); - dereference_model(model.second); - } - // remove invalid - for (auto it = temp_models.begin(); it != temp_models.end();) { - if (it->second.parent == "INVALID") { - it = temp_models.erase(it); - continue; - } - - ++it; - } - - // convert temp models to block_models - this->block_models.reserve(this->block_models.size() + temp_models.size()); - for (auto &tmodel : temp_models) { - if (this->block_models.contains(tmodel.first) && !on_conflict_replace_old) { - continue; - } - - block_model::model md; - bool skip_this_model = false; - - md.elements.reserve(tmodel.second.elements.size()); - for (auto &tele : tmodel.second.elements) { - if (skip_this_model) break; - block_model::element ele; - - // ele._from = tele.from; - for (int idx = 0; idx < 3; idx++) { - ele._from[idx] = tele.from[idx]; - ele._to[idx] = tele.to[idx]; - } - - for (uint8_t faceidx = 0; faceidx < 6; faceidx++) { - if (skip_this_model) break; - auto &tface = tele.faces[faceidx]; - ele.faces[faceidx].is_hidden = tface.is_hidden; - if (tface.is_hidden) { - ele.faces[faceidx].texture = nullptr; - continue; - } - ele.faces[faceidx].uv_start[0] = tface.uv[0]; - ele.faces[faceidx].uv_start[1] = tface.uv[1]; - ele.faces[faceidx].uv_end[0] = tface.uv[2]; - ele.faces[faceidx].uv_end[1] = tface.uv[3]; - - // try to find the image in texture/block - auto imgptr = this->find_texture(tface.texture, false); - if (imgptr == nullptr) { // try to resolve the name of this texture - auto it = tmodel.second.textures.find(tface.texture); - if (it not_eq tmodel.second.textures.end()) { - imgptr = this->find_texture(it->second, false); - } - } - - if (imgptr == nullptr) { - if (tface.texture.starts_with('#') && tmodel.second.is_inherited) { - // This model is considered to be abstract - skip_this_model = true; - continue; - } - std::string msg = fmt::format( - "Undefined reference to texture \"{}\", required by " - "model {} but no such image.\nThe textures are : \n", - tface.texture, tmodel.first); - for (const auto &pair : tmodel.second.textures) { - msg.push_back('{'); - std::string temp = - fmt::format("{}, {}\n", pair.first.data(), pair.second.data()); - msg.append(temp); - msg.push_back('}'); - } - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - - // if managed to find, go on - } - ele.faces[faceidx].texture = imgptr; - } - // finished all faces - - md.elements.emplace_back(ele); - } - // finished current model - if (!skip_this_model) { - this->block_models.emplace(tmodel.first, std::move(md)); - } - } - - for (const auto &pair : this->block_models) { - for (const auto &ele : pair.second.elements) { - for (const auto &face : ele.faces) { - if (!face.is_hidden && face.texture == nullptr) { - std::string msg = fmt::format( - "Found an error while examining all block models : " - "face.texture==nullptr in model {}", - pair.first); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - } - } - } - - return true; -} - -bool resource_pack::add_block_states( - const zipped_folder &resourece_pack_root, - const bool on_conflict_replace_old) noexcept { - const std::unordered_map *files = nullptr; - { - const zipped_folder *temp = resourece_pack_root.subfolder("assets"); - if (temp == nullptr) { - return false; - } - temp = temp->subfolder("minecraft"); - if (temp == nullptr) { - return false; - } - temp = temp->subfolder("blockstates"); - if (temp == nullptr) { - return false; - } - files = &temp->files; - } - - this->block_states.reserve(this->block_states.size() + files->size()); - - for (const auto &file : *files) { - if (this->block_states.contains(file.first) && !on_conflict_replace_old) { - continue; - } - std::variant - bs; - bool is_dest_variant; - - const bool success = parse_block_state( - (const char *)file.second.data(), - (const char *)file.second.data() + file.second.file_size(), &bs, - &is_dest_variant); - - if (!success) { - std::string msg = fmt::format( - "Failed to parse block state json file " - "assets/minecraft/blockstates/{}. This will be " - "skipped but may cause further errors.\n", - file.first); - - ::VCL_report(VCL_report_type_t::warning, msg.c_str()); - continue; - } - - const int substrlen = file.first.find_last_of('.'); - this->block_states.emplace(file.first.substr(0, substrlen), std::move(bs)); - } - - return true; -} +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include +#include +#include +#include + +#include +#include "ParseResourcePack.h" +#include "VCL_internal.h" + +using namespace resource_json; + +using njson = nlohmann::json; + +size_t resource_json::state_list::num_1() const noexcept { + size_t counter = 0; + for (const auto &s : *this) { + if (s.value.empty()) { + counter++; + } + } + return counter; +} + +bool resource_json::state_list::euqals( + const state_list &another) const noexcept { + if (this->size() <= 0) return true; + if (this->size() != another.size()) return false; + int match_num = 0; + for (const state &sa : *this) { + for (const state &sb : another) { + if ((sa.key == sb.key) && (sa.value == sb.value)) { + match_num++; + } + } + } + + if (match_num < int(this->size())) { + return false; + } else { + return true; + } +} + +bool resource_json::state_list::contains( + const state_list &another) const noexcept { + if (another.size() > this->size()) { + return false; + } + + for (const state &s_json : another) { + bool is_current_state_matched = false; + for (const state &s_block : *this) { + if (s_json.key != s_block.key) { + continue; + } + + if (s_block.value == s_json.value) { + is_current_state_matched = true; + break; + } + } + if (!is_current_state_matched) { + return false; + } + } + + return true; +} + +bool resource_json::criteria_list_and::match( + const state_list &sl) const noexcept { + const auto &cl = *this; + int match_num = 0; + for (const criteria &c : cl) { + std::string_view key = c.key; + + const char *value = nullptr; + for (const state &s : sl) { + if (s.key == key) { + value = s.value.data(); + break; + } + } + // if value is not set, it is not considered as match + if (value == nullptr) { + break; + } + + if (c.match(value)) { + match_num++; + } + } + + if (match_num < int(cl.size())) { + return false; + } + return true; +} + +bool resource_json::match_criteria_list(const criteria_list_and &cl, + const state_list &sl) noexcept { + return cl.match(sl); +} + +bool resource_json::multipart_pair::match(const state_list &sl) const noexcept { + const resource_json::criteria *when = + std::get_if(&this->criteria_variant); + if (when != nullptr) { + std::string_view key = when->key; + const char *slvalue = nullptr; + for (const state &s : sl) { + if (s.key == key) { + slvalue = s.value.data(); + break; + } + } + // if sl don't have a value for the key of criteria, it is considered as + // mismatch + if (slvalue == nullptr) { + return false; + } + + return when->match(slvalue); + } + + if (std::get_if(&this->criteria_variant) != nullptr) { + return true; + } + + const auto &when_or = std::get(this->criteria_variant); + + size_t counter = 0; + for (const criteria_list_and &cl : when_or.components) { + if (cl.match(sl)) { + counter++; + } + } + + if (when_or.is_or) { + return counter > 0; + } else { + return counter >= when_or.components.size(); + } +} + +model_pass_t block_states_variant::block_model_name( + const state_list &sl_blk) const noexcept { + model_pass_t res; + res.model_name = nullptr; + for (const auto &pair : this->LUT) { + if (sl_blk.contains(pair.first)) { + res = model_pass_t(pair.second); + return res; + } + } + + return res; +} + +void block_states_variant::sort() noexcept { + std::sort(LUT.begin(), LUT.end(), + [](const std::pair &a, + const std::pair &b) -> bool { + const size_t a_1 = a.first.num_1(); + const size_t b_1 = b.first.num_1(); + if (a_1 != b_1) { + return a_1 < b_1; + } + return a.first.size() > b.first.size(); + }); +} + +std::vector block_state_multipart::block_model_names( + const state_list &sl) const noexcept { + std::vector res; + + for (const multipart_pair &pair : this->pairs) { + if (pair.match(sl)) { + for (const auto &ms : pair.apply_blockmodel) { + res.emplace_back(model_pass_t(ms)); + } + } + // res.emplace_back(model_pass_t(pair.apply_blockmodel)); + } + + return res; +} + +struct parse_bs_buffer { + std::vector> attributes; +}; + +bool parse_block_state_variant(const njson::object_t &obj, + block_states_variant *const dest_variant); + +bool parse_block_state_multipart(const njson::object_t &obj, + block_state_multipart *const dest_variant); + +bool resource_json::parse_block_state( + const char *const json_str_beg, const char *const json_str_end, + std::variant *dest, + bool *const is_dest_variant) noexcept { + njson::object_t obj; + try { + obj = njson::parse(json_str_beg, json_str_end); + } catch (...) { + std::string msg = "nlohmann json failed to parse json string : "; + msg.append(json_str_beg, json_str_end); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + const bool has_variant = + obj.contains("variants") && obj.at("variants").is_object(); + const bool has_multipart = + obj.contains("multipart") && obj.at("multipart").is_array(); + + if (has_variant == has_multipart) { + std::string msg = fmt::format( + "Function parse_block_state failed to parse json : " + "has_variant = {}, has_multipart = {}.", + has_variant, has_multipart); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (has_variant) { + if (is_dest_variant != nullptr) *is_dest_variant = true; + + block_states_variant variant; + const bool ok = parse_block_state_variant(obj, &variant); + *dest = std::move(variant); + return ok; + } + + if (has_multipart) { + // parsing multipart is not supported yet. + if (is_dest_variant != nullptr) *is_dest_variant = false; + + block_state_multipart multipart; + const bool ok = parse_block_state_multipart(obj, &multipart); + *dest = std::move(multipart); + return ok; + // return parse_block_state_multipart(obj, dest_multipart); + } + // unreachable + return false; +} + +bool parse_block_state_list(std::string_view str, state_list *const sl, + parse_bs_buffer &buffer) noexcept { + sl->clear(); + if (str.size() <= 1) return true; + + if (str == "normal") { + return true; + } + + if (str == "all") { + return true; + } + + if (str == "map") { + return true; + } + + if (!blkid::process_state_list({str.data(), str.data() + str.size()}, + &buffer.attributes, nullptr)) { + std::string msg = fmt::format( + " Function parse_block_state_list failed to parse block state " + "list : {}", + str); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + sl->reserve(buffer.attributes.size()); + + for (const auto &pair : buffer.attributes) { + state strpair; + strpair.key.assign(pair.first.begin(), pair.first.end()); + strpair.value.assign(pair.second.begin(), pair.second.end()); + + sl->emplace_back(strpair); + } + + return true; +} + +bool parse_block_state_list(std::string_view str, + state_list *const sl) noexcept { + parse_bs_buffer buffer; + + return parse_block_state_list(str, sl, buffer); +} + +model_store_t json_to_model(const njson &obj) noexcept { + model_store_t res; + + res.model_name = obj.at("model"); + + if (obj.contains("x") && obj.at("x").is_number()) { + const int val = obj.at("x"); + + if (!block_model::is_0_90_180_270(val)) { + std::string msg; + msg = fmt::format( + "Invalid x rotation value : {}. Invalid values : 0, 90, 180, 270.", + val); + VCL_report(VCL_report_type_t::error, msg.c_str()); + return {}; + } + + res.x = block_model::int_to_face_rot(val); + } + + if (obj.contains("y") && obj.at("y").is_number()) { + const int val = obj.at("y"); + if (!block_model::is_0_90_180_270(val)) { + std::string msg; + msg = fmt::format( + "Invalid y rotation value : {}. Invalid values : 0, 90, 180, 270.", + val); + VCL_report(VCL_report_type_t::error, msg.c_str()); + return {}; + } + res.y = block_model::int_to_face_rot(val); + } + + if (obj.contains("uvlock") && obj.at("uvlock").is_boolean()) { + res.uvlock = obj.at("uvlock"); + } + + return res; +} + +bool parse_block_state_variant(const njson::object_t &obj, + block_states_variant *const dest) { + const njson &variants = obj.at("variants"); + + dest->LUT.clear(); + dest->LUT.reserve(variants.size()); + + for (auto pair : variants.items()) { + if (!pair.value().is_structured()) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : " + "value for key \"{}\" is not an object or array.", + pair.key()); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (pair.value().is_array() && pair.value().size() <= 0) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : " + "value for key \"{}\" is an empty array.", + pair.key().data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + const njson &obj = + (pair.value().is_object()) ? (pair.value()) : (pair.value().at(0)); + + if ((!obj.contains("model")) || (!obj.at("model").is_string())) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : no " + "valid value for key \"model\""); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + std::pair p; + + parse_bs_buffer buffer; + + if (!parse_block_state_list(pair.key(), &p.first, buffer)) { + std::string msg = + fmt::format("Failed to parse block state list : {}", pair.key()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + p.second = json_to_model(obj); + + dest->LUT.emplace_back(p); + } + + dest->sort(); + + return true; +} + +void parse_single_criteria_split(std::string_view key, std::string_view values, + criteria *const cr) noexcept { + cr->key = key; + cr->values.clear(); + + size_t current_value_beg_idx = 0; + + for (size_t idx = 0;; idx++) { + if (values.size() <= idx || values[idx] == '\0' || values[idx] == '|') { + cr->values.emplace_back( + values.substr(current_value_beg_idx, idx - current_value_beg_idx)); + current_value_beg_idx = idx + 1; + } + + if (values.size() <= idx || values[idx] == '\0') { + break; + } + } +} + +model_store_t parse_single_apply(const njson &single_obj) noexcept(false) { + model_store_t ms; + + ms.model_name = single_obj.at("model"); + if (single_obj.contains("x")) { + ms.x = block_model::int_to_face_rot(single_obj.at("x")); + } + if (single_obj.contains("y")) { + ms.y = block_model::int_to_face_rot(single_obj.at("y")); + } + if (single_obj.contains("uvlock")) { + ms.uvlock = single_obj.at("uvlock"); + } + + return ms; +} + +std::vector parse_multipart_apply(const njson &apply) noexcept( + false) { + std::vector ret; + + if (apply.is_object()) { + ret.emplace_back(parse_single_apply(apply)); + return ret; + } + + if (apply.is_array()) { + for (size_t i = 0; i < apply.size(); i++) { + ret.emplace_back(parse_single_apply(apply.at(i))); + } + return ret; + } + throw std::runtime_error("Invalid value for \"apply\" in a multipart."); +} + +std::variant +parse_multipart_when(const njson &when) noexcept(false) { + const bool is_or = when.contains("OR"); + const bool is_and = when.contains("AND"); + if (is_or || is_and) { + const njson &list_or_and = (is_or) ? (when.at("OR")) : (when.at("AND")); + criteria_list_or_and when_or_and; + + when_or_and.components.reserve(list_or_and.size()); + when_or_and.is_or = is_or; + + for (size_t idx = 0; idx < list_or_and.size(); idx++) { + criteria_list_and and_list; + + for (auto it = list_or_and[idx].begin(); it != list_or_and[idx].end(); + ++it) { + criteria cr; + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + + } else { + parse_single_criteria_split(it.key(), it.value().get(), + &cr); + } + // const std::string &v_str = ; + and_list.emplace_back(std::move(cr)); + } + + when_or_and.components.emplace_back(std::move(and_list)); + } + + return when_or_and; + } + + if (when.size() == 1) { + criteria cr; + + auto it = when.begin(); + + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + } else { + parse_single_criteria_split(it.key(), it.value().get(), &cr); + } + + return cr; + } + criteria_list_and and_list; + + for (auto it = when.begin(); it != when.end(); ++it) { + criteria cr; + + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + } else { + parse_single_criteria_split(it.key(), it.value().get(), &cr); + } + and_list.emplace_back(std::move(cr)); + } + + criteria_list_or_and when_or; + when_or.components.emplace_back(std::move(and_list)); + + return when_or; +} + +bool parse_block_state_multipart(const njson::object_t &obj, + block_state_multipart *const dest) { + const njson &multiparts = obj.at("multipart"); + + if (!multiparts.is_array()) { + std::string msg = fmt::format("Fatal error : multipart must be an array."); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + dest->pairs.clear(); + + for (size_t i = 0; i < multiparts.size(); i++) { + const njson &part = multiparts[i]; + + multipart_pair mpp; + + // parse apply + try { + const njson &apply = part.at("apply"); + mpp.apply_blockmodel = parse_multipart_apply(apply); + } catch (const std::exception &err) { + std::string msg = fmt::format( + "An error occurred when parsing the value of apply. Details : {}", + err.what()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + // parse when + if (!part.contains("when")) { + mpp.criteria_variant = criteria_all_pass(); + dest->pairs.emplace_back(std::move(mpp)); + continue; + } + + try { + const njson &when = part.at("when"); + + mpp.criteria_variant = parse_multipart_when(when); + + } catch (const std::exception &err) { + std::string msg = fmt::format( + "\nFatal error : failed to parse \"when\" for a multipart blockstate " + "file. Details : {}\n", + err.what()); + return false; + } + + dest->pairs.emplace_back(std::move(mpp)); + /* + if (!part.is_object()) { + printf("\nFatal error : multipart must an array of objects.\n"); + return false; + } + + if (!part.contains("apply") || !part.contains("when")) { + printf("\nFatal error : element in multipart must contains \"apply\" + and " + "\"when\"\n"); + return false; + } + + if (!apply.contains("model") || !apply.at("model").is_string()) { + printf("\nFatal error : multipart should apply a model.\n"); + return false; + } + */ + } + + return true; +} + +struct face_json_temp { + std::string texture{""}; + std::array uv{0, 0, 16, 16}; + block_model::face_idx cullface_face; + bool have_cullface{false}; + bool is_hidden{true}; ///< note that by default, is_hidden is true. +}; + +struct element_json_temp { + std::array from; + std::array to; + std::array faces; +}; + +struct block_model_json_temp { + std::string parent{""}; + std::map textures; + std::vector elements; + bool is_inherited{false}; +}; + +std::optional string_to_face_idx( + std::string_view str) noexcept { + if (str == "up") { + return block_model::face_idx::face_up; + } + if (str == "down") { + return block_model::face_idx::face_down; + } + if (str == "bottom") { + return block_model::face_idx::face_down; + } + if (str == "north") { + return block_model::face_idx::face_north; + } + if (str == "south") { + return block_model::face_idx::face_south; + } + if (str == "east") { + return block_model::face_idx::face_east; + } + if (str == "west") { + return block_model::face_idx::face_west; + } + + return std::nullopt; +} + +const char *face_idx_to_string(block_model::face_idx f) noexcept { + switch (f) { + case block_model::face_idx::face_up: + return "up"; + case block_model::face_idx::face_down: + return "down"; + case block_model::face_idx::face_north: + return "north"; + case block_model::face_idx::face_south: + return "south"; + case block_model::face_idx::face_east: + return "east"; + case block_model::face_idx::face_west: + return "west"; + } + + return nullptr; +} + +bool parse_single_model_json(const char *const json_beg, + const char *const json_end, + block_model_json_temp *const dest) { + dest->textures.clear(); + dest->elements.clear(); + // disable exceptions, and ignore comments. + njson obj = njson::parse(json_beg, json_end, nullptr, false, true); + if (obj.is_null()) { + // this may be unsafe but just keep it currently. + std::string msg = "Failed to parse block model json : "; + msg.append(json_beg, json_end); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (obj.contains("parent") && obj.at("parent").is_string()) { + std::string p_str = obj.at("parent"); + if (p_str.starts_with("minecraft:")) { + dest->parent = p_str.substr(sizeof("minecraft:") / sizeof(char) - 1); + } else { + dest->parent = p_str; + } + } + + if (obj.contains("textures") && obj.at("textures").is_object()) { + const njson &textures = obj.at("textures"); + // dest->textures.reserve(textures.size()); + for (auto temp : textures.items()) { + if (!temp.value().is_string()) { + continue; + } + + auto it = dest->textures.emplace(temp.key(), temp.value()); + + if (it.first->second.starts_with("block/") || + it.first->second.starts_with("blocks/")) { + it.first->second = "minecraft:" + it.first->second; + } + } + } + // finished textures + + if (obj.contains("elements") && obj.at("elements").is_array()) { + const njson::array_t &elearr = obj.at("elements"); + + dest->elements.reserve(obj.size()); + for (const auto &e : elearr) { + if (!e.is_object()) { + return false; + } + + element_json_temp ele; + if (!e.contains("from") || !e.at("from").is_array()) { + ::VCL_report(VCL_report_type_t::error, + "\"from\" doesn't exist, or is not an array."); + return false; + } + // from + { + const njson::array_t &arr_from = e.at("from"); + if (arr_from.size() != 3 || !arr_from.front().is_number()) { + ::VCL_report(VCL_report_type_t::error, "size of \"from\" is not 3"); + return false; + } + + for (int idx = 0; idx < 3; idx++) { + if (!arr_from[idx].is_number()) { + ::VCL_report( + VCL_report_type_t::error, + "one or more element in array \"from\" is not number."); + return false; + } + ele.from[idx] = arr_from[idx]; + } + } + if (!e.contains("to") || !e.at("to").is_array()) { + ::VCL_report(VCL_report_type_t::error, + "\"to\" doesn't exist, or is not an array."); + return false; + } + // to + { + const njson::array_t &arr_to = e.at("to"); + if (arr_to.size() != 3) { + ::VCL_report(VCL_report_type_t::error, "size of \"to\" is not 3."); + return false; + } + + for (int idx = 0; idx < 3; idx++) { + if (!arr_to[idx].is_number()) { + ::VCL_report(VCL_report_type_t::error, + "one or more element in array \"to\" is not number."); + return false; + } + ele.to[idx] = arr_to[idx]; + } + } + + // faces + { + if (!e.contains("faces") || !e.at("faces").is_object()) { + ::VCL_report(VCL_report_type_t::error, + "\"faces\" doesn't exist, or is not an object."); + return false; + } + + const njson &faces = e.at("faces"); + for (auto temp : faces.items()) { + // if the face is not object, skip current face. + if (!temp.value().is_object()) continue; + face_json_temp f; + block_model::face_idx fidx; + { + auto fidx_opt = string_to_face_idx(temp.key()); + if (not fidx_opt) { + std::string msg = fmt::format( + "Error while parsing block model json : invalid key {} " + "doesn't refer to any face.", + temp.key()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + fidx = fidx_opt.value(); + } + + const njson &curface = temp.value(); + + if (!curface.contains("texture") || + !curface.at("texture").is_string()) { + ::VCL_report( + VCL_report_type_t::error, + "Error while parsing block model json : face do not have " + "texture."); + return false; + } + + f.texture = curface.at("texture"); + if (f.texture.starts_with("block/")) { + f.texture = ("minecraft:") + f.texture; + } + // finished texture + + // cullface + { + std::string cullface_temp(""); + if (curface.contains("cullface") && + curface.at("cullface").is_string()) { + cullface_temp = curface.at("cullface"); + } + + if (!cullface_temp.empty()) { + auto cullface_fidx = string_to_face_idx(cullface_temp); + + if (not cullface_fidx) { + std::string msg = fmt::format("Invalid value for cullface : {}", + cullface_temp); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + f.cullface_face = cullface_fidx.value(); + f.have_cullface = true; + } + } + // finished cullface + + // uv + if (curface.contains("uv") && curface.at("uv").is_array()) { + const njson::array_t &uvarr = curface.at("uv"); + + if (uvarr.size() != 4) { + ::VCL_report(VCL_report_type_t::error, + "Invalid value for uv array : the size must be 4."); + return false; + } + + for (int idx = 0; idx < 4; idx++) { + if (!uvarr.at(idx).is_number()) { + ::VCL_report(VCL_report_type_t::error, + "Invalid value for uv array : the value must be " + "numbers."); + return false; + } + f.uv[idx] = uvarr[idx]; + } + } + // finished uv + + f.is_hidden = false; + // finished is_hidden + + // write in this face + ele.faces[int(fidx)] = f; + } + } + // finished all faces + + dest->elements.emplace_back(ele); + } + } + + return true; +} + +const char *dereference_texture_name( + std::map::iterator it, + std::map &text) noexcept { + if (it == text.end()) { + return nullptr; + } + + if (!it->second.starts_with('#')) { + return it->second.data(); + } + + // here it->second must be a # reference. + + auto next_it = text.find(it->second.data() + 1); + + // This line is added as a patch, to fix error when parsing 1.19.3 data packs. + // I'm not sure whether models that triggered this can be parsed correctly, it + // is only introduced to prevent endless recursion, so that errors can be + // reported + if (next_it == it) { + // found a self-reference value + return nullptr; + } + + const char *const ret = dereference_texture_name(next_it, text); + + if (ret != nullptr) { + // found a non-reference value + it->second = ret; + return ret; + } else { + // it->second is the the farest reference and no further link + return it->second.data(); + } +} + +void dereference_texture_name( + std::map &text) noexcept { + for (auto it = text.begin(); it != text.end(); ++it) { + if (!it->second.starts_with('#')) continue; + dereference_texture_name(it, text); + } +} + +void dereference_model(block_model_json_temp &model) { + // dereference_texture_name(model.textures); + + for (auto &ele : model.elements) { + for (auto &face : ele.faces) { + if (face.is_hidden) continue; + if (face.texture.starts_with('#')) { + auto it = model.textures.find(face.texture.data() + 1); + + if (it == model.textures.end()) { + continue; + } + face.texture = it->second; + } + } + // finished current face + } + // finished current element +} + +bool model_json_inherit_new(block_model_json_temp &child, + block_model_json_temp &parent, const bool) { + if (child.parent.empty()) { + ::VCL_report(VCL_report_type_t::error, "child has no parent."); + return false; + } + + parent.is_inherited = true; + + // child.textures.reserve(child.textures.size() + parent.textures.size()); + // merge textures + for (const auto &pt : parent.textures) { + if (!child.textures.contains(pt.first)) { + child.textures.emplace(pt.first, pt.second); + } + } + + dereference_texture_name(child.textures); + + // if child have a parent, and child doesn't define its own element, child + // inherit parent's elements. + if (child.elements.size() <= 0) { + child.elements = parent.elements; + } + + dereference_model(child); + + // parent + child.parent = parent.parent; + return true; +} + +bool inherit_recrusively(std::string_view childname, + block_model_json_temp &child, + std::unordered_map + &temp_models) noexcept { + if (child.parent.empty()) return true; + + // #warning This function is not finished yet. I hope to inherit from the + // root, which measn to find the root and inherit from root to leaf + + // find parent till the root + auto it = temp_models.find(child.parent); + + if (it == temp_models.end()) { + std::string msg = fmt::format( + "Failed to inherit. Undefined reference to model {}, " + "required by {}.", + child.parent.data(), childname.data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (!it->second.parent.empty()) { + // find root + const bool success = + inherit_recrusively(it->first, it->second, temp_models); + if (!success) { + return false; + } + } + /* + printf("\ninhering : parent : %s, child : %s,\n", child.parent.data(), + childname.data()); + */ + const bool success = model_json_inherit_new(child, it->second, false); + + // dereference_texture_name(child.textures); + + if (!success) { + std::string msg = fmt::format("Failed to inherit. Child : {}, parent : {}.", + childname.data(), child.parent.data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + return true; +} + +bool resource_pack::add_block_models( + const zipped_folder &resource_pack_root, + const bool on_conflict_replace_old) noexcept { + const std::unordered_map *files; + // find assets/minecraft/models/block + { + const zipped_folder *temp = resource_pack_root.subfolder("assets"); + if (temp == nullptr) return false; + temp = temp->subfolder("minecraft"); + if (temp == nullptr) return false; + temp = temp->subfolder("models"); + if (temp == nullptr) return false; + temp = temp->subfolder("block"); + if (temp == nullptr) return false; + + files = &temp->files; + } + + // the name of model is : block/ + std::unordered_map temp_models; + + temp_models.reserve(files->size()); + + std::array buffer; + + for (const auto &file : *files) { + if (!file.first.ends_with(".json")) continue; + buffer.fill('\0'); + std::strcpy(buffer.data(), "block/"); + { + const int end = file.first.find_last_of('.'); + char *const dest = buffer.data() + std::strlen(buffer.data()); + for (int idx = 0; idx < end; idx++) { + dest[idx] = file.first[idx]; + } + } + + block_model_json_temp bmjt; + + const bool ok = parse_single_model_json( + (const char *)file.second.data(), + (const char *)file.second.data() + file.second.file_size(), &bmjt); + + if (!ok) { + std::string msg = fmt::format( + "Failed to parse assets/minecraft/models/block/{}.", file.first); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + temp_models.emplace(buffer.data(), bmjt); + } + // parsed all jsons + /* + printf("Loaded %i model jsons.\n", int(temp_models.size())); + + for (const auto &file : temp_models) { + printf("%s, ", file.first.data()); + } + printf("\n\n"); + + */ + + // inherit + for (auto &model : temp_models) { + const bool ok = inherit_recrusively(model.first, model.second, temp_models); + if (!ok) { + model.second.parent = "INVALID"; + std::string msg = fmt::format( + "Failed to inherit model {}. This model will be " + "skipped, but it may cause further errors.", + model.first); + ::VCL_report(VCL_report_type_t::warning, msg.c_str()); + // #warning following line should be commented. + // return false; + continue; + } + + dereference_texture_name(model.second.textures); + dereference_model(model.second); + } + // remove invalid + for (auto it = temp_models.begin(); it != temp_models.end();) { + if (it->second.parent == "INVALID") { + it = temp_models.erase(it); + continue; + } + + ++it; + } + + // convert temp models to block_models + this->block_models.reserve(this->block_models.size() + temp_models.size()); + for (auto &tmodel : temp_models) { + if (this->block_models.contains(tmodel.first) && !on_conflict_replace_old) { + continue; + } + + block_model::model md; + bool skip_this_model = false; + + md.elements.reserve(tmodel.second.elements.size()); + for (auto &tele : tmodel.second.elements) { + if (skip_this_model) break; + block_model::element ele; + + // ele._from = tele.from; + for (int idx = 0; idx < 3; idx++) { + ele._from[idx] = tele.from[idx]; + ele._to[idx] = tele.to[idx]; + } + + for (uint8_t faceidx = 0; faceidx < 6; faceidx++) { + if (skip_this_model) break; + auto &tface = tele.faces[faceidx]; + ele.faces[faceidx].is_hidden = tface.is_hidden; + if (tface.is_hidden) { + ele.faces[faceidx].texture = nullptr; + continue; + } + ele.faces[faceidx].uv_start[0] = tface.uv[0]; + ele.faces[faceidx].uv_start[1] = tface.uv[1]; + ele.faces[faceidx].uv_end[0] = tface.uv[2]; + ele.faces[faceidx].uv_end[1] = tface.uv[3]; + + // try to find the image in texture/block + auto imgptr = this->find_texture(tface.texture, false); + if (imgptr == nullptr) { // try to resolve the name of this texture + auto it = tmodel.second.textures.find(tface.texture); + if (it not_eq tmodel.second.textures.end()) { + imgptr = this->find_texture(it->second, false); + } + } + + if (imgptr == nullptr) { + if (tface.texture.starts_with('#') && tmodel.second.is_inherited) { + // This model is considered to be abstract + skip_this_model = true; + continue; + } + std::string msg = fmt::format( + "Undefined reference to texture \"{}\", required by " + "model {} but no such image.\nThe textures are : \n", + tface.texture, tmodel.first); + for (const auto &pair : tmodel.second.textures) { + msg.push_back('{'); + std::string temp = + fmt::format("{}, {}\n", pair.first.data(), pair.second.data()); + msg.append(temp); + msg.push_back('}'); + } + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + + // if managed to find, go on + } + ele.faces[faceidx].texture = imgptr; + } + // finished all faces + + md.elements.emplace_back(ele); + } + // finished current model + if (!skip_this_model) { + this->block_models.emplace(tmodel.first, std::move(md)); + } + } + + for (const auto &pair : this->block_models) { + for (const auto &ele : pair.second.elements) { + for (const auto &face : ele.faces) { + if (!face.is_hidden && face.texture == nullptr) { + std::string msg = fmt::format( + "Found an error while examining all block models : " + "face.texture==nullptr in model {}", + pair.first); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + } + } + } + + return true; +} + +bool resource_pack::add_block_states( + const zipped_folder &resourece_pack_root, + const bool on_conflict_replace_old) noexcept { + const std::unordered_map *files = nullptr; + { + const zipped_folder *temp = resourece_pack_root.subfolder("assets"); + if (temp == nullptr) { + return false; + } + temp = temp->subfolder("minecraft"); + if (temp == nullptr) { + return false; + } + temp = temp->subfolder("blockstates"); + if (temp == nullptr) { + return false; + } + files = &temp->files; + } + + this->block_states.reserve(this->block_states.size() + files->size()); + + for (const auto &file : *files) { + if (this->block_states.contains(file.first) && !on_conflict_replace_old) { + continue; + } + std::variant + bs; + bool is_dest_variant; + + const bool success = parse_block_state( + (const char *)file.second.data(), + (const char *)file.second.data() + file.second.file_size(), &bs, + &is_dest_variant); + + if (!success) { + std::string msg = fmt::format( + "Failed to parse block state json file " + "assets/minecraft/blockstates/{}. This will be " + "skipped but may cause further errors.\n", + file.first); + + ::VCL_report(VCL_report_type_t::warning, msg.c_str()); + continue; + } + + const int substrlen = file.first.find_last_of('.'); + this->block_states.emplace(file.first.substr(0, substrlen), std::move(bs)); + } + + return true; +} diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index bab897ed..cfa96f96 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -141,6 +141,15 @@ bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { info.author_utf8 = "VisualCraftL"; info.destricption_utf8 = "This litematic is generated by VisualCraft."; - return schem.export_litematic(filename, info, nullptr, nullptr); + auto res = schem.export_litematic(filename, info); + if (not res) { + auto &err = res.error(); + auto msg = + fmt::format("Failed to export {} because {}, detail: {}\n", filename, + magic_enum::enum_name(err.first), err.second); + VCL_report(VCL_report_type_t::warning, msg.c_str(), true); + return false; + } + return true; } } From 01e876b192a6fcfc164fa8ea25d44a126d07211f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 15:37:31 +0800 Subject: [PATCH 0975/1123] Ignore pycache --- .gitignore | 2 +- py/.gitignore | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 py/.gitignore diff --git a/.gitignore b/.gitignore index 7da3463c..6f1609b1 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,4 @@ cmake-build-* ### PyCharm ### py/preprocessed -py/outputs +py/outputs \ No newline at end of file diff --git a/py/.gitignore b/py/.gitignore new file mode 100644 index 00000000..c1d3e321 --- /dev/null +++ b/py/.gitignore @@ -0,0 +1 @@ +*/__pycache__ \ No newline at end of file From cd18ddd685c6cd6047a3465b18a39df0db8b20fe Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 18:56:19 +0800 Subject: [PATCH 0976/1123] Fix id duplication in scheme Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 10 ++ tests/test_libSchem/test_libSchem.cpp | 13 +- utilities/NBTWriter/NBTWriter.h | 194 ++++++++++++-------------- utilities/Schem/Schem.cpp | 94 +++++++++++-- utilities/Schem/Schem.h | 10 +- utilities/Schem/bit_shrink.cpp | 21 ++- utilities/Schem/bit_shrink.h | 4 +- 7 files changed, 207 insertions(+), 139 deletions(-) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index bbc16fbc..a8b74f56 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -213,6 +213,16 @@ std::optional structure_3D_impl::create( if (fixed_opt.connect_mushrooms) { ret.schem.process_mushroom_states(); } + + { + const auto shrink_result = ret.schem.remove_unused_ids(); + if (not shrink_result) { + fixed_opt.ui.report_error(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS, + shrink_result.error().c_str()); + return std::nullopt; + } + } + fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); fixed_opt.ui.report_working_status(workStatus::none); diff --git a/tests/test_libSchem/test_libSchem.cpp b/tests/test_libSchem/test_libSchem.cpp index aa26a5ff..a61bcf82 100644 --- a/tests/test_libSchem/test_libSchem.cpp +++ b/tests/test_libSchem/test_libSchem.cpp @@ -38,8 +38,8 @@ const std::vector trash_id = generate_trash(); int main() { libSchem::Schem schem; - schem.set_MC_major_version_number(SCL_gameVersion::MC18); - schem.set_MC_version_number(MCDataVersion::MCDataVersion_t::Java_1_18_2); + schem.set_MC_major_version_number(SCL_gameVersion::MC21); + schem.set_MC_version_number(MCDataVersion::MCDataVersion_t::Java_1_21_1); schem.resize(12, 9, 12); @@ -96,22 +96,19 @@ int main() { // SCL_errorFlag flag; std::string error_str; if (!schem.export_litematic("test12.litematic", info, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.litematic" << endl; + cout << "Failed to export file " << "test12.litematic" << endl; cout << "Error info = " << error_str << endl; return 1; } if (!schem.export_structure("test12.nbt", true, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.nbt" << endl; + cout << "Failed to export file " << "test12.nbt" << endl; cout << "Error info = " << error_str << endl; return 1; } if (!schem.export_WESchem("test12.schem", weinfo, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.schem" << endl; + cout << "Failed to export file " << "test12.schem" << endl; cout << "Error info = " << error_str << endl; return 1; } diff --git a/utilities/NBTWriter/NBTWriter.h b/utilities/NBTWriter/NBTWriter.h index a2e86c45..18c02433 100644 --- a/utilities/NBTWriter/NBTWriter.h +++ b/utilities/NBTWriter/NBTWriter.h @@ -31,7 +31,7 @@ This file is part of SlopeCraft. #include #include #include - +#include #include // #include @@ -44,15 +44,15 @@ namespace NBT { namespace internal { class NBTWriterBase_nocompress { -protected: + protected: uint64_t bytesWritten{0}; int write_data(const void *data, const size_t bytes) noexcept; -private: + private: FILE *file{NULL}; -public: + public: /** * \brief open a file * \param newFileName the file to be opened @@ -81,15 +81,15 @@ class NBTWriterBase_nocompress { }; class NBTWriterBase_gzip { -protected: + protected: uint64_t bytesWritten{0}; int write_data(const void *data, const size_t bytes) noexcept; -private: + private: gzFile_s *file{NULL}; -public: + public: /** * \brief open a file * \param newFileName the file to be opened @@ -117,7 +117,7 @@ class NBTWriterBase_gzip { inline const gzFile_s *file_ptr() const noexcept { return file; } }; -} // namespace internal +} // namespace internal constexpr char idEnd = 0; constexpr char idByte = 1; @@ -154,8 +154,8 @@ enum tagType : char { * \param t To be converted * \return Converted */ -template inline T convertLEBE(T t) { - +template +inline T convertLEBE(T t) { uint8_t *ptr = reinterpret_cast(&t); for (int idx = 0; idx * 2 + 1 <= int(sizeof(T)); idx++) { @@ -173,7 +173,7 @@ class NBTWriter : public std::conditional_t { -public: + public: struct task_t { task_t() : currentTagType(tagType::End), taskSize(0) {} task_t(const tagType type, int size) @@ -183,10 +183,10 @@ class NBTWriter int taskSize; }; -private: + private: std::stack tasks; -public: + public: /** * \brief Default constructor */ @@ -212,13 +212,11 @@ class NBTWriter * \return If closing succeeds */ bool close() { - if (!this->is_open()) { return false; } - if (!tasks.empty()) - emergencyFill(); + if (!tasks.empty()) emergencyFill(); constexpr char fileTail[1] = {idEnd}; @@ -234,7 +232,6 @@ class NBTWriter * file can be loaded at least. \return Bytes written */ int emergencyFill() { - if (tasks.empty()) { return 0; } @@ -242,7 +239,6 @@ class NBTWriter int bytes = 0; while (!tasks.empty()) { - if (isInCompound()) { bytes += endCompound(); continue; @@ -251,70 +247,70 @@ class NBTWriter // cout<<"tasks.size() = "< - int writeSingleTag(const tagType type, const char *Name, T value) { + int writeSingleTag(const tagType type, std::string_view Name, T value) { static_assert(std::is_trivial_v); if (!this->is_open()) { @@ -418,21 +412,22 @@ class NBTWriter } int bytes = 0; - const uint16_t realNameL = strlen(Name); + if (Name.size() >= UINT16_MAX) { + return 0; + } + const uint16_t realNameL = Name.size(); const uint16_t flippedNameL = convertLEBE(realNameL); if (isInCompound()) { - bytes += this->write_data(&type, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(flippedNameL)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&value, sizeof(T)); } else { - if (!typeMatch(type)) { return 0; } @@ -451,7 +446,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeByte(const char *Name, int8_t value) { + inline int writeByte(std::string_view Name, int8_t value) { return writeSingleTag(tagType::Byte, Name, value); } @@ -461,7 +456,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeShort(const char *Name, int16_t value) { + inline int writeShort(std::string_view Name, int16_t value) { return writeSingleTag(tagType::Short, Name, value); } @@ -471,7 +466,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeInt(const char *Name, int32_t value) { + inline int writeInt(std::string_view Name, int32_t value) { return writeSingleTag(tagType::Int, Name, value); } @@ -481,7 +476,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeLong(const char *Name, int64_t value) { + inline int writeLong(std::string_view Name, int64_t value) { return writeSingleTag(tagType::Long, Name, value); } @@ -491,7 +486,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeFloat(const char *Name, float value) { + inline int writeFloat(std::string_view Name, float value) { return writeSingleTag(tagType::Float, Name, value); } @@ -501,7 +496,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeDouble(const char *Name, double value) { + inline int writeDouble(std::string_view Name, double value) { return writeSingleTag(tagType::Double, Name, value); } @@ -510,18 +505,17 @@ class NBTWriter * \param Name Name of tag * \return Bytes written */ - int writeCompound(const char *Name = "") { - if (!this->is_open()) - return 0; + int writeCompound(std::string_view Name = "") { + if (!this->is_open()) return 0; int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); if (isInCompound()) { bytes += this->write_data(&idCompound, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); tasks.emplace(task_t(End, 0)); return bytes; @@ -541,8 +535,7 @@ class NBTWriter * \return Bytes written */ int endCompound() { - if (!this->is_open()) - return 0; + if (!this->is_open()) return 0; if (!isInCompound()) { return 0; @@ -568,7 +561,8 @@ class NBTWriter * \param listSize Size of list * \return Bytes written */ - int writeListHead(const char *Name, tagType elementType, const int listSize) { + int writeListHead(std::string_view Name, tagType elementType, + const int listSize) { if (!this->is_open()) { return 0; } @@ -578,14 +572,14 @@ class NBTWriter } int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int32_t flippedListSize = convertLEBE(listSize); if (isInCompound()) { bytes += this->write_data(&idList, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&elementType, sizeof(char)); bytes += this->write_data(&flippedListSize, sizeof(int32_t)); @@ -612,10 +606,9 @@ class NBTWriter return 0; } -private: + private: template - int writeArrayHead(const char *Name, const int32_t arraySize) { - + int writeArrayHead(std::string_view Name, const int32_t arraySize) { if (!this->is_open()) { return 0; } @@ -629,24 +622,22 @@ class NBTWriter : ((elementType == Int) ? (IntArray) : (LongArray)); int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int32_t flippedArraySize = convertLEBE(arraySize); if (isInCompound()) { - bytes += this->write_data(&arrayId, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&flippedArraySize, sizeof(int32_t)); tasks.emplace(task_t(elementType, arraySize)); if (arraySize == 0) { - onElementWritten(); } @@ -654,13 +645,11 @@ class NBTWriter } if (isInListOrArray() && typeMatch(arrayId)) { - bytes += this->write_data(&flippedArraySize, sizeof(int32_t)); tasks.emplace(task_t(elementType, arraySize)); if (arraySize == 0) { - onElementWritten(); } @@ -670,14 +659,14 @@ class NBTWriter return 0; } -public: + public: /** * \brief Start to write a byte array * \param Name Name of the array * \param arraySize Elements of the array * \return Bytes written */ - inline int writeByteArrayHead(const char *Name, const int arraySize) { + inline int writeByteArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -687,7 +676,7 @@ class NBTWriter * \param arraySize Elements of the array * \return Bytes written */ - inline int writeIntArrayHead(const char *Name, const int arraySize) { + inline int writeIntArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -697,7 +686,7 @@ class NBTWriter * \param arraySize Elements of the array * \return Bytes written */ - inline int writeLongArrayHead(const char *Name, const int arraySize) { + inline int writeLongArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -707,14 +696,14 @@ class NBTWriter * \param value Value of a string * \return Bytes written */ - int writeString(const char *Name, const char *value) { + int writeString(std::string_view Name, const char *value) { if (!this->is_open()) { return 0; } int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int16_t realValueL = ::strlen(value); @@ -723,7 +712,7 @@ class NBTWriter if (isInCompound()) { bytes += this->write_data(&idString, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&flippedValueL, sizeof(int16_t)); bytes += this->write_data(value, realValueL); @@ -732,7 +721,6 @@ class NBTWriter } if (isInListOrArray() && typeMatch(String)) { - bytes += this->write_data(&flippedValueL, sizeof(int16_t)); bytes += this->write_data(value, realValueL); @@ -757,6 +745,6 @@ class NBTWriter inline size_t byteCount() const { return this->bytesWritten; } }; -}; // namespace NBT +}; // namespace NBT -#endif // SCL_NBTWRITER_H +#endif // SCL_NBTWRITER_H diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 10343863..41cde7a1 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -28,6 +28,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "Schem.h" @@ -414,6 +415,7 @@ tl::expected> Schem::pre_check( tl::expected> Schem::export_litematic(std::string_view filename, const litematic_info &info) const noexcept { + // { auto res = this->pre_check(filename, ".litematic"); if (not res) { @@ -575,6 +577,7 @@ Schem::export_litematic(std::string_view filename, tl::expected> Schem::export_structure(std::string_view filename, const bool is_air_structure_void) const noexcept { + // { auto res = this->pre_check(filename, ".nbt"); if (not res) { @@ -759,6 +762,7 @@ Schem::export_structure(std::string_view filename, tl::expected> Schem::export_WESchem( std::string_view filename, const WorldEditSchem_info &info) const noexcept { + // { auto res = this->pre_check(filename, ".schem"); if (not res) { @@ -787,10 +791,13 @@ tl::expected> Schem::export_WESchem( auto write_palette = [&]() { file.writeCompound("Palette"); { - for (int idx = 0; idx < int(block_id_list.size()); idx++) { - file.writeInt(block_id_list[idx].c_str(), idx); + for (int idx = 0; idx < static_cast(block_id_list.size()); idx++) { + // continue; + [[maybe_unused]] const auto ret = + file.writeInt(block_id_list[idx], idx); + assert(ret > 0); } - } // finished palette + } // finish palette file.endCompound(); }; auto write_offset = [&]() { @@ -808,16 +815,17 @@ tl::expected> Schem::export_WESchem( }; std::vector blockdata; - ::shrink_bytes_weSchem(xzy.data(), xzy.size(), block_id_list.size(), - &blockdata); + ::shrink_bytes_weSchem( + {this->xzy.data(), static_cast(this->xzy.size())}, + block_id_list.size(), &blockdata); auto write_blocks = [&](const char *key) { - file.writeByteArrayHead(key, blockdata.size()); - { - const int8_t *data = reinterpret_cast(blockdata.data()); - for (int64_t idx = 0; idx < int64_t(blockdata.size()); idx++) { - file.writeByte("", data[idx]); - } - } // end array + std::span data{reinterpret_cast(blockdata.data()), + blockdata.size() * sizeof(uint8_t)}; + file.writeByteArrayHead(key, data.size()); + for (int8_t d : data) { + file.writeByte("", d); + } + // end array }; if (this->MC_major_ver <= SCL_gameVersion::MC19) { @@ -853,7 +861,8 @@ tl::expected> Schem::export_WESchem( write_shape(); write_offset(); write_blocks("BlockData"); - } else { // 1.20+ + } else { + // 1.20+ file.writeCompound("Schematic"); { file.writeCompound("Metadata"); @@ -882,9 +891,9 @@ tl::expected> Schem::export_WESchem( file.writeCompound("Blocks"); { + file.writeListHead("BlockEntities", NBT::tagType::Compound, 0); write_palette(); write_blocks("Data"); - file.writeListHead("BlockEntities", NBT::tagType::Compound, 0); } file.endCompound(); // finish Blocks } @@ -894,3 +903,60 @@ tl::expected> Schem::export_WESchem( file.close(); return {}; } + +tl::expected +libSchem::Schem::remove_unused_ids() noexcept { + remove_unused_id_result stat; + stat.id_count_before = this->palette_size(); + std::vector id_used; + id_used.resize(this->palette_size(), false); + for (const ele_t blkid : *this) { + if (blkid >= this->palette_size()) [[unlikely]] { + return tl::make_unexpected( + fmt::format("The scheme required block with id = {}, but the block " + "palette has only {} blocks", + blkid, this->palette_size())); + } + id_used[blkid] = true; + } + + std::vector id_map_old_to_new; + { + ele_t next_id = 0; + for (size_t id = 0; id < id_used.size(); id++) { + if (id_used[id]) { + id_map_old_to_new.emplace_back(next_id++); + } else { + id_map_old_to_new.emplace_back(invalid_ele_t); + } + } + } + if (id_map_old_to_new.empty()) { + id_map_old_to_new.emplace_back(0); + } + // update block id list, remove unused block from palette + { + ele_t idx = 0; + for (auto it = this->block_id_list.begin(); + it not_eq this->block_id_list.end();) { + if (id_used[idx]) { + idx++; + ++it; + continue; + } + it = this->block_id_list.erase(it); + idx++; + } + } + // assert(this->block_id_list.size()==id_map_old_to_new.size()); + // update 3d matrix xzy + + for (ele_t &blkid : *this) { + assert(id_used[blkid]); + const auto new_id = id_map_old_to_new[blkid]; + blkid = new_id; + assert(new_id < this->block_id_list.size()); + } + stat.id_count_after = this->block_id_list.size(); + return stat; +} \ No newline at end of file diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 0ff688aa..6315d7c5 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -101,7 +101,7 @@ class Schem { } Schem(Schem &&) = default; Schem(int64_t x, int64_t y, int64_t z) { - xzy.resize(x, y, z); + xzy.resize(x, z, y); xzy.setZero(); } @@ -266,6 +266,14 @@ class Schem { std::span y_block_length, std::span z_block_length) const noexcept; + struct remove_unused_id_result { + size_t id_count_before; + size_t id_count_after; + }; + + [[nodiscard]] tl::expected + remove_unused_ids() noexcept; + protected: [[nodiscard]] Schem slice_no_check( std::span, 3> xyz_index_range) diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index 9900b379..d929a9d9 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -154,21 +154,20 @@ bool process_block_id( return ok; } -void shrink_bytes_weSchem(const uint16_t *src, const size_t src_count, - const int palette_max, +void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept { - if (palette_max <= 128) { - dest->resize(src_count); - for (size_t idx = 0; idx < src_count; idx++) { - dest->at(idx) = src[idx] & 0xFF; - } - return; - } + // if (palette_max <= 128) { + // dest->resize(src.size()); + // for (size_t idx = 0; idx < src.size(); idx++) { + // dest->at(idx) = src[idx] & 0xFF; + // } + // return; + //} - dest->reserve(src_count * 2); + dest->reserve(src.size() * 2); dest->clear(); - for (size_t idx = 0; idx < src_count; idx++) { + for (size_t idx = 0; idx < src.size(); idx++) { uint16_t temp = src[idx]; if (temp < 128) { dest->emplace_back(temp); diff --git a/utilities/Schem/bit_shrink.h b/utilities/Schem/bit_shrink.h index 34f236f0..09285334 100644 --- a/utilities/Schem/bit_shrink.h +++ b/utilities/Schem/bit_shrink.h @@ -24,6 +24,7 @@ This file is part of SlopeCraft. #define SCHEM_BITSHRINK_H #include +#include #include #include #include @@ -54,8 +55,7 @@ bool process_block_id( const std::string_view id, std::string *const pure_id, std::vector> *const traits); -void shrink_bytes_weSchem(const uint16_t *src, const size_t src_count, - const int palette_max, +void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept; class __mushroom_sides { From afab8fd5d45c20bbd43981126d76152091f31c55 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 19:58:00 +0800 Subject: [PATCH 0977/1123] Set needStone=[12] for slime block and brewing stand Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/README.md | 8 +------- Blocks/FixedBlocks/block_list.json | 10 ++++++++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Blocks/FixedBlocks/README.md b/Blocks/FixedBlocks/README.md index a5dc990b..9950c418 100644 --- a/Blocks/FixedBlocks/README.md +++ b/Blocks/FixedBlocks/README.md @@ -1,9 +1,3 @@ # 默认方块列表对应的图片放在这里 -我还不太确定是否应当再度引入这一堆的图片(170多个二进制文件呐! -所以这里先空着。 - -# Fixed blocks list images here -I'm not sure whether should i put images here (170+ binary files! - -So leave it empty now. \ No newline at end of file +# Fixed blocks list images here \ No newline at end of file diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 71ddc3f4..c07fe835 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -25,7 +25,10 @@ "nameEN": "Slime block", "icon": "slime_block.png", "version": 0, - "idOld": "minecraft:slime" + "idOld": "minecraft:slime", + "needStone": [ + 12 + ] }, { "baseColor": 2, @@ -167,7 +170,10 @@ "nameEN": "brewing stand", "icon": "brewing_stand.png", "version": 0, - "wallUseable": false + "wallUseable": false, + "needStone": [ + 12 + ] }, { "baseColor": 6, From c511d786b3e9c1fa758cf760d4b7d53e38f5e78e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:05:26 +0800 Subject: [PATCH 0978/1123] Fix CI Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 6 ++++-- .github/workflows/macos-build-arm64.yml | 4 +++- .github/workflows/macos-build-x64.yml | 4 +++- .github/workflows/windows-build.yml | 6 ++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index e4e0576a..d758a95b 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -100,18 +100,20 @@ jobs: cd .. - name: Upload deb pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-deb path: pack/SlopeCraft*.deb if-no-files-found: error + compression-level: 0 - name: Upload tar.xz pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-tar-xz path: pack/SlopeCraft*.tar.xz if-no-files-found: error + compression-level: 0 - name: Run CTest if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 10f4b3fe..24e336a3 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -89,10 +89,12 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang path: build/SlopeCraft*.zip + if-no-files-found: error + compression-level: 0 # nothing: # runs-on: macos-latest # steps: diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 30b5ebe5..a8df681a 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -110,10 +110,12 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vectorize-${{ matrix.vectorize }}-macos-x64-clang path: build/SlopeCraft*.zip + if-no-files-found: error + compression-level: 0 # gcc: # runs-on: macos-latest diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 9625df12..67715a38 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -148,11 +148,12 @@ jobs: # if-no-files-found: error - name: Upload 7z pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z path: pack/SlopeCraft*.7z if-no-files-found: error + compression-level: 0 gcc: runs-on: windows-latest @@ -300,8 +301,9 @@ jobs: # if-no-files-found: error - name: Upload 7z pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-gcc-7z path: pack/SlopeCraft*.7z if-no-files-found: error + compression-level: 0 From a66ad6c52da7d0bf9b0cfd08e7d6888247ce0ec2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:12:49 +0800 Subject: [PATCH 0979/1123] Use clang in windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 67715a38..725a2c3a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -120,8 +120,8 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - # -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + # - name: CMake build shell: cmd run: | From b13246da23851a915d3295fc28e5d9ea27daad87 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:16:55 +0800 Subject: [PATCH 0980/1123] Fix importing zstd for linux Signed-off-by: ToKiNoBug --- cmake/required_deps/zstd.cmake | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmake/required_deps/zstd.cmake b/cmake/required_deps/zstd.cmake index 04095ca1..5c22e941 100644 --- a/cmake/required_deps/zstd.cmake +++ b/cmake/required_deps/zstd.cmake @@ -23,10 +23,15 @@ if (NOT ZSTD_FOUND) endif () set_target_properties(zstd_manually_imported PROPERTIES IMPORTED_LOCATION ${zstd_lib_loc}) - - cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) - cmake_path(GET zstd_install_dir PARENT_PATH zstd_install_dir) - target_include_directories(zstd_manually_imported INTERFACE "${zstd_install_dir}/include") + find_file(zstd_header_loc NAMES zstd.h + HINTS "/usr/lib/include/zstd.h") + if (zstd_header_loc) + cmake_path(GET zstd_include_dir PARENT_PATH zstd_header_loc) + target_include_directories(zstd_manually_imported INTERFACE ${zstd_include_dir}) + endif () + # cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) + # cmake_path(GET zstd_install_dir PARENT_PATH zstd_install_dir) + # target_include_directories(zstd_manually_imported INTERFACE "${zstd_install_dir}/include") endif () set(SC_zstd_target_name "") From 9df94e4934e4bdfbfedc6e42d13dbcc62d7cf1bf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:35:35 +0800 Subject: [PATCH 0981/1123] Try to fix clang CI Signed-off-by: ToKiNoBug --- utilities/MCDataVersion/CMakeLists.txt | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utilities/MCDataVersion/CMakeLists.txt b/utilities/MCDataVersion/CMakeLists.txt index d7cfb6b5..5764c101 100644 --- a/utilities/MCDataVersion/CMakeLists.txt +++ b/utilities/MCDataVersion/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(MCDataVersion STATIC MCDataVersion.cpp ) -find_package(magic_enum REQUIRED) +find_package(magic_enum REQUIRED CONFIG) target_link_libraries(MCDataVersion PUBLIC magic_enum::magic_enum) target_compile_features(MCDataVersion PRIVATE cxx_std_20) diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index 6d1d7b1d..ff079bc4 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -41,7 +41,7 @@ MCDataVersion::MCDataVersion_t MCDataVersion::string_to_data_version( } const char *MCDataVersion::data_version_to_string( MCDataVersion::MCDataVersion_t v) noexcept { - const auto mcdv = magic_enum::enum_name(v); + std::string_view mcdv = magic_enum::enum_name(v); return mcdv.data(); } diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index eb4f5f98..25ffb4a5 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -25,7 +25,7 @@ This file is part of SlopeCraft. #include -#include +#include namespace MCDataVersion { From 5769d031d9eff8c25c70459ee25eaf7132ce7d7d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:35:51 +0800 Subject: [PATCH 0982/1123] Fix cmake warnings Signed-off-by: ToKiNoBug --- MapViewer/CMakeLists.txt | 2 +- SlopeCraft/CMakeLists.txt | 2 +- VisualCraft/CMakeLists.txt | 2 +- cmake/required_deps/libnbt++.cmake | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index 0bc806a1..b454e108 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(SlopeCraft_MapViewer VERSION ${SlopeCraft_version}) set(CMAKE_CXX_STANDARD 17) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index a9374514..b0564079 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(SlopeCraft_NewGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index cafb420f..42ec82b6 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(VisualCraft_Main VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 9dfca1a1..18bbf886 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.29) find_package(ZLIB REQUIRED) -find_package(libnbt++) +find_package(libnbt++ QUIET) if (libnbt++_FOUND) message(STATUS "Found installed libnbt++") From f8dfc8420037581d5a80bdb076fd32cb46b63198 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:58:58 +0800 Subject: [PATCH 0983/1123] Try to fix linux build Signed-off-by: ToKiNoBug --- cmake/required_deps/magic_enum.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/required_deps/magic_enum.cmake b/cmake/required_deps/magic_enum.cmake index 91d86cd0..b3cb587f 100644 --- a/cmake/required_deps/magic_enum.cmake +++ b/cmake/required_deps/magic_enum.cmake @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14) -find_package(magic_enum 0.8.2 QUIET) +find_package(magic_enum QUIET) if (${magic_enum_FOUND}) return() @@ -14,7 +14,7 @@ FetchContent_Declare(magic_enum # URL https://github.com/Neargye/magic_enum/releases/download/v0.8.2/magic_enum.hpp GIT_REPOSITORY https://github.com/Neargye/magic_enum.git - GIT_TAG "v0.9.6" + GIT_TAG "v0.9.7" OVERRIDE_FIND_PACKAGE EXCLUDE_FROM_ALL ) From 6486fa33554906fdc590f9530b59f2f96f41c386 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:26:30 +0800 Subject: [PATCH 0984/1123] Fix build Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 2 +- SlopeCraft/SCWind_slots.cpp | 2 +- SlopeCraftL/structure_3D.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/Schem/mushroom.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index d48ca666..7a5c56fc 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include const QString SCWind::update_url{ diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index c3880a6f..8db6af1e 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "PreviewWind.h" #include "AiCvterParameterDialog.h" diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index a8b74f56..f0926cd8 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "structure_3D.h" #include "color_table.h" diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index ff079bc4..f7dc882a 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -22,7 +22,7 @@ This file is part of SlopeCraft. #include "MCDataVersion.h" -#include +#include MCDataVersion::MCDataVersion_t MCDataVersion::string_to_data_version( const char *str, bool *ok) noexcept { diff --git a/utilities/Schem/mushroom.cpp b/utilities/Schem/mushroom.cpp index 652491e6..846ff449 100644 --- a/utilities/Schem/mushroom.cpp +++ b/utilities/Schem/mushroom.cpp @@ -1,7 +1,7 @@ #include "mushroom.h" #include #include -#include +#include #include namespace lsi = libSchem::internal; From 6df433e2eca79ced855cf33644e211ae65526254 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:29:06 +0800 Subject: [PATCH 0985/1123] Fix identifiers start with _ Signed-off-by: ToKiNoBug --- utilities/ColorManip/imageConvert.hpp | 127 +++++++++++----------- utilities/MapImageCvter/MapImageCvter.cpp | 14 +-- utilities/MapImageCvter/MapImageCvter.h | 56 +++++----- 3 files changed, 99 insertions(+), 98 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index e65827a4..de43ed43 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -103,12 +103,12 @@ class ImageCvter : public GPU_wrapper_wrapper { protected: const basic_colorset_t &basic_colorset; const allowed_colorset_t &allowed_colorset; - Eigen::ArrayXX _raw_image; + Eigen::ArrayXX raw_image_; ::SCL_convertAlgo algo; bool dither{false}; - std::unordered_map _color_hash; + std::unordered_map color_hash_; - Eigen::ArrayXX _dithered_image; + Eigen::ArrayXX dithered_image_; // Eigen::ArrayXX colorid_matrix; public: @@ -116,27 +116,27 @@ class ImageCvter : public GPU_wrapper_wrapper { // SCL_convertAlgo convert_algo{SCL_convertAlgo::RGB_Better}; inline void clear_images() noexcept { - this->_raw_image.resize(0, 0); - this->_dithered_image.resize(0, 0); + this->raw_image_.resize(0, 0); + this->dithered_image_.resize(0, 0); } /// When the colorset is changed, the hash must be cleared. inline void on_color_set_changed() noexcept { this->clear_color_hash(); } /// Call this function when the color set is changed. - inline void clear_color_hash() noexcept { this->_color_hash.clear(); } + inline void clear_color_hash() noexcept { this->color_hash_.clear(); } inline ::SCL_convertAlgo convert_algo() const noexcept { return this->algo; } inline bool is_dither() const noexcept { return this->dither; } - inline int64_t rows() const noexcept { return _raw_image.rows(); } - inline int64_t cols() const noexcept { return _raw_image.cols(); } - inline int64_t size() const noexcept { return _raw_image.size(); } + inline int64_t rows() const noexcept { return raw_image_.rows(); } + inline int64_t cols() const noexcept { return raw_image_.cols(); } + inline int64_t size() const noexcept { return raw_image_.size(); } - inline const auto &raw_image() const noexcept { return _raw_image; } + inline const auto &raw_image() const noexcept { return raw_image_; } - inline const auto &color_hash() const noexcept { return _color_hash; } + inline const auto &color_hash() const noexcept { return color_hash_; } void set_raw_image(const ARGB *const data, const int64_t _rows, const int64_t _cols, @@ -151,24 +151,24 @@ class ImageCvter : public GPU_wrapper_wrapper { if (is_col_major) { Eigen::Map> map(data, _rows, _cols); - this->_raw_image = map; + this->raw_image_ = map; } else { Eigen::Map> map(data, _rows, _cols); - this->_raw_image = map; + this->raw_image_ = map; } } - bool convert_image(::SCL_convertAlgo __algo, bool _dither, + bool convert_image(::SCL_convertAlgo algo_, bool dither_, bool try_gpu = false) noexcept { - if (__algo == ::SCL_convertAlgo::gaCvter) { - __algo = ::SCL_convertAlgo::RGB_Better; + if (algo_ == ::SCL_convertAlgo::gaCvter) { + algo_ = ::SCL_convertAlgo::RGB_Better; } - this->dither = _dither; + this->dither = dither_; ui.rangeSet(0, 100, 0); - this->algo = __algo; + this->algo = algo_; this->add_colors_to_hash(); ui.rangeSet(0, 100, 25); if (!this->match_all_TokiColors(try_gpu)) { @@ -179,22 +179,22 @@ class ImageCvter : public GPU_wrapper_wrapper { if (this->dither) { switch (this->algo) { case ::SCL_convertAlgo::RGB: - this->template __impl_dither<::SCL_convertAlgo::RGB>(); + this->template impl_dither__<::SCL_convertAlgo::RGB>(); break; case ::SCL_convertAlgo::RGB_Better: - this->template __impl_dither<::SCL_convertAlgo::RGB_Better>(); + this->template impl_dither__<::SCL_convertAlgo::RGB_Better>(); break; case ::SCL_convertAlgo::HSV: - this->template __impl_dither<::SCL_convertAlgo::HSV>(); + this->template impl_dither__<::SCL_convertAlgo::HSV>(); break; case ::SCL_convertAlgo::Lab94: - this->template __impl_dither<::SCL_convertAlgo::Lab94>(); + this->template impl_dither__<::SCL_convertAlgo::Lab94>(); break; case ::SCL_convertAlgo::Lab00: - this->template __impl_dither<::SCL_convertAlgo::Lab00>(); + this->template impl_dither__<::SCL_convertAlgo::Lab00>(); break; case ::SCL_convertAlgo::XYZ: - this->template __impl_dither<::SCL_convertAlgo::XYZ>(); + this->template impl_dither__<::SCL_convertAlgo::XYZ>(); break; default: @@ -202,7 +202,7 @@ class ImageCvter : public GPU_wrapper_wrapper { return false; } } else { - this->_dithered_image = this->_raw_image; + this->dithered_image_ = this->raw_image_; } // for (int64_t idx = 0; idx < this->_dithered_image.size(); idx++) { @@ -226,11 +226,11 @@ class ImageCvter : public GPU_wrapper_wrapper { result.setZero(this->rows(), this->cols()); for (int64_t idx = 0; idx < this->size(); idx++) { - const auto current_color = this->_dithered_image(idx); + const auto current_color = this->dithered_image_(idx); - auto it = this->_color_hash.find(convert_unit(current_color, this->algo)); + auto it = this->color_hash_.find(convert_unit(current_color, this->algo)); - if (it == this->_color_hash.end()) { + if (it == this->color_hash_.end()) { if (getA(current_color) <= 0) { result(idx) = 0; continue; @@ -252,10 +252,10 @@ class ImageCvter : public GPU_wrapper_wrapper { // sizeof(uint16_t)); for (int64_t idx = 0; idx < this->size(); idx++) { - auto it = this->_color_hash.find( - convert_unit(this->_dithered_image(idx), this->algo)); + auto it = this->color_hash_.find( + convert_unit(this->dithered_image_(idx), this->algo)); - if (it == this->_color_hash.end()) { + if (it == this->color_hash_.end()) { abort(); } @@ -267,9 +267,9 @@ class ImageCvter : public GPU_wrapper_wrapper { assert(r >= 0 && r < this->rows()); assert(c >= 0 && c < this->cols()); - const auto current_color = this->_dithered_image(r, c); - auto it = this->_color_hash.find(convert_unit{current_color, this->algo}); - if (it == this->_color_hash.end()) { + const auto current_color = this->dithered_image_(r, c); + auto it = this->color_hash_.find(convert_unit{current_color, this->algo}); + if (it == this->color_hash_.end()) { if (getA(current_color) > 0) { abort(); } @@ -300,9 +300,10 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t c = 0; c < cols(); c++) { const int64_t idx = (is_dest_col_major) ? (c * rows() + r) : (r * cols() + c); - const ARGB argb = this->_dithered_image(r, c); - auto it = this->_color_hash.find(convert_unit(argb, this->algo)); - if (it == this->_color_hash.end()) { + const ARGB argb = this->dithered_image_(r, c); + auto it = this->color_hash_.find(convert_unit(argb, this->algo)); + if (it == this->color_hash_.end()) { +#warning "Issue #130 crashed here" abort(); return; } @@ -326,13 +327,13 @@ class ImageCvter : public GPU_wrapper_wrapper { void add_colors_to_hash() noexcept { // this->_color_hash.clear(); - for (int64_t idx = 0; idx < this->_raw_image.size(); idx++) { - const ARGB argb = this->_raw_image(idx); + for (int64_t idx = 0; idx < this->raw_image_.size(); idx++) { + const ARGB argb = this->raw_image_(idx); convert_unit cu(argb, this->algo); - auto it = _color_hash.find(cu); + auto it = color_hash_.find(cu); // this key isn't inserted - if (it == _color_hash.end()) this->_color_hash.emplace(cu, TokiColor_t()); + if (it == color_hash_.end()) this->color_hash_.emplace(cu, TokiColor_t()); } } @@ -359,10 +360,10 @@ class ImageCvter : public GPU_wrapper_wrapper { // const int threadCount = omp_get_num_threads(); std::vector *> tasks; - tasks.reserve(_color_hash.size()); + tasks.reserve(color_hash_.size()); tasks.clear(); - for (auto &pair : _color_hash) { + for (auto &pair : color_hash_) { if (!pair.second.is_result_computed()) tasks.emplace_back(&pair); } const size_t taskCount = tasks.size(); @@ -391,8 +392,8 @@ class ImageCvter : public GPU_wrapper_wrapper { #pragma omp parallel for for (int64_t c = 0; c < this->cols(); c++) { for (int64_t r = 0; r < this->rows(); r++) { - auto it = this->_color_hash.find(this->_raw_image(r, c)); - if (it == this->_color_hash.end()) { + auto it = this->color_hash_.find(this->raw_image_(r, c)); + if (it == this->color_hash_.end()) { abort(); } @@ -417,10 +418,10 @@ class ImageCvter : public GPU_wrapper_wrapper { } std::vector *> tasks; - tasks.reserve(_color_hash.size()); + tasks.reserve(color_hash_.size()); tasks.clear(); - for (auto &pair : this->_color_hash) { + for (auto &pair : this->color_hash_) { if (!pair.second.is_result_computed()) { if ((pair.first._ARGB & 0xFF'00'00'00) == 0) { pair.second.compute(pair.first, this->allowed_colorset); @@ -555,20 +556,20 @@ class ImageCvter : public GPU_wrapper_wrapper { } template - void __impl_dither() noexcept { + void impl_dither__() noexcept { std::array dither_c3; for (auto &i : dither_c3) { i.setZero(this->rows() + 2, this->cols() + 2); } // dest.setZero(this->rows(), this->cols()); - this->_dithered_image.setZero(this->rows(), this->cols()); + this->dithered_image_.setZero(this->rows(), this->cols()); for (int64_t r = 0; r < this->rows(); r++) { for (int64_t c = 0; c < this->cols(); c++) { - auto it = this->_color_hash.find( - convert_unit(this->_raw_image(r, c), this->algo)); - if (it == this->_color_hash.end()) { + auto it = this->color_hash_.find( + convert_unit(this->raw_image_(r, c), this->algo)); + if (it == this->color_hash_.end()) { // unreachable abort(); return; @@ -584,7 +585,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t row = 0; row < this->rows(); row++) { if (is_dir_LR) for (int64_t col = 0; col < this->cols(); col++) { - if (::getA(this->_raw_image(row, col)) <= 0) { + if (::getA(this->raw_image_(row, col)) <= 0) { continue; } @@ -592,13 +593,13 @@ class ImageCvter : public GPU_wrapper_wrapper { dither_c3[0](row + 1, col + 1), dither_c3[1](row + 1, col + 1), dither_c3[2](row + 1, col + 1)); // ditheredImage(r, c) = Current; - this->_dithered_image(row, col) = current_argb; + this->dithered_image_(row, col) = current_argb; auto it_to_old_color = - this->_color_hash.find(convert_unit(current_argb, this->algo)); + this->color_hash_.find(convert_unit(current_argb, this->algo)); // if this color isn't matched, match it. - if (it_to_old_color == this->_color_hash.end()) { + if (it_to_old_color == this->color_hash_.end()) { convert_unit cu(current_argb, this->algo); - auto ret = this->_color_hash.emplace(cu, TokiColor_t()); + auto ret = this->color_hash_.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; @@ -625,19 +626,19 @@ class ImageCvter : public GPU_wrapper_wrapper { } else for (int64_t col = this->cols() - 1; col >= 0; col--) { - if (::getA(this->_raw_image(row, col)) <= 0) { + if (::getA(this->raw_image_(row, col)) <= 0) { continue; } const ARGB current_argb = ColorCvt( dither_c3[0](row + 1, col + 1), dither_c3[1](row + 1, col + 1), dither_c3[2](row + 1, col + 1)); - this->_dithered_image(row, col) = current_argb; + this->dithered_image_(row, col) = current_argb; convert_unit cu(current_argb, this->algo); - auto it_to_old_color = this->_color_hash.find(cu); + auto it_to_old_color = this->color_hash_.find(cu); // if this color isn't matched, match it. - if (it_to_old_color == this->_color_hash.end()) { - auto ret = this->_color_hash.emplace(cu, TokiColor_t()); + if (it_to_old_color == this->color_hash_.end()) { + auto ret = this->color_hash_.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; @@ -676,7 +677,7 @@ class ImageCvter : public GPU_wrapper_wrapper { } uint64_t task_hash(SCL_convertAlgo a, bool d) const noexcept { - const auto &img = this->_raw_image; + const auto &img = this->raw_image_; return std::hash()( std::string_view{(const char *)img.data(), diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index e441b0eb..823a7ae0 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -66,13 +66,13 @@ void libMapImageCvt::MapImageCvter::convert_image( gacvter->run(); - Eigen::ArrayXX raw_image_cache = this->_raw_image; + Eigen::ArrayXX raw_image_cache = this->raw_image_; - gacvter->resultImage(&this->_raw_image); + gacvter->resultImage(&this->raw_image_); Base_t::convert_image(::SCL_convertAlgo::RGB_Better, dither); - this->_raw_image = raw_image_cache; + this->raw_image_ = raw_image_cache; } bool libMapImageCvt::MapImageCvter::save_cache( @@ -129,8 +129,8 @@ bool libMapImageCvt::MapImageCvter::load_cache( this->load_from_itermediate(std::move(temp)); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); return true; } @@ -139,7 +139,7 @@ bool libMapImageCvt::MapImageCvter::load_cache(const char *filename) noexcept { this->load_from_itermediate(std::move(temp)); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); return true; } \ No newline at end of file diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 2ea85be9..9b9c4b58 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -91,25 +91,25 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { } dest.clear(); for (int64_t r = 0; r < this->rows(); r++) { - auto it = this->_color_hash.find( - convert_unit(this->_dithered_image(r, col), this->algo)); + auto it = this->color_hash_.find( + convert_unit(this->dithered_image_(r, col), this->algo)); dest.emplace_back(&it->second); } } - + // temp is a temporary container to pass ownership void load_from_itermediate(MapImageCvter &&temp) noexcept { - this->_raw_image = std::move(temp._raw_image); + this->raw_image_ = std::move(temp.raw_image_); this->algo = temp.algo; - this->_dithered_image = std::move(temp._dithered_image); + this->dithered_image_ = std::move(temp.dithered_image_); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); - if (this->_color_hash.empty()) { - this->_color_hash = std::move(temp._color_hash); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); + if (this->color_hash_.empty()) { + this->color_hash_ = std::move(temp.color_hash_); } else { - temp._color_hash.merge(this->_color_hash); - this->_color_hash = std::move(temp._color_hash); + temp.color_hash_.merge(this->color_hash_); + this->color_hash_ = std::move(temp.color_hash_); } } @@ -117,20 +117,20 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { friend class cereal::access; template void save(archive &ar) const { - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); - ar(this->_raw_image); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); + ar(this->raw_image_); ar(this->algo); ar(this->dither); // ar(this->_color_hash); - ar(this->_dithered_image); + ar(this->dithered_image_); // save required colorset { std::unordered_set colors_dithered_img; - colors_dithered_img.reserve(this->_dithered_image.size()); - for (int64_t i = 0; i < this->_dithered_image.size(); i++) { - colors_dithered_img.emplace(this->_dithered_image(i)); - colors_dithered_img.emplace(this->_raw_image(i)); + colors_dithered_img.reserve(this->dithered_image_.size()); + for (int64_t i = 0; i < this->dithered_image_.size(); i++) { + colors_dithered_img.emplace(this->dithered_image_(i)); + colors_dithered_img.emplace(this->raw_image_(i)); } const size_t size_colorset = colors_dithered_img.size(); @@ -150,14 +150,14 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { template void load(archive &ar) { - ar(this->_raw_image); + ar(this->raw_image_); ar(this->algo); ar(this->dither); // ar(this->_color_hash); - ar(this->_dithered_image); + ar(this->dithered_image_); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); { size_t size_colorset{0}; @@ -167,13 +167,13 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { TokiColor_t val; ar(key, val); - this->_color_hash.emplace(key, val); + this->color_hash_.emplace(key, val); } - for (int64_t i = 0; i < this->_dithered_image.size(); i++) { - auto it = this->_color_hash.find( - convert_unit{this->_dithered_image(i), this->convert_algo()}); - if (it == this->_color_hash.end()) { + for (int64_t i = 0; i < this->dithered_image_.size(); i++) { + auto it = this->color_hash_.find( + convert_unit{this->dithered_image_(i), this->convert_algo()}); + if (it == this->color_hash_.end()) { throw std::runtime_error{ "One or more colors not found in cached colorhash"}; } From 4d69e8ba96cc1a0522da7abcf355787197efc6f8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:51:16 +0800 Subject: [PATCH 0986/1123] Fix issue #130 Signed-off-by: ToKiNoBug --- utilities/ColorManip/imageConvert.hpp | 35 ++++++++++++++++++++++----- utilities/ColorManip/newTokiColor.hpp | 8 +++--- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index de43ed43..66dd0d17 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -176,6 +176,14 @@ class ImageCvter : public GPU_wrapper_wrapper { } ui.rangeSet(0, 100, 50); + // handle possible full-transparent pixel + { + convert_unit cu{ARGB32(0, 0, 0, 0), this->algo}; + TokiColor_t tk; + tk.compute(cu, this->allowed_colorset); + this->color_hash_.emplace(cu, tk); + } + if (this->dither) { switch (this->algo) { case ::SCL_convertAlgo::RGB: @@ -271,6 +279,7 @@ class ImageCvter : public GPU_wrapper_wrapper { auto it = this->color_hash_.find(convert_unit{current_color, this->algo}); if (it == this->color_hash_.end()) { if (getA(current_color) > 0) { + // logical impossible abort(); } return 0; @@ -300,12 +309,15 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t c = 0; c < cols(); c++) { const int64_t idx = (is_dest_col_major) ? (c * rows() + r) : (r * cols() + c); - const ARGB argb = this->dithered_image_(r, c); - auto it = this->color_hash_.find(convert_unit(argb, this->algo)); + ARGB argb = this->dithered_image_(r, c); + // process full-transparent image + if (::getA(argb) <= 0) { + argb = ARGB32(0, 0, 0, 0); + } + auto it = this->color_hash_.find(convert_unit{argb, this->algo}); if (it == this->color_hash_.end()) { -#warning "Issue #130 crashed here" + // logical impossible abort(); - return; } const auto color_id = it->second.color_id(); @@ -552,7 +564,6 @@ class ImageCvter : public GPU_wrapper_wrapper { } // unreachable abort(); - return 0; } template @@ -572,7 +583,6 @@ class ImageCvter : public GPU_wrapper_wrapper { if (it == this->color_hash_.end()) { // unreachable abort(); - return; } for (int ch = 0; ch < 3; ch++) { dither_c3[ch](r + 1, c + 1) = it->first.to_c3()[ch]; @@ -580,12 +590,24 @@ class ImageCvter : public GPU_wrapper_wrapper { } } + // auto handle_full_transparent_pixel = [this](ARGB color) { + // convert_unit cu{color, this->algo}; + // if (this->color_hash_.contains(cu)) { + // return; + // } + // TokiColor_t tk; + // tk.compute(cu, this->allowed_colorset); + // this->color_hash_.emplace(cu, tk); + // }; + // int64_t inserted_count = 0; bool is_dir_LR = true; for (int64_t row = 0; row < this->rows(); row++) { if (is_dir_LR) for (int64_t col = 0; col < this->cols(); col++) { if (::getA(this->raw_image_(row, col)) <= 0) { + // found full-transparent pixel + // handle_full_transparent_pixel(this->raw_image_(row, col)); continue; } @@ -627,6 +649,7 @@ class ImageCvter : public GPU_wrapper_wrapper { else for (int64_t col = this->cols() - 1; col >= 0; col--) { if (::getA(this->raw_image_(row, col)) <= 0) { + // handle_full_transparent_pixel(this->raw_image_(row, col)); continue; } diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index a787952c..65cfd4e9 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -128,13 +128,13 @@ class newTokiColor } template - void set_gpu_result(uint16_t __result_color_id, - float __result_diff) noexcept { + void set_gpu_result(uint16_t result_color_id__, + float result_diff__) noexcept { static_assert(!is_not_optical, "set_gpu_result is only avaliable for VisualCraftL."); - this->ResultDiff = __result_diff; - this->result_color_id = __result_color_id; + this->ResultDiff = result_diff__; + this->result_color_id = result_color_id__; } auto compute(convert_unit cu, const allowed_t &allowed) noexcept { From b471f2b0b04b06de2aebe5f11bd3f7308334fbcb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:00:03 +0800 Subject: [PATCH 0987/1123] Fix most identifiers starting with _ in ColorManip Signed-off-by: ToKiNoBug --- utilities/ColorManip/colorset_maptical.hpp | 97 +++++++++---------- utilities/ColorManip/colorset_optical.hpp | 103 ++++++++++++--------- utilities/ColorManip/imageConvert.hpp | 18 ++-- utilities/ColorManip/newTokiColor.hpp | 17 ++-- 4 files changed, 129 insertions(+), 106 deletions(-) diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 5b5e7930..4c9ab3dc 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -61,10 +61,10 @@ class newtokicolor_base_maptical { class alignas(32) colorset_maptical_basic { private: - Eigen::Array __rgb; - Eigen::Array __hsv; - Eigen::Array __lab; - Eigen::Array __xyz; + Eigen::Array rgb_table; + Eigen::Array hsv_table; + Eigen::Array lab_table; + Eigen::Array xyz_table; public: /// The default constructor is deleted @@ -72,32 +72,33 @@ class alignas(32) colorset_maptical_basic { /// Construct from color source colorset_maptical_basic(const float *const rgbsrc) { assert(rgbsrc); - memcpy(__rgb.data(), rgbsrc, sizeof(__rgb)); + memcpy(rgb_table.data(), rgbsrc, sizeof(rgb_table)); for (int row = 0; row < 256; row++) { - const float r = __rgb(row, 0), g = __rgb(row, 1), b = __rgb(row, 2); - RGB2HSV(r, g, b, __hsv(row, 0), __hsv(row, 1), __hsv(row, 2)); - RGB2XYZ(r, g, b, __xyz(row, 0), __xyz(row, 1), __xyz(row, 2)); - XYZ2Lab(XYZ(row, 0), XYZ(row, 1), XYZ(row, 2), __lab(row, 0), - __lab(row, 1), __lab(row, 2)); + const float r = rgb_table(row, 0), g = rgb_table(row, 1), + b = rgb_table(row, 2); + RGB2HSV(r, g, b, hsv_table(row, 0), hsv_table(row, 1), hsv_table(row, 2)); + RGB2XYZ(r, g, b, xyz_table(row, 0), xyz_table(row, 1), xyz_table(row, 2)); + XYZ2Lab(XYZ(row, 0), XYZ(row, 1), XYZ(row, 2), lab_table(row, 0), + lab_table(row, 1), lab_table(row, 2)); } } /// get the color count inline constexpr int color_count() const noexcept { return 256; } - inline const auto &RGB_mat() const noexcept { return __rgb; } + inline const auto &RGB_mat() const noexcept { return rgb_table; } inline float RGB(const int r, const int c) const noexcept { - return __rgb(r, c); + return rgb_table(r, c); } inline float HSV(const int r, const int c) const noexcept { - return __hsv(r, c); + return hsv_table(r, c); } inline float Lab(const int r, const int c) const noexcept { - return __lab(r, c); + return lab_table(r, c); } inline float XYZ(const int r, const int c) const noexcept { - return __xyz(r, c); + return xyz_table(r, c); } static inline uint8_t Map(const int r) noexcept { @@ -119,13 +120,13 @@ class alignas(32) colorset_maptical_allowed { static constexpr uint8_t invalid_color_id = 0; private: - std::array __rgb; - std::array __hsv; - std::array __lab; - std::array __xyz; - Eigen::Array __map; + std::array rgb_table; + std::array hsv_table; + std::array lab_table; + std::array xyz_table; + Eigen::Array map_table; // std::array __map; - int _color_count{0}; + int color_count_{0}; std::array depth_counter; @@ -135,65 +136,65 @@ class alignas(32) colorset_maptical_allowed { return this->depth_counter; } - inline int color_count() const noexcept { return _color_count; } + inline int color_count() const noexcept { return color_count_; } inline float RGB(int r, int c) const noexcept { assert(r < color_count()); - return __rgb[c](r); + return rgb_table[c](r); } inline float HSV(int r, int c) const noexcept { assert(r < color_count()); - return __hsv[c](r); + return hsv_table[c](r); } inline float Lab(int r, int c) const noexcept { assert(r < color_count()); - return __lab[c](r); + return lab_table[c](r); } inline float XYZ(int r, int c) const noexcept { assert(r < color_count()); - return __xyz[c](r); + return xyz_table[c](r); } inline uint8_t Map(int r) const noexcept { assert(r < color_count()); - return __map[r]; + return map_table[r]; } inline auto rgb(int channel) const noexcept { - return __rgb[channel].head(_color_count); + return rgb_table[channel].head(color_count_); } inline auto hsv(int channel) const noexcept { - return __hsv[channel].head(_color_count); + return hsv_table[channel].head(color_count_); } inline auto lab(int channel) const noexcept { - return __lab[channel].head(_color_count); + return lab_table[channel].head(color_count_); } inline auto xyz(int channel) const noexcept { - return __xyz[channel].head(_color_count); + return xyz_table[channel].head(color_count_); } - inline auto map() const noexcept { return __map.head(_color_count); } + inline auto map() const noexcept { return map_table.head(color_count_); } inline const float *rgb_data(int channel) const noexcept { - return __rgb[channel].data(); + return rgb_table[channel].data(); } inline const float *hsv_data(int channel) const noexcept { - return __hsv[channel].data(); + return hsv_table[channel].data(); } inline const float *lab_data(int channel) const noexcept { - return __lab[channel].data(); + return lab_table[channel].data(); } inline const float *xyz_data(int channel) const noexcept { - return __xyz[channel].data(); + return xyz_table[channel].data(); } - inline const uint8_t *map_data() const noexcept { return __map.data(); } + inline const uint8_t *map_data() const noexcept { return map_table.data(); } bool apply_allowed(const colorset_maptical_basic &src, std::span allow_list) noexcept { @@ -204,14 +205,14 @@ class alignas(32) colorset_maptical_allowed { } for (int c = 0; c < 3; c++) { - __rgb[c].setZero(); - __hsv[c].setZero(); - __lab[c].setZero(); - __xyz[c].setZero(); + rgb_table[c].setZero(); + hsv_table[c].setZero(); + lab_table[c].setZero(); + xyz_table[c].setZero(); } - __map.setZero(); + map_table.setZero(); - _color_count = new_color_count; + color_count_ = new_color_count; for (int writeidx = 0, readidx = 0; readidx < 256; readidx++) { const int base = (readidx & 0b111111); @@ -221,12 +222,12 @@ class alignas(32) colorset_maptical_allowed { if (allow_list[readidx]) { for (int c = 0; c < 3; c++) { - __rgb[c](writeidx) = src.RGB(readidx, c); - __hsv[c](writeidx) = src.HSV(readidx, c); - __lab[c](writeidx) = src.Lab(readidx, c); - __xyz[c](writeidx) = src.XYZ(readidx, c); + rgb_table[c](writeidx) = src.RGB(readidx, c); + hsv_table[c](writeidx) = src.HSV(readidx, c); + lab_table[c](writeidx) = src.Lab(readidx, c); + xyz_table[c](writeidx) = src.XYZ(readidx, c); } - __map[writeidx] = src.Map(readidx); + map_table[writeidx] = src.Map(readidx); writeidx++; } } diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index f731be06..8b4fa58d 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -30,32 +30,48 @@ This file is part of SlopeCraft. class alignas(32) colorset_optical_base { protected: - std::array __rgb; - std::array __hsv; - std::array __lab; - std::array __xyz; + std::array rgb_table; + std::array hsv_table; + std::array lab_table; + std::array xyz_table; private: - int _color_count; + int color_count_; public: - inline int color_count() const noexcept { return _color_count; } + inline int color_count() const noexcept { return color_count_; } - inline float RGB(int r, int c) const noexcept { return __rgb[c](r); } - inline auto rgb(int c) const noexcept { return __rgb[c].head(_color_count); } - inline const float *rgb_data(int c) const noexcept { return __rgb[c].data(); } + inline float RGB(int r, int c) const noexcept { return rgb_table[c](r); } + inline auto rgb(int c) const noexcept { + return rgb_table[c].head(color_count_); + } + inline const float *rgb_data(int c) const noexcept { + return rgb_table[c].data(); + } - inline float HSV(int r, int c) const noexcept { return __hsv[c](r); } - inline auto hsv(int c) const noexcept { return __hsv[c].head(_color_count); } - inline const float *hsv_data(int c) const noexcept { return __hsv[c].data(); } + inline float HSV(int r, int c) const noexcept { return hsv_table[c](r); } + inline auto hsv(int c) const noexcept { + return hsv_table[c].head(color_count_); + } + inline const float *hsv_data(int c) const noexcept { + return hsv_table[c].data(); + } - inline float Lab(int r, int c) const noexcept { return __lab[c](r); } - inline auto lab(int c) const noexcept { return __lab[c].head(_color_count); } - inline const float *lab_data(int c) const noexcept { return __lab[c].data(); } + inline float Lab(int r, int c) const noexcept { return lab_table[c](r); } + inline auto lab(int c) const noexcept { + return lab_table[c].head(color_count_); + } + inline const float *lab_data(int c) const noexcept { + return lab_table[c].data(); + } - inline float XYZ(int r, int c) const noexcept { return __xyz[c](r); } - inline auto xyz(int c) const noexcept { return __xyz[c].head(_color_count); } - inline const float *xyz_data(int c) const noexcept { return __xyz[c].data(); } + inline float XYZ(int r, int c) const noexcept { return xyz_table[c](r); } + inline auto xyz(int c) const noexcept { + return xyz_table[c].head(color_count_); + } + inline const float *xyz_data(int c) const noexcept { + return xyz_table[c].data(); + } protected: void resize(int new_color_count) noexcept { @@ -64,13 +80,13 @@ class alignas(32) colorset_optical_base { } for (int c = 0; c < 3; c++) { - __rgb[c].setZero(new_color_count); - __hsv[c].setZero(new_color_count); - __lab[c].setZero(new_color_count); - __xyz[c].setZero(new_color_count); + rgb_table[c].setZero(new_color_count); + hsv_table[c].setZero(new_color_count); + lab_table[c].setZero(new_color_count); + xyz_table[c].setZero(new_color_count); } - this->_color_count = new_color_count; + this->color_count_ = new_color_count; } }; @@ -103,22 +119,23 @@ class colorset_optical_basic : public colorset_optical_base { rbgsrc_colmajor, new_color_count, 3); for (int c = 0; c < 3; c++) { - memcpy(this->__rgb[c].data(), rbgsrc_colmajor + (new_color_count * c), + memcpy(this->rgb_table[c].data(), + rbgsrc_colmajor + (new_color_count * c), sizeof(float) * new_color_count); //= rgbsrcmap.col(c); } } for (int coloridx = 0; coloridx < new_color_count; coloridx++) { - RGB2HSV(this->__rgb[0](coloridx), this->__rgb[1](coloridx), - this->__rgb[2](coloridx), this->__hsv[0](coloridx), - this->__hsv[1](coloridx), this->__hsv[2](coloridx)); - RGB2XYZ(this->__rgb[0](coloridx), this->__rgb[1](coloridx), - this->__rgb[2](coloridx), this->__xyz[0](coloridx), - this->__xyz[1](coloridx), this->__xyz[2](coloridx)); - XYZ2Lab(this->__xyz[0](coloridx), this->__xyz[1](coloridx), - this->__xyz[2](coloridx), this->__lab[0](coloridx), - this->__lab[1](coloridx), this->__lab[2](coloridx)); + RGB2HSV(this->rgb_table[0](coloridx), this->rgb_table[1](coloridx), + this->rgb_table[2](coloridx), this->hsv_table[0](coloridx), + this->hsv_table[1](coloridx), this->hsv_table[2](coloridx)); + RGB2XYZ(this->rgb_table[0](coloridx), this->rgb_table[1](coloridx), + this->rgb_table[2](coloridx), this->xyz_table[0](coloridx), + this->xyz_table[1](coloridx), this->xyz_table[2](coloridx)); + XYZ2Lab(this->xyz_table[0](coloridx), this->xyz_table[1](coloridx), + this->xyz_table[2](coloridx), this->lab_table[0](coloridx), + this->lab_table[1](coloridx), this->lab_table[2](coloridx)); } return true; @@ -143,12 +160,12 @@ class colorset_optical_allowed : public colorset_optical_base { static constexpr uint16_t invalid_color_id = 0xFFFF; private: - Eigen::Array __color_id; + Eigen::Array color_id_; void resize(int new_color_count) { colorset_optical_base::resize(new_color_count); - __color_id.resize(new_color_count); - __color_id.fill(invalid_color_id); + color_id_.resize(new_color_count); + color_id_.fill(invalid_color_id); } public: @@ -179,12 +196,12 @@ class colorset_optical_allowed : public colorset_optical_base { } for (int c = 0; c < 3; c++) { - this->__rgb[c][writeidx] = src.RGB(readidx, c); - this->__hsv[c][writeidx] = src.HSV(readidx, c); - this->__lab[c][writeidx] = src.Lab(readidx, c); - this->__xyz[c][writeidx] = src.XYZ(readidx, c); + this->rgb_table[c][writeidx] = src.RGB(readidx, c); + this->hsv_table[c][writeidx] = src.HSV(readidx, c); + this->lab_table[c][writeidx] = src.Lab(readidx, c); + this->xyz_table[c][writeidx] = src.XYZ(readidx, c); } - __color_id[writeidx] = src.color_id(readidx); + color_id_[writeidx] = src.color_id(readidx); writeidx++; } @@ -193,8 +210,8 @@ class colorset_optical_allowed : public colorset_optical_base { } inline uint16_t color_id(uint16_t idx) const noexcept { - assert(idx < __color_id.size()); - return __color_id[idx]; + assert(idx < color_id_.size()); + return color_id_[idx]; } }; diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 66dd0d17..8031d11f 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -138,10 +138,10 @@ class ImageCvter : public GPU_wrapper_wrapper { inline const auto &color_hash() const noexcept { return color_hash_; } - void set_raw_image(const ARGB *const data, const int64_t _rows, - const int64_t _cols, + void set_raw_image(const ARGB *const data, const int64_t n_rows, + const int64_t n_cols, const bool is_col_major = true) noexcept { - if (_rows <= 0 || _cols <= 0) { + if (n_rows <= 0 || n_cols <= 0) { return; } if (data == nullptr) { @@ -150,13 +150,19 @@ class ImageCvter : public GPU_wrapper_wrapper { if (is_col_major) { Eigen::Map> - map(data, _rows, _cols); + map(data, n_rows, n_cols); this->raw_image_ = map; } else { Eigen::Map> - map(data, _rows, _cols); + map(data, n_rows, n_cols); this->raw_image_ = map; } + // filter full-transparent colors + // for (ARGB &color : this->raw_image_.) { + // if (getA(color) <= 0) { + // color = ARGB32(0, 0, 0, 0); + // } + // } } bool convert_image(::SCL_convertAlgo algo_, bool dither_, @@ -435,7 +441,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (auto &pair : this->color_hash_) { if (!pair.second.is_result_computed()) { - if ((pair.first._ARGB & 0xFF'00'00'00) == 0) { + if ((pair.first.ARGB_ & 0xFF'00'00'00) == 0) { pair.second.compute(pair.first, this->allowed_colorset); } else { tasks.emplace_back(&pair); diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 65cfd4e9..3bb46928 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -43,17 +43,17 @@ inline constexpr float threshold = 1e-10f; } // namespace struct convert_unit { convert_unit() = default; - explicit convert_unit(ARGB _a, ::SCL_convertAlgo _c) : _ARGB(_a), algo(_c) {} - ARGB _ARGB; + explicit convert_unit(ARGB a_, ::SCL_convertAlgo c_) : ARGB_(a_), algo(c_) {} + ARGB ARGB_; ::SCL_convertAlgo algo; inline bool operator==(const convert_unit another) const noexcept { - return (_ARGB == another._ARGB) && (algo == another.algo); + return (ARGB_ == another.ARGB_) && (algo == another.algo); } inline Eigen::Array3f to_c3() const noexcept { Eigen::Array3f c3; - const ::ARGB rawColor = this->_ARGB; + const ::ARGB rawColor = this->ARGB_; switch (this->algo) { case ::SCL_convertAlgo::RGB: case ::SCL_convertAlgo::RGB_Better: @@ -84,18 +84,18 @@ struct convert_unit { template void save(archive &ar) const { - ar(this->_ARGB, this->algo); + ar(this->ARGB_, this->algo); } template void load(archive &ar) { - ar(this->_ARGB, this->algo); + ar(this->ARGB_, this->algo); } }; struct hash_cvt_unit { public: inline size_t operator()(const convert_unit cu) const noexcept { - return std::hash()(cu._ARGB) ^ + return std::hash()(cu.ARGB_) ^ std::hash()(uint8_t(cu.algo)); } }; @@ -138,7 +138,7 @@ class newTokiColor } auto compute(convert_unit cu, const allowed_t &allowed) noexcept { - if (getA(cu._ARGB) == 0) { + if (getA(cu.ARGB_) == 0) { if constexpr (is_not_optical) { this->Result = 0; return this->Result; @@ -175,7 +175,6 @@ class newTokiColor default: abort(); - return result_t(0); } } From c6f35e17fc4e2f4d9fa91cd5417d2a80ad1f312d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:09:56 +0800 Subject: [PATCH 0988/1123] Update version number to 5.3.1 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4d6cd91..502a9595 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.3.0) +set(SlopeCraft_version 5.3.1) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From ba8fd3f7e89a1a84f56da7dcad026fa9767e30b1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:15:11 +0800 Subject: [PATCH 0989/1123] Fix manually searching for zstd Signed-off-by: ToKiNoBug --- cmake/required_deps/zstd.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/zstd.cmake b/cmake/required_deps/zstd.cmake index 5c22e941..ac459ba5 100644 --- a/cmake/required_deps/zstd.cmake +++ b/cmake/required_deps/zstd.cmake @@ -26,7 +26,7 @@ if (NOT ZSTD_FOUND) find_file(zstd_header_loc NAMES zstd.h HINTS "/usr/lib/include/zstd.h") if (zstd_header_loc) - cmake_path(GET zstd_include_dir PARENT_PATH zstd_header_loc) + cmake_path(GET zstd_header_loc PARENT_PATH zstd_include_dir) target_include_directories(zstd_manually_imported INTERFACE ${zstd_include_dir}) endif () # cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) From 7a1919cecb707ad446a3b75737e0e3587015de5e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:27:51 +0800 Subject: [PATCH 0990/1123] Fix windows build for VC Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 2 +- VisualCraftL/TokiVC_export_test.cpp | 4 ++-- VisualCraftL/VisualCraftL.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index 7ce0bade..bc6be30e 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include "ParseResourcePack.h" #include "VCL_internal.h" -#include +#include VCL_block::VCL_block() { this->initialize_attributes(); } diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index cfa96f96..02efacd8 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -20,11 +20,11 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ +#include +#include #include "TokiVC.h" #include "VCL_internal.h" #include "VisualCraftL.h" -#include -#include const VCL_block *find_first_mark_block( const std::unordered_map diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index d37a24ea..f8ed00de 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1182,7 +1182,7 @@ VCL_EXPORT_FUN VCL_biome_info VCL_get_biome_info(VCL_biome_t biome) { return VCL_biome_info{NAN, NAN}; } -#include +#include const char *VCL_biome_name_ZH(VCL_biome_t b) noexcept { switch (b) { From 1d20ec90b37977ed6f5e3167c76036ec47fb9a0d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:28:06 +0800 Subject: [PATCH 0991/1123] Try to fix mac build Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 3 ++- utilities/Schem/Schem.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index fb9cded2..509f875a 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,6 +14,8 @@ add_library(Schem item.cpp item.h ) +target_compile_features(Schem PUBLIC cxx_std_23) + find_package(Eigen3 REQUIRED) find_package(cereal REQUIRED) @@ -34,7 +36,6 @@ target_link_libraries(Schem PUBLIC if (TARGET Boost::multi_array) target_link_libraries(Schem PUBLIC Boost::multi_array) endif () -target_compile_features(Schem PUBLIC cxx_std_23) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) if (CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 41cde7a1..faa3663d 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -20,10 +20,10 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ +#include #include #include #include -#include #include #include #include From 472be08b3b61d749f26c20298b5038dcdf0e4340 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:44:25 +0800 Subject: [PATCH 0992/1123] Use gcc 14 instead of 12 in linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index d758a95b..9ba0d7f1 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: - sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libboost-tools-dev libboost-doc libexpected-dev p7zip-full + sudo apt install gcc-14 g++-14 zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libboost-tools-dev libboost-doc libexpected-dev p7zip-full - name: Install xsimd run: | @@ -81,7 +81,7 @@ jobs: uses: actions/checkout@v4 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-14 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-14 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: CMake build run: cmake --build ./build --parallel From 57869cf4bedfb2d3ddcae5da573a86bbf588ee01 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:49:34 +0800 Subject: [PATCH 0993/1123] Remove use of std::views::enumerate to support clang19+libc++ Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index faa3663d..6af8df2c 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -191,8 +191,8 @@ Schem::split_by_block_size( this->z_range()}; for (size_t dim = 0; dim < 3; dim++) { int64_t cur_block_start_index = 0; - for (auto [blk_idx, block_len] : - xyz_block_len[dim] | std::views::enumerate) { + for (size_t blk_idx = 0; blk_idx < xyz_block_len[dim].size(); blk_idx++) { + const auto block_len = xyz_block_len[dim][blk_idx]; if (block_len <= 0) { return tl::make_unexpected(fmt::format( "Found non-positive block length in dim = {}, block index = {}", @@ -220,12 +220,12 @@ Schem::split_by_block_size( [xyz_block_index_pairs[1].size()] [xyz_block_index_pairs[2].size()]}; - for (auto [x_idx, x_range] : - xyz_block_index_pairs[0] | std::views::enumerate) { - for (auto [y_idx, y_range] : - xyz_block_index_pairs[1] | std::views::enumerate) { - for (auto [z_idx, z_range] : - xyz_block_index_pairs[2] | std::views::enumerate) { + for (size_t x_idx = 0; x_idx < xyz_block_index_pairs[0].size(); x_idx++) { + const auto x_range = xyz_block_index_pairs[0][x_idx]; + for (size_t y_idx = 0; y_idx < xyz_block_index_pairs[1].size(); y_idx++) { + const auto y_range = xyz_block_index_pairs[1][y_idx]; + for (size_t z_idx = 0; z_idx < xyz_block_index_pairs[2].size(); z_idx++) { + const auto z_range = xyz_block_index_pairs[2][z_idx]; const Eigen::Array offset{x_range.first, y_range.first, z_range.first}; auto &dest = ret[x_idx][y_idx][z_idx]; From c595f94e93666e531a78e8c7c74e4104500e793a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:49:48 +0800 Subject: [PATCH 0994/1123] Fix vccl including magic_enum Signed-off-by: ToKiNoBug --- vccl/vccl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 6f80d992..5ace058f 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -26,7 +26,7 @@ This file is part of SlopeCraft. #include "vccl_internal.h" #include #include -#include +#include #include #include From f61893edbb14f32494402dc3e648dc86a6131471 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:56:28 +0800 Subject: [PATCH 0995/1123] Try to fix mac build Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 6af8df2c..83847e33 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,7 +47,12 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } - this->xzy.resize(x, z, y); + this->xzy.resize({x, z, y}); + // #ifdef __APPLE__ + // this->xzy.resize({x, z, y}); + // #else + // this->xzy.resize(x, z, y); + // #endif } std::string Schem::check_size() const noexcept { From 2d3fd4b1ad1a0fd96d608ebba7a5da9826076b01 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:58:16 +0800 Subject: [PATCH 0996/1123] Fix including magic_enum Signed-off-by: ToKiNoBug --- VisualCraft/BiomeBrowser.cpp | 2 +- VisualCraft/BlockBrowser.cpp | 2 +- VisualCraft/BlockSelectorCriteria.cpp | 2 +- VisualCraft/VCWind.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VisualCraft/BiomeBrowser.cpp b/VisualCraft/BiomeBrowser.cpp index f3bbc11b..febc9fb4 100644 --- a/VisualCraft/BiomeBrowser.cpp +++ b/VisualCraft/BiomeBrowser.cpp @@ -26,7 +26,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include BiomeBrowser::BiomeBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::BiomeBrowser) { diff --git a/VisualCraft/BlockBrowser.cpp b/VisualCraft/BlockBrowser.cpp index 9ed0b7dd..01b99745 100644 --- a/VisualCraft/BlockBrowser.cpp +++ b/VisualCraft/BlockBrowser.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include BlockBrowser::BlockBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::BlockBrowser) { diff --git a/VisualCraft/BlockSelectorCriteria.cpp b/VisualCraft/BlockSelectorCriteria.cpp index dc06b64d..ef51bb55 100644 --- a/VisualCraft/BlockSelectorCriteria.cpp +++ b/VisualCraft/BlockSelectorCriteria.cpp @@ -22,7 +22,7 @@ This file is part of SlopeCraft. #include "BlockSelector.h" #include "ui_BlockSelectorCriteria.h" -#include +#include BlockSelectorCriteria::BlockSelectorCriteria(QWidget *parent) : QWidget(parent), ui(new Ui::BlockSelectorCriteria) { diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 76999465..43b25c2e 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include #include #include "VC_block_class.h" #include "ui_VCWind.h" From ed77602ea1bad561b6ac13532ca18876f2666247 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:59:37 +0800 Subject: [PATCH 0997/1123] Disable vulkan backend for macos temporarily Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 4 +++- .github/workflows/macos-build-x64.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 24e336a3..25281c7e 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -12,7 +12,9 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, Vulkan ] + gpu_api: [ None, + # Vulkan + ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index a8df681a..e4ec9344 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -12,7 +12,9 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, Vulkan ] + gpu_api: [ None, + # Vulkan + ] vectorize: [ ON, OFF ] env: BUILD_TYPE: ${{ matrix.build_type }} From 79f979562667a3248cbd194146594ea5473f6aa5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:03:32 +0800 Subject: [PATCH 0998/1123] Fix Schem::resize Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 83847e33..844899f9 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,12 +47,11 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } +#ifdef __APPLE__ this->xzy.resize({x, z, y}); - // #ifdef __APPLE__ - // this->xzy.resize({x, z, y}); - // #else - // this->xzy.resize(x, z, y); - // #endif +#else + this->xzy.resize(x, z, y); +#endif } std::string Schem::check_size() const noexcept { From c1c12b51f7358d555358e08af99dca5d6de4e060 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:07:43 +0800 Subject: [PATCH 0999/1123] Try to fix Eigen tensor issues around libScheme Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 509f875a..5275eadd 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(Schem item.cpp item.h ) -target_compile_features(Schem PUBLIC cxx_std_23) +target_compile_features(Schem PUBLIC cxx_std_17) find_package(Eigen3 REQUIRED) From 12464111233c4c56f17d084f2f57bf936689ba4d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:12:33 +0800 Subject: [PATCH 1000/1123] Try to fix Eigen tensor issues around libScheme Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 2 +- utilities/Schem/Schem.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 5275eadd..f7383856 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(Schem item.cpp item.h ) -target_compile_features(Schem PUBLIC cxx_std_17) +target_compile_features(Schem PUBLIC cxx_std_14) find_package(Eigen3 REQUIRED) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 844899f9..6af8df2c 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,11 +47,7 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } -#ifdef __APPLE__ - this->xzy.resize({x, z, y}); -#else this->xzy.resize(x, z, y); -#endif } std::string Schem::check_size() const noexcept { From 5a6306f490e29d64f4ee91f73771eb0899f73137 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:32:39 +0800 Subject: [PATCH 1001/1123] Try to fix libSchem on macos Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 4 +++- utilities/Schem/bit_shrink.cpp | 11 +---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 6af8df2c..1b39f1e4 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -162,7 +162,9 @@ Schem Schem::slice_no_check(std::span, 3> extent[0] = xyz_index_range[0].second - xyz_index_range[0].first; extent[1] = xyz_index_range[2].second - xyz_index_range[2].first; extent[2] = xyz_index_range[1].second - xyz_index_range[1].first; - ret.xzy = this->xzy.slice(start, extent); + // avoid Tensor::resize which is problematic on mac + decltype(ret.xzy) temp{this->xzy.slice(start, extent)}; + ret.xzy = std::move(temp); } for (auto &entity : this->entities) { diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index d929a9d9..f884b8b4 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -156,19 +156,10 @@ bool process_block_id( void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept { - // if (palette_max <= 128) { - // dest->resize(src.size()); - // for (size_t idx = 0; idx < src.size(); idx++) { - // dest->at(idx) = src[idx] & 0xFF; - // } - // return; - //} - dest->reserve(src.size() * 2); dest->clear(); - for (size_t idx = 0; idx < src.size(); idx++) { - uint16_t temp = src[idx]; + for (const uint16_t temp : src) { if (temp < 128) { dest->emplace_back(temp); } else { From 7c475abdcb04d39ec480439894a208e9366fc8c9 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:38:46 +0800 Subject: [PATCH 1002/1123] Try to fix libSchem on macos Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 1b39f1e4..5fdbcde0 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -155,7 +155,7 @@ Schem Schem::slice_no_check(std::span, 3> pos_max[dim] = xyz_index_range[dim].second; } { - Eigen::array start, extent; + Eigen::array start, extent; start[0] = xyz_index_range[0].first; start[1] = xyz_index_range[2].first; start[2] = xyz_index_range[1].first; From c222abbcb712ff8dcaa44cad33c51600f2a806e7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 17 Dec 2024 14:02:09 +0800 Subject: [PATCH 1003/1123] add git attributes Signed-off-by: ToKiNoBug --- .gitattribute => .gitattributes | 2 ++ 1 file changed, 2 insertions(+) rename .gitattribute => .gitattributes (84%) diff --git a/.gitattribute b/.gitattributes similarity index 84% rename from .gitattribute rename to .gitattributes index 2e0ce43b..688db333 100644 --- a/.gitattribute +++ b/.gitattributes @@ -1,3 +1,5 @@ +*.zip filter=lfs diff=lfs merge=lfs -text + * text=crlf *.bat text eol=crlf *.sh text eol=lf From 22f3369dbbcac0eb02d9cfd481cefb117f27c27a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 22 Dec 2024 17:06:24 +0800 Subject: [PATCH 1004/1123] fix windows-clang19-msvc build Signed-off-by: ToKiNoBug --- cmake/required_deps/HeuristicFlow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/HeuristicFlow.cmake b/cmake/required_deps/HeuristicFlow.cmake index 47bdb998..5b0fcd08 100644 --- a/cmake/required_deps/HeuristicFlow.cmake +++ b/cmake/required_deps/HeuristicFlow.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare(Heu GIT_REPOSITORY https://github.com/SlopeCraft/HeuristicFlow.git - GIT_TAG v1.6.4.1 + GIT_TAG v1.6.4.3 OVERRIDE_FIND_PACKAGE EXCLUDE_FROM_ALL ) From 8054cf3253fa27d5b1f1089f914ca4bdfd171c8e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:56:04 +0800 Subject: [PATCH 1005/1123] pass an identical change in ParseResourcePack_json.cpp Signed-off-by: ToKiNoBug --- VisualCraftL/ParseResourcePack_json.cpp | 2535 +++++++++++------------ 1 file changed, 1267 insertions(+), 1268 deletions(-) diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index ce9178b9..c0af1e8a 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -1,1268 +1,1267 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include -#include -#include -#include - -#include -#include "ParseResourcePack.h" -#include "VCL_internal.h" - -using namespace resource_json; - -using njson = nlohmann::json; - -size_t resource_json::state_list::num_1() const noexcept { - size_t counter = 0; - for (const auto &s : *this) { - if (s.value.empty()) { - counter++; - } - } - return counter; -} - -bool resource_json::state_list::euqals( - const state_list &another) const noexcept { - if (this->size() <= 0) return true; - if (this->size() != another.size()) return false; - int match_num = 0; - for (const state &sa : *this) { - for (const state &sb : another) { - if ((sa.key == sb.key) && (sa.value == sb.value)) { - match_num++; - } - } - } - - if (match_num < int(this->size())) { - return false; - } else { - return true; - } -} - -bool resource_json::state_list::contains( - const state_list &another) const noexcept { - if (another.size() > this->size()) { - return false; - } - - for (const state &s_json : another) { - bool is_current_state_matched = false; - for (const state &s_block : *this) { - if (s_json.key != s_block.key) { - continue; - } - - if (s_block.value == s_json.value) { - is_current_state_matched = true; - break; - } - } - if (!is_current_state_matched) { - return false; - } - } - - return true; -} - -bool resource_json::criteria_list_and::match( - const state_list &sl) const noexcept { - const auto &cl = *this; - int match_num = 0; - for (const criteria &c : cl) { - std::string_view key = c.key; - - const char *value = nullptr; - for (const state &s : sl) { - if (s.key == key) { - value = s.value.data(); - break; - } - } - // if value is not set, it is not considered as match - if (value == nullptr) { - break; - } - - if (c.match(value)) { - match_num++; - } - } - - if (match_num < int(cl.size())) { - return false; - } - return true; -} - -bool resource_json::match_criteria_list(const criteria_list_and &cl, - const state_list &sl) noexcept { - return cl.match(sl); -} - -bool resource_json::multipart_pair::match(const state_list &sl) const noexcept { - const resource_json::criteria *when = - std::get_if(&this->criteria_variant); - if (when != nullptr) { - std::string_view key = when->key; - const char *slvalue = nullptr; - for (const state &s : sl) { - if (s.key == key) { - slvalue = s.value.data(); - break; - } - } - // if sl don't have a value for the key of criteria, it is considered as - // mismatch - if (slvalue == nullptr) { - return false; - } - - return when->match(slvalue); - } - - if (std::get_if(&this->criteria_variant) != nullptr) { - return true; - } - - const auto &when_or = std::get(this->criteria_variant); - - size_t counter = 0; - for (const criteria_list_and &cl : when_or.components) { - if (cl.match(sl)) { - counter++; - } - } - - if (when_or.is_or) { - return counter > 0; - } else { - return counter >= when_or.components.size(); - } -} - -model_pass_t block_states_variant::block_model_name( - const state_list &sl_blk) const noexcept { - model_pass_t res; - res.model_name = nullptr; - for (const auto &pair : this->LUT) { - if (sl_blk.contains(pair.first)) { - res = model_pass_t(pair.second); - return res; - } - } - - return res; -} - -void block_states_variant::sort() noexcept { - std::sort(LUT.begin(), LUT.end(), - [](const std::pair &a, - const std::pair &b) -> bool { - const size_t a_1 = a.first.num_1(); - const size_t b_1 = b.first.num_1(); - if (a_1 != b_1) { - return a_1 < b_1; - } - return a.first.size() > b.first.size(); - }); -} - -std::vector block_state_multipart::block_model_names( - const state_list &sl) const noexcept { - std::vector res; - - for (const multipart_pair &pair : this->pairs) { - if (pair.match(sl)) { - for (const auto &ms : pair.apply_blockmodel) { - res.emplace_back(model_pass_t(ms)); - } - } - // res.emplace_back(model_pass_t(pair.apply_blockmodel)); - } - - return res; -} - -struct parse_bs_buffer { - std::vector> attributes; -}; - -bool parse_block_state_variant(const njson::object_t &obj, - block_states_variant *const dest_variant); - -bool parse_block_state_multipart(const njson::object_t &obj, - block_state_multipart *const dest_variant); - -bool resource_json::parse_block_state( - const char *const json_str_beg, const char *const json_str_end, - std::variant *dest, - bool *const is_dest_variant) noexcept { - njson::object_t obj; - try { - obj = njson::parse(json_str_beg, json_str_end); - } catch (...) { - std::string msg = "nlohmann json failed to parse json string : "; - msg.append(json_str_beg, json_str_end); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - const bool has_variant = - obj.contains("variants") && obj.at("variants").is_object(); - const bool has_multipart = - obj.contains("multipart") && obj.at("multipart").is_array(); - - if (has_variant == has_multipart) { - std::string msg = fmt::format( - "Function parse_block_state failed to parse json : " - "has_variant = {}, has_multipart = {}.", - has_variant, has_multipart); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (has_variant) { - if (is_dest_variant != nullptr) *is_dest_variant = true; - - block_states_variant variant; - const bool ok = parse_block_state_variant(obj, &variant); - *dest = std::move(variant); - return ok; - } - - if (has_multipart) { - // parsing multipart is not supported yet. - if (is_dest_variant != nullptr) *is_dest_variant = false; - - block_state_multipart multipart; - const bool ok = parse_block_state_multipart(obj, &multipart); - *dest = std::move(multipart); - return ok; - // return parse_block_state_multipart(obj, dest_multipart); - } - // unreachable - return false; -} - -bool parse_block_state_list(std::string_view str, state_list *const sl, - parse_bs_buffer &buffer) noexcept { - sl->clear(); - if (str.size() <= 1) return true; - - if (str == "normal") { - return true; - } - - if (str == "all") { - return true; - } - - if (str == "map") { - return true; - } - - if (!blkid::process_state_list({str.data(), str.data() + str.size()}, - &buffer.attributes, nullptr)) { - std::string msg = fmt::format( - " Function parse_block_state_list failed to parse block state " - "list : {}", - str); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - sl->reserve(buffer.attributes.size()); - - for (const auto &pair : buffer.attributes) { - state strpair; - strpair.key.assign(pair.first.begin(), pair.first.end()); - strpair.value.assign(pair.second.begin(), pair.second.end()); - - sl->emplace_back(strpair); - } - - return true; -} - -bool parse_block_state_list(std::string_view str, - state_list *const sl) noexcept { - parse_bs_buffer buffer; - - return parse_block_state_list(str, sl, buffer); -} - -model_store_t json_to_model(const njson &obj) noexcept { - model_store_t res; - - res.model_name = obj.at("model"); - - if (obj.contains("x") && obj.at("x").is_number()) { - const int val = obj.at("x"); - - if (!block_model::is_0_90_180_270(val)) { - std::string msg; - msg = fmt::format( - "Invalid x rotation value : {}. Invalid values : 0, 90, 180, 270.", - val); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return {}; - } - - res.x = block_model::int_to_face_rot(val); - } - - if (obj.contains("y") && obj.at("y").is_number()) { - const int val = obj.at("y"); - if (!block_model::is_0_90_180_270(val)) { - std::string msg; - msg = fmt::format( - "Invalid y rotation value : {}. Invalid values : 0, 90, 180, 270.", - val); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return {}; - } - res.y = block_model::int_to_face_rot(val); - } - - if (obj.contains("uvlock") && obj.at("uvlock").is_boolean()) { - res.uvlock = obj.at("uvlock"); - } - - return res; -} - -bool parse_block_state_variant(const njson::object_t &obj, - block_states_variant *const dest) { - const njson &variants = obj.at("variants"); - - dest->LUT.clear(); - dest->LUT.reserve(variants.size()); - - for (auto pair : variants.items()) { - if (!pair.value().is_structured()) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : " - "value for key \"{}\" is not an object or array.", - pair.key()); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (pair.value().is_array() && pair.value().size() <= 0) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : " - "value for key \"{}\" is an empty array.", - pair.key().data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - const njson &obj = - (pair.value().is_object()) ? (pair.value()) : (pair.value().at(0)); - - if ((!obj.contains("model")) || (!obj.at("model").is_string())) { - std::string msg = fmt::format( - "Function parse_block_state_variant failed to parse json : no " - "valid value for key \"model\""); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - std::pair p; - - parse_bs_buffer buffer; - - if (!parse_block_state_list(pair.key(), &p.first, buffer)) { - std::string msg = - fmt::format("Failed to parse block state list : {}", pair.key()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - p.second = json_to_model(obj); - - dest->LUT.emplace_back(p); - } - - dest->sort(); - - return true; -} - -void parse_single_criteria_split(std::string_view key, std::string_view values, - criteria *const cr) noexcept { - cr->key = key; - cr->values.clear(); - - size_t current_value_beg_idx = 0; - - for (size_t idx = 0;; idx++) { - if (values.size() <= idx || values[idx] == '\0' || values[idx] == '|') { - cr->values.emplace_back( - values.substr(current_value_beg_idx, idx - current_value_beg_idx)); - current_value_beg_idx = idx + 1; - } - - if (values.size() <= idx || values[idx] == '\0') { - break; - } - } -} - -model_store_t parse_single_apply(const njson &single_obj) noexcept(false) { - model_store_t ms; - - ms.model_name = single_obj.at("model"); - if (single_obj.contains("x")) { - ms.x = block_model::int_to_face_rot(single_obj.at("x")); - } - if (single_obj.contains("y")) { - ms.y = block_model::int_to_face_rot(single_obj.at("y")); - } - if (single_obj.contains("uvlock")) { - ms.uvlock = single_obj.at("uvlock"); - } - - return ms; -} - -std::vector parse_multipart_apply(const njson &apply) noexcept( - false) { - std::vector ret; - - if (apply.is_object()) { - ret.emplace_back(parse_single_apply(apply)); - return ret; - } - - if (apply.is_array()) { - for (size_t i = 0; i < apply.size(); i++) { - ret.emplace_back(parse_single_apply(apply.at(i))); - } - return ret; - } - throw std::runtime_error("Invalid value for \"apply\" in a multipart."); -} - -std::variant -parse_multipart_when(const njson &when) noexcept(false) { - const bool is_or = when.contains("OR"); - const bool is_and = when.contains("AND"); - if (is_or || is_and) { - const njson &list_or_and = (is_or) ? (when.at("OR")) : (when.at("AND")); - criteria_list_or_and when_or_and; - - when_or_and.components.reserve(list_or_and.size()); - when_or_and.is_or = is_or; - - for (size_t idx = 0; idx < list_or_and.size(); idx++) { - criteria_list_and and_list; - - for (auto it = list_or_and[idx].begin(); it != list_or_and[idx].end(); - ++it) { - criteria cr; - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - - } else { - parse_single_criteria_split(it.key(), it.value().get(), - &cr); - } - // const std::string &v_str = ; - and_list.emplace_back(std::move(cr)); - } - - when_or_and.components.emplace_back(std::move(and_list)); - } - - return when_or_and; - } - - if (when.size() == 1) { - criteria cr; - - auto it = when.begin(); - - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - } else { - parse_single_criteria_split(it.key(), it.value().get(), &cr); - } - - return cr; - } - criteria_list_and and_list; - - for (auto it = when.begin(); it != when.end(); ++it) { - criteria cr; - - if (it.value().is_boolean()) { - cr.key = it.key(); - cr.values.emplace_back((it.value()) ? ("true") : ("false")); - } else { - parse_single_criteria_split(it.key(), it.value().get(), &cr); - } - and_list.emplace_back(std::move(cr)); - } - - criteria_list_or_and when_or; - when_or.components.emplace_back(std::move(and_list)); - - return when_or; -} - -bool parse_block_state_multipart(const njson::object_t &obj, - block_state_multipart *const dest) { - const njson &multiparts = obj.at("multipart"); - - if (!multiparts.is_array()) { - std::string msg = fmt::format("Fatal error : multipart must be an array."); - - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - dest->pairs.clear(); - - for (size_t i = 0; i < multiparts.size(); i++) { - const njson &part = multiparts[i]; - - multipart_pair mpp; - - // parse apply - try { - const njson &apply = part.at("apply"); - mpp.apply_blockmodel = parse_multipart_apply(apply); - } catch (const std::exception &err) { - std::string msg = fmt::format( - "An error occurred when parsing the value of apply. Details : {}", - err.what()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - // parse when - if (!part.contains("when")) { - mpp.criteria_variant = criteria_all_pass(); - dest->pairs.emplace_back(std::move(mpp)); - continue; - } - - try { - const njson &when = part.at("when"); - - mpp.criteria_variant = parse_multipart_when(when); - - } catch (const std::exception &err) { - std::string msg = fmt::format( - "\nFatal error : failed to parse \"when\" for a multipart blockstate " - "file. Details : {}\n", - err.what()); - return false; - } - - dest->pairs.emplace_back(std::move(mpp)); - /* - if (!part.is_object()) { - printf("\nFatal error : multipart must an array of objects.\n"); - return false; - } - - if (!part.contains("apply") || !part.contains("when")) { - printf("\nFatal error : element in multipart must contains \"apply\" - and " - "\"when\"\n"); - return false; - } - - if (!apply.contains("model") || !apply.at("model").is_string()) { - printf("\nFatal error : multipart should apply a model.\n"); - return false; - } - */ - } - - return true; -} - -struct face_json_temp { - std::string texture{""}; - std::array uv{0, 0, 16, 16}; - block_model::face_idx cullface_face; - bool have_cullface{false}; - bool is_hidden{true}; ///< note that by default, is_hidden is true. -}; - -struct element_json_temp { - std::array from; - std::array to; - std::array faces; -}; - -struct block_model_json_temp { - std::string parent{""}; - std::map textures; - std::vector elements; - bool is_inherited{false}; -}; - -std::optional string_to_face_idx( - std::string_view str) noexcept { - if (str == "up") { - return block_model::face_idx::face_up; - } - if (str == "down") { - return block_model::face_idx::face_down; - } - if (str == "bottom") { - return block_model::face_idx::face_down; - } - if (str == "north") { - return block_model::face_idx::face_north; - } - if (str == "south") { - return block_model::face_idx::face_south; - } - if (str == "east") { - return block_model::face_idx::face_east; - } - if (str == "west") { - return block_model::face_idx::face_west; - } - - return std::nullopt; -} - -const char *face_idx_to_string(block_model::face_idx f) noexcept { - switch (f) { - case block_model::face_idx::face_up: - return "up"; - case block_model::face_idx::face_down: - return "down"; - case block_model::face_idx::face_north: - return "north"; - case block_model::face_idx::face_south: - return "south"; - case block_model::face_idx::face_east: - return "east"; - case block_model::face_idx::face_west: - return "west"; - } - - return nullptr; -} - -bool parse_single_model_json(const char *const json_beg, - const char *const json_end, - block_model_json_temp *const dest) { - dest->textures.clear(); - dest->elements.clear(); - // disable exceptions, and ignore comments. - njson obj = njson::parse(json_beg, json_end, nullptr, false, true); - if (obj.is_null()) { - // this may be unsafe but just keep it currently. - std::string msg = "Failed to parse block model json : "; - msg.append(json_beg, json_end); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (obj.contains("parent") && obj.at("parent").is_string()) { - std::string p_str = obj.at("parent"); - if (p_str.starts_with("minecraft:")) { - dest->parent = p_str.substr(sizeof("minecraft:") / sizeof(char) - 1); - } else { - dest->parent = p_str; - } - } - - if (obj.contains("textures") && obj.at("textures").is_object()) { - const njson &textures = obj.at("textures"); - // dest->textures.reserve(textures.size()); - for (auto temp : textures.items()) { - if (!temp.value().is_string()) { - continue; - } - - auto it = dest->textures.emplace(temp.key(), temp.value()); - - if (it.first->second.starts_with("block/") || - it.first->second.starts_with("blocks/")) { - it.first->second = "minecraft:" + it.first->second; - } - } - } - // finished textures - - if (obj.contains("elements") && obj.at("elements").is_array()) { - const njson::array_t &elearr = obj.at("elements"); - - dest->elements.reserve(obj.size()); - for (const auto &e : elearr) { - if (!e.is_object()) { - return false; - } - - element_json_temp ele; - if (!e.contains("from") || !e.at("from").is_array()) { - ::VCL_report(VCL_report_type_t::error, - "\"from\" doesn't exist, or is not an array."); - return false; - } - // from - { - const njson::array_t &arr_from = e.at("from"); - if (arr_from.size() != 3 || !arr_from.front().is_number()) { - ::VCL_report(VCL_report_type_t::error, "size of \"from\" is not 3"); - return false; - } - - for (int idx = 0; idx < 3; idx++) { - if (!arr_from[idx].is_number()) { - ::VCL_report( - VCL_report_type_t::error, - "one or more element in array \"from\" is not number."); - return false; - } - ele.from[idx] = arr_from[idx]; - } - } - if (!e.contains("to") || !e.at("to").is_array()) { - ::VCL_report(VCL_report_type_t::error, - "\"to\" doesn't exist, or is not an array."); - return false; - } - // to - { - const njson::array_t &arr_to = e.at("to"); - if (arr_to.size() != 3) { - ::VCL_report(VCL_report_type_t::error, "size of \"to\" is not 3."); - return false; - } - - for (int idx = 0; idx < 3; idx++) { - if (!arr_to[idx].is_number()) { - ::VCL_report(VCL_report_type_t::error, - "one or more element in array \"to\" is not number."); - return false; - } - ele.to[idx] = arr_to[idx]; - } - } - - // faces - { - if (!e.contains("faces") || !e.at("faces").is_object()) { - ::VCL_report(VCL_report_type_t::error, - "\"faces\" doesn't exist, or is not an object."); - return false; - } - - const njson &faces = e.at("faces"); - for (auto temp : faces.items()) { - // if the face is not object, skip current face. - if (!temp.value().is_object()) continue; - face_json_temp f; - block_model::face_idx fidx; - { - auto fidx_opt = string_to_face_idx(temp.key()); - if (not fidx_opt) { - std::string msg = fmt::format( - "Error while parsing block model json : invalid key {} " - "doesn't refer to any face.", - temp.key()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - fidx = fidx_opt.value(); - } - - const njson &curface = temp.value(); - - if (!curface.contains("texture") || - !curface.at("texture").is_string()) { - ::VCL_report( - VCL_report_type_t::error, - "Error while parsing block model json : face do not have " - "texture."); - return false; - } - - f.texture = curface.at("texture"); - if (f.texture.starts_with("block/")) { - f.texture = ("minecraft:") + f.texture; - } - // finished texture - - // cullface - { - std::string cullface_temp(""); - if (curface.contains("cullface") && - curface.at("cullface").is_string()) { - cullface_temp = curface.at("cullface"); - } - - if (!cullface_temp.empty()) { - auto cullface_fidx = string_to_face_idx(cullface_temp); - - if (not cullface_fidx) { - std::string msg = fmt::format("Invalid value for cullface : {}", - cullface_temp); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - f.cullface_face = cullface_fidx.value(); - f.have_cullface = true; - } - } - // finished cullface - - // uv - if (curface.contains("uv") && curface.at("uv").is_array()) { - const njson::array_t &uvarr = curface.at("uv"); - - if (uvarr.size() != 4) { - ::VCL_report(VCL_report_type_t::error, - "Invalid value for uv array : the size must be 4."); - return false; - } - - for (int idx = 0; idx < 4; idx++) { - if (!uvarr.at(idx).is_number()) { - ::VCL_report(VCL_report_type_t::error, - "Invalid value for uv array : the value must be " - "numbers."); - return false; - } - f.uv[idx] = uvarr[idx]; - } - } - // finished uv - - f.is_hidden = false; - // finished is_hidden - - // write in this face - ele.faces[int(fidx)] = f; - } - } - // finished all faces - - dest->elements.emplace_back(ele); - } - } - - return true; -} - -const char *dereference_texture_name( - std::map::iterator it, - std::map &text) noexcept { - if (it == text.end()) { - return nullptr; - } - - if (!it->second.starts_with('#')) { - return it->second.data(); - } - - // here it->second must be a # reference. - - auto next_it = text.find(it->second.data() + 1); - - // This line is added as a patch, to fix error when parsing 1.19.3 data packs. - // I'm not sure whether models that triggered this can be parsed correctly, it - // is only introduced to prevent endless recursion, so that errors can be - // reported - if (next_it == it) { - // found a self-reference value - return nullptr; - } - - const char *const ret = dereference_texture_name(next_it, text); - - if (ret != nullptr) { - // found a non-reference value - it->second = ret; - return ret; - } else { - // it->second is the the farest reference and no further link - return it->second.data(); - } -} - -void dereference_texture_name( - std::map &text) noexcept { - for (auto it = text.begin(); it != text.end(); ++it) { - if (!it->second.starts_with('#')) continue; - dereference_texture_name(it, text); - } -} - -void dereference_model(block_model_json_temp &model) { - // dereference_texture_name(model.textures); - - for (auto &ele : model.elements) { - for (auto &face : ele.faces) { - if (face.is_hidden) continue; - if (face.texture.starts_with('#')) { - auto it = model.textures.find(face.texture.data() + 1); - - if (it == model.textures.end()) { - continue; - } - face.texture = it->second; - } - } - // finished current face - } - // finished current element -} - -bool model_json_inherit_new(block_model_json_temp &child, - block_model_json_temp &parent, const bool) { - if (child.parent.empty()) { - ::VCL_report(VCL_report_type_t::error, "child has no parent."); - return false; - } - - parent.is_inherited = true; - - // child.textures.reserve(child.textures.size() + parent.textures.size()); - // merge textures - for (const auto &pt : parent.textures) { - if (!child.textures.contains(pt.first)) { - child.textures.emplace(pt.first, pt.second); - } - } - - dereference_texture_name(child.textures); - - // if child have a parent, and child doesn't define its own element, child - // inherit parent's elements. - if (child.elements.size() <= 0) { - child.elements = parent.elements; - } - - dereference_model(child); - - // parent - child.parent = parent.parent; - return true; -} - -bool inherit_recrusively(std::string_view childname, - block_model_json_temp &child, - std::unordered_map - &temp_models) noexcept { - if (child.parent.empty()) return true; - - // #warning This function is not finished yet. I hope to inherit from the - // root, which measn to find the root and inherit from root to leaf - - // find parent till the root - auto it = temp_models.find(child.parent); - - if (it == temp_models.end()) { - std::string msg = fmt::format( - "Failed to inherit. Undefined reference to model {}, " - "required by {}.", - child.parent.data(), childname.data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - if (!it->second.parent.empty()) { - // find root - const bool success = - inherit_recrusively(it->first, it->second, temp_models); - if (!success) { - return false; - } - } - /* - printf("\ninhering : parent : %s, child : %s,\n", child.parent.data(), - childname.data()); - */ - const bool success = model_json_inherit_new(child, it->second, false); - - // dereference_texture_name(child.textures); - - if (!success) { - std::string msg = fmt::format("Failed to inherit. Child : {}, parent : {}.", - childname.data(), child.parent.data()); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - return true; -} - -bool resource_pack::add_block_models( - const zipped_folder &resource_pack_root, - const bool on_conflict_replace_old) noexcept { - const std::unordered_map *files; - // find assets/minecraft/models/block - { - const zipped_folder *temp = resource_pack_root.subfolder("assets"); - if (temp == nullptr) return false; - temp = temp->subfolder("minecraft"); - if (temp == nullptr) return false; - temp = temp->subfolder("models"); - if (temp == nullptr) return false; - temp = temp->subfolder("block"); - if (temp == nullptr) return false; - - files = &temp->files; - } - - // the name of model is : block/ - std::unordered_map temp_models; - - temp_models.reserve(files->size()); - - std::array buffer; - - for (const auto &file : *files) { - if (!file.first.ends_with(".json")) continue; - buffer.fill('\0'); - std::strcpy(buffer.data(), "block/"); - { - const int end = file.first.find_last_of('.'); - char *const dest = buffer.data() + std::strlen(buffer.data()); - for (int idx = 0; idx < end; idx++) { - dest[idx] = file.first[idx]; - } - } - - block_model_json_temp bmjt; - - const bool ok = parse_single_model_json( - (const char *)file.second.data(), - (const char *)file.second.data() + file.second.file_size(), &bmjt); - - if (!ok) { - std::string msg = fmt::format( - "Failed to parse assets/minecraft/models/block/{}.", file.first); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - temp_models.emplace(buffer.data(), bmjt); - } - // parsed all jsons - /* - printf("Loaded %i model jsons.\n", int(temp_models.size())); - - for (const auto &file : temp_models) { - printf("%s, ", file.first.data()); - } - printf("\n\n"); - - */ - - // inherit - for (auto &model : temp_models) { - const bool ok = inherit_recrusively(model.first, model.second, temp_models); - if (!ok) { - model.second.parent = "INVALID"; - std::string msg = fmt::format( - "Failed to inherit model {}. This model will be " - "skipped, but it may cause further errors.", - model.first); - ::VCL_report(VCL_report_type_t::warning, msg.c_str()); - // #warning following line should be commented. - // return false; - continue; - } - - dereference_texture_name(model.second.textures); - dereference_model(model.second); - } - // remove invalid - for (auto it = temp_models.begin(); it != temp_models.end();) { - if (it->second.parent == "INVALID") { - it = temp_models.erase(it); - continue; - } - - ++it; - } - - // convert temp models to block_models - this->block_models.reserve(this->block_models.size() + temp_models.size()); - for (auto &tmodel : temp_models) { - if (this->block_models.contains(tmodel.first) && !on_conflict_replace_old) { - continue; - } - - block_model::model md; - bool skip_this_model = false; - - md.elements.reserve(tmodel.second.elements.size()); - for (auto &tele : tmodel.second.elements) { - if (skip_this_model) break; - block_model::element ele; - - // ele._from = tele.from; - for (int idx = 0; idx < 3; idx++) { - ele._from[idx] = tele.from[idx]; - ele._to[idx] = tele.to[idx]; - } - - for (uint8_t faceidx = 0; faceidx < 6; faceidx++) { - if (skip_this_model) break; - auto &tface = tele.faces[faceidx]; - ele.faces[faceidx].is_hidden = tface.is_hidden; - if (tface.is_hidden) { - ele.faces[faceidx].texture = nullptr; - continue; - } - ele.faces[faceidx].uv_start[0] = tface.uv[0]; - ele.faces[faceidx].uv_start[1] = tface.uv[1]; - ele.faces[faceidx].uv_end[0] = tface.uv[2]; - ele.faces[faceidx].uv_end[1] = tface.uv[3]; - - // try to find the image in texture/block - auto imgptr = this->find_texture(tface.texture, false); - if (imgptr == nullptr) { // try to resolve the name of this texture - auto it = tmodel.second.textures.find(tface.texture); - if (it not_eq tmodel.second.textures.end()) { - imgptr = this->find_texture(it->second, false); - } - } - - if (imgptr == nullptr) { - if (tface.texture.starts_with('#') && tmodel.second.is_inherited) { - // This model is considered to be abstract - skip_this_model = true; - continue; - } - std::string msg = fmt::format( - "Undefined reference to texture \"{}\", required by " - "model {} but no such image.\nThe textures are : \n", - tface.texture, tmodel.first); - for (const auto &pair : tmodel.second.textures) { - msg.push_back('{'); - std::string temp = - fmt::format("{}, {}\n", pair.first.data(), pair.second.data()); - msg.append(temp); - msg.push_back('}'); - } - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - - // if managed to find, go on - } - ele.faces[faceidx].texture = imgptr; - } - // finished all faces - - md.elements.emplace_back(ele); - } - // finished current model - if (!skip_this_model) { - this->block_models.emplace(tmodel.first, std::move(md)); - } - } - - for (const auto &pair : this->block_models) { - for (const auto &ele : pair.second.elements) { - for (const auto &face : ele.faces) { - if (!face.is_hidden && face.texture == nullptr) { - std::string msg = fmt::format( - "Found an error while examining all block models : " - "face.texture==nullptr in model {}", - pair.first); - ::VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - } - } - } - - return true; -} - -bool resource_pack::add_block_states( - const zipped_folder &resourece_pack_root, - const bool on_conflict_replace_old) noexcept { - const std::unordered_map *files = nullptr; - { - const zipped_folder *temp = resourece_pack_root.subfolder("assets"); - if (temp == nullptr) { - return false; - } - temp = temp->subfolder("minecraft"); - if (temp == nullptr) { - return false; - } - temp = temp->subfolder("blockstates"); - if (temp == nullptr) { - return false; - } - files = &temp->files; - } - - this->block_states.reserve(this->block_states.size() + files->size()); - - for (const auto &file : *files) { - if (this->block_states.contains(file.first) && !on_conflict_replace_old) { - continue; - } - std::variant - bs; - bool is_dest_variant; - - const bool success = parse_block_state( - (const char *)file.second.data(), - (const char *)file.second.data() + file.second.file_size(), &bs, - &is_dest_variant); - - if (!success) { - std::string msg = fmt::format( - "Failed to parse block state json file " - "assets/minecraft/blockstates/{}. This will be " - "skipped but may cause further errors.\n", - file.first); - - ::VCL_report(VCL_report_type_t::warning, msg.c_str()); - continue; - } - - const int substrlen = file.first.find_last_of('.'); - this->block_states.emplace(file.first.substr(0, substrlen), std::move(bs)); - } - - return true; -} +/* + Copyright © 2021-2023 TokiNoBug +This file is part of SlopeCraft. + + SlopeCraft is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SlopeCraft 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SlopeCraft. If not, see . + + Contact with me: + github:https://github.com/SlopeCraft/SlopeCraft + bilibili:https://space.bilibili.com/351429231 +*/ + +#include +#include +#include +#include + +#include +#include "ParseResourcePack.h" +#include "VCL_internal.h" + +using namespace resource_json; + +using njson = nlohmann::json; + +size_t resource_json::state_list::num_1() const noexcept { + size_t counter = 0; + for (const auto &s : *this) { + if (s.value.empty()) { + counter++; + } + } + return counter; +} + +bool resource_json::state_list::euqals( + const state_list &another) const noexcept { + if (this->size() <= 0) return true; + if (this->size() != another.size()) return false; + int match_num = 0; + for (const state &sa : *this) { + for (const state &sb : another) { + if ((sa.key == sb.key) && (sa.value == sb.value)) { + match_num++; + } + } + } + + if (match_num < int(this->size())) { + return false; + } else { + return true; + } +} + +bool resource_json::state_list::contains( + const state_list &another) const noexcept { + if (another.size() > this->size()) { + return false; + } + + for (const state &s_json : another) { + bool is_current_state_matched = false; + for (const state &s_block : *this) { + if (s_json.key != s_block.key) { + continue; + } + + if (s_block.value == s_json.value) { + is_current_state_matched = true; + break; + } + } + if (!is_current_state_matched) { + return false; + } + } + + return true; +} + +bool resource_json::criteria_list_and::match( + const state_list &sl) const noexcept { + const auto &cl = *this; + int match_num = 0; + for (const criteria &c : cl) { + std::string_view key = c.key; + + const char *value = nullptr; + for (const state &s : sl) { + if (s.key == key) { + value = s.value.data(); + break; + } + } + // if value is not set, it is not considered as match + if (value == nullptr) { + break; + } + + if (c.match(value)) { + match_num++; + } + } + + if (match_num < int(cl.size())) { + return false; + } + return true; +} + +bool resource_json::match_criteria_list(const criteria_list_and &cl, + const state_list &sl) noexcept { + return cl.match(sl); +} + +bool resource_json::multipart_pair::match(const state_list &sl) const noexcept { + const resource_json::criteria *when = + std::get_if(&this->criteria_variant); + if (when != nullptr) { + std::string_view key = when->key; + const char *slvalue = nullptr; + for (const state &s : sl) { + if (s.key == key) { + slvalue = s.value.data(); + break; + } + } + // if sl don't have a value for the key of criteria, it is considered as + // mismatch + if (slvalue == nullptr) { + return false; + } + + return when->match(slvalue); + } + + if (std::get_if(&this->criteria_variant) != nullptr) { + return true; + } + + const auto &when_or = std::get(this->criteria_variant); + + size_t counter = 0; + for (const criteria_list_and &cl : when_or.components) { + if (cl.match(sl)) { + counter++; + } + } + + if (when_or.is_or) { + return counter > 0; + } else { + return counter >= when_or.components.size(); + } +} + +model_pass_t block_states_variant::block_model_name( + const state_list &sl_blk) const noexcept { + model_pass_t res; + res.model_name = nullptr; + for (const auto &pair : this->LUT) { + if (sl_blk.contains(pair.first)) { + res = model_pass_t(pair.second); + return res; + } + } + + return res; +} + +void block_states_variant::sort() noexcept { + std::sort(LUT.begin(), LUT.end(), + [](const std::pair &a, + const std::pair &b) -> bool { + const size_t a_1 = a.first.num_1(); + const size_t b_1 = b.first.num_1(); + if (a_1 != b_1) { + return a_1 < b_1; + } + return a.first.size() > b.first.size(); + }); +} + +std::vector block_state_multipart::block_model_names( + const state_list &sl) const noexcept { + std::vector res; + for (const multipart_pair &pair : this->pairs) { + if (pair.match(sl)) { + for (const auto &ms : pair.apply_blockmodel) { + res.emplace_back(model_pass_t(ms)); + } + } + // res.emplace_back(model_pass_t(pair.apply_blockmodel)); + } + + return res; +} + +struct parse_bs_buffer { + std::vector> attributes; +}; + +bool parse_block_state_variant(const njson::object_t &obj, + block_states_variant *const dest_variant); + +bool parse_block_state_multipart(const njson::object_t &obj, + block_state_multipart *const dest_variant); + +bool resource_json::parse_block_state( + const char *const json_str_beg, const char *const json_str_end, + std::variant *dest, + bool *const is_dest_variant) noexcept { + njson::object_t obj; + try { + obj = njson::parse(json_str_beg, json_str_end); + } catch (...) { + std::string msg = "nlohmann json failed to parse json string : "; + msg.append(json_str_beg, json_str_end); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + const bool has_variant = + obj.contains("variants") && obj.at("variants").is_object(); + const bool has_multipart = + obj.contains("multipart") && obj.at("multipart").is_array(); + + if (has_variant == has_multipart) { + std::string msg = fmt::format( + "Function parse_block_state failed to parse json : " + "has_variant = {}, has_multipart = {}.", + has_variant, has_multipart); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (has_variant) { + if (is_dest_variant != nullptr) *is_dest_variant = true; + + block_states_variant variant; + const bool ok = parse_block_state_variant(obj, &variant); + *dest = std::move(variant); + return ok; + } + + if (has_multipart) { + // parsing multipart is not supported yet. + if (is_dest_variant != nullptr) *is_dest_variant = false; + + block_state_multipart multipart; + const bool ok = parse_block_state_multipart(obj, &multipart); + *dest = std::move(multipart); + return ok; + // return parse_block_state_multipart(obj, dest_multipart); + } + // unreachable + return false; +} + +bool parse_block_state_list(std::string_view str, state_list *const sl, + parse_bs_buffer &buffer) noexcept { + sl->clear(); + if (str.size() <= 1) return true; + + if (str == "normal") { + return true; + } + + if (str == "all") { + return true; + } + + if (str == "map") { + return true; + } + + if (!blkid::process_state_list({str.data(), str.data() + str.size()}, + &buffer.attributes, nullptr)) { + std::string msg = fmt::format( + " Function parse_block_state_list failed to parse block state " + "list : {}", + str); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + sl->reserve(buffer.attributes.size()); + + for (const auto &pair : buffer.attributes) { + state strpair; + strpair.key.assign(pair.first.begin(), pair.first.end()); + strpair.value.assign(pair.second.begin(), pair.second.end()); + + sl->emplace_back(strpair); + } + + return true; +} + +bool parse_block_state_list(std::string_view str, + state_list *const sl) noexcept { + parse_bs_buffer buffer; + + return parse_block_state_list(str, sl, buffer); +} + +model_store_t json_to_model(const njson &obj) noexcept { + model_store_t res; + + res.model_name = obj.at("model"); + + if (obj.contains("x") && obj.at("x").is_number()) { + const int val = obj.at("x"); + + if (!block_model::is_0_90_180_270(val)) { + std::string msg; + msg = fmt::format( + "Invalid x rotation value : {}. Invalid values : 0, 90, 180, 270.", + val); + VCL_report(VCL_report_type_t::error, msg.c_str()); + return {}; + } + + res.x = block_model::int_to_face_rot(val); + } + + if (obj.contains("y") && obj.at("y").is_number()) { + const int val = obj.at("y"); + if (!block_model::is_0_90_180_270(val)) { + std::string msg; + msg = fmt::format( + "Invalid y rotation value : {}. Invalid values : 0, 90, 180, 270.", + val); + VCL_report(VCL_report_type_t::error, msg.c_str()); + return {}; + } + res.y = block_model::int_to_face_rot(val); + } + + if (obj.contains("uvlock") && obj.at("uvlock").is_boolean()) { + res.uvlock = obj.at("uvlock"); + } + + return res; +} + +bool parse_block_state_variant(const njson::object_t &obj, + block_states_variant *const dest) { + const njson &variants = obj.at("variants"); + + dest->LUT.clear(); + dest->LUT.reserve(variants.size()); + + for (auto pair : variants.items()) { + if (!pair.value().is_structured()) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : " + "value for key \"{}\" is not an object or array.", + pair.key()); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (pair.value().is_array() && pair.value().size() <= 0) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : " + "value for key \"{}\" is an empty array.", + pair.key().data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + const njson &obj = + (pair.value().is_object()) ? (pair.value()) : (pair.value().at(0)); + + if ((!obj.contains("model")) || (!obj.at("model").is_string())) { + std::string msg = fmt::format( + "Function parse_block_state_variant failed to parse json : no " + "valid value for key \"model\""); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + std::pair p; + + parse_bs_buffer buffer; + + if (!parse_block_state_list(pair.key(), &p.first, buffer)) { + std::string msg = + fmt::format("Failed to parse block state list : {}", pair.key()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + p.second = json_to_model(obj); + + dest->LUT.emplace_back(p); + } + + dest->sort(); + + return true; +} + +void parse_single_criteria_split(std::string_view key, std::string_view values, + criteria *const cr) noexcept { + cr->key = key; + cr->values.clear(); + + size_t current_value_beg_idx = 0; + + for (size_t idx = 0;; idx++) { + if (values.size() <= idx || values[idx] == '\0' || values[idx] == '|') { + cr->values.emplace_back( + values.substr(current_value_beg_idx, idx - current_value_beg_idx)); + current_value_beg_idx = idx + 1; + } + + if (values.size() <= idx || values[idx] == '\0') { + break; + } + } +} + +model_store_t parse_single_apply(const njson &single_obj) noexcept(false) { + model_store_t ms; + + ms.model_name = single_obj.at("model"); + if (single_obj.contains("x")) { + ms.x = block_model::int_to_face_rot(single_obj.at("x")); + } + if (single_obj.contains("y")) { + ms.y = block_model::int_to_face_rot(single_obj.at("y")); + } + if (single_obj.contains("uvlock")) { + ms.uvlock = single_obj.at("uvlock"); + } + + return ms; +} + +std::vector parse_multipart_apply(const njson &apply) noexcept( + false) { + std::vector ret; + + if (apply.is_object()) { + ret.emplace_back(parse_single_apply(apply)); + return ret; + } + + if (apply.is_array()) { + for (size_t i = 0; i < apply.size(); i++) { + ret.emplace_back(parse_single_apply(apply.at(i))); + } + return ret; + } + throw std::runtime_error("Invalid value for \"apply\" in a multipart."); +} + +std::variant +parse_multipart_when(const njson &when) noexcept(false) { + const bool is_or = when.contains("OR"); + const bool is_and = when.contains("AND"); + if (is_or || is_and) { + const njson &list_or_and = (is_or) ? (when.at("OR")) : (when.at("AND")); + criteria_list_or_and when_or_and; + + when_or_and.components.reserve(list_or_and.size()); + when_or_and.is_or = is_or; + + for (size_t idx = 0; idx < list_or_and.size(); idx++) { + criteria_list_and and_list; + + for (auto it = list_or_and[idx].begin(); it != list_or_and[idx].end(); + ++it) { + criteria cr; + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + + } else { + parse_single_criteria_split(it.key(), it.value().get(), + &cr); + } + // const std::string &v_str = ; + and_list.emplace_back(std::move(cr)); + } + + when_or_and.components.emplace_back(std::move(and_list)); + } + + return when_or_and; + } + + if (when.size() == 1) { + criteria cr; + + auto it = when.begin(); + + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + } else { + parse_single_criteria_split(it.key(), it.value().get(), &cr); + } + + return cr; + } + criteria_list_and and_list; + + for (auto it = when.begin(); it != when.end(); ++it) { + criteria cr; + + if (it.value().is_boolean()) { + cr.key = it.key(); + cr.values.emplace_back((it.value()) ? ("true") : ("false")); + } else { + parse_single_criteria_split(it.key(), it.value().get(), &cr); + } + and_list.emplace_back(std::move(cr)); + } + + criteria_list_or_and when_or; + when_or.components.emplace_back(std::move(and_list)); + + return when_or; +} + +bool parse_block_state_multipart(const njson::object_t &obj, + block_state_multipart *const dest) { + const njson &multiparts = obj.at("multipart"); + + if (!multiparts.is_array()) { + std::string msg = fmt::format("Fatal error : multipart must be an array."); + + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + dest->pairs.clear(); + + for (size_t i = 0; i < multiparts.size(); i++) { + const njson &part = multiparts[i]; + + multipart_pair mpp; + + // parse apply + try { + const njson &apply = part.at("apply"); + mpp.apply_blockmodel = parse_multipart_apply(apply); + } catch (const std::exception &err) { + std::string msg = fmt::format( + "An error occurred when parsing the value of apply. Details : {}", + err.what()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + // parse when + if (!part.contains("when")) { + mpp.criteria_variant = criteria_all_pass(); + dest->pairs.emplace_back(std::move(mpp)); + continue; + } + + try { + const njson &when = part.at("when"); + + mpp.criteria_variant = parse_multipart_when(when); + + } catch (const std::exception &err) { + std::string msg = fmt::format( + "\nFatal error : failed to parse \"when\" for a multipart blockstate " + "file. Details : {}\n", + err.what()); + return false; + } + + dest->pairs.emplace_back(std::move(mpp)); + /* + if (!part.is_object()) { + printf("\nFatal error : multipart must an array of objects.\n"); + return false; + } + + if (!part.contains("apply") || !part.contains("when")) { + printf("\nFatal error : element in multipart must contains \"apply\" + and " + "\"when\"\n"); + return false; + } + + if (!apply.contains("model") || !apply.at("model").is_string()) { + printf("\nFatal error : multipart should apply a model.\n"); + return false; + } + */ + } + + return true; +} + +struct face_json_temp { + std::string texture{""}; + std::array uv{0, 0, 16, 16}; + block_model::face_idx cullface_face; + bool have_cullface{false}; + bool is_hidden{true}; ///< note that by default, is_hidden is true. +}; + +struct element_json_temp { + std::array from; + std::array to; + std::array faces; +}; + +struct block_model_json_temp { + std::string parent{""}; + std::map textures; + std::vector elements; + bool is_inherited{false}; +}; + +std::optional string_to_face_idx( + std::string_view str) noexcept { + if (str == "up") { + return block_model::face_idx::face_up; + } + if (str == "down") { + return block_model::face_idx::face_down; + } + if (str == "bottom") { + return block_model::face_idx::face_down; + } + if (str == "north") { + return block_model::face_idx::face_north; + } + if (str == "south") { + return block_model::face_idx::face_south; + } + if (str == "east") { + return block_model::face_idx::face_east; + } + if (str == "west") { + return block_model::face_idx::face_west; + } + + return std::nullopt; +} + +const char *face_idx_to_string(block_model::face_idx f) noexcept { + switch (f) { + case block_model::face_idx::face_up: + return "up"; + case block_model::face_idx::face_down: + return "down"; + case block_model::face_idx::face_north: + return "north"; + case block_model::face_idx::face_south: + return "south"; + case block_model::face_idx::face_east: + return "east"; + case block_model::face_idx::face_west: + return "west"; + } + + return nullptr; +} + +bool parse_single_model_json(const char *const json_beg, + const char *const json_end, + block_model_json_temp *const dest) { + dest->textures.clear(); + dest->elements.clear(); + // disable exceptions, and ignore comments. + njson obj = njson::parse(json_beg, json_end, nullptr, false, true); + if (obj.is_null()) { + // this may be unsafe but just keep it currently. + std::string msg = "Failed to parse block model json : "; + msg.append(json_beg, json_end); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (obj.contains("parent") && obj.at("parent").is_string()) { + std::string p_str = obj.at("parent"); + if (p_str.starts_with("minecraft:")) { + dest->parent = p_str.substr(sizeof("minecraft:") / sizeof(char) - 1); + } else { + dest->parent = p_str; + } + } + + if (obj.contains("textures") && obj.at("textures").is_object()) { + const njson &textures = obj.at("textures"); + // dest->textures.reserve(textures.size()); + for (auto temp : textures.items()) { + if (!temp.value().is_string()) { + continue; + } + + auto it = dest->textures.emplace(temp.key(), temp.value()); + + if (it.first->second.starts_with("block/") || + it.first->second.starts_with("blocks/")) { + it.first->second = "minecraft:" + it.first->second; + } + } + } + // finished textures + + if (obj.contains("elements") && obj.at("elements").is_array()) { + const njson::array_t &elearr = obj.at("elements"); + + dest->elements.reserve(obj.size()); + for (const auto &e : elearr) { + if (!e.is_object()) { + return false; + } + + element_json_temp ele; + if (!e.contains("from") || !e.at("from").is_array()) { + ::VCL_report(VCL_report_type_t::error, + "\"from\" doesn't exist, or is not an array."); + return false; + } + // from + { + const njson::array_t &arr_from = e.at("from"); + if (arr_from.size() != 3 || !arr_from.front().is_number()) { + ::VCL_report(VCL_report_type_t::error, "size of \"from\" is not 3"); + return false; + } + + for (int idx = 0; idx < 3; idx++) { + if (!arr_from[idx].is_number()) { + ::VCL_report( + VCL_report_type_t::error, + "one or more element in array \"from\" is not number."); + return false; + } + ele.from[idx] = arr_from[idx]; + } + } + if (!e.contains("to") || !e.at("to").is_array()) { + ::VCL_report(VCL_report_type_t::error, + "\"to\" doesn't exist, or is not an array."); + return false; + } + // to + { + const njson::array_t &arr_to = e.at("to"); + if (arr_to.size() != 3) { + ::VCL_report(VCL_report_type_t::error, "size of \"to\" is not 3."); + return false; + } + + for (int idx = 0; idx < 3; idx++) { + if (!arr_to[idx].is_number()) { + ::VCL_report(VCL_report_type_t::error, + "one or more element in array \"to\" is not number."); + return false; + } + ele.to[idx] = arr_to[idx]; + } + } + + // faces + { + if (!e.contains("faces") || !e.at("faces").is_object()) { + ::VCL_report(VCL_report_type_t::error, + "\"faces\" doesn't exist, or is not an object."); + return false; + } + + const njson &faces = e.at("faces"); + for (auto temp : faces.items()) { + // if the face is not object, skip current face. + if (!temp.value().is_object()) continue; + face_json_temp f; + block_model::face_idx fidx; + { + auto fidx_opt = string_to_face_idx(temp.key()); + if (not fidx_opt) { + std::string msg = fmt::format( + "Error while parsing block model json : invalid key {} " + "doesn't refer to any face.", + temp.key()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + fidx = fidx_opt.value(); + } + + const njson &curface = temp.value(); + + if (!curface.contains("texture") || + !curface.at("texture").is_string()) { + ::VCL_report( + VCL_report_type_t::error, + "Error while parsing block model json : face do not have " + "texture."); + return false; + } + + f.texture = curface.at("texture"); + if (f.texture.starts_with("block/")) { + f.texture = ("minecraft:") + f.texture; + } + // finished texture + + // cullface + { + std::string cullface_temp(""); + if (curface.contains("cullface") && + curface.at("cullface").is_string()) { + cullface_temp = curface.at("cullface"); + } + + if (!cullface_temp.empty()) { + auto cullface_fidx = string_to_face_idx(cullface_temp); + + if (not cullface_fidx) { + std::string msg = fmt::format("Invalid value for cullface : {}", + cullface_temp); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + f.cullface_face = cullface_fidx.value(); + f.have_cullface = true; + } + } + // finished cullface + + // uv + if (curface.contains("uv") && curface.at("uv").is_array()) { + const njson::array_t &uvarr = curface.at("uv"); + + if (uvarr.size() != 4) { + ::VCL_report(VCL_report_type_t::error, + "Invalid value for uv array : the size must be 4."); + return false; + } + + for (int idx = 0; idx < 4; idx++) { + if (!uvarr.at(idx).is_number()) { + ::VCL_report(VCL_report_type_t::error, + "Invalid value for uv array : the value must be " + "numbers."); + return false; + } + f.uv[idx] = uvarr[idx]; + } + } + // finished uv + + f.is_hidden = false; + // finished is_hidden + + // write in this face + ele.faces[int(fidx)] = f; + } + } + // finished all faces + + dest->elements.emplace_back(ele); + } + } + + return true; +} + +const char *dereference_texture_name( + std::map::iterator it, + std::map &text) noexcept { + if (it == text.end()) { + return nullptr; + } + + if (!it->second.starts_with('#')) { + return it->second.data(); + } + + // here it->second must be a # reference. + + auto next_it = text.find(it->second.data() + 1); + + // This line is added as a patch, to fix error when parsing 1.19.3 data packs. + // I'm not sure whether models that triggered this can be parsed correctly, it + // is only introduced to prevent endless recursion, so that errors can be + // reported + if (next_it == it) { + // found a self-reference value + return nullptr; + } + + const char *const ret = dereference_texture_name(next_it, text); + + if (ret != nullptr) { + // found a non-reference value + it->second = ret; + return ret; + } else { + // it->second is the the farest reference and no further link + return it->second.data(); + } +} + +void dereference_texture_name( + std::map &text) noexcept { + for (auto it = text.begin(); it != text.end(); ++it) { + if (!it->second.starts_with('#')) continue; + dereference_texture_name(it, text); + } +} + +void dereference_model(block_model_json_temp &model) { + // dereference_texture_name(model.textures); + + for (auto &ele : model.elements) { + for (auto &face : ele.faces) { + if (face.is_hidden) continue; + if (face.texture.starts_with('#')) { + auto it = model.textures.find(face.texture.data() + 1); + + if (it == model.textures.end()) { + continue; + } + face.texture = it->second; + } + } + // finished current face + } + // finished current element +} + +bool model_json_inherit_new(block_model_json_temp &child, + block_model_json_temp &parent, const bool) { + if (child.parent.empty()) { + ::VCL_report(VCL_report_type_t::error, "child has no parent."); + return false; + } + + parent.is_inherited = true; + + // child.textures.reserve(child.textures.size() + parent.textures.size()); + // merge textures + for (const auto &pt : parent.textures) { + if (!child.textures.contains(pt.first)) { + child.textures.emplace(pt.first, pt.second); + } + } + + dereference_texture_name(child.textures); + + // if child have a parent, and child doesn't define its own element, child + // inherit parent's elements. + if (child.elements.size() <= 0) { + child.elements = parent.elements; + } + + dereference_model(child); + + // parent + child.parent = parent.parent; + return true; +} + +bool inherit_recrusively(std::string_view childname, + block_model_json_temp &child, + std::unordered_map + &temp_models) noexcept { + if (child.parent.empty()) return true; + + // #warning This function is not finished yet. I hope to inherit from the + // root, which measn to find the root and inherit from root to leaf + + // find parent till the root + auto it = temp_models.find(child.parent); + + if (it == temp_models.end()) { + std::string msg = fmt::format( + "Failed to inherit. Undefined reference to model {}, " + "required by {}.", + child.parent.data(), childname.data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + if (!it->second.parent.empty()) { + // find root + const bool success = + inherit_recrusively(it->first, it->second, temp_models); + if (!success) { + return false; + } + } + /* + printf("\ninhering : parent : %s, child : %s,\n", child.parent.data(), + childname.data()); + */ + const bool success = model_json_inherit_new(child, it->second, false); + + // dereference_texture_name(child.textures); + + if (!success) { + std::string msg = fmt::format("Failed to inherit. Child : {}, parent : {}.", + childname.data(), child.parent.data()); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + return true; +} + +bool resource_pack::add_block_models( + const zipped_folder &resource_pack_root, + const bool on_conflict_replace_old) noexcept { + const std::unordered_map *files; + // find assets/minecraft/models/block + { + const zipped_folder *temp = resource_pack_root.subfolder("assets"); + if (temp == nullptr) return false; + temp = temp->subfolder("minecraft"); + if (temp == nullptr) return false; + temp = temp->subfolder("models"); + if (temp == nullptr) return false; + temp = temp->subfolder("block"); + if (temp == nullptr) return false; + + files = &temp->files; + } + + // the name of model is : block/ + std::unordered_map temp_models; + + temp_models.reserve(files->size()); + + std::array buffer; + + for (const auto &file : *files) { + if (!file.first.ends_with(".json")) continue; + buffer.fill('\0'); + std::strcpy(buffer.data(), "block/"); + { + const int end = file.first.find_last_of('.'); + char *const dest = buffer.data() + std::strlen(buffer.data()); + for (int idx = 0; idx < end; idx++) { + dest[idx] = file.first[idx]; + } + } + + block_model_json_temp bmjt; + + const bool ok = parse_single_model_json( + (const char *)file.second.data(), + (const char *)file.second.data() + file.second.file_size(), &bmjt); + + if (!ok) { + std::string msg = fmt::format( + "Failed to parse assets/minecraft/models/block/{}.", file.first); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + + temp_models.emplace(buffer.data(), bmjt); + } + // parsed all jsons + /* + printf("Loaded %i model jsons.\n", int(temp_models.size())); + + for (const auto &file : temp_models) { + printf("%s, ", file.first.data()); + } + printf("\n\n"); + + */ + + // inherit + for (auto &model : temp_models) { + const bool ok = inherit_recrusively(model.first, model.second, temp_models); + if (!ok) { + model.second.parent = "INVALID"; + std::string msg = fmt::format( + "Failed to inherit model {}. This model will be " + "skipped, but it may cause further errors.", + model.first); + ::VCL_report(VCL_report_type_t::warning, msg.c_str()); + // #warning following line should be commented. + // return false; + continue; + } + + dereference_texture_name(model.second.textures); + dereference_model(model.second); + } + // remove invalid + for (auto it = temp_models.begin(); it != temp_models.end();) { + if (it->second.parent == "INVALID") { + it = temp_models.erase(it); + continue; + } + + ++it; + } + + // convert temp models to block_models + this->block_models.reserve(this->block_models.size() + temp_models.size()); + for (auto &tmodel : temp_models) { + if (this->block_models.contains(tmodel.first) && !on_conflict_replace_old) { + continue; + } + + block_model::model md; + bool skip_this_model = false; + + md.elements.reserve(tmodel.second.elements.size()); + for (auto &tele : tmodel.second.elements) { + if (skip_this_model) break; + block_model::element ele; + + // ele._from = tele.from; + for (int idx = 0; idx < 3; idx++) { + ele._from[idx] = tele.from[idx]; + ele._to[idx] = tele.to[idx]; + } + + for (uint8_t faceidx = 0; faceidx < 6; faceidx++) { + if (skip_this_model) break; + auto &tface = tele.faces[faceidx]; + ele.faces[faceidx].is_hidden = tface.is_hidden; + if (tface.is_hidden) { + ele.faces[faceidx].texture = nullptr; + continue; + } + ele.faces[faceidx].uv_start[0] = tface.uv[0]; + ele.faces[faceidx].uv_start[1] = tface.uv[1]; + ele.faces[faceidx].uv_end[0] = tface.uv[2]; + ele.faces[faceidx].uv_end[1] = tface.uv[3]; + + // try to find the image in texture/block + auto imgptr = this->find_texture(tface.texture, false); + if (imgptr == nullptr) { // try to resolve the name of this texture + auto it = tmodel.second.textures.find(tface.texture); + if (it not_eq tmodel.second.textures.end()) { + imgptr = this->find_texture(it->second, false); + } + } + + if (imgptr == nullptr) { + if (tface.texture.starts_with('#') && tmodel.second.is_inherited) { + // This model is considered to be abstract + skip_this_model = true; + continue; + } + std::string msg = fmt::format( + "Undefined reference to texture \"{}\", required by " + "model {} but no such image.\nThe textures are : \n", + tface.texture, tmodel.first); + for (const auto &pair : tmodel.second.textures) { + msg.push_back('{'); + std::string temp = + fmt::format("{}, {}\n", pair.first.data(), pair.second.data()); + msg.append(temp); + msg.push_back('}'); + } + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + + // if managed to find, go on + } + ele.faces[faceidx].texture = imgptr; + } + // finished all faces + + md.elements.emplace_back(ele); + } + // finished current model + if (!skip_this_model) { + this->block_models.emplace(tmodel.first, std::move(md)); + } + } + + for (const auto &pair : this->block_models) { + for (const auto &ele : pair.second.elements) { + for (const auto &face : ele.faces) { + if (!face.is_hidden && face.texture == nullptr) { + std::string msg = fmt::format( + "Found an error while examining all block models : " + "face.texture==nullptr in model {}", + pair.first); + ::VCL_report(VCL_report_type_t::error, msg.c_str()); + return false; + } + } + } + } + + return true; +} + +bool resource_pack::add_block_states( + const zipped_folder &resourece_pack_root, + const bool on_conflict_replace_old) noexcept { + const std::unordered_map *files = nullptr; + { + const zipped_folder *temp = resourece_pack_root.subfolder("assets"); + if (temp == nullptr) { + return false; + } + temp = temp->subfolder("minecraft"); + if (temp == nullptr) { + return false; + } + temp = temp->subfolder("blockstates"); + if (temp == nullptr) { + return false; + } + files = &temp->files; + } + + this->block_states.reserve(this->block_states.size() + files->size()); + + for (const auto &file : *files) { + if (this->block_states.contains(file.first) && !on_conflict_replace_old) { + continue; + } + std::variant + bs; + bool is_dest_variant; + + const bool success = parse_block_state( + (const char *)file.second.data(), + (const char *)file.second.data() + file.second.file_size(), &bs, + &is_dest_variant); + + if (!success) { + std::string msg = fmt::format( + "Failed to parse block state json file " + "assets/minecraft/blockstates/{}. This will be " + "skipped but may cause further errors.\n", + file.first); + + ::VCL_report(VCL_report_type_t::warning, msg.c_str()); + continue; + } + + const int substrlen = file.first.find_last_of('.'); + this->block_states.emplace(file.first.substr(0, substrlen), std::move(bs)); + } + + return true; +} From d56c5888bc83562abf6be1e2c167f77921780398 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 22 Dec 2024 17:11:44 +0800 Subject: [PATCH 1006/1123] fix a warning in TokiVC Signed-off-by: ToKiNoBug --- VisualCraftL/ParseResourcePack_json.cpp | 1 + VisualCraftL/TokiVC_export_test.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index c0af1e8a..301cfa45 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -195,6 +195,7 @@ void block_states_variant::sort() noexcept { std::vector block_state_multipart::block_model_names( const state_list &sl) const noexcept { std::vector res; + for (const multipart_pair &pair : this->pairs) { if (pair.match(sl)) { for (const auto &ms : pair.apply_blockmodel) { diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index bab897ed..cfa96f96 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -141,6 +141,15 @@ bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { info.author_utf8 = "VisualCraftL"; info.destricption_utf8 = "This litematic is generated by VisualCraft."; - return schem.export_litematic(filename, info, nullptr, nullptr); + auto res = schem.export_litematic(filename, info); + if (not res) { + auto &err = res.error(); + auto msg = + fmt::format("Failed to export {} because {}, detail: {}\n", filename, + magic_enum::enum_name(err.first), err.second); + VCL_report(VCL_report_type_t::warning, msg.c_str(), true); + return false; + } + return true; } } From 05a179bfbba3db0709d93537a587259c1df04487 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 15:37:31 +0800 Subject: [PATCH 1007/1123] Ignore pycache --- .gitignore | 2 +- py/.gitignore | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 py/.gitignore diff --git a/.gitignore b/.gitignore index 7da3463c..6f1609b1 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,4 @@ cmake-build-* ### PyCharm ### py/preprocessed -py/outputs +py/outputs \ No newline at end of file diff --git a/py/.gitignore b/py/.gitignore new file mode 100644 index 00000000..c1d3e321 --- /dev/null +++ b/py/.gitignore @@ -0,0 +1 @@ +*/__pycache__ \ No newline at end of file From bb470a7ba5ccd4115030f0d08a0f9d5bff1d1830 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 18:56:19 +0800 Subject: [PATCH 1008/1123] Fix id duplication in scheme Signed-off-by: ToKiNoBug --- SlopeCraftL/structure_3D.cpp | 10 ++ tests/test_libSchem/test_libSchem.cpp | 13 +- utilities/NBTWriter/NBTWriter.h | 194 ++++++++++++-------------- utilities/Schem/Schem.cpp | 94 +++++++++++-- utilities/Schem/Schem.h | 10 +- utilities/Schem/bit_shrink.cpp | 21 ++- utilities/Schem/bit_shrink.h | 4 +- 7 files changed, 207 insertions(+), 139 deletions(-) diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index bbc16fbc..a8b74f56 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -213,6 +213,16 @@ std::optional structure_3D_impl::create( if (fixed_opt.connect_mushrooms) { ret.schem.process_mushroom_states(); } + + { + const auto shrink_result = ret.schem.remove_unused_ids(); + if (not shrink_result) { + fixed_opt.ui.report_error(SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS, + shrink_result.error().c_str()); + return std::nullopt; + } + } + fixed_opt.main_progressbar.set_range(0, 9 * cvted.size(), 9 * cvted.size()); fixed_opt.ui.report_working_status(workStatus::none); diff --git a/tests/test_libSchem/test_libSchem.cpp b/tests/test_libSchem/test_libSchem.cpp index aa26a5ff..a61bcf82 100644 --- a/tests/test_libSchem/test_libSchem.cpp +++ b/tests/test_libSchem/test_libSchem.cpp @@ -38,8 +38,8 @@ const std::vector trash_id = generate_trash(); int main() { libSchem::Schem schem; - schem.set_MC_major_version_number(SCL_gameVersion::MC18); - schem.set_MC_version_number(MCDataVersion::MCDataVersion_t::Java_1_18_2); + schem.set_MC_major_version_number(SCL_gameVersion::MC21); + schem.set_MC_version_number(MCDataVersion::MCDataVersion_t::Java_1_21_1); schem.resize(12, 9, 12); @@ -96,22 +96,19 @@ int main() { // SCL_errorFlag flag; std::string error_str; if (!schem.export_litematic("test12.litematic", info, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.litematic" << endl; + cout << "Failed to export file " << "test12.litematic" << endl; cout << "Error info = " << error_str << endl; return 1; } if (!schem.export_structure("test12.nbt", true, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.nbt" << endl; + cout << "Failed to export file " << "test12.nbt" << endl; cout << "Error info = " << error_str << endl; return 1; } if (!schem.export_WESchem("test12.schem", weinfo, nullptr, &error_str)) { - cout << "Failed to export file " - << "test12.schem" << endl; + cout << "Failed to export file " << "test12.schem" << endl; cout << "Error info = " << error_str << endl; return 1; } diff --git a/utilities/NBTWriter/NBTWriter.h b/utilities/NBTWriter/NBTWriter.h index a2e86c45..18c02433 100644 --- a/utilities/NBTWriter/NBTWriter.h +++ b/utilities/NBTWriter/NBTWriter.h @@ -31,7 +31,7 @@ This file is part of SlopeCraft. #include #include #include - +#include #include // #include @@ -44,15 +44,15 @@ namespace NBT { namespace internal { class NBTWriterBase_nocompress { -protected: + protected: uint64_t bytesWritten{0}; int write_data(const void *data, const size_t bytes) noexcept; -private: + private: FILE *file{NULL}; -public: + public: /** * \brief open a file * \param newFileName the file to be opened @@ -81,15 +81,15 @@ class NBTWriterBase_nocompress { }; class NBTWriterBase_gzip { -protected: + protected: uint64_t bytesWritten{0}; int write_data(const void *data, const size_t bytes) noexcept; -private: + private: gzFile_s *file{NULL}; -public: + public: /** * \brief open a file * \param newFileName the file to be opened @@ -117,7 +117,7 @@ class NBTWriterBase_gzip { inline const gzFile_s *file_ptr() const noexcept { return file; } }; -} // namespace internal +} // namespace internal constexpr char idEnd = 0; constexpr char idByte = 1; @@ -154,8 +154,8 @@ enum tagType : char { * \param t To be converted * \return Converted */ -template inline T convertLEBE(T t) { - +template +inline T convertLEBE(T t) { uint8_t *ptr = reinterpret_cast(&t); for (int idx = 0; idx * 2 + 1 <= int(sizeof(T)); idx++) { @@ -173,7 +173,7 @@ class NBTWriter : public std::conditional_t { -public: + public: struct task_t { task_t() : currentTagType(tagType::End), taskSize(0) {} task_t(const tagType type, int size) @@ -183,10 +183,10 @@ class NBTWriter int taskSize; }; -private: + private: std::stack tasks; -public: + public: /** * \brief Default constructor */ @@ -212,13 +212,11 @@ class NBTWriter * \return If closing succeeds */ bool close() { - if (!this->is_open()) { return false; } - if (!tasks.empty()) - emergencyFill(); + if (!tasks.empty()) emergencyFill(); constexpr char fileTail[1] = {idEnd}; @@ -234,7 +232,6 @@ class NBTWriter * file can be loaded at least. \return Bytes written */ int emergencyFill() { - if (tasks.empty()) { return 0; } @@ -242,7 +239,6 @@ class NBTWriter int bytes = 0; while (!tasks.empty()) { - if (isInCompound()) { bytes += endCompound(); continue; @@ -251,70 +247,70 @@ class NBTWriter // cout<<"tasks.size() = "< - int writeSingleTag(const tagType type, const char *Name, T value) { + int writeSingleTag(const tagType type, std::string_view Name, T value) { static_assert(std::is_trivial_v); if (!this->is_open()) { @@ -418,21 +412,22 @@ class NBTWriter } int bytes = 0; - const uint16_t realNameL = strlen(Name); + if (Name.size() >= UINT16_MAX) { + return 0; + } + const uint16_t realNameL = Name.size(); const uint16_t flippedNameL = convertLEBE(realNameL); if (isInCompound()) { - bytes += this->write_data(&type, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(flippedNameL)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&value, sizeof(T)); } else { - if (!typeMatch(type)) { return 0; } @@ -451,7 +446,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeByte(const char *Name, int8_t value) { + inline int writeByte(std::string_view Name, int8_t value) { return writeSingleTag(tagType::Byte, Name, value); } @@ -461,7 +456,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeShort(const char *Name, int16_t value) { + inline int writeShort(std::string_view Name, int16_t value) { return writeSingleTag(tagType::Short, Name, value); } @@ -471,7 +466,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeInt(const char *Name, int32_t value) { + inline int writeInt(std::string_view Name, int32_t value) { return writeSingleTag(tagType::Int, Name, value); } @@ -481,7 +476,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeLong(const char *Name, int64_t value) { + inline int writeLong(std::string_view Name, int64_t value) { return writeSingleTag(tagType::Long, Name, value); } @@ -491,7 +486,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeFloat(const char *Name, float value) { + inline int writeFloat(std::string_view Name, float value) { return writeSingleTag(tagType::Float, Name, value); } @@ -501,7 +496,7 @@ class NBTWriter * \param value Value of tag * \return Bytes written */ - inline int writeDouble(const char *Name, double value) { + inline int writeDouble(std::string_view Name, double value) { return writeSingleTag(tagType::Double, Name, value); } @@ -510,18 +505,17 @@ class NBTWriter * \param Name Name of tag * \return Bytes written */ - int writeCompound(const char *Name = "") { - if (!this->is_open()) - return 0; + int writeCompound(std::string_view Name = "") { + if (!this->is_open()) return 0; int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); if (isInCompound()) { bytes += this->write_data(&idCompound, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); tasks.emplace(task_t(End, 0)); return bytes; @@ -541,8 +535,7 @@ class NBTWriter * \return Bytes written */ int endCompound() { - if (!this->is_open()) - return 0; + if (!this->is_open()) return 0; if (!isInCompound()) { return 0; @@ -568,7 +561,8 @@ class NBTWriter * \param listSize Size of list * \return Bytes written */ - int writeListHead(const char *Name, tagType elementType, const int listSize) { + int writeListHead(std::string_view Name, tagType elementType, + const int listSize) { if (!this->is_open()) { return 0; } @@ -578,14 +572,14 @@ class NBTWriter } int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int32_t flippedListSize = convertLEBE(listSize); if (isInCompound()) { bytes += this->write_data(&idList, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&elementType, sizeof(char)); bytes += this->write_data(&flippedListSize, sizeof(int32_t)); @@ -612,10 +606,9 @@ class NBTWriter return 0; } -private: + private: template - int writeArrayHead(const char *Name, const int32_t arraySize) { - + int writeArrayHead(std::string_view Name, const int32_t arraySize) { if (!this->is_open()) { return 0; } @@ -629,24 +622,22 @@ class NBTWriter : ((elementType == Int) ? (IntArray) : (LongArray)); int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int32_t flippedArraySize = convertLEBE(arraySize); if (isInCompound()) { - bytes += this->write_data(&arrayId, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&flippedArraySize, sizeof(int32_t)); tasks.emplace(task_t(elementType, arraySize)); if (arraySize == 0) { - onElementWritten(); } @@ -654,13 +645,11 @@ class NBTWriter } if (isInListOrArray() && typeMatch(arrayId)) { - bytes += this->write_data(&flippedArraySize, sizeof(int32_t)); tasks.emplace(task_t(elementType, arraySize)); if (arraySize == 0) { - onElementWritten(); } @@ -670,14 +659,14 @@ class NBTWriter return 0; } -public: + public: /** * \brief Start to write a byte array * \param Name Name of the array * \param arraySize Elements of the array * \return Bytes written */ - inline int writeByteArrayHead(const char *Name, const int arraySize) { + inline int writeByteArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -687,7 +676,7 @@ class NBTWriter * \param arraySize Elements of the array * \return Bytes written */ - inline int writeIntArrayHead(const char *Name, const int arraySize) { + inline int writeIntArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -697,7 +686,7 @@ class NBTWriter * \param arraySize Elements of the array * \return Bytes written */ - inline int writeLongArrayHead(const char *Name, const int arraySize) { + inline int writeLongArrayHead(std::string_view Name, const int arraySize) { return writeArrayHead(Name, arraySize); } @@ -707,14 +696,14 @@ class NBTWriter * \param value Value of a string * \return Bytes written */ - int writeString(const char *Name, const char *value) { + int writeString(std::string_view Name, const char *value) { if (!this->is_open()) { return 0; } int bytes = 0; - const int16_t realNameL = ::strlen(Name); + const int16_t realNameL = Name.size(); const int16_t flippedNameL = convertLEBE(realNameL); const int16_t realValueL = ::strlen(value); @@ -723,7 +712,7 @@ class NBTWriter if (isInCompound()) { bytes += this->write_data(&idString, sizeof(char)); bytes += this->write_data(&flippedNameL, sizeof(int16_t)); - bytes += this->write_data(Name, realNameL); + bytes += this->write_data(Name.data(), realNameL); bytes += this->write_data(&flippedValueL, sizeof(int16_t)); bytes += this->write_data(value, realValueL); @@ -732,7 +721,6 @@ class NBTWriter } if (isInListOrArray() && typeMatch(String)) { - bytes += this->write_data(&flippedValueL, sizeof(int16_t)); bytes += this->write_data(value, realValueL); @@ -757,6 +745,6 @@ class NBTWriter inline size_t byteCount() const { return this->bytesWritten; } }; -}; // namespace NBT +}; // namespace NBT -#endif // SCL_NBTWRITER_H +#endif // SCL_NBTWRITER_H diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 10343863..41cde7a1 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -28,6 +28,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include "Schem.h" @@ -414,6 +415,7 @@ tl::expected> Schem::pre_check( tl::expected> Schem::export_litematic(std::string_view filename, const litematic_info &info) const noexcept { + // { auto res = this->pre_check(filename, ".litematic"); if (not res) { @@ -575,6 +577,7 @@ Schem::export_litematic(std::string_view filename, tl::expected> Schem::export_structure(std::string_view filename, const bool is_air_structure_void) const noexcept { + // { auto res = this->pre_check(filename, ".nbt"); if (not res) { @@ -759,6 +762,7 @@ Schem::export_structure(std::string_view filename, tl::expected> Schem::export_WESchem( std::string_view filename, const WorldEditSchem_info &info) const noexcept { + // { auto res = this->pre_check(filename, ".schem"); if (not res) { @@ -787,10 +791,13 @@ tl::expected> Schem::export_WESchem( auto write_palette = [&]() { file.writeCompound("Palette"); { - for (int idx = 0; idx < int(block_id_list.size()); idx++) { - file.writeInt(block_id_list[idx].c_str(), idx); + for (int idx = 0; idx < static_cast(block_id_list.size()); idx++) { + // continue; + [[maybe_unused]] const auto ret = + file.writeInt(block_id_list[idx], idx); + assert(ret > 0); } - } // finished palette + } // finish palette file.endCompound(); }; auto write_offset = [&]() { @@ -808,16 +815,17 @@ tl::expected> Schem::export_WESchem( }; std::vector blockdata; - ::shrink_bytes_weSchem(xzy.data(), xzy.size(), block_id_list.size(), - &blockdata); + ::shrink_bytes_weSchem( + {this->xzy.data(), static_cast(this->xzy.size())}, + block_id_list.size(), &blockdata); auto write_blocks = [&](const char *key) { - file.writeByteArrayHead(key, blockdata.size()); - { - const int8_t *data = reinterpret_cast(blockdata.data()); - for (int64_t idx = 0; idx < int64_t(blockdata.size()); idx++) { - file.writeByte("", data[idx]); - } - } // end array + std::span data{reinterpret_cast(blockdata.data()), + blockdata.size() * sizeof(uint8_t)}; + file.writeByteArrayHead(key, data.size()); + for (int8_t d : data) { + file.writeByte("", d); + } + // end array }; if (this->MC_major_ver <= SCL_gameVersion::MC19) { @@ -853,7 +861,8 @@ tl::expected> Schem::export_WESchem( write_shape(); write_offset(); write_blocks("BlockData"); - } else { // 1.20+ + } else { + // 1.20+ file.writeCompound("Schematic"); { file.writeCompound("Metadata"); @@ -882,9 +891,9 @@ tl::expected> Schem::export_WESchem( file.writeCompound("Blocks"); { + file.writeListHead("BlockEntities", NBT::tagType::Compound, 0); write_palette(); write_blocks("Data"); - file.writeListHead("BlockEntities", NBT::tagType::Compound, 0); } file.endCompound(); // finish Blocks } @@ -894,3 +903,60 @@ tl::expected> Schem::export_WESchem( file.close(); return {}; } + +tl::expected +libSchem::Schem::remove_unused_ids() noexcept { + remove_unused_id_result stat; + stat.id_count_before = this->palette_size(); + std::vector id_used; + id_used.resize(this->palette_size(), false); + for (const ele_t blkid : *this) { + if (blkid >= this->palette_size()) [[unlikely]] { + return tl::make_unexpected( + fmt::format("The scheme required block with id = {}, but the block " + "palette has only {} blocks", + blkid, this->palette_size())); + } + id_used[blkid] = true; + } + + std::vector id_map_old_to_new; + { + ele_t next_id = 0; + for (size_t id = 0; id < id_used.size(); id++) { + if (id_used[id]) { + id_map_old_to_new.emplace_back(next_id++); + } else { + id_map_old_to_new.emplace_back(invalid_ele_t); + } + } + } + if (id_map_old_to_new.empty()) { + id_map_old_to_new.emplace_back(0); + } + // update block id list, remove unused block from palette + { + ele_t idx = 0; + for (auto it = this->block_id_list.begin(); + it not_eq this->block_id_list.end();) { + if (id_used[idx]) { + idx++; + ++it; + continue; + } + it = this->block_id_list.erase(it); + idx++; + } + } + // assert(this->block_id_list.size()==id_map_old_to_new.size()); + // update 3d matrix xzy + + for (ele_t &blkid : *this) { + assert(id_used[blkid]); + const auto new_id = id_map_old_to_new[blkid]; + blkid = new_id; + assert(new_id < this->block_id_list.size()); + } + stat.id_count_after = this->block_id_list.size(); + return stat; +} \ No newline at end of file diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 0ff688aa..6315d7c5 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -101,7 +101,7 @@ class Schem { } Schem(Schem &&) = default; Schem(int64_t x, int64_t y, int64_t z) { - xzy.resize(x, y, z); + xzy.resize(x, z, y); xzy.setZero(); } @@ -266,6 +266,14 @@ class Schem { std::span y_block_length, std::span z_block_length) const noexcept; + struct remove_unused_id_result { + size_t id_count_before; + size_t id_count_after; + }; + + [[nodiscard]] tl::expected + remove_unused_ids() noexcept; + protected: [[nodiscard]] Schem slice_no_check( std::span, 3> xyz_index_range) diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index 9900b379..d929a9d9 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -154,21 +154,20 @@ bool process_block_id( return ok; } -void shrink_bytes_weSchem(const uint16_t *src, const size_t src_count, - const int palette_max, +void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept { - if (palette_max <= 128) { - dest->resize(src_count); - for (size_t idx = 0; idx < src_count; idx++) { - dest->at(idx) = src[idx] & 0xFF; - } - return; - } + // if (palette_max <= 128) { + // dest->resize(src.size()); + // for (size_t idx = 0; idx < src.size(); idx++) { + // dest->at(idx) = src[idx] & 0xFF; + // } + // return; + //} - dest->reserve(src_count * 2); + dest->reserve(src.size() * 2); dest->clear(); - for (size_t idx = 0; idx < src_count; idx++) { + for (size_t idx = 0; idx < src.size(); idx++) { uint16_t temp = src[idx]; if (temp < 128) { dest->emplace_back(temp); diff --git a/utilities/Schem/bit_shrink.h b/utilities/Schem/bit_shrink.h index 34f236f0..09285334 100644 --- a/utilities/Schem/bit_shrink.h +++ b/utilities/Schem/bit_shrink.h @@ -24,6 +24,7 @@ This file is part of SlopeCraft. #define SCHEM_BITSHRINK_H #include +#include #include #include #include @@ -54,8 +55,7 @@ bool process_block_id( const std::string_view id, std::string *const pure_id, std::vector> *const traits); -void shrink_bytes_weSchem(const uint16_t *src, const size_t src_count, - const int palette_max, +void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept; class __mushroom_sides { From e1283699ee46f2240fda6af429ef4775901819ef Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 19:58:00 +0800 Subject: [PATCH 1009/1123] Set needStone=[12] for slime block and brewing stand Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/README.md | 8 +------- Blocks/FixedBlocks/block_list.json | 10 ++++++++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Blocks/FixedBlocks/README.md b/Blocks/FixedBlocks/README.md index a5dc990b..9950c418 100644 --- a/Blocks/FixedBlocks/README.md +++ b/Blocks/FixedBlocks/README.md @@ -1,9 +1,3 @@ # 默认方块列表对应的图片放在这里 -我还不太确定是否应当再度引入这一堆的图片(170多个二进制文件呐! -所以这里先空着。 - -# Fixed blocks list images here -I'm not sure whether should i put images here (170+ binary files! - -So leave it empty now. \ No newline at end of file +# Fixed blocks list images here \ No newline at end of file diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 71ddc3f4..c07fe835 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -25,7 +25,10 @@ "nameEN": "Slime block", "icon": "slime_block.png", "version": 0, - "idOld": "minecraft:slime" + "idOld": "minecraft:slime", + "needStone": [ + 12 + ] }, { "baseColor": 2, @@ -167,7 +170,10 @@ "nameEN": "brewing stand", "icon": "brewing_stand.png", "version": 0, - "wallUseable": false + "wallUseable": false, + "needStone": [ + 12 + ] }, { "baseColor": 6, From 162c3dde3f39187eca19ff379d695ebe6de4777e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:05:26 +0800 Subject: [PATCH 1010/1123] Fix CI Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 6 ++++-- .github/workflows/macos-build-arm64.yml | 4 +++- .github/workflows/macos-build-x64.yml | 4 +++- .github/workflows/windows-build.yml | 6 ++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index e4e0576a..d758a95b 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -100,18 +100,20 @@ jobs: cd .. - name: Upload deb pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-deb path: pack/SlopeCraft*.deb if-no-files-found: error + compression-level: 0 - name: Upload tar.xz pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-linux-gcc-tar-xz path: pack/SlopeCraft*.tar.xz if-no-files-found: error + compression-level: 0 - name: Run CTest if: (matrix.build_type == 'Release')&&(matrix.gpu_api == 'None') diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 10f4b3fe..24e336a3 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -89,10 +89,12 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-macos-m2-clang path: build/SlopeCraft*.zip + if-no-files-found: error + compression-level: 0 # nothing: # runs-on: macos-latest # steps: diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 30b5ebe5..a8df681a 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -110,10 +110,12 @@ jobs: - name: Get short SHA run: echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vectorize-${{ matrix.vectorize }}-macos-x64-clang path: build/SlopeCraft*.zip + if-no-files-found: error + compression-level: 0 # gcc: # runs-on: macos-latest diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 9625df12..67715a38 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -148,11 +148,12 @@ jobs: # if-no-files-found: error - name: Upload 7z pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-clang-7z path: pack/SlopeCraft*.7z if-no-files-found: error + compression-level: 0 gcc: runs-on: windows-latest @@ -300,8 +301,9 @@ jobs: # if-no-files-found: error - name: Upload 7z pack - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SlopeCraft-dev-${{ env.SHORT_SHA }}-${{ matrix.build_type }}-${{ matrix.gpu_api }}-vec=${{ matrix.vectorize }}-windows-gcc-7z path: pack/SlopeCraft*.7z if-no-files-found: error + compression-level: 0 From b1847d8a8c2f3a9719ac4c0e4463aca4b9dc1ada Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:12:49 +0800 Subject: [PATCH 1011/1123] Use clang in windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 67715a38..725a2c3a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -120,8 +120,8 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=cl -DCMAKE_CXX_COMPILER:FILEPATH=cl -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations - # -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + # - name: CMake build shell: cmd run: | From c3c10ae347f1e19d753c4a251b6693078d0df669 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:16:55 +0800 Subject: [PATCH 1012/1123] Fix importing zstd for linux Signed-off-by: ToKiNoBug --- cmake/required_deps/zstd.cmake | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmake/required_deps/zstd.cmake b/cmake/required_deps/zstd.cmake index 04095ca1..5c22e941 100644 --- a/cmake/required_deps/zstd.cmake +++ b/cmake/required_deps/zstd.cmake @@ -23,10 +23,15 @@ if (NOT ZSTD_FOUND) endif () set_target_properties(zstd_manually_imported PROPERTIES IMPORTED_LOCATION ${zstd_lib_loc}) - - cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) - cmake_path(GET zstd_install_dir PARENT_PATH zstd_install_dir) - target_include_directories(zstd_manually_imported INTERFACE "${zstd_install_dir}/include") + find_file(zstd_header_loc NAMES zstd.h + HINTS "/usr/lib/include/zstd.h") + if (zstd_header_loc) + cmake_path(GET zstd_include_dir PARENT_PATH zstd_header_loc) + target_include_directories(zstd_manually_imported INTERFACE ${zstd_include_dir}) + endif () + # cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) + # cmake_path(GET zstd_install_dir PARENT_PATH zstd_install_dir) + # target_include_directories(zstd_manually_imported INTERFACE "${zstd_install_dir}/include") endif () set(SC_zstd_target_name "") From 79968883c385ae8aa2d67f86ad0c2ccdcf2e5e0b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:35:35 +0800 Subject: [PATCH 1013/1123] Try to fix clang CI Signed-off-by: ToKiNoBug --- utilities/MCDataVersion/CMakeLists.txt | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utilities/MCDataVersion/CMakeLists.txt b/utilities/MCDataVersion/CMakeLists.txt index d7cfb6b5..5764c101 100644 --- a/utilities/MCDataVersion/CMakeLists.txt +++ b/utilities/MCDataVersion/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(MCDataVersion STATIC MCDataVersion.cpp ) -find_package(magic_enum REQUIRED) +find_package(magic_enum REQUIRED CONFIG) target_link_libraries(MCDataVersion PUBLIC magic_enum::magic_enum) target_compile_features(MCDataVersion PRIVATE cxx_std_20) diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index 6d1d7b1d..ff079bc4 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -41,7 +41,7 @@ MCDataVersion::MCDataVersion_t MCDataVersion::string_to_data_version( } const char *MCDataVersion::data_version_to_string( MCDataVersion::MCDataVersion_t v) noexcept { - const auto mcdv = magic_enum::enum_name(v); + std::string_view mcdv = magic_enum::enum_name(v); return mcdv.data(); } diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index eb4f5f98..25ffb4a5 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -25,7 +25,7 @@ This file is part of SlopeCraft. #include -#include +#include namespace MCDataVersion { From 429cfe5e0299c01c0b640753a1734418ad0c3966 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:35:51 +0800 Subject: [PATCH 1014/1123] Fix cmake warnings Signed-off-by: ToKiNoBug --- MapViewer/CMakeLists.txt | 2 +- SlopeCraft/CMakeLists.txt | 2 +- VisualCraft/CMakeLists.txt | 2 +- cmake/required_deps/libnbt++.cmake | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MapViewer/CMakeLists.txt b/MapViewer/CMakeLists.txt index 0bc806a1..b454e108 100644 --- a/MapViewer/CMakeLists.txt +++ b/MapViewer/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(SlopeCraft_MapViewer VERSION ${SlopeCraft_version}) set(CMAKE_CXX_STANDARD 17) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index a9374514..b0564079 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(SlopeCraft_NewGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/VisualCraft/CMakeLists.txt b/VisualCraft/CMakeLists.txt index cafb420f..42ec82b6 100644 --- a/VisualCraft/CMakeLists.txt +++ b/VisualCraft/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(VisualCraft_Main VERSION ${SlopeCraft_version} LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 9dfca1a1..18bbf886 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.29) find_package(ZLIB REQUIRED) -find_package(libnbt++) +find_package(libnbt++ QUIET) if (libnbt++_FOUND) message(STATUS "Found installed libnbt++") From 4cdb4d82fc26dbe80b8c3b126831b18bafed1779 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 2 Mar 2025 20:58:58 +0800 Subject: [PATCH 1015/1123] Try to fix linux build Signed-off-by: ToKiNoBug --- cmake/required_deps/magic_enum.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/required_deps/magic_enum.cmake b/cmake/required_deps/magic_enum.cmake index 91d86cd0..b3cb587f 100644 --- a/cmake/required_deps/magic_enum.cmake +++ b/cmake/required_deps/magic_enum.cmake @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14) -find_package(magic_enum 0.8.2 QUIET) +find_package(magic_enum QUIET) if (${magic_enum_FOUND}) return() @@ -14,7 +14,7 @@ FetchContent_Declare(magic_enum # URL https://github.com/Neargye/magic_enum/releases/download/v0.8.2/magic_enum.hpp GIT_REPOSITORY https://github.com/Neargye/magic_enum.git - GIT_TAG "v0.9.6" + GIT_TAG "v0.9.7" OVERRIDE_FIND_PACKAGE EXCLUDE_FROM_ALL ) From f81474e636ad8a0cf5f0c0a11ccab26d51f9b755 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:26:30 +0800 Subject: [PATCH 1016/1123] Fix build Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.cpp | 2 +- SlopeCraft/SCWind_slots.cpp | 2 +- SlopeCraftL/structure_3D.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/Schem/mushroom.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SlopeCraft/SCWind.cpp b/SlopeCraft/SCWind.cpp index d48ca666..7a5c56fc 100644 --- a/SlopeCraft/SCWind.cpp +++ b/SlopeCraft/SCWind.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include const QString SCWind::update_url{ diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index c3880a6f..8db6af1e 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "PreviewWind.h" #include "AiCvterParameterDialog.h" diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index a8b74f56..f0926cd8 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "structure_3D.h" #include "color_table.h" diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index ff079bc4..f7dc882a 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -22,7 +22,7 @@ This file is part of SlopeCraft. #include "MCDataVersion.h" -#include +#include MCDataVersion::MCDataVersion_t MCDataVersion::string_to_data_version( const char *str, bool *ok) noexcept { diff --git a/utilities/Schem/mushroom.cpp b/utilities/Schem/mushroom.cpp index 652491e6..846ff449 100644 --- a/utilities/Schem/mushroom.cpp +++ b/utilities/Schem/mushroom.cpp @@ -1,7 +1,7 @@ #include "mushroom.h" #include #include -#include +#include #include namespace lsi = libSchem::internal; From 4faac946ed5ad4b2e981bebafe77a29ef97a8757 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:29:06 +0800 Subject: [PATCH 1017/1123] Fix identifiers start with _ Signed-off-by: ToKiNoBug --- utilities/ColorManip/imageConvert.hpp | 127 +++++++++++----------- utilities/MapImageCvter/MapImageCvter.cpp | 14 +-- utilities/MapImageCvter/MapImageCvter.h | 56 +++++----- 3 files changed, 99 insertions(+), 98 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index e65827a4..de43ed43 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -103,12 +103,12 @@ class ImageCvter : public GPU_wrapper_wrapper { protected: const basic_colorset_t &basic_colorset; const allowed_colorset_t &allowed_colorset; - Eigen::ArrayXX _raw_image; + Eigen::ArrayXX raw_image_; ::SCL_convertAlgo algo; bool dither{false}; - std::unordered_map _color_hash; + std::unordered_map color_hash_; - Eigen::ArrayXX _dithered_image; + Eigen::ArrayXX dithered_image_; // Eigen::ArrayXX colorid_matrix; public: @@ -116,27 +116,27 @@ class ImageCvter : public GPU_wrapper_wrapper { // SCL_convertAlgo convert_algo{SCL_convertAlgo::RGB_Better}; inline void clear_images() noexcept { - this->_raw_image.resize(0, 0); - this->_dithered_image.resize(0, 0); + this->raw_image_.resize(0, 0); + this->dithered_image_.resize(0, 0); } /// When the colorset is changed, the hash must be cleared. inline void on_color_set_changed() noexcept { this->clear_color_hash(); } /// Call this function when the color set is changed. - inline void clear_color_hash() noexcept { this->_color_hash.clear(); } + inline void clear_color_hash() noexcept { this->color_hash_.clear(); } inline ::SCL_convertAlgo convert_algo() const noexcept { return this->algo; } inline bool is_dither() const noexcept { return this->dither; } - inline int64_t rows() const noexcept { return _raw_image.rows(); } - inline int64_t cols() const noexcept { return _raw_image.cols(); } - inline int64_t size() const noexcept { return _raw_image.size(); } + inline int64_t rows() const noexcept { return raw_image_.rows(); } + inline int64_t cols() const noexcept { return raw_image_.cols(); } + inline int64_t size() const noexcept { return raw_image_.size(); } - inline const auto &raw_image() const noexcept { return _raw_image; } + inline const auto &raw_image() const noexcept { return raw_image_; } - inline const auto &color_hash() const noexcept { return _color_hash; } + inline const auto &color_hash() const noexcept { return color_hash_; } void set_raw_image(const ARGB *const data, const int64_t _rows, const int64_t _cols, @@ -151,24 +151,24 @@ class ImageCvter : public GPU_wrapper_wrapper { if (is_col_major) { Eigen::Map> map(data, _rows, _cols); - this->_raw_image = map; + this->raw_image_ = map; } else { Eigen::Map> map(data, _rows, _cols); - this->_raw_image = map; + this->raw_image_ = map; } } - bool convert_image(::SCL_convertAlgo __algo, bool _dither, + bool convert_image(::SCL_convertAlgo algo_, bool dither_, bool try_gpu = false) noexcept { - if (__algo == ::SCL_convertAlgo::gaCvter) { - __algo = ::SCL_convertAlgo::RGB_Better; + if (algo_ == ::SCL_convertAlgo::gaCvter) { + algo_ = ::SCL_convertAlgo::RGB_Better; } - this->dither = _dither; + this->dither = dither_; ui.rangeSet(0, 100, 0); - this->algo = __algo; + this->algo = algo_; this->add_colors_to_hash(); ui.rangeSet(0, 100, 25); if (!this->match_all_TokiColors(try_gpu)) { @@ -179,22 +179,22 @@ class ImageCvter : public GPU_wrapper_wrapper { if (this->dither) { switch (this->algo) { case ::SCL_convertAlgo::RGB: - this->template __impl_dither<::SCL_convertAlgo::RGB>(); + this->template impl_dither__<::SCL_convertAlgo::RGB>(); break; case ::SCL_convertAlgo::RGB_Better: - this->template __impl_dither<::SCL_convertAlgo::RGB_Better>(); + this->template impl_dither__<::SCL_convertAlgo::RGB_Better>(); break; case ::SCL_convertAlgo::HSV: - this->template __impl_dither<::SCL_convertAlgo::HSV>(); + this->template impl_dither__<::SCL_convertAlgo::HSV>(); break; case ::SCL_convertAlgo::Lab94: - this->template __impl_dither<::SCL_convertAlgo::Lab94>(); + this->template impl_dither__<::SCL_convertAlgo::Lab94>(); break; case ::SCL_convertAlgo::Lab00: - this->template __impl_dither<::SCL_convertAlgo::Lab00>(); + this->template impl_dither__<::SCL_convertAlgo::Lab00>(); break; case ::SCL_convertAlgo::XYZ: - this->template __impl_dither<::SCL_convertAlgo::XYZ>(); + this->template impl_dither__<::SCL_convertAlgo::XYZ>(); break; default: @@ -202,7 +202,7 @@ class ImageCvter : public GPU_wrapper_wrapper { return false; } } else { - this->_dithered_image = this->_raw_image; + this->dithered_image_ = this->raw_image_; } // for (int64_t idx = 0; idx < this->_dithered_image.size(); idx++) { @@ -226,11 +226,11 @@ class ImageCvter : public GPU_wrapper_wrapper { result.setZero(this->rows(), this->cols()); for (int64_t idx = 0; idx < this->size(); idx++) { - const auto current_color = this->_dithered_image(idx); + const auto current_color = this->dithered_image_(idx); - auto it = this->_color_hash.find(convert_unit(current_color, this->algo)); + auto it = this->color_hash_.find(convert_unit(current_color, this->algo)); - if (it == this->_color_hash.end()) { + if (it == this->color_hash_.end()) { if (getA(current_color) <= 0) { result(idx) = 0; continue; @@ -252,10 +252,10 @@ class ImageCvter : public GPU_wrapper_wrapper { // sizeof(uint16_t)); for (int64_t idx = 0; idx < this->size(); idx++) { - auto it = this->_color_hash.find( - convert_unit(this->_dithered_image(idx), this->algo)); + auto it = this->color_hash_.find( + convert_unit(this->dithered_image_(idx), this->algo)); - if (it == this->_color_hash.end()) { + if (it == this->color_hash_.end()) { abort(); } @@ -267,9 +267,9 @@ class ImageCvter : public GPU_wrapper_wrapper { assert(r >= 0 && r < this->rows()); assert(c >= 0 && c < this->cols()); - const auto current_color = this->_dithered_image(r, c); - auto it = this->_color_hash.find(convert_unit{current_color, this->algo}); - if (it == this->_color_hash.end()) { + const auto current_color = this->dithered_image_(r, c); + auto it = this->color_hash_.find(convert_unit{current_color, this->algo}); + if (it == this->color_hash_.end()) { if (getA(current_color) > 0) { abort(); } @@ -300,9 +300,10 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t c = 0; c < cols(); c++) { const int64_t idx = (is_dest_col_major) ? (c * rows() + r) : (r * cols() + c); - const ARGB argb = this->_dithered_image(r, c); - auto it = this->_color_hash.find(convert_unit(argb, this->algo)); - if (it == this->_color_hash.end()) { + const ARGB argb = this->dithered_image_(r, c); + auto it = this->color_hash_.find(convert_unit(argb, this->algo)); + if (it == this->color_hash_.end()) { +#warning "Issue #130 crashed here" abort(); return; } @@ -326,13 +327,13 @@ class ImageCvter : public GPU_wrapper_wrapper { void add_colors_to_hash() noexcept { // this->_color_hash.clear(); - for (int64_t idx = 0; idx < this->_raw_image.size(); idx++) { - const ARGB argb = this->_raw_image(idx); + for (int64_t idx = 0; idx < this->raw_image_.size(); idx++) { + const ARGB argb = this->raw_image_(idx); convert_unit cu(argb, this->algo); - auto it = _color_hash.find(cu); + auto it = color_hash_.find(cu); // this key isn't inserted - if (it == _color_hash.end()) this->_color_hash.emplace(cu, TokiColor_t()); + if (it == color_hash_.end()) this->color_hash_.emplace(cu, TokiColor_t()); } } @@ -359,10 +360,10 @@ class ImageCvter : public GPU_wrapper_wrapper { // const int threadCount = omp_get_num_threads(); std::vector *> tasks; - tasks.reserve(_color_hash.size()); + tasks.reserve(color_hash_.size()); tasks.clear(); - for (auto &pair : _color_hash) { + for (auto &pair : color_hash_) { if (!pair.second.is_result_computed()) tasks.emplace_back(&pair); } const size_t taskCount = tasks.size(); @@ -391,8 +392,8 @@ class ImageCvter : public GPU_wrapper_wrapper { #pragma omp parallel for for (int64_t c = 0; c < this->cols(); c++) { for (int64_t r = 0; r < this->rows(); r++) { - auto it = this->_color_hash.find(this->_raw_image(r, c)); - if (it == this->_color_hash.end()) { + auto it = this->color_hash_.find(this->raw_image_(r, c)); + if (it == this->color_hash_.end()) { abort(); } @@ -417,10 +418,10 @@ class ImageCvter : public GPU_wrapper_wrapper { } std::vector *> tasks; - tasks.reserve(_color_hash.size()); + tasks.reserve(color_hash_.size()); tasks.clear(); - for (auto &pair : this->_color_hash) { + for (auto &pair : this->color_hash_) { if (!pair.second.is_result_computed()) { if ((pair.first._ARGB & 0xFF'00'00'00) == 0) { pair.second.compute(pair.first, this->allowed_colorset); @@ -555,20 +556,20 @@ class ImageCvter : public GPU_wrapper_wrapper { } template - void __impl_dither() noexcept { + void impl_dither__() noexcept { std::array dither_c3; for (auto &i : dither_c3) { i.setZero(this->rows() + 2, this->cols() + 2); } // dest.setZero(this->rows(), this->cols()); - this->_dithered_image.setZero(this->rows(), this->cols()); + this->dithered_image_.setZero(this->rows(), this->cols()); for (int64_t r = 0; r < this->rows(); r++) { for (int64_t c = 0; c < this->cols(); c++) { - auto it = this->_color_hash.find( - convert_unit(this->_raw_image(r, c), this->algo)); - if (it == this->_color_hash.end()) { + auto it = this->color_hash_.find( + convert_unit(this->raw_image_(r, c), this->algo)); + if (it == this->color_hash_.end()) { // unreachable abort(); return; @@ -584,7 +585,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t row = 0; row < this->rows(); row++) { if (is_dir_LR) for (int64_t col = 0; col < this->cols(); col++) { - if (::getA(this->_raw_image(row, col)) <= 0) { + if (::getA(this->raw_image_(row, col)) <= 0) { continue; } @@ -592,13 +593,13 @@ class ImageCvter : public GPU_wrapper_wrapper { dither_c3[0](row + 1, col + 1), dither_c3[1](row + 1, col + 1), dither_c3[2](row + 1, col + 1)); // ditheredImage(r, c) = Current; - this->_dithered_image(row, col) = current_argb; + this->dithered_image_(row, col) = current_argb; auto it_to_old_color = - this->_color_hash.find(convert_unit(current_argb, this->algo)); + this->color_hash_.find(convert_unit(current_argb, this->algo)); // if this color isn't matched, match it. - if (it_to_old_color == this->_color_hash.end()) { + if (it_to_old_color == this->color_hash_.end()) { convert_unit cu(current_argb, this->algo); - auto ret = this->_color_hash.emplace(cu, TokiColor_t()); + auto ret = this->color_hash_.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; @@ -625,19 +626,19 @@ class ImageCvter : public GPU_wrapper_wrapper { } else for (int64_t col = this->cols() - 1; col >= 0; col--) { - if (::getA(this->_raw_image(row, col)) <= 0) { + if (::getA(this->raw_image_(row, col)) <= 0) { continue; } const ARGB current_argb = ColorCvt( dither_c3[0](row + 1, col + 1), dither_c3[1](row + 1, col + 1), dither_c3[2](row + 1, col + 1)); - this->_dithered_image(row, col) = current_argb; + this->dithered_image_(row, col) = current_argb; convert_unit cu(current_argb, this->algo); - auto it_to_old_color = this->_color_hash.find(cu); + auto it_to_old_color = this->color_hash_.find(cu); // if this color isn't matched, match it. - if (it_to_old_color == this->_color_hash.end()) { - auto ret = this->_color_hash.emplace(cu, TokiColor_t()); + if (it_to_old_color == this->color_hash_.end()) { + auto ret = this->color_hash_.emplace(cu, TokiColor_t()); it_to_old_color = ret.first; it_to_old_color->second.compute(cu, this->allowed_colorset); // inserted_count++; @@ -676,7 +677,7 @@ class ImageCvter : public GPU_wrapper_wrapper { } uint64_t task_hash(SCL_convertAlgo a, bool d) const noexcept { - const auto &img = this->_raw_image; + const auto &img = this->raw_image_; return std::hash()( std::string_view{(const char *)img.data(), diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index e441b0eb..823a7ae0 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -66,13 +66,13 @@ void libMapImageCvt::MapImageCvter::convert_image( gacvter->run(); - Eigen::ArrayXX raw_image_cache = this->_raw_image; + Eigen::ArrayXX raw_image_cache = this->raw_image_; - gacvter->resultImage(&this->_raw_image); + gacvter->resultImage(&this->raw_image_); Base_t::convert_image(::SCL_convertAlgo::RGB_Better, dither); - this->_raw_image = raw_image_cache; + this->raw_image_ = raw_image_cache; } bool libMapImageCvt::MapImageCvter::save_cache( @@ -129,8 +129,8 @@ bool libMapImageCvt::MapImageCvter::load_cache( this->load_from_itermediate(std::move(temp)); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); return true; } @@ -139,7 +139,7 @@ bool libMapImageCvt::MapImageCvter::load_cache(const char *filename) noexcept { this->load_from_itermediate(std::move(temp)); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); return true; } \ No newline at end of file diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 2ea85be9..9b9c4b58 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -91,25 +91,25 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { } dest.clear(); for (int64_t r = 0; r < this->rows(); r++) { - auto it = this->_color_hash.find( - convert_unit(this->_dithered_image(r, col), this->algo)); + auto it = this->color_hash_.find( + convert_unit(this->dithered_image_(r, col), this->algo)); dest.emplace_back(&it->second); } } - + // temp is a temporary container to pass ownership void load_from_itermediate(MapImageCvter &&temp) noexcept { - this->_raw_image = std::move(temp._raw_image); + this->raw_image_ = std::move(temp.raw_image_); this->algo = temp.algo; - this->_dithered_image = std::move(temp._dithered_image); + this->dithered_image_ = std::move(temp.dithered_image_); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); - if (this->_color_hash.empty()) { - this->_color_hash = std::move(temp._color_hash); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); + if (this->color_hash_.empty()) { + this->color_hash_ = std::move(temp.color_hash_); } else { - temp._color_hash.merge(this->_color_hash); - this->_color_hash = std::move(temp._color_hash); + temp.color_hash_.merge(this->color_hash_); + this->color_hash_ = std::move(temp.color_hash_); } } @@ -117,20 +117,20 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { friend class cereal::access; template void save(archive &ar) const { - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); - ar(this->_raw_image); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); + ar(this->raw_image_); ar(this->algo); ar(this->dither); // ar(this->_color_hash); - ar(this->_dithered_image); + ar(this->dithered_image_); // save required colorset { std::unordered_set colors_dithered_img; - colors_dithered_img.reserve(this->_dithered_image.size()); - for (int64_t i = 0; i < this->_dithered_image.size(); i++) { - colors_dithered_img.emplace(this->_dithered_image(i)); - colors_dithered_img.emplace(this->_raw_image(i)); + colors_dithered_img.reserve(this->dithered_image_.size()); + for (int64_t i = 0; i < this->dithered_image_.size(); i++) { + colors_dithered_img.emplace(this->dithered_image_(i)); + colors_dithered_img.emplace(this->raw_image_(i)); } const size_t size_colorset = colors_dithered_img.size(); @@ -150,14 +150,14 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { template void load(archive &ar) { - ar(this->_raw_image); + ar(this->raw_image_); ar(this->algo); ar(this->dither); // ar(this->_color_hash); - ar(this->_dithered_image); + ar(this->dithered_image_); - assert(this->_raw_image.rows() == this->_dithered_image.rows()); - assert(this->_raw_image.cols() == this->_dithered_image.cols()); + assert(this->raw_image_.rows() == this->dithered_image_.rows()); + assert(this->raw_image_.cols() == this->dithered_image_.cols()); { size_t size_colorset{0}; @@ -167,13 +167,13 @@ class MapImageCvter : public ::libImageCvt::ImageCvter { TokiColor_t val; ar(key, val); - this->_color_hash.emplace(key, val); + this->color_hash_.emplace(key, val); } - for (int64_t i = 0; i < this->_dithered_image.size(); i++) { - auto it = this->_color_hash.find( - convert_unit{this->_dithered_image(i), this->convert_algo()}); - if (it == this->_color_hash.end()) { + for (int64_t i = 0; i < this->dithered_image_.size(); i++) { + auto it = this->color_hash_.find( + convert_unit{this->dithered_image_(i), this->convert_algo()}); + if (it == this->color_hash_.end()) { throw std::runtime_error{ "One or more colors not found in cached colorhash"}; } From 24fe23ae80dad91205e24225d10a7d23b2d1b827 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 11:51:16 +0800 Subject: [PATCH 1018/1123] Fix issue #130 Signed-off-by: ToKiNoBug --- utilities/ColorManip/imageConvert.hpp | 35 ++++++++++++++++++++++----- utilities/ColorManip/newTokiColor.hpp | 8 +++--- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index de43ed43..66dd0d17 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -176,6 +176,14 @@ class ImageCvter : public GPU_wrapper_wrapper { } ui.rangeSet(0, 100, 50); + // handle possible full-transparent pixel + { + convert_unit cu{ARGB32(0, 0, 0, 0), this->algo}; + TokiColor_t tk; + tk.compute(cu, this->allowed_colorset); + this->color_hash_.emplace(cu, tk); + } + if (this->dither) { switch (this->algo) { case ::SCL_convertAlgo::RGB: @@ -271,6 +279,7 @@ class ImageCvter : public GPU_wrapper_wrapper { auto it = this->color_hash_.find(convert_unit{current_color, this->algo}); if (it == this->color_hash_.end()) { if (getA(current_color) > 0) { + // logical impossible abort(); } return 0; @@ -300,12 +309,15 @@ class ImageCvter : public GPU_wrapper_wrapper { for (int64_t c = 0; c < cols(); c++) { const int64_t idx = (is_dest_col_major) ? (c * rows() + r) : (r * cols() + c); - const ARGB argb = this->dithered_image_(r, c); - auto it = this->color_hash_.find(convert_unit(argb, this->algo)); + ARGB argb = this->dithered_image_(r, c); + // process full-transparent image + if (::getA(argb) <= 0) { + argb = ARGB32(0, 0, 0, 0); + } + auto it = this->color_hash_.find(convert_unit{argb, this->algo}); if (it == this->color_hash_.end()) { -#warning "Issue #130 crashed here" + // logical impossible abort(); - return; } const auto color_id = it->second.color_id(); @@ -552,7 +564,6 @@ class ImageCvter : public GPU_wrapper_wrapper { } // unreachable abort(); - return 0; } template @@ -572,7 +583,6 @@ class ImageCvter : public GPU_wrapper_wrapper { if (it == this->color_hash_.end()) { // unreachable abort(); - return; } for (int ch = 0; ch < 3; ch++) { dither_c3[ch](r + 1, c + 1) = it->first.to_c3()[ch]; @@ -580,12 +590,24 @@ class ImageCvter : public GPU_wrapper_wrapper { } } + // auto handle_full_transparent_pixel = [this](ARGB color) { + // convert_unit cu{color, this->algo}; + // if (this->color_hash_.contains(cu)) { + // return; + // } + // TokiColor_t tk; + // tk.compute(cu, this->allowed_colorset); + // this->color_hash_.emplace(cu, tk); + // }; + // int64_t inserted_count = 0; bool is_dir_LR = true; for (int64_t row = 0; row < this->rows(); row++) { if (is_dir_LR) for (int64_t col = 0; col < this->cols(); col++) { if (::getA(this->raw_image_(row, col)) <= 0) { + // found full-transparent pixel + // handle_full_transparent_pixel(this->raw_image_(row, col)); continue; } @@ -627,6 +649,7 @@ class ImageCvter : public GPU_wrapper_wrapper { else for (int64_t col = this->cols() - 1; col >= 0; col--) { if (::getA(this->raw_image_(row, col)) <= 0) { + // handle_full_transparent_pixel(this->raw_image_(row, col)); continue; } diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index a787952c..65cfd4e9 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -128,13 +128,13 @@ class newTokiColor } template - void set_gpu_result(uint16_t __result_color_id, - float __result_diff) noexcept { + void set_gpu_result(uint16_t result_color_id__, + float result_diff__) noexcept { static_assert(!is_not_optical, "set_gpu_result is only avaliable for VisualCraftL."); - this->ResultDiff = __result_diff; - this->result_color_id = __result_color_id; + this->ResultDiff = result_diff__; + this->result_color_id = result_color_id__; } auto compute(convert_unit cu, const allowed_t &allowed) noexcept { From 308108c222fc42f7e5809d424e92503f30e35e69 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:00:03 +0800 Subject: [PATCH 1019/1123] Fix most identifiers starting with _ in ColorManip Signed-off-by: ToKiNoBug --- utilities/ColorManip/colorset_maptical.hpp | 97 +++++++++---------- utilities/ColorManip/colorset_optical.hpp | 103 ++++++++++++--------- utilities/ColorManip/imageConvert.hpp | 18 ++-- utilities/ColorManip/newTokiColor.hpp | 17 ++-- 4 files changed, 129 insertions(+), 106 deletions(-) diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 5b5e7930..4c9ab3dc 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -61,10 +61,10 @@ class newtokicolor_base_maptical { class alignas(32) colorset_maptical_basic { private: - Eigen::Array __rgb; - Eigen::Array __hsv; - Eigen::Array __lab; - Eigen::Array __xyz; + Eigen::Array rgb_table; + Eigen::Array hsv_table; + Eigen::Array lab_table; + Eigen::Array xyz_table; public: /// The default constructor is deleted @@ -72,32 +72,33 @@ class alignas(32) colorset_maptical_basic { /// Construct from color source colorset_maptical_basic(const float *const rgbsrc) { assert(rgbsrc); - memcpy(__rgb.data(), rgbsrc, sizeof(__rgb)); + memcpy(rgb_table.data(), rgbsrc, sizeof(rgb_table)); for (int row = 0; row < 256; row++) { - const float r = __rgb(row, 0), g = __rgb(row, 1), b = __rgb(row, 2); - RGB2HSV(r, g, b, __hsv(row, 0), __hsv(row, 1), __hsv(row, 2)); - RGB2XYZ(r, g, b, __xyz(row, 0), __xyz(row, 1), __xyz(row, 2)); - XYZ2Lab(XYZ(row, 0), XYZ(row, 1), XYZ(row, 2), __lab(row, 0), - __lab(row, 1), __lab(row, 2)); + const float r = rgb_table(row, 0), g = rgb_table(row, 1), + b = rgb_table(row, 2); + RGB2HSV(r, g, b, hsv_table(row, 0), hsv_table(row, 1), hsv_table(row, 2)); + RGB2XYZ(r, g, b, xyz_table(row, 0), xyz_table(row, 1), xyz_table(row, 2)); + XYZ2Lab(XYZ(row, 0), XYZ(row, 1), XYZ(row, 2), lab_table(row, 0), + lab_table(row, 1), lab_table(row, 2)); } } /// get the color count inline constexpr int color_count() const noexcept { return 256; } - inline const auto &RGB_mat() const noexcept { return __rgb; } + inline const auto &RGB_mat() const noexcept { return rgb_table; } inline float RGB(const int r, const int c) const noexcept { - return __rgb(r, c); + return rgb_table(r, c); } inline float HSV(const int r, const int c) const noexcept { - return __hsv(r, c); + return hsv_table(r, c); } inline float Lab(const int r, const int c) const noexcept { - return __lab(r, c); + return lab_table(r, c); } inline float XYZ(const int r, const int c) const noexcept { - return __xyz(r, c); + return xyz_table(r, c); } static inline uint8_t Map(const int r) noexcept { @@ -119,13 +120,13 @@ class alignas(32) colorset_maptical_allowed { static constexpr uint8_t invalid_color_id = 0; private: - std::array __rgb; - std::array __hsv; - std::array __lab; - std::array __xyz; - Eigen::Array __map; + std::array rgb_table; + std::array hsv_table; + std::array lab_table; + std::array xyz_table; + Eigen::Array map_table; // std::array __map; - int _color_count{0}; + int color_count_{0}; std::array depth_counter; @@ -135,65 +136,65 @@ class alignas(32) colorset_maptical_allowed { return this->depth_counter; } - inline int color_count() const noexcept { return _color_count; } + inline int color_count() const noexcept { return color_count_; } inline float RGB(int r, int c) const noexcept { assert(r < color_count()); - return __rgb[c](r); + return rgb_table[c](r); } inline float HSV(int r, int c) const noexcept { assert(r < color_count()); - return __hsv[c](r); + return hsv_table[c](r); } inline float Lab(int r, int c) const noexcept { assert(r < color_count()); - return __lab[c](r); + return lab_table[c](r); } inline float XYZ(int r, int c) const noexcept { assert(r < color_count()); - return __xyz[c](r); + return xyz_table[c](r); } inline uint8_t Map(int r) const noexcept { assert(r < color_count()); - return __map[r]; + return map_table[r]; } inline auto rgb(int channel) const noexcept { - return __rgb[channel].head(_color_count); + return rgb_table[channel].head(color_count_); } inline auto hsv(int channel) const noexcept { - return __hsv[channel].head(_color_count); + return hsv_table[channel].head(color_count_); } inline auto lab(int channel) const noexcept { - return __lab[channel].head(_color_count); + return lab_table[channel].head(color_count_); } inline auto xyz(int channel) const noexcept { - return __xyz[channel].head(_color_count); + return xyz_table[channel].head(color_count_); } - inline auto map() const noexcept { return __map.head(_color_count); } + inline auto map() const noexcept { return map_table.head(color_count_); } inline const float *rgb_data(int channel) const noexcept { - return __rgb[channel].data(); + return rgb_table[channel].data(); } inline const float *hsv_data(int channel) const noexcept { - return __hsv[channel].data(); + return hsv_table[channel].data(); } inline const float *lab_data(int channel) const noexcept { - return __lab[channel].data(); + return lab_table[channel].data(); } inline const float *xyz_data(int channel) const noexcept { - return __xyz[channel].data(); + return xyz_table[channel].data(); } - inline const uint8_t *map_data() const noexcept { return __map.data(); } + inline const uint8_t *map_data() const noexcept { return map_table.data(); } bool apply_allowed(const colorset_maptical_basic &src, std::span allow_list) noexcept { @@ -204,14 +205,14 @@ class alignas(32) colorset_maptical_allowed { } for (int c = 0; c < 3; c++) { - __rgb[c].setZero(); - __hsv[c].setZero(); - __lab[c].setZero(); - __xyz[c].setZero(); + rgb_table[c].setZero(); + hsv_table[c].setZero(); + lab_table[c].setZero(); + xyz_table[c].setZero(); } - __map.setZero(); + map_table.setZero(); - _color_count = new_color_count; + color_count_ = new_color_count; for (int writeidx = 0, readidx = 0; readidx < 256; readidx++) { const int base = (readidx & 0b111111); @@ -221,12 +222,12 @@ class alignas(32) colorset_maptical_allowed { if (allow_list[readidx]) { for (int c = 0; c < 3; c++) { - __rgb[c](writeidx) = src.RGB(readidx, c); - __hsv[c](writeidx) = src.HSV(readidx, c); - __lab[c](writeidx) = src.Lab(readidx, c); - __xyz[c](writeidx) = src.XYZ(readidx, c); + rgb_table[c](writeidx) = src.RGB(readidx, c); + hsv_table[c](writeidx) = src.HSV(readidx, c); + lab_table[c](writeidx) = src.Lab(readidx, c); + xyz_table[c](writeidx) = src.XYZ(readidx, c); } - __map[writeidx] = src.Map(readidx); + map_table[writeidx] = src.Map(readidx); writeidx++; } } diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index f731be06..8b4fa58d 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -30,32 +30,48 @@ This file is part of SlopeCraft. class alignas(32) colorset_optical_base { protected: - std::array __rgb; - std::array __hsv; - std::array __lab; - std::array __xyz; + std::array rgb_table; + std::array hsv_table; + std::array lab_table; + std::array xyz_table; private: - int _color_count; + int color_count_; public: - inline int color_count() const noexcept { return _color_count; } + inline int color_count() const noexcept { return color_count_; } - inline float RGB(int r, int c) const noexcept { return __rgb[c](r); } - inline auto rgb(int c) const noexcept { return __rgb[c].head(_color_count); } - inline const float *rgb_data(int c) const noexcept { return __rgb[c].data(); } + inline float RGB(int r, int c) const noexcept { return rgb_table[c](r); } + inline auto rgb(int c) const noexcept { + return rgb_table[c].head(color_count_); + } + inline const float *rgb_data(int c) const noexcept { + return rgb_table[c].data(); + } - inline float HSV(int r, int c) const noexcept { return __hsv[c](r); } - inline auto hsv(int c) const noexcept { return __hsv[c].head(_color_count); } - inline const float *hsv_data(int c) const noexcept { return __hsv[c].data(); } + inline float HSV(int r, int c) const noexcept { return hsv_table[c](r); } + inline auto hsv(int c) const noexcept { + return hsv_table[c].head(color_count_); + } + inline const float *hsv_data(int c) const noexcept { + return hsv_table[c].data(); + } - inline float Lab(int r, int c) const noexcept { return __lab[c](r); } - inline auto lab(int c) const noexcept { return __lab[c].head(_color_count); } - inline const float *lab_data(int c) const noexcept { return __lab[c].data(); } + inline float Lab(int r, int c) const noexcept { return lab_table[c](r); } + inline auto lab(int c) const noexcept { + return lab_table[c].head(color_count_); + } + inline const float *lab_data(int c) const noexcept { + return lab_table[c].data(); + } - inline float XYZ(int r, int c) const noexcept { return __xyz[c](r); } - inline auto xyz(int c) const noexcept { return __xyz[c].head(_color_count); } - inline const float *xyz_data(int c) const noexcept { return __xyz[c].data(); } + inline float XYZ(int r, int c) const noexcept { return xyz_table[c](r); } + inline auto xyz(int c) const noexcept { + return xyz_table[c].head(color_count_); + } + inline const float *xyz_data(int c) const noexcept { + return xyz_table[c].data(); + } protected: void resize(int new_color_count) noexcept { @@ -64,13 +80,13 @@ class alignas(32) colorset_optical_base { } for (int c = 0; c < 3; c++) { - __rgb[c].setZero(new_color_count); - __hsv[c].setZero(new_color_count); - __lab[c].setZero(new_color_count); - __xyz[c].setZero(new_color_count); + rgb_table[c].setZero(new_color_count); + hsv_table[c].setZero(new_color_count); + lab_table[c].setZero(new_color_count); + xyz_table[c].setZero(new_color_count); } - this->_color_count = new_color_count; + this->color_count_ = new_color_count; } }; @@ -103,22 +119,23 @@ class colorset_optical_basic : public colorset_optical_base { rbgsrc_colmajor, new_color_count, 3); for (int c = 0; c < 3; c++) { - memcpy(this->__rgb[c].data(), rbgsrc_colmajor + (new_color_count * c), + memcpy(this->rgb_table[c].data(), + rbgsrc_colmajor + (new_color_count * c), sizeof(float) * new_color_count); //= rgbsrcmap.col(c); } } for (int coloridx = 0; coloridx < new_color_count; coloridx++) { - RGB2HSV(this->__rgb[0](coloridx), this->__rgb[1](coloridx), - this->__rgb[2](coloridx), this->__hsv[0](coloridx), - this->__hsv[1](coloridx), this->__hsv[2](coloridx)); - RGB2XYZ(this->__rgb[0](coloridx), this->__rgb[1](coloridx), - this->__rgb[2](coloridx), this->__xyz[0](coloridx), - this->__xyz[1](coloridx), this->__xyz[2](coloridx)); - XYZ2Lab(this->__xyz[0](coloridx), this->__xyz[1](coloridx), - this->__xyz[2](coloridx), this->__lab[0](coloridx), - this->__lab[1](coloridx), this->__lab[2](coloridx)); + RGB2HSV(this->rgb_table[0](coloridx), this->rgb_table[1](coloridx), + this->rgb_table[2](coloridx), this->hsv_table[0](coloridx), + this->hsv_table[1](coloridx), this->hsv_table[2](coloridx)); + RGB2XYZ(this->rgb_table[0](coloridx), this->rgb_table[1](coloridx), + this->rgb_table[2](coloridx), this->xyz_table[0](coloridx), + this->xyz_table[1](coloridx), this->xyz_table[2](coloridx)); + XYZ2Lab(this->xyz_table[0](coloridx), this->xyz_table[1](coloridx), + this->xyz_table[2](coloridx), this->lab_table[0](coloridx), + this->lab_table[1](coloridx), this->lab_table[2](coloridx)); } return true; @@ -143,12 +160,12 @@ class colorset_optical_allowed : public colorset_optical_base { static constexpr uint16_t invalid_color_id = 0xFFFF; private: - Eigen::Array __color_id; + Eigen::Array color_id_; void resize(int new_color_count) { colorset_optical_base::resize(new_color_count); - __color_id.resize(new_color_count); - __color_id.fill(invalid_color_id); + color_id_.resize(new_color_count); + color_id_.fill(invalid_color_id); } public: @@ -179,12 +196,12 @@ class colorset_optical_allowed : public colorset_optical_base { } for (int c = 0; c < 3; c++) { - this->__rgb[c][writeidx] = src.RGB(readidx, c); - this->__hsv[c][writeidx] = src.HSV(readidx, c); - this->__lab[c][writeidx] = src.Lab(readidx, c); - this->__xyz[c][writeidx] = src.XYZ(readidx, c); + this->rgb_table[c][writeidx] = src.RGB(readidx, c); + this->hsv_table[c][writeidx] = src.HSV(readidx, c); + this->lab_table[c][writeidx] = src.Lab(readidx, c); + this->xyz_table[c][writeidx] = src.XYZ(readidx, c); } - __color_id[writeidx] = src.color_id(readidx); + color_id_[writeidx] = src.color_id(readidx); writeidx++; } @@ -193,8 +210,8 @@ class colorset_optical_allowed : public colorset_optical_base { } inline uint16_t color_id(uint16_t idx) const noexcept { - assert(idx < __color_id.size()); - return __color_id[idx]; + assert(idx < color_id_.size()); + return color_id_[idx]; } }; diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 66dd0d17..8031d11f 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -138,10 +138,10 @@ class ImageCvter : public GPU_wrapper_wrapper { inline const auto &color_hash() const noexcept { return color_hash_; } - void set_raw_image(const ARGB *const data, const int64_t _rows, - const int64_t _cols, + void set_raw_image(const ARGB *const data, const int64_t n_rows, + const int64_t n_cols, const bool is_col_major = true) noexcept { - if (_rows <= 0 || _cols <= 0) { + if (n_rows <= 0 || n_cols <= 0) { return; } if (data == nullptr) { @@ -150,13 +150,19 @@ class ImageCvter : public GPU_wrapper_wrapper { if (is_col_major) { Eigen::Map> - map(data, _rows, _cols); + map(data, n_rows, n_cols); this->raw_image_ = map; } else { Eigen::Map> - map(data, _rows, _cols); + map(data, n_rows, n_cols); this->raw_image_ = map; } + // filter full-transparent colors + // for (ARGB &color : this->raw_image_.) { + // if (getA(color) <= 0) { + // color = ARGB32(0, 0, 0, 0); + // } + // } } bool convert_image(::SCL_convertAlgo algo_, bool dither_, @@ -435,7 +441,7 @@ class ImageCvter : public GPU_wrapper_wrapper { for (auto &pair : this->color_hash_) { if (!pair.second.is_result_computed()) { - if ((pair.first._ARGB & 0xFF'00'00'00) == 0) { + if ((pair.first.ARGB_ & 0xFF'00'00'00) == 0) { pair.second.compute(pair.first, this->allowed_colorset); } else { tasks.emplace_back(&pair); diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 65cfd4e9..3bb46928 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -43,17 +43,17 @@ inline constexpr float threshold = 1e-10f; } // namespace struct convert_unit { convert_unit() = default; - explicit convert_unit(ARGB _a, ::SCL_convertAlgo _c) : _ARGB(_a), algo(_c) {} - ARGB _ARGB; + explicit convert_unit(ARGB a_, ::SCL_convertAlgo c_) : ARGB_(a_), algo(c_) {} + ARGB ARGB_; ::SCL_convertAlgo algo; inline bool operator==(const convert_unit another) const noexcept { - return (_ARGB == another._ARGB) && (algo == another.algo); + return (ARGB_ == another.ARGB_) && (algo == another.algo); } inline Eigen::Array3f to_c3() const noexcept { Eigen::Array3f c3; - const ::ARGB rawColor = this->_ARGB; + const ::ARGB rawColor = this->ARGB_; switch (this->algo) { case ::SCL_convertAlgo::RGB: case ::SCL_convertAlgo::RGB_Better: @@ -84,18 +84,18 @@ struct convert_unit { template void save(archive &ar) const { - ar(this->_ARGB, this->algo); + ar(this->ARGB_, this->algo); } template void load(archive &ar) { - ar(this->_ARGB, this->algo); + ar(this->ARGB_, this->algo); } }; struct hash_cvt_unit { public: inline size_t operator()(const convert_unit cu) const noexcept { - return std::hash()(cu._ARGB) ^ + return std::hash()(cu.ARGB_) ^ std::hash()(uint8_t(cu.algo)); } }; @@ -138,7 +138,7 @@ class newTokiColor } auto compute(convert_unit cu, const allowed_t &allowed) noexcept { - if (getA(cu._ARGB) == 0) { + if (getA(cu.ARGB_) == 0) { if constexpr (is_not_optical) { this->Result = 0; return this->Result; @@ -175,7 +175,6 @@ class newTokiColor default: abort(); - return result_t(0); } } From 971b3668cbe4f323b7cd815b00ad93e356db9c08 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:09:56 +0800 Subject: [PATCH 1020/1123] Update version number to 5.3.1 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1637a062..b741072d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.3.0) +set(SlopeCraft_version 5.3.1) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From cfc6e2f647953e933ff3206c62ec52277fe33fe1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:15:11 +0800 Subject: [PATCH 1021/1123] Fix manually searching for zstd Signed-off-by: ToKiNoBug --- cmake/required_deps/zstd.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/zstd.cmake b/cmake/required_deps/zstd.cmake index 5c22e941..ac459ba5 100644 --- a/cmake/required_deps/zstd.cmake +++ b/cmake/required_deps/zstd.cmake @@ -26,7 +26,7 @@ if (NOT ZSTD_FOUND) find_file(zstd_header_loc NAMES zstd.h HINTS "/usr/lib/include/zstd.h") if (zstd_header_loc) - cmake_path(GET zstd_include_dir PARENT_PATH zstd_header_loc) + cmake_path(GET zstd_header_loc PARENT_PATH zstd_include_dir) target_include_directories(zstd_manually_imported INTERFACE ${zstd_include_dir}) endif () # cmake_path(GET zstd_lib_loc PARENT_PATH zstd_install_dir) From a8a2331c813d3ab86716b7b877ca1e1fa25f866f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:27:51 +0800 Subject: [PATCH 1022/1123] Fix windows build for VC Signed-off-by: ToKiNoBug --- VisualCraftL/BlockStateList.cpp | 2 +- VisualCraftL/TokiVC_export_test.cpp | 4 ++-- VisualCraftL/VisualCraftL.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index 7ce0bade..bc6be30e 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include "ParseResourcePack.h" #include "VCL_internal.h" -#include +#include VCL_block::VCL_block() { this->initialize_attributes(); } diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index cfa96f96..02efacd8 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -20,11 +20,11 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ +#include +#include #include "TokiVC.h" #include "VCL_internal.h" #include "VisualCraftL.h" -#include -#include const VCL_block *find_first_mark_block( const std::unordered_map diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index d37a24ea..f8ed00de 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1182,7 +1182,7 @@ VCL_EXPORT_FUN VCL_biome_info VCL_get_biome_info(VCL_biome_t biome) { return VCL_biome_info{NAN, NAN}; } -#include +#include const char *VCL_biome_name_ZH(VCL_biome_t b) noexcept { switch (b) { From 04fce2d32f20be0780eaa279d2f91c34f7049168 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 12:28:06 +0800 Subject: [PATCH 1023/1123] Try to fix mac build Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 3 ++- utilities/Schem/Schem.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index fb9cded2..509f875a 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,6 +14,8 @@ add_library(Schem item.cpp item.h ) +target_compile_features(Schem PUBLIC cxx_std_23) + find_package(Eigen3 REQUIRED) find_package(cereal REQUIRED) @@ -34,7 +36,6 @@ target_link_libraries(Schem PUBLIC if (TARGET Boost::multi_array) target_link_libraries(Schem PUBLIC Boost::multi_array) endif () -target_compile_features(Schem PUBLIC cxx_std_23) target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) if (CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 41cde7a1..faa3663d 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -20,10 +20,10 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ +#include #include #include #include -#include #include #include #include From b3f10e874ab0d7d21919e33443e1696fc0a133da Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:44:25 +0800 Subject: [PATCH 1024/1123] Use gcc 14 instead of 12 in linux build Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index d758a95b..9ba0d7f1 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -35,7 +35,7 @@ jobs: - name: Install dependencies run: - sudo apt install zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libboost-tools-dev libboost-doc libexpected-dev p7zip-full + sudo apt install gcc-14 g++-14 zstd libzstd-dev xz-utils bzip2 libzip-dev zipcmp ziptool zipmerge libpng-dev libeigen3-dev libboost-all-dev libboost-tools-dev libboost-doc libexpected-dev p7zip-full - name: Install xsimd run: | @@ -81,7 +81,7 @@ jobs: uses: actions/checkout@v4 - name: CMake configure - run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-12 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-12 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-14 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-14 -DCMAKE_INSTALL_PREFIX:PATH=./install -DSlopeCraft_GPU_API:STRING=$GPU_API -DCMAKE_BUILD_TYPE:STRING=$BUILD_TYPE -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: CMake build run: cmake --build ./build --parallel From 58548b3cfe38a1cbc22df3812f289b56afe5d96e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:49:34 +0800 Subject: [PATCH 1025/1123] Remove use of std::views::enumerate to support clang19+libc++ Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index faa3663d..6af8df2c 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -191,8 +191,8 @@ Schem::split_by_block_size( this->z_range()}; for (size_t dim = 0; dim < 3; dim++) { int64_t cur_block_start_index = 0; - for (auto [blk_idx, block_len] : - xyz_block_len[dim] | std::views::enumerate) { + for (size_t blk_idx = 0; blk_idx < xyz_block_len[dim].size(); blk_idx++) { + const auto block_len = xyz_block_len[dim][blk_idx]; if (block_len <= 0) { return tl::make_unexpected(fmt::format( "Found non-positive block length in dim = {}, block index = {}", @@ -220,12 +220,12 @@ Schem::split_by_block_size( [xyz_block_index_pairs[1].size()] [xyz_block_index_pairs[2].size()]}; - for (auto [x_idx, x_range] : - xyz_block_index_pairs[0] | std::views::enumerate) { - for (auto [y_idx, y_range] : - xyz_block_index_pairs[1] | std::views::enumerate) { - for (auto [z_idx, z_range] : - xyz_block_index_pairs[2] | std::views::enumerate) { + for (size_t x_idx = 0; x_idx < xyz_block_index_pairs[0].size(); x_idx++) { + const auto x_range = xyz_block_index_pairs[0][x_idx]; + for (size_t y_idx = 0; y_idx < xyz_block_index_pairs[1].size(); y_idx++) { + const auto y_range = xyz_block_index_pairs[1][y_idx]; + for (size_t z_idx = 0; z_idx < xyz_block_index_pairs[2].size(); z_idx++) { + const auto z_range = xyz_block_index_pairs[2][z_idx]; const Eigen::Array offset{x_range.first, y_range.first, z_range.first}; auto &dest = ret[x_idx][y_idx][z_idx]; From 9d10ab122d3e52d1712139f888f03604d74a25b5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:49:48 +0800 Subject: [PATCH 1026/1123] Fix vccl including magic_enum Signed-off-by: ToKiNoBug --- vccl/vccl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 6f80d992..5ace058f 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -26,7 +26,7 @@ This file is part of SlopeCraft. #include "vccl_internal.h" #include #include -#include +#include #include #include From ad113ec3ba85e599538ee1b860f658ec3c82a2e4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:56:28 +0800 Subject: [PATCH 1027/1123] Try to fix mac build Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 6af8df2c..83847e33 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,7 +47,12 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } - this->xzy.resize(x, z, y); + this->xzy.resize({x, z, y}); + // #ifdef __APPLE__ + // this->xzy.resize({x, z, y}); + // #else + // this->xzy.resize(x, z, y); + // #endif } std::string Schem::check_size() const noexcept { From 220a1c7527412c17c068fabbfd02ae3d2798f20f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:58:16 +0800 Subject: [PATCH 1028/1123] Fix including magic_enum Signed-off-by: ToKiNoBug --- VisualCraft/BiomeBrowser.cpp | 2 +- VisualCraft/BlockBrowser.cpp | 2 +- VisualCraft/BlockSelectorCriteria.cpp | 2 +- VisualCraft/VCWind.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VisualCraft/BiomeBrowser.cpp b/VisualCraft/BiomeBrowser.cpp index f3bbc11b..febc9fb4 100644 --- a/VisualCraft/BiomeBrowser.cpp +++ b/VisualCraft/BiomeBrowser.cpp @@ -26,7 +26,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include BiomeBrowser::BiomeBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::BiomeBrowser) { diff --git a/VisualCraft/BlockBrowser.cpp b/VisualCraft/BlockBrowser.cpp index 9ed0b7dd..01b99745 100644 --- a/VisualCraft/BlockBrowser.cpp +++ b/VisualCraft/BlockBrowser.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include BlockBrowser::BlockBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::BlockBrowser) { diff --git a/VisualCraft/BlockSelectorCriteria.cpp b/VisualCraft/BlockSelectorCriteria.cpp index dc06b64d..ef51bb55 100644 --- a/VisualCraft/BlockSelectorCriteria.cpp +++ b/VisualCraft/BlockSelectorCriteria.cpp @@ -22,7 +22,7 @@ This file is part of SlopeCraft. #include "BlockSelector.h" #include "ui_BlockSelectorCriteria.h" -#include +#include BlockSelectorCriteria::BlockSelectorCriteria(QWidget *parent) : QWidget(parent), ui(new Ui::BlockSelectorCriteria) { diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 76999465..43b25c2e 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include #include #include "VC_block_class.h" #include "ui_VCWind.h" From 6032bcbaeab5264db7aa00beb04f5c7ed6be79e3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 13:59:37 +0800 Subject: [PATCH 1029/1123] Disable vulkan backend for macos temporarily Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 4 +++- .github/workflows/macos-build-x64.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 24e336a3..25281c7e 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -12,7 +12,9 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, Vulkan ] + gpu_api: [ None, + # Vulkan + ] env: BUILD_TYPE: ${{ matrix.build_type }} GPU_API: ${{ matrix.gpu_api }} diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index a8df681a..e4ec9344 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -12,7 +12,9 @@ jobs: strategy: matrix: build_type: [ Debug, Release ] - gpu_api: [ None, Vulkan ] + gpu_api: [ None, + # Vulkan + ] vectorize: [ ON, OFF ] env: BUILD_TYPE: ${{ matrix.build_type }} From 086af543ed275e00cd25ef0b7462b0d4da115171 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:03:32 +0800 Subject: [PATCH 1030/1123] Fix Schem::resize Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 83847e33..844899f9 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,12 +47,11 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } +#ifdef __APPLE__ this->xzy.resize({x, z, y}); - // #ifdef __APPLE__ - // this->xzy.resize({x, z, y}); - // #else - // this->xzy.resize(x, z, y); - // #endif +#else + this->xzy.resize(x, z, y); +#endif } std::string Schem::check_size() const noexcept { From 7dfa49c129b32484fdb5f313802dda7ce34e3a80 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:07:43 +0800 Subject: [PATCH 1031/1123] Try to fix Eigen tensor issues around libScheme Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 509f875a..5275eadd 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(Schem item.cpp item.h ) -target_compile_features(Schem PUBLIC cxx_std_23) +target_compile_features(Schem PUBLIC cxx_std_17) find_package(Eigen3 REQUIRED) From 0ed186bac3ce399e3dbca477a4ab7cfe52f29199 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:12:33 +0800 Subject: [PATCH 1032/1123] Try to fix Eigen tensor issues around libScheme Signed-off-by: ToKiNoBug --- utilities/Schem/CMakeLists.txt | 2 +- utilities/Schem/Schem.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 5275eadd..f7383856 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(Schem item.cpp item.h ) -target_compile_features(Schem PUBLIC cxx_std_17) +target_compile_features(Schem PUBLIC cxx_std_14) find_package(Eigen3 REQUIRED) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 844899f9..6af8df2c 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -47,11 +47,7 @@ void Schem::resize(int64_t x, int64_t y, int64_t z) { if (x < 0 || y < 0 || z < 0) { return; } -#ifdef __APPLE__ - this->xzy.resize({x, z, y}); -#else this->xzy.resize(x, z, y); -#endif } std::string Schem::check_size() const noexcept { From f46260fca1db85ab5bc9335ad97d8d6e8e66732d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:32:39 +0800 Subject: [PATCH 1033/1123] Try to fix libSchem on macos Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 4 +++- utilities/Schem/bit_shrink.cpp | 11 +---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 6af8df2c..1b39f1e4 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -162,7 +162,9 @@ Schem Schem::slice_no_check(std::span, 3> extent[0] = xyz_index_range[0].second - xyz_index_range[0].first; extent[1] = xyz_index_range[2].second - xyz_index_range[2].first; extent[2] = xyz_index_range[1].second - xyz_index_range[1].first; - ret.xzy = this->xzy.slice(start, extent); + // avoid Tensor::resize which is problematic on mac + decltype(ret.xzy) temp{this->xzy.slice(start, extent)}; + ret.xzy = std::move(temp); } for (auto &entity : this->entities) { diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index d929a9d9..f884b8b4 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -156,19 +156,10 @@ bool process_block_id( void shrink_bytes_weSchem(std::span src, const int palette_max, std::vector *const dest) noexcept { - // if (palette_max <= 128) { - // dest->resize(src.size()); - // for (size_t idx = 0; idx < src.size(); idx++) { - // dest->at(idx) = src[idx] & 0xFF; - // } - // return; - //} - dest->reserve(src.size() * 2); dest->clear(); - for (size_t idx = 0; idx < src.size(); idx++) { - uint16_t temp = src[idx]; + for (const uint16_t temp : src) { if (temp < 128) { dest->emplace_back(temp); } else { From 185bc39b5189e383014c0042cc00b08aae71b6ac Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 14:38:46 +0800 Subject: [PATCH 1034/1123] Try to fix libSchem on macos Signed-off-by: ToKiNoBug --- utilities/Schem/Schem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 1b39f1e4..5fdbcde0 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -155,7 +155,7 @@ Schem Schem::slice_no_check(std::span, 3> pos_max[dim] = xyz_index_range[dim].second; } { - Eigen::array start, extent; + Eigen::array start, extent; start[0] = xyz_index_range[0].first; start[1] = xyz_index_range[2].first; start[2] = xyz_index_range[1].first; From 3b1f94b448e3d83ac904c1ade087e1133639143e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 15:00:17 +0800 Subject: [PATCH 1035/1123] activate vulkan support for macos CI Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 25281c7e..ac3159da 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -13,7 +13,7 @@ jobs: matrix: build_type: [ Debug, Release ] gpu_api: [ None, - # Vulkan + Vulkan ] env: BUILD_TYPE: ${{ matrix.build_type }} diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index e4ec9344..51eaf19c 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -13,7 +13,7 @@ jobs: matrix: build_type: [ Debug, Release ] gpu_api: [ None, - # Vulkan + Vulkan ] vectorize: [ ON, OFF ] env: From c2a100cee60a8cc8b671f0738b0a3fb2a81256e3 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 15:08:53 +0800 Subject: [PATCH 1036/1123] Revert "activate vulkan support for macos CI" This reverts commit 3b1f94b448e3d83ac904c1ade087e1133639143e. --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index ac3159da..25281c7e 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -13,7 +13,7 @@ jobs: matrix: build_type: [ Debug, Release ] gpu_api: [ None, - Vulkan + # Vulkan ] env: BUILD_TYPE: ${{ matrix.build_type }} diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 51eaf19c..e4ec9344 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -13,7 +13,7 @@ jobs: matrix: build_type: [ Debug, Release ] gpu_api: [ None, - Vulkan + # Vulkan ] vectorize: [ ON, OFF ] env: From 22d8835dfb34edf7ac272f47e68194ec5cb1b3ee Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 15:13:12 +0800 Subject: [PATCH 1037/1123] Fix BlockListManager Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BlockListManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 633d6aac..aedb5d22 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -63,7 +63,7 @@ uint64_t std::hash::operator()(const selection &s) const noexcept { // } std::unique_ptr -BlockListManager::impl_addblocklist(const char *filename) noexcept { +BlockListManager::impl_addblocklist(const QByteArray &file_content) noexcept { std::string errmsg; errmsg.resize(8192); auto sd_err = SlopeCraft::string_deliver::from_string(errmsg); @@ -73,7 +73,8 @@ BlockListManager::impl_addblocklist(const char *filename) noexcept { SlopeCraft::block_list_create_info option{SC_VERSION_U64, &sd_warn, &sd_err}; SlopeCraft::block_list_interface *bli = - SlopeCraft::SCL_create_block_list(filename, option); + SlopeCraft::SCL_create_block_list_from_buffer( + file_content.data(), file_content.size(), option); errmsg.resize(sd_err.size); warning.resize(sd_warn.size); From d734adbf596897f092d8accde348918d497ba996 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 15:49:02 +0800 Subject: [PATCH 1038/1123] Update to 1.21.5 Signed-off-by: ToKiNoBug --- VisualCraft/vc-config.json | 2 +- cmake/required_deps/vanilla_zips.cmake | 2 +- vccl/vccl-config.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VisualCraft/vc-config.json b/VisualCraft/vc-config.json index 07599109..ff343083 100644 --- a/VisualCraft/vc-config.json +++ b/VisualCraft/vc-config.json @@ -38,7 +38,7 @@ ], [ 21, - "./Blocks_VCL/Vanilla_1_21_1.zip" + "./Blocks_VCL/Vanilla_1_21_5.zip" ] ], "default_block_state_list": [ diff --git a/cmake/required_deps/vanilla_zips.cmake b/cmake/required_deps/vanilla_zips.cmake index 2b942ea5..82275662 100644 --- a/cmake/required_deps/vanilla_zips.cmake +++ b/cmake/required_deps/vanilla_zips.cmake @@ -8,7 +8,7 @@ set(VCL_zip_names "Vanilla_1_18_2.zip" "Vanilla_1_19_3.zip" "Vanilla_1_20_6.zip" - "Vanilla_1_21_1.zip" + "Vanilla_1_21_5.zip" ) #https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/Vanilla_1_20_1.zip set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") diff --git a/vccl/vccl-config.json b/vccl/vccl-config.json index 07599109..ff343083 100644 --- a/vccl/vccl-config.json +++ b/vccl/vccl-config.json @@ -38,7 +38,7 @@ ], [ 21, - "./Blocks_VCL/Vanilla_1_21_1.zip" + "./Blocks_VCL/Vanilla_1_21_5.zip" ] ], "default_block_state_list": [ From d6646aee90ab330ffc533b1c666df7e6209872f4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:11:16 +0800 Subject: [PATCH 1039/1123] Fix reading zips in SC Signed-off-by: ToKiNoBug --- SlopeCraftL/block_list.cpp | 5 +-- .../BlockListManager/BlockListManager.cpp | 36 ++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp index f1ea8369..b6cdbc60 100644 --- a/SlopeCraftL/block_list.cpp +++ b/SlopeCraftL/block_list.cpp @@ -329,8 +329,9 @@ block_list_create_result create_block_list_from_buffer( zip_open_from_source(source, ZIP_RDONLY | ZIP_CHECKCONS, &err)}; if (archive == nullptr) { zip_source_free(source); - return {tl::make_unexpected(fmt::format("Failed to open zip: {}", - zip_error_strerror(&err))), + return {tl::make_unexpected( + fmt::format("Failed to open zip, zip_err = {}, sys_err = {}", + err.zip_err, err.sys_err)), {}}; } diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index aedb5d22..70989493 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -124,17 +124,35 @@ bool BlockListManager::add_blocklist(QString filename) noexcept { } } // Test for multiple encodings - for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { - std::unique_ptr tmp = - this->impl_addblocklist(encoding.data()); - if (not tmp) { - continue; - } - - this->blockslists.emplace_back(name, std::move(tmp)); - return true; + QFile archive{filename}; + if (not archive.open(QIODevice::OpenModeFlag::ExistingOnly | + QIODevice::OpenModeFlag::ReadOnly)) { + QMessageBox::warning(this, tr("无法加载方块列表"), + tr("无法读取文件 %1 ,它可能被误删。").arg(filename)); + return false; } + auto file_content = archive.readAll(); + std::unique_ptr tmp = + this->impl_addblocklist(file_content); + if (not tmp) { + return false; + } + this->blockslists.emplace_back(name, std::move(tmp)); + return true; + + // for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { + // std::unique_ptr tmp + // = + // this->impl_addblocklist(encoding.data()); + // + // if (not tmp) { + // continue; + // } + // + // this->blockslists.emplace_back(name, std::move(tmp)); + // return true; + // } return false; } From e3480e2bb9e0dd6a291a6b4c770d11ff315e9da5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:14:45 +0800 Subject: [PATCH 1040/1123] Update translations Signed-off-by: ToKiNoBug --- .../others/BlockListManager_en_US.ts | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index 9d48eb00..c28a4f78 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -17,44 +17,50 @@ BlockListManager - + 解析方块列表失败 Failed to parse block list - + 解析方块列表成功,但出现警告 Block list parsed with warnings - + + 无法加载方块列表 Failed to parse block list - + 名为 %1 的方块列表已经加载,不允许加载同名的方块列表。 Block list named %1 was already loaded, and it's not allowed to load multiple block list with identity name. - + + 无法读取文件 %1 ,它可能被误删。 + Unable to read zip archive "%1", it might be deleted accidentally. + + + 无法删除方块列表 "%1",没有加载同名的方块列表。已加载:%2 Failed to load block list \"%1\", no block list for such name. Loaded: %2 - - + + 加载预设错误 Failed to load preset - + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors - + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id From 43ea07e75daa39e4caea44088db1fbc0c6b12b02 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:32:39 +0800 Subject: [PATCH 1041/1123] Use clang 20.1.3 for windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 725a2c3a..c38b94d4 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -60,9 +60,17 @@ jobs: - name: make dirs run: | mkdir bin + mkdir bin/llvm mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty + - name: Download and extract llvm 20.1.3 + shell: pwsh + run: | + cd bin + curl -o LLVM-20.1.3-win64.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe + 7z x ./LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' + - name: Install winget if: matrix.gpu_api == 'Vulkan' shell: pwsh @@ -120,7 +128,7 @@ jobs: mkdir build mkdir install set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=clang-cl -DCMAKE_RC_COMPILER:FILEPATH=llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_RC_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # - name: CMake build shell: cmd From c063f1e02c9bf45423d0d0e41aff5edcf3a3cfb5 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:41:54 +0800 Subject: [PATCH 1042/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c38b94d4..caaf488a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -29,6 +29,13 @@ jobs: echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" + - name: Download and extract llvm 20.1.3 + shell: pwsh + run: | + cd bin + curl -o LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" + 7z x ./LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' + - name: Install ninja shell: cmd run: | @@ -64,13 +71,6 @@ jobs: mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty - - name: Download and extract llvm 20.1.3 - shell: pwsh - run: | - cd bin - curl -o LLVM-20.1.3-win64.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe - 7z x ./LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' - - name: Install winget if: matrix.gpu_api == 'Vulkan' shell: pwsh @@ -127,7 +127,7 @@ jobs: run: | mkdir build mkdir install - set PATH=C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps + set PATH=D:\a\SlopeCraft\SlopeCraft\bin\llvm\bin;C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_RC_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # - name: CMake build @@ -240,7 +240,7 @@ jobs: curl -JL -o C:/vcpkg/downloads/tukaani-project-xz-v5.4.4.tar.gz "https://github.com/xz-mirror/xz/archive/refs/tags/v5.4.4.tar.gz" cd C:/vcpkg git pull - vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected magic-enum + vcpkg install --triplet=x64-mingw-dynamic zlib bzip2 zstd liblzma libpng libzip eigen3 xsimd boost-iostreams boost-uuid boost-multi-array tl-expected magic-enum fmt cereal - name: Install OpenCL with vcpkg From 97c1aeb8d0cf4532fde77ada7d5448a06db05a6a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:42:57 +0800 Subject: [PATCH 1043/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index caaf488a..f7d55d6d 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -28,6 +28,13 @@ jobs: run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" + + - name: make dirs + run: | + mkdir bin + mkdir bin/llvm + mkdir bin/Qt6.5.0-msvc-shared + mkdir 3rdParty - name: Download and extract llvm 20.1.3 shell: pwsh @@ -64,12 +71,6 @@ jobs: echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - name: make dirs - run: | - mkdir bin - mkdir bin/llvm - mkdir bin/Qt6.5.0-msvc-shared - mkdir 3rdParty - name: Install winget if: matrix.gpu_api == 'Vulkan' From af435b177854e2e225ee5fcd3a95bad35955ac66 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:45:41 +0800 Subject: [PATCH 1044/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index f7d55d6d..678867b2 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - bugfix/windows-CI jobs: msvc: @@ -28,7 +29,7 @@ jobs: run: | echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" - + - name: make dirs run: | mkdir bin @@ -40,7 +41,7 @@ jobs: shell: pwsh run: | cd bin - curl -o LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" + wget "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" 7z x ./LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' - name: Install ninja From a001c8c553f5a54efbd4326901a712d30949e70f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:47:17 +0800 Subject: [PATCH 1045/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 678867b2..e832b5eb 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -38,11 +38,12 @@ jobs: mkdir 3rdParty - name: Download and extract llvm 20.1.3 - shell: pwsh + shell: cmd run: | cd bin - wget "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" - 7z x ./LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' + curl -JL -o .\LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" + 7z x .\LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' + .\llvm\bin\clang-cl --version - name: Install ninja shell: cmd From 4c1ed8c9f8b6ae081fd03c45173ecc3832ca306b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 16:50:16 +0800 Subject: [PATCH 1046/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index e832b5eb..01f39331 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -42,7 +42,7 @@ jobs: run: | cd bin curl -JL -o .\LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" - 7z x .\LLVM-20.1.3-win64.exe -ollvm '-xr!$PLUGINSDIR' + 7z x .\LLVM-20.1.3-win64.exe -ollvm "-xr!$PLUGINSDIR" .\llvm\bin\clang-cl --version - name: Install ninja From 9ad4891490346120dd13c191d70b016083fab320 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 17:02:46 +0800 Subject: [PATCH 1047/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 01f39331..fbecb76c 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -131,7 +131,7 @@ jobs: mkdir build mkdir install set PATH=D:\a\SlopeCraft\SlopeCraft\bin\llvm\bin;C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_CXX_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl -DCMAKE_RC_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe -DCMAKE_CXX_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe -DCMAKE_RC_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc.exe -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # - name: CMake build shell: cmd From 2be34bc823f4f272862487c0da17503309b44de6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 17:20:38 +0800 Subject: [PATCH 1048/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index fbecb76c..3b8b50c1 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -131,7 +131,7 @@ jobs: mkdir build mkdir install set PATH=D:\a\SlopeCraft\SlopeCraft\bin\llvm\bin;C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe -DCMAKE_CXX_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe -DCMAKE_RC_COMPILER:FILEPATH=D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc.exe -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe" -DCMAKE_RC_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc.exe" -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # - name: CMake build shell: cmd From a710c505d7f4720a2abec24e05832f504fb6183c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 18:17:00 +0800 Subject: [PATCH 1049/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 3b8b50c1..6559082e 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -37,14 +37,6 @@ jobs: mkdir bin/Qt6.5.0-msvc-shared mkdir 3rdParty - - name: Download and extract llvm 20.1.3 - shell: cmd - run: | - cd bin - curl -JL -o .\LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" - 7z x .\LLVM-20.1.3-win64.exe -ollvm "-xr!$PLUGINSDIR" - .\llvm\bin\clang-cl --version - - name: Install ninja shell: cmd run: | @@ -102,7 +94,7 @@ jobs: curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-msvc-windows/Qt6.5.0-msvc-shared.7z" 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z exit - tree /f bin/Qt6.5.0-msvc-shared + tree /f bin # Qt installation dir: bin/Qt6.5.0-msvc-shared # - name: Configure libnbt++ @@ -125,6 +117,14 @@ jobs: # cd .. # tree /f libnbt++ + - name: Download and extract llvm 20.1.3 + shell: cmd + run: | + cd bin + curl -JL -o .\LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" + 7z x .\LLVM-20.1.3-win64.exe -ollvm "-xr!$PLUGINSDIR" + .\llvm\bin\clang-cl --version + - name: CMake configure shell: cmd run: | From de2c870a60020971b4ba1c42797dd5de48852c23 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 18:26:01 +0800 Subject: [PATCH 1050/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 6559082e..546f5c71 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -89,13 +89,10 @@ jobs: # tree /f "C:\Program Files\VulkanSDK" - name: Download Qt6.5.0-msvc-shared and extract + shell: cmd run: | - cmd curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-msvc-windows/Qt6.5.0-msvc-shared.7z" 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z - exit - tree /f bin - # Qt installation dir: bin/Qt6.5.0-msvc-shared # - name: Configure libnbt++ # shell: cmd @@ -120,11 +117,13 @@ jobs: - name: Download and extract llvm 20.1.3 shell: cmd run: | - cd bin + cd /d bin curl -JL -o .\LLVM-20.1.3-win64.exe "https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-win64.exe" 7z x .\LLVM-20.1.3-win64.exe -ollvm "-xr!$PLUGINSDIR" .\llvm\bin\clang-cl --version - + cd .. + tree /f bin + - name: CMake configure shell: cmd run: | From 50013bd481b0c6e3e5648a32273808cae9866f02 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 19:02:38 +0800 Subject: [PATCH 1051/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 546f5c71..db3b81b3 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -91,8 +91,9 @@ jobs: - name: Download Qt6.5.0-msvc-shared and extract shell: cmd run: | - curl -JL -o bin/Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-msvc-windows/Qt6.5.0-msvc-shared.7z" - 7z x -o"bin/Qt6.5.0-msvc-shared" bin/Qt6.5.0-msvc-shared.7z + cd bin + curl -JL -o .\Qt6.5.0-msvc-shared.7z "https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.5.0-x86_64-msvc-windows/Qt6.5.0-msvc-shared.7z" + 7z x -oQt6.5.0-msvc-shared .\Qt6.5.0-msvc-shared.7z # - name: Configure libnbt++ # shell: cmd From 6c66d2ba5e95fc9262872f3a89568d69bc391223 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 21:02:31 +0800 Subject: [PATCH 1052/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index db3b81b3..d643757c 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -30,13 +30,6 @@ jobs: echo "env:BUILD_TYPE = $env:BUILD_TYPE" echo "env:GPU_API = $env:GPU_API" - - name: make dirs - run: | - mkdir bin - mkdir bin/llvm - mkdir bin/Qt6.5.0-msvc-shared - mkdir 3rdParty - - name: Install ninja shell: cmd run: | @@ -58,6 +51,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: make dirs + run: | + mkdir bin + mkdir bin/llvm + mkdir bin/Qt6.5.0-msvc-shared + mkdir 3rdParty + - name: Get short SHA run: | echo "GITHUB_SHA = $env:GITHUB_SHA" From 53ad75f72b51bcbc922272d623d22cbf37693508 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 21 Apr 2025 22:57:38 +0800 Subject: [PATCH 1053/1123] Fix windows CI Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index d643757c..4a00fa4f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -123,13 +123,14 @@ jobs: 7z x .\LLVM-20.1.3-win64.exe -ollvm "-xr!$PLUGINSDIR" .\llvm\bin\clang-cl --version cd .. - tree /f bin + tree /f D:\a\SlopeCraft\SlopeCraft\bin\llvm - name: CMake configure shell: cmd run: | mkdir build mkdir install + .\bin\llvm\bin\clang-cl --version set PATH=D:\a\SlopeCraft\SlopeCraft\bin\llvm\bin;C:\Program Files\VulkanSDK\1.3.250.1\Bin;C:\Program Files\PowerShell\7;C:\vcpkg;C:\Program Files (x86)\NSIS\;C:\Program Files\dotnet;C:\Program Files (x86)\GitHub CLI;C:\Program Files\Git\bin;C:\Program Files\OpenSSL\bin;C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\wbin;C:\Program Files\Microsoft\jdk-11.0.16.101-hotspot\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\dotnet\;C:\Program Files\PowerShell\7\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files\CMake\bin;C:\Program Files\Microsoft SDKs\Service Fabric\Tools\ServiceFabricLocalClusterManager;C:\Program Files\Git\cmd;C:\Program Files\GitHub CLI\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\LLVM\bin;C:\Users\runneradmin\.dotnet\tools;C:\Users\runneradmin\.cargo\bin;C:\Users\runneradmin\AppData\Local\Microsoft\WindowsApps "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" & cmake -S . -B ./build -G Ninja -DCMAKE_C_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/clang-cl.exe" -DCMAKE_RC_COMPILER:FILEPATH="D:/a/SlopeCraft/SlopeCraft/bin/llvm/bin/llvm-rc.exe" -DCMAKE_PREFIX_PATH:PATH="D:/a/SlopeCraft/SlopeCraft/bin/Qt6.5.0-msvc-shared;C:/vcpkg/installed/x64-windows/;D:/a/SlopeCraft/SlopeCraft/3rdParty/libnbt++;C:/Program Files/VulkanSDK/1.3.250.1" -DCMAKE_INSTALL_PREFIX:PATH=D:/a/SlopeCraft/SlopeCraft/install -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" -DSlopeCraft_GPU_API:STRING="${{ matrix.gpu_api }}" -DSlopeCraft_vectorize:BOOL="${{ matrix.vectorize }}" -DSlopeCraft_windeployqt_flags_install:STRING=-release;--no-translations # From f5d29fa2e07bd8671e2fb5c71a51444789a984fb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 24 Apr 2025 11:24:00 +0800 Subject: [PATCH 1054/1123] Update todo Signed-off-by: ToKiNoBug --- docs/TODO.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index 29da804a..4ba88c2a 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -3,10 +3,11 @@ - ~~继续改进抖动算法~~(感觉没什么可改的了) - ~~有损压缩立体地图画的高度~~(已经实现) - ~~边缘识别 - 填充算法,考虑用遗传算法修补边缘识别结果,确保边缘绝对完整。~~(已实现) - - ~~如果成功了,那也许是第一个使用了人工智能的地图画生成器,哈哈~~(已经实现,虽然不是这个功能) + - ~~如果成功了,那也许是第一个使用了人工智能的地图画生成器,哈哈~~(已经实现,虽然不是这个功能) - ~~允许玩家旋转平板地图画(特别是垂直方向的旋转)~~(已经实现,叫做墙面像素画) - ~~跟进 Minecraft 1.18~~ -- 跟进 Minecraft 1.20 +- ~~跟进 Minecraft 1.20~~ +- 跟进 Minecraft 1.22 - 调整颜色后,允许玩家精修像素的颜色 - ~~可以考虑一下对基岩版的支持~~(原理不同,支持不了) - 想办法将颜色调整模块分离出来,为基岩版编写新的 SlopeCraftL.dll,尽量复用核心代码和界面代码 @@ -15,15 +16,15 @@ - ~~自定义添加新的方块~~(已经实现) - ~~修整代码风格~~(已经实现) - ~~导出原版结构方块格式的文件~~(已经实现) - - 方便 forge 端 + - 方便 forge 端 - 导出为 WorldEdit 的 schem 文件 - - 同样方便 Forge 端 + - 同样方便 Forge 端 - ~~在可燃方块周围添加玻璃方块,防止着火~~(已经实现) - - ~~也许可以用类似的方式防止末影人偷方块~~ + - ~~也许可以用类似的方式防止末影人偷方块~~ - 预览 - - 三维结构预览 - - ~~平面预览,显示每个顶端方块的材质和高度~~(已经实现) - - 应当支持分层和导出为图片 + - 三维结构预览 + - ~~平面预览,显示每个顶端方块的材质和高度~~(已经实现) + - 应当支持分层和导出为图片 - ~~批量处理~~(已实现) - - ~~批量生成纯文件地图画~~ + - ~~批量生成纯文件地图画~~ - 使用更先进的图像分割算法,提高调整颜色的能力 From acb5b99749d98851b5efd92abc8987f848f75ec7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 24 Apr 2025 11:25:36 +0800 Subject: [PATCH 1055/1123] Fix typo Signed-off-by: ToKiNoBug --- cmake/required_deps/magic_enum.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/magic_enum.cmake b/cmake/required_deps/magic_enum.cmake index b3cb587f..52c3eb21 100644 --- a/cmake/required_deps/magic_enum.cmake +++ b/cmake/required_deps/magic_enum.cmake @@ -19,6 +19,6 @@ FetchContent_Declare(magic_enum EXCLUDE_FROM_ALL ) -message(STATUS "Downaloding magic_enum......") +message(STATUS "Downloading magic_enum......") FetchContent_MakeAvailable(magic_enum) \ No newline at end of file From 908159f58124f77322877dd10851aceb29ebae4e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 24 Apr 2025 11:52:20 +0800 Subject: [PATCH 1056/1123] Support very long GPU error info Signed-off-by: ToKiNoBug --- VisualCraft/VCWind_gpu.cpp | 41 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index 7aa28b50..b0d1d7be 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -39,10 +39,10 @@ QString get_cpu_name(bool &error) noexcept { #elif defined(__linux__) const char *command = "sh -c \"cat /proc/cpuinfo | grep name\""; #elif defined(__APPLE__) - const char * command="sysctl machdep.cpu.brand_string"; + const char *command = "sysctl machdep.cpu.brand_string"; #else #warning Unknown OS - const char * command=nullptr; + const char *command = nullptr; return {}; #endif @@ -92,19 +92,19 @@ QString get_cpu_name(bool &error) noexcept { #elif defined(__APPLE__) output.remove('\n'); - auto split_out=output.split(':'); - if (split_out.size()<2) { + auto split_out = output.split(':'); + if (split_out.size() < 2) { return {}; } - if (split_out[0]!="machdep.cpu.brand_string") { + if (split_out[0] != "machdep.cpu.brand_string") { return {}; } - auto cpu_name=split_out[1]; + auto cpu_name = split_out[1]; cpu_name.remove('\t'); - while(cpu_name.front()==' ') { + while (cpu_name.front() == ' ') { cpu_name.removeFirst(); } - while(cpu_name.back()==' ') { + while (cpu_name.back() == ' ') { cpu_name.removeLast(); } #else @@ -229,17 +229,20 @@ void VCWind::on_combobox_select_device_currentIndexChanged(int idx) noexcept { const QString err = this->update_gpu_device(current_choice); - if (!err.isEmpty()) { - auto ret = QMessageBox::critical( - this, VCWind::tr("设置计算设备失败"), - tr("%1\n\n这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU " - "计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft") - .arg(err), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}); - if (ret == QMessageBox::StandardButton::Close) { - exit(1); - } + if (err.isEmpty()) { + return; + } + QMessageBox msg_box{this}; + msg_box.setStandardButtons(QMessageBox::StandardButtons{ + QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); + msg_box.setWindowTitle(VCWind::tr("设置计算设备失败")); + msg_box.setText( + tr("这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU " + "计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft")); + msg_box.setDetailedText(err); + auto ret = msg_box.exec(); + if (ret == QMessageBox::StandardButton::Close) { + exit(1); } } From d782b439b1b7f8e4db2507703c123d0684bc9c5a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 24 Apr 2025 11:54:07 +0800 Subject: [PATCH 1057/1123] update translations Signed-off-by: ToKiNoBug --- VisualCraft/others/VisualCraft_en_US.ts | 247 ++++++++++++------------ 1 file changed, 128 insertions(+), 119 deletions(-) diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 15efb5bb..54c6dc5c 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -212,28 +212,28 @@ If you select a block in "Avaliable blocks" page, the other page will block %1 - + 获取颜色表失败 Failed to retrive colorset - + 在尝试获取第%1个颜色(color_id = %2)时出现错误。函数VCL_get_basic_color_composition返回值为%3,正常情况下应当返回正数。 An error occurred when trying to get color %1 (color_id = %2). Function VCL_get_basic_color_composition returned %3, but a positive number is expected. - - + + 计算投影图像失败 Failed to compute projection image - + 在尝试获取方块 "%1" 的方块模型时出现错误。 An error occurred when trying to get block model for block "%1" (color_id = %2) - + 成功获取到方块 "%1" 的方块模型,但计算投影图像失败。 Managed to get a block model for block '%1", but subsequent computation of projection image failed. @@ -256,435 +256,435 @@ If you select a block in "Avaliable blocks" page, the other page will MC version - + 最大厚度: Max layers: - + 资源包 Resource packs - - + + 添加 Add - - + + 删除 Remove - + 方块id文件(json) Block state list files (json) - + 像素画方向 Pixel art direction - + 侧面(侧视) Side - + 上面(俯视) Up - + 下面(仰视) Down - + 树叶透明 Transparent leaves - + 方块列表 Blocks - - + + 全部方块 All blocks - + 快捷键 Hot keys - + 全部启用 Select all - + 全部禁用 Deselect all - + 高级匹配 Advanced - + 禁用罕见方块 Disable rare blocks - + 禁用不可再生 Disable non-reproducible - + 全部反选 Select reversely blockwise - + 按类反选 Select reversely classwise - + 预设 Presets - + 加载预设 Load preset - + 保存当前预设 Save current preset - + 选择图片 Select images - + 显示原始尺寸 Original size - + 调色算法 Convertion algorithm - + 抖动 Dithering - + 显示原图 Display original - + 显示转化后图像 Display converted - + 导出 Export - + 图像 Image - + 大小(行,列) Size (rows, cols) - + 生成litematica Litematica file - + 生成结构方块文件 Structure file - + 生成WE原理图 WE schem file - + 生成转化后图像 Converted image - + 生成平面示意图 Flat diagram - + 进度 Progress - + 导出类型 Export type - + litematic投影 Litematica - + 原版结构方块文件 Vanilla structure - + WorldEdit原理图 WorldEdit schematic - + 转化后图像 Converted image - + 平面示意图 Flat diagram - + 开始执行 Start - + 设置导出位置 Set export directory - + 平面示意图(*.png) Flat diagram(*.png) - + png压缩级别: png compress level: - - + + 方块 blocks - - + + 间距: margin: - + 垂直分隔线 Vertical split line - + 水平分隔线 Horizontal split line - + png压缩内存级别: png compress memory level: - + 联系开发者 Contact developer - + 关于VisualCraft About VisualCraft - + 反馈bug Report bugs - - + + Github仓库 Github repository - + bilibili ? bilibili - + 生成测试投影 Generate testing litematic - + 查看所有颜色 Browse all colors - + 查看可用颜色 Browse avaliable colors - + 检查更新 Check updates - + 刷新警告信息 Flush warnings - + 使用教程 Tutorial - + 原版结构方块文件(*.nbt) Vanilla structure(*.nbt) - + 用结构空位表示空气 Use structure void as air - + Litematica投影(*.litematic) Litematica file (*.litematic) - + 导出选项 Export options - + 区域名称 Region name - + 投影名称(非文件名) Schematic name(not file name) - + WorldEdit原理图(*.schem) (仅1.13+) WorldEdit schematic(*schem) (1.13+ only) - + 名称(非文件名) Name (not file name) - + 需要的mod名(一行一个,默认为空) Required mods (one mod in one line) - + 显卡设置 GPU settings - + 计算设置 Computation settings - + CPU线程数: CPU threads: - + 选择计算设备 Select compute device - + 测试 Test - + 查看 Browse - + 资源 Resources - + 关于 About - + 方块 Blocks - + 加载资源 Load resources - + 设置可用的方块 Set avaliable blocks - + 生物群系 Biomes @@ -716,18 +716,18 @@ If you select a block in "Avaliable blocks" page, the other page will Vanilla - + 选择资源包 Select resource pack - + 资源包解析失败 Failed to parse resource pack - - + + 在此窗口之前弹出的错误信息非常重要,请将它汇报给开发者。 Error messages shown before this window is really important. Report it to the deveploer. @@ -737,62 +737,67 @@ If you select a block in "Avaliable blocks" page, the other page will Vanilla - + + 无法读取文件 %1 + Unable to load file %1 + + + 选择方块 id json 文件 Select block id json file - + 方块状态列表 json 解析失败 Failed to parse block state json list - + 资源包/方块状态列表 json 解析失败 The resource pack or block list json failed to be parsed - + 部分方块的投影图像计算失败,或者总颜色数量超过上限(65534)。尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Failed to compute projection image for some blocks, or the total color amout exceeds the limit of 65534. You can try removing resource packs or block state list jsons that failed to be parsed, or reduce the max layers. - + 设置可用方块失败 Failed to set avaliable blocks - + 可能是总颜色数量超过上限(65536),尝试移除解析失败的资源包/方块列表,或者减小最大层数。 Probably the count of colors exceeds the upper bound(65536). Try removing some resource packs or jsons, or reduce the maximum layers. - + 调色算法 (共%1种颜色) Convert algorithms(%1 colors avaliable) - + 选择图片(可多选) Select images - + 读取图片失败 Failed to load image. - + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. - + 设置图片失败 Failed to set image - + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. @@ -858,33 +863,37 @@ If you select a block in "Avaliable blocks" page, the other page will Failed to retrieve device infomation, please check your deiver. OpenCL error code: %1 - + + 这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft + This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft + + %1 这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft - %1 + %1 This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - + 创建 GPU 平台失败,平台序号为%1,设备序号为%2 Failed to create GPU platform, Platform index = %1, device index = %2 - + 创建 GPU 设备失败,平台序号为%1,设备序号为%2 Failed to create GPU device, Platform index = %1, device index = %2 - + 设置 GPU 设备失败。平台序号为%1,设备序号为%2,详细错误信息: %3 Failed to set GPU device. Platform index = %1, device index = %2, detailed information: %3 - + 设置计算设备失败 Failed to set compute device From b4db609fa774fa1c6aed2602240b000f2180bf09 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 24 Apr 2025 13:16:59 +0800 Subject: [PATCH 1058/1123] Fix exporting schematic with very few types of block Signed-off-by: ToKiNoBug --- tests/test_libSchem/test_libSchem.cpp | 9 ++++----- utilities/Schem/bit_shrink.cpp | 12 +++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/test_libSchem/test_libSchem.cpp b/tests/test_libSchem/test_libSchem.cpp index a61bcf82..e4a00049 100644 --- a/tests/test_libSchem/test_libSchem.cpp +++ b/tests/test_libSchem/test_libSchem.cpp @@ -51,11 +51,10 @@ int main() { } ids[0] = "minecraft:air"; - ids.reserve(trash_id.size() + 1); - - while (ids.size() < 254) { - ids.emplace_back(trash_id[ids.size() - 1].data()); - } + // ids.reserve(trash_id.size() + 1); + // while (ids.size() < 254) { + // ids.emplace_back(trash_id[ids.size() - 1].data()); + // } /* for (const auto &id : trash_id) { ids.emplace_back(id.data()); diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index f884b8b4..bba31adb 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -101,13 +101,15 @@ void bit_shrink_inverse_skip(void *const dest, const int64_t head_skip_bits, void shrink_bits(const uint16_t *const src, const size_t src_count, const int block_types, std::vector *const dest) noexcept { - if (src == nullptr || dest == nullptr || src_count <= 0 || block_types <= 1) { + if (src == nullptr || dest == nullptr || src_count <= 0) { return; } - const int bits_per_element = std::ceil(std::log2(block_types)); + const int bits_per_element = + std::max(std::ceil(std::log2(std::max(block_types, 1))), 2); //::std::cout << "bits_per_element = " << bits_per_element << ::std::endl; + assert(bits_per_element >= 2); assert(bits_per_element <= 16); // if (bits_per_element > 16) { // exit(1); @@ -124,9 +126,9 @@ void shrink_bits(const uint16_t *const src, const size_t src_count, memset(dest->data(), 0, bytes_required); const size_t head_skip_bits = bytes_required * 8 - total_bits; - //::std::cout << "total_bits = " << total_bits << '\n'; - //::std::cout << "bytes_required = " << bytes_required << '\n'; - //::std::cout << "head_skip_bits = " << head_skip_bits << '\n'; + // ::std::cout << "total_bits = " << total_bits << '\n'; + // ::std::cout << "bytes_required = " << bytes_required << '\n'; + // ::std::cout << "head_skip_bits = " << head_skip_bits << '\n'; bit_shrink_inverse_skip(dest->data(), head_skip_bits, src, src_count, bits_per_element); From d638a95ab168da26cffc7d5fa435abdc2b4f02bf Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 24 Jun 2025 12:16:20 +0800 Subject: [PATCH 1059/1123] Add carpets to SCL Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 165 +++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index c07fe835..235c42ae 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -285,6 +285,17 @@ "version": 0, "idOld": "minecraft:wool[color=white]" }, + { + "baseColor": 8, + "id": "minecraft:white_carpet", + "nameZH": "白色地毯", + "nameEN": "White carpet", + "icon": "white_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=white]", + "burnable": true, + "needStone": true + }, { "baseColor": 8, "id": "minecraft:white_stained_glass", @@ -459,6 +470,17 @@ "version": 0, "idOld": "minecraft:wool[color=orange]" }, + { + "baseColor": 15, + "id": "minecraft:orange_carpet", + "nameZH": "橙色地毯", + "nameEN": "Orange carpet", + "icon": "orange_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=orange]", + "burnable": true, + "needStone": true + }, { "baseColor": 15, "id": "minecraft:orange_stained_glass", @@ -583,6 +605,17 @@ "version": 0, "idOld": "minecraft:wool[color=magenta]" }, + { + "baseColor": 16, + "id": "minecraft:magenta_carpet", + "nameZH": "品红色地毯", + "nameEN": "Magenta carpet", + "icon": "magenta_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=magenta]", + "burnable": true, + "needStone": true + }, { "baseColor": 16, "id": "minecraft:magenta_stained_glass", @@ -651,6 +684,17 @@ "version": 0, "idOld": "minecraft:wool[color=yellow]" }, + { + "baseColor": 18, + "id": "minecraft:yellow_carpet", + "nameZH": "黄色地毯", + "nameEN": "Yellow carpet", + "icon": "yellow_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=yellow]", + "burnable": true, + "needStone": true + }, { "baseColor": 18, "id": "minecraft:yellow_stained_glass", @@ -689,6 +733,17 @@ "version": 0, "idOld": "minecraft:wool[color=lime]" }, + { + "baseColor": 19, + "id": "minecraft:lime_carpet", + "nameZH": "黄绿色地毯", + "nameEN": "Lime carpet", + "icon": "lime_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=lime]", + "burnable": true, + "needStone": true + }, { "baseColor": 19, "id": "minecraft:lime_stained_glass", @@ -719,6 +774,17 @@ "version": 0, "idOld": "minecraft:wool[color=pink]" }, + { + "baseColor": 20, + "id": "minecraft:pink_carpet", + "nameZH": "粉色地毯", + "nameEN": "Pink carpet", + "icon": "pink_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=pink]", + "burnable": true, + "needStone": true + }, { "baseColor": 20, "id": "minecraft:pink_stained_glass", @@ -759,6 +825,17 @@ "idOld": "minecraft:wool[color=gray]", "burnable": true }, + { + "baseColor": 21, + "id": "minecraft:gray_carpet", + "nameZH": "灰色地毯", + "nameEN": "Gray carpet", + "icon": "gray_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=gray]", + "burnable": true, + "needStone": true + }, { "baseColor": 21, "id": "minecraft:gray_stained_glass", @@ -798,6 +875,17 @@ "idOld": "minecraft:wool[color=silver]", "burnable": true }, + { + "baseColor": 22, + "id": "minecraft:light_gray_carpet", + "nameZH": "浅灰色地毯", + "nameEN": "Light gray carpet", + "icon": "light_gray_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=light_gray]", + "burnable": true, + "needStone": true + }, { "baseColor": 22, "id": "minecraft:light_gray_stained_glass", @@ -829,6 +917,17 @@ "idOld": "minecraft:wool[color=cyan]", "burnable": true }, + { + "baseColor": 23, + "id": "minecraft:cyan_carpet", + "nameZH": "青色地毯", + "nameEN": "Cyan carpet", + "icon": "cyan_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=cyan]", + "burnable": true, + "needStone": true + }, { "baseColor": 23, "id": "minecraft:cyan_stained_glass", @@ -877,6 +976,17 @@ "idOld": "minecraft:wool[color=purple]", "burnable": true }, + { + "baseColor": 24, + "id": "minecraft:purple_carpet", + "nameZH": "紫色地毯", + "nameEN": "Purple carpet", + "icon": "purple_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=purple]", + "burnable": true, + "needStone": true + }, { "baseColor": 24, "id": "minecraft:purple_stained_glass", @@ -916,6 +1026,17 @@ "idOld": "minecraft:wool[color=blue]", "burnable": true }, + { + "baseColor": 25, + "id": "minecraft:blue_carpet", + "nameZH": "蓝色地毯", + "nameEN": "Blue carpet", + "icon": "blue_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=blue]", + "burnable": true, + "needStone": true + }, { "baseColor": 25, "id": "minecraft:blue_stained_glass", @@ -947,6 +1068,17 @@ "idOld": "minecraft:wool[color=brown]", "burnable": true }, + { + "baseColor": 26, + "id": "minecraft:brown_carpet", + "nameZH": "棕色地毯", + "nameEN": "Brown carpet", + "icon": "brown_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=brown]", + "burnable": true, + "needStone": true + }, { "baseColor": 26, "id": "minecraft:brown_stained_glass", @@ -1004,6 +1136,17 @@ "idOld": "minecraft:wool[color=green]", "burnable": true }, + { + "baseColor": 27, + "id": "minecraft:green_carpet", + "nameZH": "绿色地毯", + "nameEN": "Green carpet", + "icon": "green_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=green]", + "burnable": true, + "needStone": true + }, { "baseColor": 27, "id": "minecraft:green_stained_glass", @@ -1043,6 +1186,17 @@ "idOld": "minecraft:wool[color=red]", "burnable": true }, + { + "baseColor": 28, + "id": "minecraft:red_carpet", + "nameZH": "红色地毯", + "nameEN": "Red carpet", + "icon": "red_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=red]", + "burnable": true, + "needStone": true + }, { "baseColor": 28, "id": "minecraft:red_stained_glass", @@ -1119,6 +1273,17 @@ "idOld": "minecraft:wool[color=black]", "burnable": true }, + { + "baseColor": 29, + "id": "minecraft:black_carpet", + "nameZH": "黑色地毯", + "nameEN": "Black carpet", + "icon": "black_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=black]", + "burnable": true, + "needStone": true + }, { "baseColor": 29, "id": "minecraft:black_stained_glass", From 4c674b55a5f62093565f251cfbbad91657822fcb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 24 Jun 2025 12:32:33 +0800 Subject: [PATCH 1060/1123] fix base color of bamboo block Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 235c42ae..84166d56 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -267,6 +267,15 @@ "version": 0, "idOld": "minecraft:leaves2[variant=dark_oak,check_decay=false,decayable=false]" }, + { + "baseColor": 7, + "id": "minecraft:bamboo_block[axis=x]", + "nameZH": "竹块(侧面)", + "nameEN": "Bamboo block(axis=x)", + "icon": "bamboo_block.png", + "version": 20, + "burnable": true + }, { "baseColor": 8, "id": "minecraft:white_concrete", @@ -1969,15 +1978,6 @@ "version": 20, "burnable": true }, - { - "baseColor": 18, - "id": "minecraft:bamboo_block[axis=x]", - "nameZH": "竹块(侧面)", - "nameEN": "Bamboo block(axis=x)", - "icon": "bamboo_block.png", - "version": 20, - "burnable": true - }, { "baseColor": 20, "id": "minecraft:cherry_leaves[persistent=true]", From e2b6ffe2468adf7720623c2c3d9ab1ba2df38fbb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 26 Jun 2025 17:54:50 +0800 Subject: [PATCH 1061/1123] Add light blue carpet and resort colored blocks Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 341 +++++++++++++++-------------- 1 file changed, 176 insertions(+), 165 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 84166d56..2688f616 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -294,17 +294,6 @@ "version": 0, "idOld": "minecraft:wool[color=white]" }, - { - "baseColor": 8, - "id": "minecraft:white_carpet", - "nameZH": "白色地毯", - "nameEN": "White carpet", - "icon": "white_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=white]", - "burnable": true, - "needStone": true - }, { "baseColor": 8, "id": "minecraft:white_stained_glass", @@ -317,6 +306,17 @@ 12 ] }, + { + "baseColor": 8, + "id": "minecraft:white_carpet", + "nameZH": "白色地毯", + "nameEN": "White carpet", + "icon": "white_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=white]", + "burnable": true, + "needStone": true + }, { "baseColor": 8, "id": "minecraft:snow_block", @@ -479,17 +479,6 @@ "version": 0, "idOld": "minecraft:wool[color=orange]" }, - { - "baseColor": 15, - "id": "minecraft:orange_carpet", - "nameZH": "橙色地毯", - "nameEN": "Orange carpet", - "icon": "orange_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=orange]", - "burnable": true, - "needStone": true - }, { "baseColor": 15, "id": "minecraft:orange_stained_glass", @@ -502,6 +491,17 @@ 12 ] }, + { + "baseColor": 15, + "id": "minecraft:orange_carpet", + "nameZH": "橙色地毯", + "nameEN": "Orange carpet", + "icon": "orange_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=orange]", + "burnable": true, + "needStone": true + }, { "baseColor": 15, "id": "minecraft:acacia_planks", @@ -614,17 +614,6 @@ "version": 0, "idOld": "minecraft:wool[color=magenta]" }, - { - "baseColor": 16, - "id": "minecraft:magenta_carpet", - "nameZH": "品红色地毯", - "nameEN": "Magenta carpet", - "icon": "magenta_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=magenta]", - "burnable": true, - "needStone": true - }, { "baseColor": 16, "id": "minecraft:magenta_stained_glass", @@ -637,6 +626,17 @@ 12 ] }, + { + "baseColor": 16, + "id": "minecraft:magenta_carpet", + "nameZH": "品红色地毯", + "nameEN": "Magenta carpet", + "icon": "magenta_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=magenta]", + "burnable": true, + "needStone": true + }, { "baseColor": 16, "id": "minecraft:purpur_block", @@ -675,6 +675,17 @@ 12 ] }, + { + "baseColor": 17, + "id": "minecraft:light_blue_carpet", + "nameZH": "淡蓝色地毯", + "nameEN": "Light blue carpet", + "icon": "light_blue_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=light_blue]", + "burnable": true, + "needStone": true + }, { "baseColor": 18, "id": "minecraft:yellow_concrete", @@ -693,17 +704,6 @@ "version": 0, "idOld": "minecraft:wool[color=yellow]" }, - { - "baseColor": 18, - "id": "minecraft:yellow_carpet", - "nameZH": "黄色地毯", - "nameEN": "Yellow carpet", - "icon": "yellow_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=yellow]", - "burnable": true, - "needStone": true - }, { "baseColor": 18, "id": "minecraft:yellow_stained_glass", @@ -716,6 +716,17 @@ 12 ] }, + { + "baseColor": 18, + "id": "minecraft:yellow_carpet", + "nameZH": "黄色地毯", + "nameEN": "Yellow carpet", + "icon": "yellow_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=yellow]", + "burnable": true, + "needStone": true + }, { "baseColor": 18, "id": "minecraft:hay_block[axis=y]", @@ -742,17 +753,6 @@ "version": 0, "idOld": "minecraft:wool[color=lime]" }, - { - "baseColor": 19, - "id": "minecraft:lime_carpet", - "nameZH": "黄绿色地毯", - "nameEN": "Lime carpet", - "icon": "lime_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=lime]", - "burnable": true, - "needStone": true - }, { "baseColor": 19, "id": "minecraft:lime_stained_glass", @@ -765,6 +765,17 @@ 12 ] }, + { + "baseColor": 19, + "id": "minecraft:lime_carpet", + "nameZH": "黄绿色地毯", + "nameEN": "Lime carpet", + "icon": "lime_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=lime]", + "burnable": true, + "needStone": true + }, { "baseColor": 20, "id": "minecraft:pink_concrete", @@ -783,17 +794,6 @@ "version": 0, "idOld": "minecraft:wool[color=pink]" }, - { - "baseColor": 20, - "id": "minecraft:pink_carpet", - "nameZH": "粉色地毯", - "nameEN": "Pink carpet", - "icon": "pink_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=pink]", - "burnable": true, - "needStone": true - }, { "baseColor": 20, "id": "minecraft:pink_stained_glass", @@ -806,6 +806,17 @@ 12 ] }, + { + "baseColor": 20, + "id": "minecraft:pink_carpet", + "nameZH": "粉色地毯", + "nameEN": "Pink carpet", + "icon": "pink_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=pink]", + "burnable": true, + "needStone": true + }, { "baseColor": 20, "id": "minecraft:pearlescent_froglight[axis=y]", @@ -834,17 +845,6 @@ "idOld": "minecraft:wool[color=gray]", "burnable": true }, - { - "baseColor": 21, - "id": "minecraft:gray_carpet", - "nameZH": "灰色地毯", - "nameEN": "Gray carpet", - "icon": "gray_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=gray]", - "burnable": true, - "needStone": true - }, { "baseColor": 21, "id": "minecraft:gray_stained_glass", @@ -857,6 +857,17 @@ 12 ] }, + { + "baseColor": 21, + "id": "minecraft:gray_carpet", + "nameZH": "灰色地毯", + "nameEN": "Gray carpet", + "icon": "gray_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=gray]", + "burnable": true, + "needStone": true + }, { "baseColor": 21, "id": "minecraft:tinted_glass", @@ -884,17 +895,6 @@ "idOld": "minecraft:wool[color=silver]", "burnable": true }, - { - "baseColor": 22, - "id": "minecraft:light_gray_carpet", - "nameZH": "浅灰色地毯", - "nameEN": "Light gray carpet", - "icon": "light_gray_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=light_gray]", - "burnable": true, - "needStone": true - }, { "baseColor": 22, "id": "minecraft:light_gray_stained_glass", @@ -907,6 +907,17 @@ 12 ] }, + { + "baseColor": 22, + "id": "minecraft:light_gray_carpet", + "nameZH": "浅灰色地毯", + "nameEN": "Light gray carpet", + "icon": "light_gray_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=light_gray]", + "burnable": true, + "needStone": true + }, { "baseColor": 23, "id": "minecraft:cyan_concrete", @@ -926,17 +937,6 @@ "idOld": "minecraft:wool[color=cyan]", "burnable": true }, - { - "baseColor": 23, - "id": "minecraft:cyan_carpet", - "nameZH": "青色地毯", - "nameEN": "Cyan carpet", - "icon": "cyan_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=cyan]", - "burnable": true, - "needStone": true - }, { "baseColor": 23, "id": "minecraft:cyan_stained_glass", @@ -949,6 +949,17 @@ 12 ] }, + { + "baseColor": 23, + "id": "minecraft:cyan_carpet", + "nameZH": "青色地毯", + "nameEN": "Cyan carpet", + "icon": "cyan_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=cyan]", + "burnable": true, + "needStone": true + }, { "baseColor": 23, "id": "minecraft:prismarine", @@ -985,17 +996,6 @@ "idOld": "minecraft:wool[color=purple]", "burnable": true }, - { - "baseColor": 24, - "id": "minecraft:purple_carpet", - "nameZH": "紫色地毯", - "nameEN": "Purple carpet", - "icon": "purple_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=purple]", - "burnable": true, - "needStone": true - }, { "baseColor": 24, "id": "minecraft:purple_stained_glass", @@ -1008,6 +1008,17 @@ 12 ] }, + { + "baseColor": 24, + "id": "minecraft:purple_carpet", + "nameZH": "紫色地毯", + "nameEN": "Purple carpet", + "icon": "purple_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=purple]", + "burnable": true, + "needStone": true + }, { "baseColor": 24, "id": "minecraft:amethyst_block", @@ -1035,17 +1046,6 @@ "idOld": "minecraft:wool[color=blue]", "burnable": true }, - { - "baseColor": 25, - "id": "minecraft:blue_carpet", - "nameZH": "蓝色地毯", - "nameEN": "Blue carpet", - "icon": "blue_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=blue]", - "burnable": true, - "needStone": true - }, { "baseColor": 25, "id": "minecraft:blue_stained_glass", @@ -1058,6 +1058,17 @@ 12 ] }, + { + "baseColor": 25, + "id": "minecraft:blue_carpet", + "nameZH": "蓝色地毯", + "nameEN": "Blue carpet", + "icon": "blue_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=blue]", + "burnable": true, + "needStone": true + }, { "baseColor": 26, "id": "minecraft:brown_concrete", @@ -1077,17 +1088,6 @@ "idOld": "minecraft:wool[color=brown]", "burnable": true }, - { - "baseColor": 26, - "id": "minecraft:brown_carpet", - "nameZH": "棕色地毯", - "nameEN": "Brown carpet", - "icon": "brown_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=brown]", - "burnable": true, - "needStone": true - }, { "baseColor": 26, "id": "minecraft:brown_stained_glass", @@ -1100,6 +1100,17 @@ 12 ] }, + { + "baseColor": 26, + "id": "minecraft:brown_carpet", + "nameZH": "棕色地毯", + "nameEN": "Brown carpet", + "icon": "brown_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=brown]", + "burnable": true, + "needStone": true + }, { "baseColor": 26, "id": "minecraft:dark_oak_planks", @@ -1145,17 +1156,6 @@ "idOld": "minecraft:wool[color=green]", "burnable": true }, - { - "baseColor": 27, - "id": "minecraft:green_carpet", - "nameZH": "绿色地毯", - "nameEN": "Green carpet", - "icon": "green_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=green]", - "burnable": true, - "needStone": true - }, { "baseColor": 27, "id": "minecraft:green_stained_glass", @@ -1168,6 +1168,17 @@ 12 ] }, + { + "baseColor": 27, + "id": "minecraft:green_carpet", + "nameZH": "绿色地毯", + "nameEN": "Green carpet", + "icon": "green_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=green]", + "burnable": true, + "needStone": true + }, { "baseColor": 27, "id": "minecraft:dried_kelp_block", @@ -1195,17 +1206,6 @@ "idOld": "minecraft:wool[color=red]", "burnable": true }, - { - "baseColor": 28, - "id": "minecraft:red_carpet", - "nameZH": "红色地毯", - "nameEN": "Red carpet", - "icon": "red_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=red]", - "burnable": true, - "needStone": true - }, { "baseColor": 28, "id": "minecraft:red_stained_glass", @@ -1218,6 +1218,17 @@ 12 ] }, + { + "baseColor": 28, + "id": "minecraft:red_carpet", + "nameZH": "红色地毯", + "nameEN": "Red carpet", + "icon": "red_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=red]", + "burnable": true, + "needStone": true + }, { "baseColor": 28, "id": "minecraft:bricks", @@ -1282,17 +1293,6 @@ "idOld": "minecraft:wool[color=black]", "burnable": true }, - { - "baseColor": 29, - "id": "minecraft:black_carpet", - "nameZH": "黑色地毯", - "nameEN": "Black carpet", - "icon": "black_wool.png", - "version": 0, - "idOld": "minecraft:carpet[color=black]", - "burnable": true, - "needStone": true - }, { "baseColor": 29, "id": "minecraft:black_stained_glass", @@ -1305,6 +1305,17 @@ 12 ] }, + { + "baseColor": 29, + "id": "minecraft:black_carpet", + "nameZH": "黑色地毯", + "nameEN": "Black carpet", + "icon": "black_wool.png", + "version": 0, + "idOld": "minecraft:carpet[color=black]", + "burnable": true, + "needStone": true + }, { "baseColor": 29, "id": "minecraft:obsidian", From 862ba6215a10dfe23a1ff85db7103f1fe3cd7ecc Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 26 Jun 2025 17:55:40 +0800 Subject: [PATCH 1062/1123] Add buttons to prefer carpets or pressure plate Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 2 ++ SlopeCraft/SCWind.ui | 58 +++++++++++++++++++++++-------------- SlopeCraft/SCWind_slots.cpp | 12 ++++++++ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index f1b0afe8..bfec0f9d 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -103,6 +103,8 @@ class SCWind : public QMainWindow { void on_pb_prefer_planks_clicked() noexcept; void on_pb_prefer_logs_clicked() noexcept; void on_pb_prefer_slabs_clicked() noexcept; + void on_pb_prefer_carpets_clicked() noexcept; + void on_pb_prefer_pressure_plates_clicked() noexcept; void on_pb_select_all_clicked() noexcept; void on_pb_deselect_all_clicked() noexcept; diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index 7553ce54..f0979762 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -281,24 +281,24 @@ 0 - - + + - 优先彩色玻璃 + 优先木板 - - + + - 优先羊毛 + 全选 - - + + - 优先木板 + 优先彩色玻璃 @@ -309,6 +309,20 @@ + + + + 优先混凝土 + + + + + + + 反选 + + + @@ -316,31 +330,31 @@ - - + + - 优先混凝土 + 优先羊毛 - - + + - 全选 + 全不选 - - + + - 全不选 + 优先地毯 - - + + - 反选 + 优先压力板 @@ -357,7 +371,7 @@ 0 0 750 - 653 + 624 diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 8db6af1e..1f76a531 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -256,6 +256,18 @@ void SCWind::on_pb_prefer_slabs_clicked() noexcept { -> int { return impl_select_blk_by_id(blks, "_slab"); }); } +void SCWind::on_pb_prefer_carpets_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "_carpet"); }); +} + +void SCWind::on_pb_prefer_pressure_plates_clicked() noexcept { + this->ui->blm->select_block_by_callback( + [](const std::vector &blks) + -> int { return impl_select_blk_by_id(blks, "_pressure_plate"); }); +} + void SCWind::on_pb_select_all_clicked() noexcept { for (size_t bc = 0; bc < this->ui->blm->num_basecolor_widgets(); bc++) { this->ui->blm->basecolorwidget_at(bc)->set_enabled(true); From 9e84e8dba3c10c86578b174ad4b44bdb3f2bff27 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 26 Jun 2025 18:08:45 +0800 Subject: [PATCH 1063/1123] Update SC presets Signed-off-by: ToKiNoBug --- .../others/presets/cheap.sc_preset_json | 32 +++++++++---------- .../others/presets/elegant.sc_preset_json | 2 +- .../others/presets/shiny.sc_preset_json | 4 +-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/SlopeCraft/others/presets/cheap.sc_preset_json b/SlopeCraft/others/presets/cheap.sc_preset_json index 0994ce0a..f7ef0b1f 100644 --- a/SlopeCraft/others/presets/cheap.sc_preset_json +++ b/SlopeCraft/others/presets/cheap.sc_preset_json @@ -11,7 +11,7 @@ }, { "baseColor": 2, - "blockId": "minecraft:end_stone", + "blockId": "minecraft:birch_planks", "enabled": true }, { @@ -76,77 +76,77 @@ }, { "baseColor": 15, - "blockId": "minecraft:orange_concrete", + "blockId": "minecraft:orange_carpet", "enabled": true }, { "baseColor": 16, - "blockId": "minecraft:magenta_concrete", + "blockId": "minecraft:magenta_carpet", "enabled": true }, { "baseColor": 17, - "blockId": "minecraft:light_blue_concrete", + "blockId": "minecraft:light_blue_carpet", "enabled": true }, { "baseColor": 18, - "blockId": "minecraft:yellow_concrete", + "blockId": "minecraft:yellow_carpet", "enabled": true }, { "baseColor": 19, - "blockId": "minecraft:lime_concrete", + "blockId": "minecraft:lime_carpet", "enabled": true }, { "baseColor": 20, - "blockId": "minecraft:pink_concrete", + "blockId": "minecraft:pink_carpet", "enabled": true }, { "baseColor": 21, - "blockId": "minecraft:gray_concrete", + "blockId": "minecraft:gray_carpet", "enabled": true }, { "baseColor": 22, - "blockId": "minecraft:light_gray_concrete", + "blockId": "minecraft:light_gray_carpet", "enabled": true }, { "baseColor": 23, - "blockId": "minecraft:cyan_concrete", + "blockId": "minecraft:cyan_carpet", "enabled": true }, { "baseColor": 24, - "blockId": "minecraft:purple_concrete", + "blockId": "minecraft:purple_carpet", "enabled": true }, { "baseColor": 25, - "blockId": "minecraft:blue_concrete", + "blockId": "minecraft:blue_carpet", "enabled": true }, { "baseColor": 26, - "blockId": "minecraft:brown_concrete", + "blockId": "minecraft:brown_carpet", "enabled": true }, { "baseColor": 27, - "blockId": "minecraft:green_concrete", + "blockId": "minecraft:green_carpet", "enabled": true }, { "baseColor": 28, - "blockId": "minecraft:red_concrete", + "blockId": "minecraft:red_carpet", "enabled": true }, { "baseColor": 29, - "blockId": "minecraft:black_concrete", + "blockId": "minecraft:black_carpet", "enabled": true }, { diff --git a/SlopeCraft/others/presets/elegant.sc_preset_json b/SlopeCraft/others/presets/elegant.sc_preset_json index 035af21a..e73cbfcb 100644 --- a/SlopeCraft/others/presets/elegant.sc_preset_json +++ b/SlopeCraft/others/presets/elegant.sc_preset_json @@ -306,7 +306,7 @@ }, { "baseColor": 61, - "blockId": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", + "blockId": "minecraft:verdant_froglight[axis=y]", "enabled": true } ] \ No newline at end of file diff --git a/SlopeCraft/others/presets/shiny.sc_preset_json b/SlopeCraft/others/presets/shiny.sc_preset_json index 4ee55292..41356ae5 100644 --- a/SlopeCraft/others/presets/shiny.sc_preset_json +++ b/SlopeCraft/others/presets/shiny.sc_preset_json @@ -101,7 +101,7 @@ }, { "baseColor": 20, - "blockId": "minecraft:pink_concrete", + "blockId": "minecraft:pearlescent_froglight[axis=y]", "enabled": true }, { @@ -306,7 +306,7 @@ }, { "baseColor": 61, - "blockId": "minecraft:glow_lichen[down=true,east=false,north=false,south=false,up=false,waterlogged=false]", + "blockId": "minecraft:verdant_froglight[axis=y]", "enabled": true } ] \ No newline at end of file From 7fa37a2531850106625379c9f0c4913564d1d33e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 9 Jul 2025 22:14:38 +0800 Subject: [PATCH 1064/1123] Hide too long file names (#134 Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 1f76a531..c613afff 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -371,13 +371,14 @@ void SCWind::on_pb_save_converted_clicked() noexcept { goto save_image; } - auto ret = QMessageBox::warning( + const auto ret = QMessageBox::warning( this, tr("将要覆盖已存在的图像"), tr("%1将被覆盖,确认覆盖吗?").arg(filename), QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No, QMessageBox::StandardButton::YesToAll, QMessageBox::StandardButton::NoToAll}); + bool replace; switch (ret) { case QMessageBox::StandardButton::Yes: @@ -396,7 +397,7 @@ void SCWind::on_pb_save_converted_clicked() noexcept { break; } - if (!replace) { + if (not replace) { continue; } } @@ -707,13 +708,17 @@ void SCWind::on_pb_export_file_clicked() noexcept { } if (exisiting_num > 0) { - const auto ret = QMessageBox::warning( - this, tr("%1 个文件将被替换").arg(exisiting_num), - tr("以下文件将被替换:\n%1\n点击 Yes " - "将替换它们,点击 No 将取消这次导出。") - .arg(to_be_replaced), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Yes, - QMessageBox::StandardButton::No}); + QMessageBox msg_box{this}; + { + msg_box.setStandardButtons(QMessageBox::StandardButtons{ + QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No}); + msg_box.setWindowTitle(tr("%1 个文件将被替换").arg(exisiting_num)); + msg_box.setText( + tr("以下文件将被替换:\n点击 Yes " + "将替换它们,点击 No 将取消这次导出。")); + msg_box.setDetailedText(to_be_replaced); + } + const auto ret = msg_box.exec(); if (ret != QMessageBox::StandardButton::Yes) { return; From 8da432594d6d89bafe1ef20f4d74e0d90f54e9b7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 10 Jul 2025 13:44:17 +0800 Subject: [PATCH 1065/1123] Fix material list Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 61 ++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 3ab6f226..de19db55 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -344,29 +344,38 @@ void color_table_impl::stat_blocks(const structure_3D &s, const auto &structure = dynamic_cast(s); const auto schem_stat = structure.schem.stat_blocks(); - for (size_t schem_blk_id = 0; schem_blk_id < structure.schem.palette_size(); - schem_blk_id++) { - if (schem_blk_id == 0) { // ignore air - continue; - } - assert(schem_blk_id > 0); - if (schem_stat[schem_blk_id] <= 0) { + assert(schem_stat.size() == structure.palette_length()); + assert(schem_stat.size() == structure.schem.palette().size()); + for (size_t idx_table = 0; idx_table < this->blocks.size(); idx_table++) { + const auto &blk_info = this->blocks[idx_table]; + size_t count = 0; + blkid::char_range pure_id; + const bool ok = blkid::process_blk_id( + blk_info.idForVersion(this->mc_version()), nullptr, &pure_id, nullptr); + assert(ok); + if (not ok) { continue; } - const auto strid = structure.schem.palette()[schem_blk_id]; - const auto blkp = this->find_block_for_index(schem_blk_id - 1, strid); - if (blkp == nullptr) { - std::cerr << fmt::format( - "Failed to find \"{}\" in color_table, this type of block will not " - "be counted.\n", - strid); - continue; + for (size_t idx_schem = 0; idx_schem < structure.schem.palette_size(); + idx_schem++) { + auto &schem_blkid = structure.schem.palette()[idx_schem]; + if (schem_blkid == "minecraft:air") { + continue; + } + assert(not schem_blkid.empty()); + blkid::char_range pure_id_schem; + const bool ok_schem = + blkid::process_blk_id(schem_blkid, nullptr, &pure_id_schem, nullptr); + assert(ok_schem); + if (not ok_schem) { + continue; + } + if (std::string_view{pure_id} == std::string_view{pure_id_schem}) { + count += schem_stat[idx_schem]; + } } - const ptrdiff_t index_in_palette = blkp - this->blocks.data(); - assert(index_in_palette >= 0); - assert(index_in_palette < this->blocks.size()); - buffer[index_in_palette] += schem_stat[schem_blk_id]; + buffer[idx_table] = count; } } @@ -374,7 +383,7 @@ std::string color_table_impl::impl_generate_test_schematic( std::string_view filename, const test_blocklist_options &option) const noexcept { if (!filename.ends_with(".nbt")) { - return "File name should ends with \".nbt\""; + return "File name should end with \".nbt\""; } libSchem::Schem test; test.set_MC_major_version_number(this->mc_version_); @@ -430,14 +439,16 @@ std::string color_table_impl::impl_generate_test_schematic( test(block_counter[base].size(), 1, base) = 1; // glass block } - SCL_errorFlag err; - std::string detail; - const bool success = test.export_structure(filename, true, &err, &detail); + // SCL_errorFlag err; + // std::string detail; + auto ok = test.export_structure(filename, true); + // const bool success = test.export_structure(filename, true, &err, &detail); - if (!success) { + if (not ok) { + auto &err = ok.error(); return fmt::format( "Failed to export structure file {}, error code = {}, detail: {}", - filename, int(err), detail); + filename, int(err.first), err.second); } else { return {}; } From 5df6a975bebf89259c433778186f8b8397f1a0fe Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 10 Jul 2025 13:49:48 +0800 Subject: [PATCH 1066/1123] update translation Signed-off-by: ToKiNoBug --- MapViewer/MapViewer_en_US.ts | 22 +- SlopeCraft/others/SlopeCraft_en_US.ts | 525 +++++++++++++------------- 2 files changed, 284 insertions(+), 263 deletions(-) diff --git a/MapViewer/MapViewer_en_US.ts b/MapViewer/MapViewer_en_US.ts index bfbee63a..d81dbb7e 100644 --- a/MapViewer/MapViewer_en_US.ts +++ b/MapViewer/MapViewer_en_US.ts @@ -41,7 +41,7 @@ - + 请选择地图文件 Please select files @@ -97,8 +97,8 @@ - - + + 保存为图片 Save @@ -108,43 +108,43 @@ Show grid - + 地图数: Map count: - + There is/are - + 个像素点出现未知的基色,它们使用了Mojang未定义的基色。这可能是因为软件版本较旧而游戏版本太新,或者地图文件损坏。 其行、列坐标分别为: pixel(s) which have unknown base color, they are using basecolors out of Mojang's defination. This may be caused by damaged map data file, or the software version is too old. - + 地图中有Mojang未定义基色 Undefined basecolor in map data files (undefined by Mojang) - + 选择地图数据文件 Select map data files - + 加载地图文件失败 Failed to load map data file(s) - + 出错的文件: Map data file: - + 错误信息: diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 6b83dcbe..43181a15 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -37,42 +37,42 @@ BLD_block_info_provider - + 最低版本 Minimum version - + 依附方块 Attached block - + 发光 Glowing - + 末影人可搬走 Enderman pickable - + 可燃 Burnable - + 一组数量 Stack size - + 远古版本 Very old - + 未来版本 Future @@ -80,7 +80,7 @@ BLD_block_list_provider - + SlopeCraft 内部错误,方块列表的列表中出现 nullptr SlopeCraft internal error, nullptr found in list of blocklist @@ -88,7 +88,7 @@ BLD_block_provider - + SlopeCraft 内部错误,方块列表中出现 nullptr SlopeCraft internal error, nullptr found in list of blocklist @@ -136,32 +136,32 @@ English name - + 选择方块列表 Select block list - + 不能删除基础方块列表 Can not remove fundamental block list - + FixedBlocks.zip 是基础方块列表,不允许移除。 FixedBlocks.zip is the fundamental block list, not allowed to remove. - + 删除方块列表 %1 失败 Failed to deleta block list %1 - + 删除方块列表成功 Removed block list - + 删除了 %1 个方块列表,移除了 %2 个方块 Removed %1 block list(s) and %2 block(s) @@ -394,22 +394,22 @@ File-only Map - + 优先彩色玻璃 Use stained glass - + 优先混凝土 Use Concrete - + 优先羊毛 Use Wool - + 优先木板 Use planks @@ -419,76 +419,76 @@ Use logs - + 导入图像并转化 Load image and convert - + 原图 Original image - + 转化后 Converted image - + 删除 Delete - - + + 项目池 Task pool - + 添加 Add - + 转化算法 Convert algorithm - + 抖动 Dithering - + 转化当前图像 Convert current image - - - + + + 保存转化后图像 Save converted image - + 全部转化 Convert all - + 导出 Export - + Litematica - - + + 结构方块文件 Vanilla structure @@ -503,233 +503,243 @@ Only vanilla blocks are loaded by default, click button above to load other block lists. - + 优先台阶 Use slabs - + 全选 Select all - + 全不选 Deselect all - + 反选 Invert selection - + + 优先地毯 + Use carpets + + + + 优先压力板 + Use pressure plates + + + 显示缩略图 View images - + 替换 Replace - - + + WE原理图 WE Schem - - + + 平面示意图 Flat diagram - + 地图文件 Map data files - + 其他选项 Others - + 防火 Fire Proof - + 防末影人 Enderman Proof - + 连接蘑菇块 Connect mushroom blocks - + 压缩高度 Compress - + 有损压缩 Lossy Compression - + 无损压缩 Lossless Compress - + 最大允许高度: Max height: - + 搭桥 Glass Bridge - + 允许搭桥 Construct Glass Bridge - + layer(s) - + 搭桥间隔: Glass bridge interval: - + 投影区域名称 Region name - + 投影名称 Litematic name - + 用结构空位替代空气 Replace air with structure void - + offset - + WEOffset - - - - - - + + + + + + 0 - + 原理图名称 Name of schematic - + 依赖 mod 名称 Depend mods - + 在这里输入依赖 mod 的名字。用换行符分割多个 mod Input names of required mods here. To represent multiple mods, split them with a line break - - + + 方块 block(s) - - + + 间距: Line interval: - + 垂直分割线 Vertical split line - + 水平分割线 Horizontal split line - + 大小与方块数量 Size and block count - - + + 大小: Size: - - + + 方块数量: Block count: - + 全部导出 Export all - + 预览 Preview - + 预览材料表 Material list - + 预览压缩效果 Compress effect - + 预构建三维结构 Construct 3d structure - + 批量获得地图物品的指令 /give command to get map items - + 💡tips: 设置地图画起始序号后,点击“导出”,选择输出地图数据文件的位置,就完成导出任务了。 在下面的表格里可以看到每个图像对应的文件名。 @@ -742,218 +752,218 @@ You can see filenames of each image. Map data are stored in map data files, assembled maps can take effect only after you must import map data files into the save. - + 地图画起始序号: Map beginning index: - + 导出批量获得地图物品的命令(txt) Export command to get map items - + 导出命令 Export commands - + 生存模式不可破坏展示框;移除它依附的方块,展示框也不会消失。 Item frams can not be removed in survivial mode; it will not disappear even the attached block is removed. - + 展示框不可破坏 Fixed frame - + 1.20.5后,物品格式发生重大改变 Item format is changed greatly after 1.20.5 - + MC版本≥1.20.5+ MC ≥ 1.20.5 - + 采用荧光物品显示框 Use glowing item frame - + 荧光物品显示框 Glowing item frame - + 导出包含物品展示框的投影/结构方块文件 Export the litematica / vanilla structure containing item frames - + 导出组装的地图画 Export assembled maps - + 导出map_i.dat的地图数据文件 Export map data files like map_i.dat - + 导出地图文件 Export map data files - + 展示框背景将不可见 The background of item frames will be invisible - + 展示框透明 Transprant frame - + 地图画可依附于方块的侧面、顶面和底面 Map can attach to a block by side, top and bottom - + 地图画方向 Map direction - + 导出组装地图画的格式 Format to export assembled maps - + 导出Litematica Export as litematica - + 导出结构方块文件 Export as structure - + 内存使用策略 Memory policy - + 缓存全部三维结构 Cache all 3D structures - + 查看方块列表 View block lists - + 语言 Language - + 高级 Advanced - + 缓存 Cache - + 关于 About - + 联系作者 Contact with me - + 帮助 Help - + GA转化器参数 GACvter parameters - + open_cache_dir - + 打开缓存文件夹 Open cache directory - + 清除缓存 Clean caches - - + + 关于 SlopeCraft About SlopeCraft - + 反馈 bug Report bugs - + 检查更新 Check updates - + 测试方块列表 Test block list - + 输出当前颜色表 Export current colorset - + 查看 SlopeCraft 文档 Documentation - + 使用教程 Tutorial - + 常见问题 FAQ - + 加载默认预设失败 Failed to load default presets - + 一个或多个内置的预设不能被解析。SlopeCraft 可能已经损坏,请重新安装。 具体报错信息: %1 @@ -962,74 +972,74 @@ Detail information: %1 - + 可用颜色数量:%1 Avaliable colors: %1 - + 应用预设失败 Failed to apply preset - + 无法保存第%1个转化后图像 Failed to save the %1-th converted image - + 该图像未被转化,或者转化之后修改了颜色表/转化算法。请重新转化它。 This image is not converted, or you have changed the color palette/convert algo. Please convert it again. - + 保存图像失败 Failed to save image - + 保存%1时失败。可能是因为文件路径错误,或者图片格式不支持。 Failed when saving %1. This may because of a file path error, or the image format is not supported. - + 大小: %1 × %2 × %3 Size: %1 × %2 × %3 - + 方块数量:%1 Block count: %1 - + WE 原理图参数有错:输入给 offset 的值"%1"不是一个有效的坐标,应当输入一个整数。 Invalid option for WE schem: the given value of offset "%1" is not a valid coordinate, please input an integer. - + WE 原理图参数有错:输入给 we offset 的值"%1"不是一个有效的数字,应当输入一个整数。 Invalid option for WE schem: the given value of we offset "%1" is not a valid coordinate, please input an integer. - + 平面示意图的分割线间距无效:水平间距为 %1,垂直间距为 %2, 但间距必须为正数。 Invalid split line interval for flat diagram: the horzontal interval is %1, and that of vertical is %2, but intervals must be positive numbers. - + 错误类型:%1,错误码:%2。详细信息: %3 Error type: %1, error code: %2, details: %3 - + SlopeCraft 出现错误 An error occurred to SlopeCraft - + %1 点击 Ok 以忽略这个错误,点击 Close 将退出 SlopeCraft。 @@ -1093,282 +1103,288 @@ Detailed information: %2 Failed to generate preset file "%1", detail: %2 - - - - + + + + 未选择图像 No image selected - - - + + + 请在左侧任务池选择一个图像 Please select a image in the left - + 请在左侧任务池选择一个或多个图像 Please select one or more images in the left - + 将要覆盖已存在的图像 Existing file(s) will be replaced - + %1将被覆盖,确认覆盖吗? %1 will be replaced, are you sure to replace it? - - - + + + 该图像尚未被转化 The image is not converted - - + + 必须先转化一个图像,然后再为它构建三维结构 You must convert a image before building 3d structure for it - + 可能是在转化完成之后又修改了转化算法,因此之前的转化无效。必须重新转化该图像。 You may have changed the convertion algorithm after the convertion finished. You must convert it again. - + 尚未构建三维结构 3d structure not built - + 在预览材料表之前,必须先构建三维结构。出现这个警告,可能是因为你在构建三维结构之后,又修改了三维结构的选项,因此之前的结果无效。 You must construct 3d structure before you view the material list. This error may because you changed the option of 3d structure after you built it. Thus, previous result is useless. - + 导出设置有错 Error in export options - + 导出设置存在如下错误: %1 There is an error in your export option: %1 - + 你点错按钮了 Wrong button - + 导出为纯文件地图画的按钮在另外一页。按理来说你不应该能点击这个按钮,这可能是一个小小的 bug(特性)。 the button to export file only maps is on another page. Generally you are not able to click this button, this may be a bug(FEATURE). - + 无可导出的任务 Nothing to export - + 任务池为空,请先转化一个或一些图像 The task pool is empty, please convert one or more images - + 选择导出位置 Select export directory - + 将要覆盖已经存在的文件 Existing files will be replaced - + 确定要覆盖这些文件吗?以下文件将被覆盖: %1 Are you sure to replace these files: %1 - + 导出失败 Failed to export - + 导出%1时失败。原图像文件名为%2 点击 Ignore 将跳过这个图像,点击 Cancel 将放弃导出任务。 Failed when exporting %1. The corresponding image is %2 Click Ignore to skip this image, and Cancel to cancel. - - - + + + 设置导出位置 Set export directory - + %1 个文件将被替换 %1 files will be replaced - 以下文件将被替换: %1 点击 Yes 将替换它们,点击 No 将取消这次导出。 - These files will be replaced: + These files will be replaced: %1 Click Yes to replace them, or No to cancel. - + + 以下文件将被替换: +点击 Yes 将替换它们,点击 No 将取消这次导出。 + Following files will be replaced. +Click Yes to replace them, or No to cancel. + + + %1 个图片导出失败 Failed to export %1 image(s) - + 导出失败的图片依次为: %1 Following image(s) failed to export: %1 - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。 SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). - + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) - + 感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量 Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software - + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. - + 同时选中多个图片时,不显示 /give 命令。如果想预览导出的命令,请只选择一个图片。 Can't show /give command when you selecte multiple images. To view the command, select one image only. - + 无法为 %1 生成命令:%2 Failed to generate command for %1: %2 - + 无法创建/打开文件 %1:%2 Failed to create/open file %1: %2 - + 无法写入文件 %1:%2 Failed to write file %1: %2 - - + + %1 个文件保存失败 Failed to save %1 file(s) - + SlopeCraftL 未提供详细报错信息。 SlopeCraftL doesn't give further details. - + 错误码:%1,详情:%2 Error code: %1, details: %2 - + %1 生成失败,%2 Failed to generate %1, %2 - - + + 无法加载方块列表 Failed to load block list - + 存储方块列表的文件夹 "%1" 不存在,或不是文件夹。 Directory of block list zips \"%1\" doesn't exist or is not a directory. - - + + SlopeCraft 必须退出。 SlopeCraft must exit. - + 无法加载 FixedBlocks.zip ,SlopeCraft 缺乏最基础的方块列表。 Failed to load FixedBlocks.zip, fundamental blocks are missing for SlopeCraft. - + 部分方块列表加载失败 Some block lists failed to be loaded - + 以下 %1 个方块列表文件无法被加载: %2 由于它们不是必需,你可以忽略此错误并继续使用。 @@ -1377,136 +1393,141 @@ Click Ignore to skip, Retry to retry and Cancel to cancel Since they are not essential, you can ignore this error and go on. - + 墙面 Wall - + 顶面 Top - + 底面 Bottom - + north - + south - + east - + 西 west - + %1,向%2 %1, %2 - - + + 没有可用颜色 No available color - - + + 没有勾选任何颜色,无法转化图像。请至少勾选3~16种颜色。 You didn't enable ANY COLOR, unable to convert image. Please enable at least 3~16 colors. - + 勾选颜色太少 Too few colors enabled - + 仅仅勾选了%1种颜色,颜色过少,转化效率可能非常差。您可以点Yes继续转化,但非常建议请尽量多勾选一些颜色。 You only enabled %1 color(s), it is so few that the conversion effect may be terrible. You can click Yes to go on, but it's strongly recommended to enable more colors. - + + %1行,%2列 + %1 row(s), %2 col(s) + + + 生成命令失败: %1 Failed to generate command: %1 - + 正在构建高度矩阵 Making height matrix - + 正在构建三维结构 Building 3D structure - + 正在收集整张图片的颜色 Collecting colors of the whole image - + 正在压缩立体地图画 Compressing 3D map pixel arts - + 正在为立体地图画搭桥 Constructing glass bridge - + 正在匹配颜色 Matching colors - + 正在使用抖动仿色 Dithering - + 正在将平板地图画变为墙面地图画 Converting flat map art to wall map art - + 正在写入三维结构 Writing 3D structure - + 正在写入方块列表 Writing block palette - + 正在写入地图数据文件 Writing map data - + 正在写入基础信息 Writing meta data - + 这不是严重的问题,你可以直接忽略这个警告,或者把它反馈给开发者,不影响正常使用。只是 Slopecraft 可能占用更多的内存。 详细信息: %1 @@ -1515,48 +1536,48 @@ Details: %1 - + 获取本进程的内存占用失败 Failed to query memory usage of this process - + 获取操作系统内存占用失败 Failed to query system memory usage - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: From 80e8d616f9dd06e4b37bf88bdb390a7124ad7d0d Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 15:09:37 +0800 Subject: [PATCH 1067/1123] Exclude non-PNG images Signed-off-by: ToKiNoBug --- utilities/libpngReader/libpng_reader.cpp | 219 ++++++++++++----------- 1 file changed, 118 insertions(+), 101 deletions(-) diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index 4f1e721a..e22ec7fb 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -19,8 +19,7 @@ void png_callback_read_data_from_memory(png_struct *png, png_byte *data, const size_t can_read_bytes = ioptr->max_length - ioptr->offset; if (can_read_bytes < read_length) { png_error(png, "EOF"); - - // return; + return; } memcpy(data, (char *)(ioptr->data) + ioptr->offset, read_length); @@ -31,125 +30,143 @@ std::tuple, std::string> parse_png_into_argb32(std::span encoded, std::vector &pixels) noexcept { std::string warnings{}; - png_struct *png = - png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png == NULL) { - return {tl::make_unexpected("Failed to create png read struct."), warnings}; + if (encoded.size() < 8) { + return { + tl::make_unexpected(fmt::format( + "File is too small ({} bytes) to be possible PNG", encoded.size())), + warnings}; } + try { + png_struct *png = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png == NULL) { + return {tl::make_unexpected("Failed to create png read struct."), + warnings}; + } - png_info *info = png_create_info_struct(png); - if (info == NULL) { - png_destroy_read_struct(&png, &info, NULL); - return {tl::make_unexpected("Failed to create png info struct."), warnings}; - } + png_info *info = png_create_info_struct(png); + if (info == NULL) { + png_destroy_read_struct(&png, &info, NULL); + return {tl::make_unexpected("Failed to create png info struct."), + warnings}; + } - png_info *info_end = png_create_info_struct(png); - if (info_end == NULL) { - png_destroy_read_struct(&png, &info, &info_end); - return {tl::make_unexpected("Failed to create png info_end struct."), - warnings}; - } + png_info *info_end = png_create_info_struct(png); + if (info_end == NULL) { + png_destroy_read_struct(&png, &info, &info_end); + return {tl::make_unexpected("Failed to create png info_end struct."), + warnings}; + } + { + const auto compare_result = png_sig_cmp(encoded.data(), 0, 8); + if (compare_result not_eq 0) { + return {tl::make_unexpected("Not a png file."), warnings}; + } + } - // make a ioptr for libpng - read_buffer_wrapper wrapper; - wrapper.data = encoded.data(); - wrapper.offset = 0; - wrapper.max_length = encoded.size_bytes(); + // make a ioptr for libpng + read_buffer_wrapper wrapper; + wrapper.data = encoded.data(); + wrapper.offset = 0; // read file header + wrapper.max_length = encoded.size_bytes(); - png_set_read_fn(png, &wrapper, png_callback_read_data_from_memory); + png_set_read_fn(png, &wrapper, png_callback_read_data_from_memory); - png_read_info(png, info); + png_read_info(png, info); - uint32_t width{0}, height{0}; - int bit_depth, color_type, interlace_method, compress_method, filter_method; - bool add_alpha = false; + uint32_t width{0}, height{0}; + int bit_depth, color_type, interlace_method, compress_method, filter_method; + bool add_alpha = false; - png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, - &interlace_method, &compress_method, &filter_method); + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, + &interlace_method, &compress_method, &filter_method); - // cout << "\nwidth = " << width; - // cout << "\nheight = " << height; - // cout << "\nbit_depth = " << bit_depth; - // cout << "\ncolor_type = " << color_type << " ("; + // cout << "\nwidth = " << width; + // cout << "\nheight = " << height; + // cout << "\nbit_depth = " << bit_depth; + // cout << "\ncolor_type = " << color_type << " ("; - if (bit_depth > 8) { - png_set_strip_16(png); - } - if (bit_depth < 8) png_set_expand(png); - - switch (color_type) { - case PNG_COLOR_TYPE_GRAY: // fixed - png_set_gray_to_rgb(png); - add_alpha = true; - // cout << "PNG_COLOR_TYPE_GRAY"; - break; - case PNG_COLOR_TYPE_PALETTE: // fixed - - png_set_palette_to_rgb(png); - png_set_bgr(png); - { - int num_trans = 0; - png_get_tRNS(png, info, NULL, &num_trans, NULL); - if (num_trans <= 0) { - add_alpha = true; + if (bit_depth > 8) { + png_set_strip_16(png); + } + if (bit_depth < 8) png_set_expand(png); + + switch (color_type) { + case PNG_COLOR_TYPE_GRAY: // fixed + png_set_gray_to_rgb(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_GRAY"; + break; + case PNG_COLOR_TYPE_PALETTE: // fixed + + png_set_palette_to_rgb(png); + png_set_bgr(png); + { + int num_trans = 0; + png_get_tRNS(png, info, NULL, &num_trans, NULL); + if (num_trans <= 0) { + add_alpha = true; + } + // cout << "num_trans = " << num_trans << endl; } - // cout << "num_trans = " << num_trans << endl; - } - // cout << "PNG_COLOR_TYPE_PALETTE"; - break; - case PNG_COLOR_TYPE_RGB: // fixed - png_set_bgr(png); - add_alpha = true; - // cout << "PNG_COLOR_TYPE_RGB"; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: // fixed - png_set_bgr(png); - // cout << "PNG_COLOR_TYPE_RGB_ALPHA"; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: // fixed - png_set_gray_to_rgb(png); - // png_set_swap_alpha(png); - // cout << "PNG_COLOR_TYPE_GRAY_ALPHA"; - break; - default: - png_destroy_read_struct(&png, &info, &info_end); - return { - tl::make_unexpected(fmt::format("Unknown color type {}", color_type)), - warnings}; - } - // cout << ")\n"; - // #warning here + // cout << "PNG_COLOR_TYPE_PALETTE"; + break; + case PNG_COLOR_TYPE_RGB: // fixed + png_set_bgr(png); + add_alpha = true; + // cout << "PNG_COLOR_TYPE_RGB"; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: // fixed + png_set_bgr(png); + // cout << "PNG_COLOR_TYPE_RGB_ALPHA"; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: // fixed + png_set_gray_to_rgb(png); + // png_set_swap_alpha(png); + // cout << "PNG_COLOR_TYPE_GRAY_ALPHA"; + break; + default: + png_destroy_read_struct(&png, &info, &info_end); + return {tl::make_unexpected( + fmt::format("Unknown color type {}", color_type)), + warnings}; + } + // cout << ")\n"; + // #warning here - pixels.resize(height * width); - // img->resize(height, width); + pixels.resize(height * width); + // img->resize(height, width); - std::vector row_ptrs; - row_ptrs.resize(height); - for (int r = 0; r < int(height); r++) { - row_ptrs[r] = reinterpret_cast(pixels.data() + r * width); - } + std::vector row_ptrs; + row_ptrs.resize(height); + for (int r = 0; r < int(height); r++) { + row_ptrs[r] = reinterpret_cast(pixels.data() + r * width); + } - png_read_image(png, row_ptrs.data()); + png_read_image(png, row_ptrs.data()); - if (add_alpha) { // add alpha manually - for (int r = 0; r < int(height); r++) { - uint8_t *const current_row = row_ptrs[r]; - for (int pixel_idx = width - 1; pixel_idx > 0; pixel_idx--) { - const uint8_t *const data_src = current_row + pixel_idx * 3; - uint8_t *const data_dest = current_row + pixel_idx * 4; + if (add_alpha) { // add alpha manually + for (int r = 0; r < int(height); r++) { + uint8_t *const current_row = row_ptrs[r]; + for (int pixel_idx = width - 1; pixel_idx > 0; pixel_idx--) { + const uint8_t *const data_src = current_row + pixel_idx * 3; + uint8_t *const data_dest = current_row + pixel_idx * 4; - for (int i = 2; i >= 0; i--) { - data_dest[i] = data_src[i]; + for (int i = 2; i >= 0; i--) { + data_dest[i] = data_src[i]; + } + data_dest[3] = 0xFF; } - data_dest[3] = 0xFF; + current_row[3] = 0xFF; } - current_row[3] = 0xFF; } - } - // png_destroy_info_struct(png, &info); - png_destroy_read_struct(&png, &info, &info_end); + // png_destroy_info_struct(png, &info); + png_destroy_read_struct(&png, &info, &info_end); - return {image_info{height, width}, warnings}; + return {image_info{height, width}, warnings}; + } catch (const std::exception &e) { + return {tl::make_unexpected(e.what()), warnings}; + } } From 558a9c0a0a7f5afaa29914bcb21ad10a46fe61ef Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 15:26:49 +0800 Subject: [PATCH 1068/1123] Add endermanPickable to mud and moss_block Signed-off-by: ToKiNoBug --- Blocks/CustomBlocks/block_list.json | 3 ++- Blocks/FixedBlocks/block_list.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Blocks/CustomBlocks/block_list.json b/Blocks/CustomBlocks/block_list.json index af7d4add..3814efe8 100644 --- a/Blocks/CustomBlocks/block_list.json +++ b/Blocks/CustomBlocks/block_list.json @@ -425,7 +425,8 @@ "nameZH": "苔藓块", "nameEN": "Moss block", "icon": "moss_block.png", - "version": 17 + "version": 17, + "endermanPickable": true }, { "baseColor": 29, diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 2688f616..0e168c6d 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -1648,7 +1648,8 @@ "nameZH": "泥巴", "nameEN": "Mud", "icon": "mud.png", - "version": 19 + "version": 19, + "endermanPickable": true }, { "baseColor": 46, From d127ad4ce4b392709696a04204543e4f63476ee8 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 16:07:19 +0800 Subject: [PATCH 1069/1123] Display warnings of blocklist Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.h | 1 + utilities/BlockListManager/BlockListManager.cpp | 17 +---------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/SlopeCraft/SCWind.h b/SlopeCraft/SCWind.h index bfec0f9d..a2be7a01 100644 --- a/SlopeCraft/SCWind.h +++ b/SlopeCraft/SCWind.h @@ -86,6 +86,7 @@ class SCWind : public QMainWindow { flat_diagram, data_file }; + private slots: void on_pb_add_image_clicked() noexcept; void on_pb_remove_image_clicked() noexcept; diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 70989493..8f97e240 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -79,7 +79,7 @@ BlockListManager::impl_addblocklist(const QByteArray &file_content) noexcept { errmsg.resize(sd_err.size); warning.resize(sd_warn.size); - if (not errmsg.empty()) { + if ((not errmsg.empty()) or (not warning.empty())) { errmsg.append(QStringLiteral("\npwd: %1") .arg(QFileInfo{"."}.absolutePath()) .toLocal8Bit()); @@ -140,21 +140,6 @@ bool BlockListManager::add_blocklist(QString filename) noexcept { } this->blockslists.emplace_back(name, std::move(tmp)); return true; - - // for (auto &encoding : {filename.toLocal8Bit(), filename.toUtf8()}) { - // std::unique_ptr tmp - // = - // this->impl_addblocklist(encoding.data()); - // - // if (not tmp) { - // continue; - // } - // - // this->blockslists.emplace_back(name, std::move(tmp)); - // return true; - // } - - return false; } void BlockListManager::finish_blocklist() noexcept { From e4e723c131b7686c3f3c7e6d160afce2862caa0f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 16:07:41 +0800 Subject: [PATCH 1070/1123] Update doc of blocklist Signed-off-by: ToKiNoBug --- Blocks/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Blocks/README.md b/Blocks/README.md index 53641cf1..fbe168be 100644 --- a/Blocks/README.md +++ b/Blocks/README.md @@ -1,13 +1,13 @@ # 方块列表 -这个文件夹存储了方块列表相关。 +这个压缩包存储了方块列表相关,包含`block_list.json`和若干方块对应的图片(必须为PNG格式)。 -**FixedBlocks.json**是软件固定的方块列表,是最基础的那部分。每个方块相应的图片都存储在**FixedBlocks**文件夹下。正常情况下无需任何改动。 +**FixedBlocks.zip**是软件固定的方块列表,是最基础的那部分。每个方块相应的图片都存储在**FixedBlocks**文件夹下。正常情况下无需任何改动。 -**CustomBlocks.json**是用户自定义的方块列表,允许用户灵活编辑。我在里面写了一些半砖方块,可以作为参考。**CustomBlocks** +**CustomBlocks.zip**是用户自定义的方块列表,允许用户灵活编辑。我在里面写了一些半砖方块,可以作为参考。**CustomBlocks** 文件夹里有用户自定义方块的图片。 -每个方块拥有以下属性: +`block_list.json`记录了所有方块,每个方块拥有以下属性: | 属性名 | 类型 | 是否必填 | 默认值 | 说明 | |:----------------:|:------:|:----:|:-----:|---------------------------------------------------| @@ -18,10 +18,10 @@ | nameEN | string | 是 | | 方块的英文名 | | icon | string | 是 | | 方块对应图片的文件名(仅文件名,如*cobblestone.png*) | | idOld | string | 否 | 空字符串 | 方块在 1.12 的 id | -| needGlass | bool | 否 | false | 指示方块底部是否必须有其他方块(如灯笼) | -| isGlowing | bool | 否 | false | 指示方块是否发光 | -| endermanPickable | bool | 否 | false | 指示方块是否可以被末影人偷走 | -| burnable | bool | 否 | false | 指示方块是否可以被烧毁 | +| needGlass | bool | 否 | false | 方块底部是否必须有其他方块(如灯笼) | +| isGlowing | bool | 否 | false | 是否发光 | +| endermanPickable | bool | 否 | false | 是否可以被末影人偷走 | +| burnable | bool | 否 | false | 是否可以被烧毁 | 其中选填项可以跳过不填,SlopeCraft 会自动补全为默认值。 @@ -30,17 +30,17 @@ # block_list -Everything about blocklist is in this directory. +Everything about blocklist is in this zip, including `block_list.json` and block images (must be PNG format). -**FixedBlocks.json** stores all default blocks, acting as a fundamental blocklist to make sure that each +**FixedBlocks.zip** stores all default blocks, acting as a fundamental blocklist to make sure that each basecolor_widgets has at least one block. Image of each block is stored in directory named **FixedBlocks**. Usually you don't need to change anything about fixed blocklist. -**CustomBlocks.json** stores all user custom blocks, enabling users to use their favorite blocks in map art. Some slab +**CustomBlocks.zip** stores all user custom blocks, enabling users to use their favorite blocks in map art. Some slab blocks have been already written in this file as examples. Each block should have a corresponding image in * *CustomBlocks** directory. Different blocks can share single image file. -Each block has following attributes: +Each block has the following attributes: | Name | Type | Is Compulsory Item | Default Value | Description | |:----------------:|:------:|:------------------:|:-------------:|:-----------------------------------------------------------------------------------------------------------| From b6276540c51052756b5de14dd3d852aa9f7c505c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 16:07:57 +0800 Subject: [PATCH 1071/1123] Fix Quark mod blocks Signed-off-by: ToKiNoBug --- Blocks/QuarkModBlocks/block_list.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Blocks/QuarkModBlocks/block_list.json b/Blocks/QuarkModBlocks/block_list.json index aadb8db9..ac5a370b 100644 --- a/Blocks/QuarkModBlocks/block_list.json +++ b/Blocks/QuarkModBlocks/block_list.json @@ -269,7 +269,7 @@ "version": 14 }, { - "baseColor": 41, + "baseColor": 42, "id": "quark:pink_shingles_slab[type=bottom]", "nameZH": "粉色陶瓦砖瓦台阶", "nameEN": "Pink shingles slab", @@ -277,7 +277,7 @@ "version": 14 }, { - "baseColor": 42, + "baseColor": 41, "id": "quark:lime_shingles_slab[type=bottom]", "nameZH": "黄绿色陶瓦砖瓦台阶", "nameEN": "Lime shingles slab", From 4562eba11f5df1a39e711fe5b39aab95f402c864 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 28 Jul 2025 16:28:31 +0800 Subject: [PATCH 1072/1123] Add pale woods, resin blocks and redstone lamp Signed-off-by: ToKiNoBug --- Blocks/FixedBlocks/block_list.json | 58 +++++++++++++++++++++++++ Blocks/FixedBlocks/block_of_resin.png | Bin 0 -> 574 bytes Blocks/FixedBlocks/pale_moss_block.png | Bin 0 -> 656 bytes Blocks/FixedBlocks/pale_oak_leaves.png | Bin 0 -> 539 bytes Blocks/FixedBlocks/pale_oak_planks.png | Bin 0 -> 460 bytes Blocks/FixedBlocks/pale_oak_slab.png | Bin 0 -> 329 bytes Blocks/FixedBlocks/redstone_lamp.png | Bin 0 -> 638 bytes Blocks/FixedBlocks/resin_bricks.png | Bin 0 -> 446 bytes 8 files changed, 58 insertions(+) create mode 100644 Blocks/FixedBlocks/block_of_resin.png create mode 100644 Blocks/FixedBlocks/pale_moss_block.png create mode 100644 Blocks/FixedBlocks/pale_oak_leaves.png create mode 100644 Blocks/FixedBlocks/pale_oak_planks.png create mode 100644 Blocks/FixedBlocks/pale_oak_slab.png create mode 100644 Blocks/FixedBlocks/redstone_lamp.png create mode 100644 Blocks/FixedBlocks/resin_bricks.png diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 0e168c6d..a8916a7f 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -213,6 +213,14 @@ "version": 14, "wallUseable": false }, + { + "baseColor": 6, + "id": "minecraft:pale_oak_leaves[distance=7,persistent=true]", + "nameZH": "苍白橡树树叶", + "nameEN": "Pale oak leaves", + "icon": "pale_oak_leaves.png", + "version": 21 + }, { "baseColor": 7, "id": "minecraft:oak_leaves[distance=7,persistent=true]", @@ -461,6 +469,24 @@ "icon": "target.png", "version": 16 }, + { + "baseColor": 14, + "id": "minecraft:pale_oak_planks", + "nameZH": "苍白橡木木板", + "nameEN": "pale oak plank", + "icon": "pale_oak_planks.png", + "version": 21, + "burnable": true + }, + { + "baseColor": 14, + "id": "minecraft:pale_oak_slab[type=top,waterlogged=false]", + "nameZH": "苍白橡木台阶", + "nameEN": "Pale oak slab", + "icon": "pale_oak_slab.png", + "version": 21, + "burnable": true + }, { "baseColor": 15, "id": "minecraft:orange_concrete", @@ -918,6 +944,14 @@ "burnable": true, "needStone": true }, + { + "baseColor": 22, + "id": "minecraft:pale_moss_block", + "nameZH": "苍白苔藓块", + "nameEN": "Pale moss block", + "icon": "pale_moss_block.png", + "version": 21 + }, { "baseColor": 23, "id": "minecraft:cyan_concrete", @@ -1530,6 +1564,30 @@ "version": 0, "idOld": "minecraft:stained_hardened_clay[color=orange]" }, + { + "baseColor": 37, + "id": "minecraft:redstone_lamp", + "nameZH": "红石灯", + "nameEN": "Redstone lamp", + "icon": "redstone_lamp.png", + "version": 21 + }, + { + "baseColor": 37, + "id": "minecraft:resin_block", + "nameZH": "树脂块", + "nameEN": "Resin block", + "icon": "block_of_resin.png", + "version": 21 + }, + { + "baseColor": 37, + "id": "minecraft:resin_bricks", + "nameZH": "树脂砖", + "nameEN": "Resin brick", + "icon": "resin_bricks.png", + "version": 21 + }, { "baseColor": 38, "id": "minecraft:magenta_terracotta", diff --git a/Blocks/FixedBlocks/block_of_resin.png b/Blocks/FixedBlocks/block_of_resin.png new file mode 100644 index 0000000000000000000000000000000000000000..a57614fde9ca5335a6188dd0961d59d1eda2ff58 GIT binary patch literal 574 zcmV-E0>S->P)wB#>8De}TO)f<17;;c)Mt)Sd6NwBxs?&k;eE>jyRD{zJ<~N^#ZZ;hs zfa=eI>U01gTEyf>^{Kfy3rxpHZ8C;3^Z@w#{E9n~q=_P0#7GCK(}ChFAi1DFcOr3t zm#01RRe-TwjcPp&7t|(ervS_Xvu)n(D`tV&-rH8mP^02Dk7VfKl0i?u2A%~byL|*k9!^KdrH4`cwCnPH&~9CSf}RZUaBl#x{axSu8*h(yb$?}5 z+O4&w`IQX469cVXjIT`!fa&-YXVEg!jq_C(pO!nctr8ujbZC-`i18JU zbQ1cy+s*7Hqe1#U*jCx3pegBWqjh{ka~7CH>zIdogEYC^G|SNAKdemvXOwloCIA2c M07*qoM6N<$f@?bikN^Mx literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/pale_moss_block.png b/Blocks/FixedBlocks/pale_moss_block.png new file mode 100644 index 0000000000000000000000000000000000000000..249efbd3a1b97dc51ff994b374df5094a0389e32 GIT binary patch literal 656 zcmV;B0&o3^P)c=4H5sf1rAD)n&WD<`^(;Wcn`Gwhh z%E`^In=e23;nZgHDewC?I(`?GC|d0%9lz^_gkc|m{7|5EMy(<0?DZ=Ev-ykKIb zr#4|J1ac_QIwMVYn9}fZ{3IF<+;^+pBnWz_=NJ6oM`b}hzYvCfw9bge5tDd?DGif& zL^K?rb;kL{8CTbru7TNniYX02(5o`A$u1WwI)2wxX%zufqFl8qQEuQV;1oN4m*rxG z6qOa5L95*)8b_GpvGVRo9v_}60^6^x&6EbMGq;UF&||aSq7sD^f{)`TrZnFP(sajW zy>+44o}+Q(DD1l->I6ZL>51=9H qZcW3m?}mk8AC)LaXlrk^oBRjgDl@9y@?gvW0000lq2!e$m(@dRaL9nq-6SC~WF2bTuu;L;FY!XsS`nlt^9N*w>5zcUx zobufNKleZX`4vF7-*K(hIRHr-V~Ub*_hTh*06SyZJa3ebPtq8DeRJ&qw%d1-GzR#T zeAm9kFTrX7gkiwz%UccT_B$>N0|4&Yw>81Ne0Wmx*+K!Bq9n^l&VLWXfHMFw(Aqt}{`{yt5yGH1Q~+5%azdWZ z7Ang}PFK}|(=tWL&e$V0GB`0*uy5yM1wGl^I&*O;PY^St>m(G(@y?K|_?Ldm{^-cb4b z3fUh5pe4Q%m@o`#*Zp9L7lLgj5m`QRXTD4^#+U8;;IGzdon!4D{rK>t{4n|F6MvF4 duCsrdi~qjs<|PvF>D>ST002ovPDHLkV1hdH^Bn*H literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/pale_oak_planks.png b/Blocks/FixedBlocks/pale_oak_planks.png new file mode 100644 index 0000000000000000000000000000000000000000..82fcc1cfce00836e737468e1e24e1b34715a0411 GIT binary patch literal 460 zcmV;-0WfS`8|^+vdQ-Jf-bGV z$Bim0{>;Bmrg$bz1Yncx0f?g|or^a9pieL8))%y{xo9>6z*|KNaT|Lhhcb} zz-FL6a2aSV|M5$Mk5r|6j7MV9M5HQ3s!~jvh)EOq7?0|l_Gw*n-YQziDUaJ)b(OZw z>ou;Tg=nLCK>_Ba;r`+7B-DlvY`?oaY$ob|JH7#PwLj)ob8l||0000#MCtBz-@s$GjHCNthlyWVPmbjekEIjwCP(5h7GrC|7e#iUZ!=r z(!rW<&F8C47y6iY=Q0@J0c0RVB7mAMRu+8o>$)aJ}J6XR3Rl`>eEA; z?XN%IbT0g$orxFNcD5VfGh~gAXLcoeqgl+t7qqpgx z=ygiRXnWzFqjSzZccWR+?|H(P1+Wc`XgJ4n6dJAtKs)H;hXMf4QF!ZZV`w?P{OsU| zLSnMOKVZG60?=?RdaDW1a8ARu==LXcfmd}02=T)?0GU)l!?mbcWrT>?RI{{$KGAS4 z)f5X^0A|aWhHGIP+M1x6Us1El7+Q|Ht#jhv;D-XwQ8+r-!Vd-KS0Od4EWKCrt2IGu z&t))O07#EV2V1oET+EUxNlyG50QPGp?_0Y7D3wy-Q@ot=tXSaeGLT@iq!Nv0u#sW9 zSkbJOIPFZx{8{2!I$tlY38(i-h<+#@0!w6@C6#V}0>F5dC@U7Sc#e|Hp7)4`V!g(6 z6KVRRMJ&DQMU`z+lW#w~m9sK~k8kRDj)HAy9ADfaL@Wc_RFi*PMPokyxWzU!KD?~p zIm$YN=9bQ;n&b5gi_T!l_s)RnbWHuZNi>>qb{X*P_Xyk2INV8yZC&G6Zf|2Qx+v{ z+qd70Nr=Xjb(5^e}8gqncmQ+H)Dt793yP$zy7`7VV%lEdT%j literal 0 HcmV?d00001 diff --git a/Blocks/FixedBlocks/resin_bricks.png b/Blocks/FixedBlocks/resin_bricks.png new file mode 100644 index 0000000000000000000000000000000000000000..62f0834d8c7a77bf52d2640b6eab4ad280c706d9 GIT binary patch literal 446 zcmV;v0YUzWP)d Date: Tue, 29 Jul 2025 23:09:07 +0800 Subject: [PATCH 1073/1123] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E8=AF=91=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Blocks/CustomBlocks/block_list.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Blocks/CustomBlocks/block_list.json b/Blocks/CustomBlocks/block_list.json index 3814efe8..914b9c6b 100644 --- a/Blocks/CustomBlocks/block_list.json +++ b/Blocks/CustomBlocks/block_list.json @@ -9,7 +9,7 @@ // id 是这种方块的 id,也是必填项,最好附带完整的方块状态,必须加 minecraft:前缀", "id": "minecraft:waxed_cut_copper_slab[type=top,waterlogged=false]", // nameZH 是方块中文名称,必填", - "nameZH": "涂蜡切制铜台阶", + "nameZH": "涂蜡的切制铜台阶", // nameEN 是方块英文名称,必填", "nameEN": "Waxed cut copper slab", // icon 是方块对应图片的文件名,它应当放在 CustomBlocks 文件夹下。必填", @@ -67,7 +67,7 @@ { "baseColor": 11, "id": "minecraft:smooth_stone_slab[type=top,waterlogged=false]", - "nameZH": "平滑石台阶", + "nameZH": "平滑石头台阶", "nameEN": "Smooth stone slab", "icon": "smooth_stone_slab.png", "version": 0, From f3d9c97b4e9d303bf942ad90a4c3100d0a688b5d Mon Sep 17 00:00:00 2001 From: Mifan-T <49829769+Mifan-T@users.noreply.github.com> Date: Tue, 29 Jul 2025 23:47:00 +0800 Subject: [PATCH 1074/1123] =?UTF-8?q?=E8=A1=A5=E5=85=85=20endermanPickable?= =?UTF-8?q?=20=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Blocks/CustomBlocks/block_list.json | 6 ++++-- Blocks/FixedBlocks/block_list.json | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Blocks/CustomBlocks/block_list.json b/Blocks/CustomBlocks/block_list.json index 914b9c6b..36787117 100644 --- a/Blocks/CustomBlocks/block_list.json +++ b/Blocks/CustomBlocks/block_list.json @@ -409,7 +409,8 @@ "nameEN": "Melon", "icon": "melon_top.png", "version": 0, - "idOld": "minecraft:melon_block" + "idOld": "minecraft:melon_block", + "endermanPickable": true }, { "baseColor": 24, @@ -417,7 +418,8 @@ "nameZH": "菌丝体", "nameEN": "Mycelium", "icon": "mycelium_top.png", - "version": 0 + "version": 0, + "endermanPickable": true }, { "baseColor": 27, diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index a8916a7f..12fe72c6 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -950,7 +950,8 @@ "nameZH": "苍白苔藓块", "nameEN": "Pale moss block", "icon": "pale_moss_block.png", - "version": 21 + "version": 21, + "endermanPickable": true }, { "baseColor": 23, From 67f16b40d3f8756793956b214b384b76d77986eb Mon Sep 17 00:00:00 2001 From: Mifan-T <49829769+Mifan-T@users.noreply.github.com> Date: Wed, 30 Jul 2025 05:23:34 +0800 Subject: [PATCH 1075/1123] =?UTF-8?q?=E5=AE=8C=E6=95=B4=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E8=AF=91=E5=90=8D=20(MC1.21)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Blocks/FixedBlocks/block_list.json | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Blocks/FixedBlocks/block_list.json b/Blocks/FixedBlocks/block_list.json index 12fe72c6..f8fb4baf 100644 --- a/Blocks/FixedBlocks/block_list.json +++ b/Blocks/FixedBlocks/block_list.json @@ -337,7 +337,7 @@ { "baseColor": 9, "id": "minecraft:clay", - "nameZH": "黏土块", + "nameZH": "黏土", "nameEN": "Clay block", "icon": "clay.png", "version": 0, @@ -593,7 +593,7 @@ { "baseColor": 15, "id": "minecraft:waxed_copper_block", - "nameZH": "涂蜡铜块", + "nameZH": "涂蜡的铜块", "nameEN": "Waxed copper", "icon": "waxed_copper_block.png", "version": 17 @@ -601,7 +601,7 @@ { "baseColor": 15, "id": "minecraft:waxed_cut_copper", - "nameZH": "涂蜡切制铜块", + "nameZH": "涂蜡的切制铜块", "nameEN": "Waxed cut copper", "icon": "waxed_cut_copper.png", "version": 17 @@ -609,7 +609,7 @@ { "baseColor": 15, "id": "minecraft:waxed_copper_bulb", - "nameZH": "涂蜡铜灯", + "nameZH": "涂蜡的铜灯", "nameEN": "Waxed copper bulb", "icon": "copper_bulb.png", "version": 21 @@ -617,7 +617,7 @@ { "baseColor": 15, "id": "minecraft:waxed_copper_grate", - "nameZH": "涂蜡铜格栅", + "nameZH": "涂蜡的铜格栅", "nameEN": "Waxed copper grate", "icon": "copper_grate.png", "version": 21 @@ -936,7 +936,7 @@ { "baseColor": 22, "id": "minecraft:light_gray_carpet", - "nameZH": "浅灰色地毯", + "nameZH": "淡灰色地毯", "nameEN": "Light gray carpet", "icon": "light_gray_wool.png", "version": 0, @@ -1655,7 +1655,7 @@ { "baseColor": 44, "id": "minecraft:waxed_exposed_copper", - "nameZH": "斑驳的涂蜡铜块", + "nameZH": "涂蜡的斑驳铜块", "nameEN": "Waxed exposed copper", "icon": "waxed_exposed_copper.png", "version": 17 @@ -1663,7 +1663,7 @@ { "baseColor": 44, "id": "minecraft:waxed_exposed_cut_copper", - "nameZH": "斑驳的涂蜡切制铜块", + "nameZH": "涂蜡的斑驳切制铜块", "nameEN": "Waxed exposed cut copper", "icon": "waxed_exposed_cut_copper.png", "version": 17 @@ -1679,7 +1679,7 @@ { "baseColor": 44, "id": "minecraft:waxed_exposed_copper_bulb", - "nameZH": "斑驳的涂蜡铜灯", + "nameZH": "涂蜡的斑驳铜灯", "nameEN": "Waxed exposed copper bulb", "icon": "exposed_copper_bulb.png", "version": 21 @@ -1687,7 +1687,7 @@ { "baseColor": 44, "id": "minecraft:waxed_exposed_copper_grate", - "nameZH": "斑驳的涂蜡铜格栅", + "nameZH": "涂蜡的斑驳铜格栅", "nameEN": "Waxed exposed copper grate", "icon": "exposed_copper_grate.png", "version": 21 @@ -1831,7 +1831,7 @@ { "baseColor": 55, "id": "minecraft:waxed_oxidized_copper", - "nameZH": "氧化的涂蜡铜块", + "nameZH": "涂蜡的氧化铜块", "nameEN": "Waxed oxidized copper", "icon": "waxed_oxidized_copper.png", "version": 17 @@ -1839,7 +1839,7 @@ { "baseColor": 55, "id": "minecraft:waxed_oxidized_cut_copper", - "nameZH": "氧化的涂蜡切制铜块", + "nameZH": "涂蜡的氧化切制铜块", "nameEN": "Waxed oxidized cut copper", "icon": "waxed_oxidized_cut_copper.png", "version": 17 @@ -1847,7 +1847,7 @@ { "baseColor": 55, "id": "minecraft:waxed_oxidized_copper_bulb", - "nameZH": "氧化的涂蜡铜灯", + "nameZH": "涂蜡的氧化铜灯", "nameEN": "Waxed oxidized copper bulb", "icon": "oxidized_copper_bulb.png", "version": 21 @@ -1855,7 +1855,7 @@ { "baseColor": 55, "id": "minecraft:waxed_oxidized_copper_grate", - "nameZH": "氧化的涂蜡铜格栅", + "nameZH": "涂蜡的氧化铜格栅", "nameEN": "Waxed oxidized copper grate", "icon": "oxidized_copper_grate.png", "version": 21 @@ -1881,7 +1881,7 @@ { "baseColor": 56, "id": "minecraft:waxed_weathered_copper", - "nameZH": "锈蚀的涂蜡铜块", + "nameZH": "涂蜡的锈蚀铜块", "nameEN": "Waxed weathered copper", "icon": "waxed_weathered_copper.png", "version": 17 @@ -1889,7 +1889,7 @@ { "baseColor": 56, "id": "minecraft:waxed_weathered_cut_copper", - "nameZH": "锈蚀的涂蜡切制铜块", + "nameZH": "涂蜡的锈蚀切制铜块", "nameEN": "Waxed weathered cut copper", "icon": "waxed_weathered_cut_copper.png", "version": 17 @@ -1897,7 +1897,7 @@ { "baseColor": 56, "id": "minecraft:waxed_weathered_copper_bulb", - "nameZH": "锈蚀的涂蜡铜灯", + "nameZH": "涂蜡的锈蚀铜灯", "nameEN": "Waxed weathered copper bulb", "icon": "weathered_copper_bulb.png", "version": 21 @@ -1905,7 +1905,7 @@ { "baseColor": 56, "id": "minecraft:waxed_weathered_copper_grate", - "nameZH": "锈蚀的涂蜡铜格栅", + "nameZH": "涂蜡的锈蚀铜格栅", "nameEN": "Waxed weathered copper grate", "icon": "weathered_copper_grate.png", "version": 21 @@ -2016,7 +2016,7 @@ { "baseColor": 43, "id": "minecraft:cherry_wood", - "nameZH": "樱花木头", + "nameZH": "樱花原木", "nameEN": "Cherry wood", "icon": "cherry_log.png", "version": 20, @@ -2034,7 +2034,7 @@ { "baseColor": 42, "id": "minecraft:stripped_cherry_wood[axis=y]", - "nameZH": "去皮樱花木头", + "nameZH": "去皮樱花原木", "nameEN": "Stripped cherry wood", "icon": "stripped_cherry_log.png", "version": 20, From accb0761e71c8602e4a472f2fef9eb8959993a82 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Thu, 7 Aug 2025 16:46:15 +0800 Subject: [PATCH 1076/1123] Fix image corruption in VC (#138 Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 43b25c2e..543c83da 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -698,7 +698,7 @@ void VCWind::on_tb_remove_images_clicked() noexcept { void VCWind::setup_image(const QImage &img) noexcept { this->setup_allowed_colorset(); bool ok = this->kernel->set_image( - img.height(), img.width(), + img.width(), img.height(), reinterpret_cast(img.scanLine(0)), true); if (!ok) { const auto ret = QMessageBox::critical( @@ -761,7 +761,7 @@ void VCWind::show_image(decltype(image_cache)::iterator it) noexcept { return; } - QImage img(cols, rows, QImage::Format_ARGB32); + QImage img(rows, cols, QImage::Format_ARGB32); memset(img.scanLine(0), 0xFF, img.sizeInBytes()); this->kernel->converted_image(reinterpret_cast(img.scanLine(0)), From e403901805b10652c10f6eefda2f4c66e10e31af Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 11:41:27 +0800 Subject: [PATCH 1077/1123] Fix image corruption in VC (#138 Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 8 +++++--- VisualCraft/VCWind_export.cpp | 2 +- VisualCraftL/TokiVC.cpp | 2 +- utilities/ColorManip/imageConvert.hpp | 21 +++++++++++++++------ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 543c83da..011a246e 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -750,14 +750,16 @@ void VCWind::show_image(decltype(image_cache)::iterator it) noexcept { const bool ok = this->kernel->convert(this->current_selected_algo(), this->ui->cb_algo_dither->isChecked()); if (!ok) { - assert(false); + it->second.second = QImage{}; + this->ui->lable_converted->setPixmap(QPixmap{}); return; } - int64_t rows, cols; + int64_t rows = 0, cols = 0; this->kernel->converted_image(nullptr, &rows, &cols, true); if (rows <= 0 || cols <= 0) { - assert(false); + it->second.second = QImage{}; + this->ui->lable_converted->setPixmap(QPixmap{}); return; } diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 4819c184..4b33a69c 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -397,7 +397,7 @@ void VCWind::on_pb_execute_clicked() noexcept { ->setText( QStringLiteral("%i %").arg(100.0f * task_finished / task_num)); - QImage new_img(it->second.first.height(), it->second.first.width(), + QImage new_img(it->second.first.width(), it->second.first.height(), QImage::Format_ARGB32); this->kernel->converted_image((uint32_t *)new_img.scanLine(0), nullptr, nullptr, true); diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 0db8dbff..636bc746 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -710,7 +710,7 @@ void TokiVC::converted_image(uint32_t *dest, int64_t *rows, int64_t *cols, // constexpr size_t sz = sizeof(decltype(this->img_cvter)::TokiColor_t); - this->img_cvter.converted_image(dest, rows, cols, !write_dest_row_major); + this->img_cvter.converted_image(dest, rows, cols, not write_dest_row_major); } bool TokiVC::set_gpu_resource(const VCL_GPU_Platform *p, diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 8031d11f..96a63c56 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -311,10 +311,14 @@ class ImageCvter : public GPU_wrapper_wrapper { } if (data_dest != nullptr) { + Eigen::Map< + Eigen::Array> + dest{data_dest, rows(), cols()}; for (int64_t r = 0; r < rows(); r++) { for (int64_t c = 0; c < cols(); c++) { - const int64_t idx = - (is_dest_col_major) ? (c * rows() + r) : (r * cols() + c); + // const int64_t idx = + // (is_dest_col_major) ? (r * cols() + c) : (c * rows() + + // r); ARGB argb = this->dithered_image_(r, c); // process full-transparent image if (::getA(argb) <= 0) { @@ -329,15 +333,20 @@ class ImageCvter : public GPU_wrapper_wrapper { const auto color_id = it->second.color_id(); const auto color_index = basic_colorset.colorindex_of_colorid(color_id); + ARGB color; if (color_index != allowed_colorset_t::invalid_color_id) { - data_dest[idx] = RGB2ARGB(basic_colorset.RGB(color_index, 0), - basic_colorset.RGB(color_index, 1), - basic_colorset.RGB(color_index, 2)); + color = RGB2ARGB(basic_colorset.RGB(color_index, 0), + basic_colorset.RGB(color_index, 1), + basic_colorset.RGB(color_index, 2)); } else { - data_dest[idx] = 0x00'00'00'00; + color = 0x00'00'00'00; } + dest(r, c) = color; } } + if (is_dest_col_major) { + dest.transposeInPlace(); + } } } From df9d06a74bf1d4cb524db4f6bc4cf2ca9f6b9153 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 12:38:58 +0800 Subject: [PATCH 1078/1123] Update mc data version to 1.21.10 Signed-off-by: ToKiNoBug --- utilities/MCDataVersion/MCDataVersion.h | 82 +++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index 25ffb4a5..a83c67a0 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,6 +30,88 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + Snapshot_25w44a = 4659, + Snapshot_25w43a = 4655, + Snapshot_25w42a = 4654, + Snapshot_25w41a = 4653, + Java_1_21_10 = 4556, + Java_1_21_10__rc1 = 4555, + Java_1_21_9 = 4554, + Java_1_21_9__rc1 = 4553, + Java_1_21_9__pre4 = 4552, + Java_1_21_9__pre3 = 4551, + Java_1_21_9__pre2 = 4550, + Java_1_21_9__pre1 = 4549, + Snapshot_25w37a = 4547, + Snapshot_25w36b = 4546, + Snapshot_25w36a = 4545, + Snapshot_25w35a = 4542, + Snapshot_25w34b = 4540, + Snapshot_25w34a = 4539, + Snapshot_25w33a = 4538, + Snapshot_25w32a = 4536, + Snapshot_25w31a = 4534, + Java_1_21_8 = 4440, + Java_1_21_8__rc1 = 4439, + Java_1_21_7 = 4438, + Java_1_21_7__rc2 = 4437, + Java_1_21_7__rc1 = 4436, + Java_1_21_6 = 4435, + Java_1_21_6__rc1 = 4434, + Java_1_21_6__pre4 = 4433, + Java_1_21_6__pre3 = 4432, + Java_1_21_6__pre2 = 4431, + Java_1_21_6__pre1 = 4430, + Snapshot_25w21a = 4429, + Snapshot_25w20a = 4428, + Snapshot_25w19a = 4427, + Snapshot_25w18a = 4426, + Snapshot_25w17a = 4425, + Snapshot_25w16a = 4423, + Snapshot_25w15a = 4422, + Java_1_21_5 = 4325, + Java_1_21_5__rc2 = 4324, + Java_1_21_5__rc1 = 4323, + Java_1_21_5__pre3 = 4322, + Java_1_21_5__pre2 = 4321, + Java_1_21_5__pre1 = 4320, + Snapshot_25w10a = 4319, + Snapshot_25w09b = 4318, + Snapshot_25w09a = 4317, + Snapshot_25w08a = 4316, + Snapshot_25w07a = 4315, + Snapshot_25w06a = 4313, + Snapshot_25w05a = 4310, + Snapshot_25w04a = 4308, + Snapshot_25w03a = 4304, + Snapshot_25w02a = 4298, + Java_1_21_4 = 4189, + Java_1_21_4__rc3 = 4188, + Java_1_21_4__rc2 = 4186, + Java_1_21_4__rc1 = 4184, + Java_1_21_4__pre3 = 4183, + Java_1_21_4__pre2 = 4182, + Java_1_21_4__pre1 = 4179, + Snapshot_24w46a = 4178, + Snapshot_24w45a = 4177, + Snapshot_24w44a = 4174, + Java_1_21_3 = 4082, + Java_1_21_2 = 4080, + Java_1_21_2__rc2 = 4079, + Java_1_21_2__rc1 = 4078, + Java_1_21_2__pre5 = 4077, + Java_1_21_2__pre4 = 4076, + Java_1_21_2__pre3 = 4075, + Java_1_21_2__pre2 = 4074, + Java_1_21_2__pre1 = 4073, + Snapshot_24w40a = 4072, + Snapshot_24w39a = 4069, + Snapshot_24w38a = 4066, + Snapshot_24w37a = 4065, + Snapshot_24w36a = 4063, + Snapshot_24w35a = 4062, + Snapshot_24w34a = 4060, + Snapshot_24w33a = 4058, Java_1_21_1 = 3955, Java_1_21_1__rc1 = 3954, Java_1_21 = 3953, From ca98b7d147461c5e2b8b633cde4e63985c7f33d7 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 12:43:43 +0800 Subject: [PATCH 1079/1123] [CI] Use apple clang for all macOS Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 5 +++-- .github/workflows/macos-build-x64.yml | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 25281c7e..3522aa1a 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -37,7 +37,8 @@ jobs: - name: Install dependencies run: | - brew install llvm boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip + brew install boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip + #llvm #https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz - name: Install qt6.6.0-static @@ -58,7 +59,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ "-DCMAKE_PREFIX_PATH=$HOME/Downloads/qt6.6.0-arm64-apple-darwin;/opt/homebrew" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ "-DCMAKE_PREFIX_PATH=$HOME/Downloads/qt6.6.0-arm64-apple-darwin;/opt/homebrew" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index e4ec9344..8b4af4eb 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -32,9 +32,9 @@ jobs: # brew remove aws-sam-cli pipx cfn-lint # brew remove python # brew upgrade - - name: Install LLVM clang - run: | - brew install llvm + # - name: Install LLVM clang + # run: | + # brew install llvm - name: Check clang run: /usr/local/opt/llvm/bin/clang --version - name: echo matrix variables (build_type = ${{ matrix.build_type }}) @@ -76,7 +76,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build From e35a372d7e7c73c3c18b5f1acba960ad8dde8976 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 13:18:33 +0800 Subject: [PATCH 1080/1123] Revert "[CI] Use apple clang for all macOS" This reverts commit ca98b7d147461c5e2b8b633cde4e63985c7f33d7. --- .github/workflows/macos-build-arm64.yml | 5 ++--- .github/workflows/macos-build-x64.yml | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 3522aa1a..25281c7e 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -37,8 +37,7 @@ jobs: - name: Install dependencies run: | - brew install boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip - #llvm + brew install llvm boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip #https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz - name: Install qt6.6.0-static @@ -59,7 +58,7 @@ jobs: glslc --version - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ "-DCMAKE_PREFIX_PATH=$HOME/Downloads/qt6.6.0-arm64-apple-darwin;/opt/homebrew" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ "-DCMAKE_PREFIX_PATH=$HOME/Downloads/qt6.6.0-arm64-apple-darwin;/opt/homebrew" -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index 8b4af4eb..e4ec9344 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -32,9 +32,9 @@ jobs: # brew remove aws-sam-cli pipx cfn-lint # brew remove python # brew upgrade - # - name: Install LLVM clang - # run: | - # brew install llvm + - name: Install LLVM clang + run: | + brew install llvm - name: Check clang run: /usr/local/opt/llvm/bin/clang --version - name: echo matrix variables (build_type = ${{ matrix.build_type }}) @@ -76,7 +76,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build From acfe0a666058f5803058a9be14a9319df395d847 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 13:46:24 +0800 Subject: [PATCH 1081/1123] Update version to 5.3.2 Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b741072d..19093f63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.3.1) +set(SlopeCraft_version 5.3.2) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From 8f3b67c5139c35f736731d42c4b8e0082d683194 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 13:49:26 +0800 Subject: [PATCH 1082/1123] Fix a cmake warning finding boost Signed-off-by: ToKiNoBug --- cmake/required_deps/boost.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/required_deps/boost.cmake b/cmake/required_deps/boost.cmake index ee21ad3c..2539097f 100644 --- a/cmake/required_deps/boost.cmake +++ b/cmake/required_deps/boost.cmake @@ -2,6 +2,7 @@ if (${WIN32}) find_package(Boost COMPONENTS iostreams OPTIONAL_COMPONENTS multi_array + CONFIG ) else () message(STATUS "Finding boost without multi_array to avoid a fucking stupid error in BoostConfig.cmake") From f1d5a9c2fbe58ccaeb8a972cea6104899bcc0d5f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 13:49:41 +0800 Subject: [PATCH 1083/1123] [CI] Try to fix macOS build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 3 +++ .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 25281c7e..c8228959 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -39,6 +39,9 @@ jobs: run: | brew install llvm boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip + - name: Check clang + run: /opt/homebrew/opt/llvm/bin/clang -v + #https://github.com/SlopeCraft/QtBinaries/releases/download/qt6.6.0-arm64-apple-darwin/qt6.6.0-static-arm64-apple-darwin.tar.xz - name: Install qt6.6.0-static run: | diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index e4ec9344..b99c43d2 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -36,7 +36,7 @@ jobs: run: | brew install llvm - name: Check clang - run: /usr/local/opt/llvm/bin/clang --version + run: /usr/local/opt/llvm/bin/clang -v - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE From 66a45080029ea2d01d0d92dc2abce0b262fce009 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 14:04:42 +0800 Subject: [PATCH 1084/1123] Fix cmake warnings Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 2 +- utilities/BlockListManager/CMakeLists.txt | 2 +- utilities/ColorManip/CMakeLists.txt | 2 +- utilities/ExternalConverters/GAConverter/CMakeLists.txt | 2 +- utilities/Schem/CMakeLists.txt | 2 +- utilities/StatMemory/CMakeLists.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index 18ca9af7..ed39b771 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(OpenMP REQUIRED) find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) -find_package(Boost COMPONENTS iostreams OPTIONAL_COMPONENTS multi_array REQUIRED) +find_package(Boost COMPONENTS iostreams OPTIONAL_COMPONENTS multi_array CONFIG REQUIRED) find_package(libzip REQUIRED) find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) diff --git a/utilities/BlockListManager/CMakeLists.txt b/utilities/BlockListManager/CMakeLists.txt index 7ae8d62d..324f9aa9 100644 --- a/utilities/BlockListManager/CMakeLists.txt +++ b/utilities/BlockListManager/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) -find_package(Boost REQUIRED) +find_package(Boost CONFIG REQUIRED) set(BlockListManager_header_files BlockListManager.h diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index 02938ce6..bb11bc06 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) find_package(cereal REQUIRED) find_package(xsimd REQUIRED) -find_package(Boost REQUIRED) +find_package(Boost CONFIG REQUIRED) add_library(ColorManip diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index dd466a25..52d69220 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(SlopeCraft_GAConverter VERSION ${SlopeCraft_version} LANGUAGES CXX) # set(CMAKE_CXX_STANDARD 20) diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index f7383856..6a2b503c 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -22,7 +22,7 @@ find_package(cereal REQUIRED) find_package(fmt REQUIRED) find_package(magic_enum REQUIRED) -find_package(Boost) +find_package(Boost CONFIG) # target_compile_options(Schem BEFORE PUBLIC -std=c++17) target_link_libraries(Schem PUBLIC diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 99ae049b..faa0578b 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -19,7 +19,7 @@ elseif (${LINUX}) target_sources(StatMemory PRIVATE stat_memory_src/linux.cpp) elseif (${APPLE}) target_sources(StatMemory PRIVATE stat_memory_src/macos.cpp) -elseif () +else () message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") endif () From 40c0e3fa3465801296783f73186fc7a956d68e8c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 14:37:25 +0800 Subject: [PATCH 1085/1123] Display to be replaced files Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index c613afff..8b2f9436 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -714,9 +714,22 @@ void SCWind::on_pb_export_file_clicked() noexcept { QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::No}); msg_box.setWindowTitle(tr("%1 个文件将被替换").arg(exisiting_num)); msg_box.setText( - tr("以下文件将被替换:\n点击 Yes " - "将替换它们,点击 No 将取消这次导出。")); + tr("%1 个文件将被替换。点击 Show Details 可以查看它们。\n点击 Yes " + "将替换它们,点击 No 将取消这次导出。") + .arg(exisiting_num)); msg_box.setDetailedText(to_be_replaced); + // Click the button "Show Detail". If not found, let it go + for (QAbstractButton *abtn : msg_box.buttons()) { + QPushButton *btn = dynamic_cast(abtn); + if (not btn) [[unlikely]] { + continue; + } + const auto str = btn->text().toLower(); + if (str.contains("detail")) { + emit btn->click(); + break; + } + } } const auto ret = msg_box.exec(); From a4f67b8a44640d72bcdd3f7de9cffb7e1f7d39de Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 14:42:33 +0800 Subject: [PATCH 1086/1123] Update translations Signed-off-by: ToKiNoBug --- SlopeCraft/others/SlopeCraft_en_US.ts | 76 +++++++++---------- VisualCraft/others/VisualCraft_en_US.ts | 8 -- .../others/BlockListManager_en_US.ts | 10 +-- 3 files changed, 39 insertions(+), 55 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 43181a15..63dc153f 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -918,7 +918,7 @@ Map data are stored in map data files, assembled maps can take effect only after - + 关于 SlopeCraft About SlopeCraft @@ -1223,8 +1223,8 @@ Click Ignore to skip this image, and Cancel to cancel. - - + + 设置导出位置 Set export directory @@ -1233,124 +1233,116 @@ Click Ignore to skip this image, and Cancel to cancel. %1 个文件将被替换 %1 files will be replaced - - 以下文件将被替换: -%1 -点击 Yes 将替换它们,点击 No 将取消这次导出。 - These files will be replaced: -%1 -Click Yes to replace them, or No to cancel. - - 以下文件将被替换: + %1 个文件将被替换。点击 Show Details 可以查看它们。 点击 Yes 将替换它们,点击 No 将取消这次导出。 - Following files will be replaced. -Click Yes to replace them, or No to cancel. + %1 file(s) will be replaced. Click "Show Details" to view them. +Click Yes to replace, and No to cancel. - + %1 个图片导出失败 Failed to export %1 image(s) - + 导出失败的图片依次为: %1 Following image(s) failed to export: %1 - + 删除缓存失败 Failed to clean cache - + 无法删除文件或文件夹"%1"。 点击 Ignore 以跳过,点击 Retry 以重试,点击 Cancel 以取消这次操作 Failed to remove file or directory named "%1". Click Ignore to skip, Retry to retry and Cancel to cancel - + SlopeCraft 是一款由 ToKiNoBug 开发的立体地图画生成器,主要用于在 Minecraft 中制造可以生存实装的立体地图画(但同样支持传统的平板地图画)。 SlopeCraft is a Minecraft 3D pixel map arts generator developed by ToKiNoBug, mainly used to generate 3D pixel map arts that can be implemented in vanilla Minecraft survival mode (but also supports traditional flat pixel map arts). - + 本软件的开发持续集成与 macOS 软件适配由 iXOR Technology (Cubik65536 以及贡献者) 提供 The continuous integration solution and macOS version maintenance of this software is provided by iXOR Technology (Cubik65536 and contributors) - + 感谢 AbrasiveBoar902 为本软件的设计和优化贡献的力量 Thanks to AbrasiveBoar902 for his contribution to the design and optimization of this software - + 感谢 67au 为本软件的 macOS 与 Linux 适配做出的贡献 Thanks to 67au for his contribution during the development of macOS and Linux version of this software - + SlopeCraft 在开发时使用了 Qt,zlib 和 eigen 等开源库,对上述库的开发者表示感谢。 Open source libraries such as Qt, zlib and eigen are used during the development of SlopeCraft, thanks to the developers of these libraries. - + 本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。 This program is released under license GPL-3.0 or later. - + Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. - + 同时选中多个图片时,不显示 /give 命令。如果想预览导出的命令,请只选择一个图片。 Can't show /give command when you selecte multiple images. To view the command, select one image only. - + 无法为 %1 生成命令:%2 Failed to generate command for %1: %2 - + 无法创建/打开文件 %1:%2 Failed to create/open file %1: %2 - + 无法写入文件 %1:%2 Failed to write file %1: %2 - - + + %1 个文件保存失败 Failed to save %1 file(s) - + SlopeCraftL 未提供详细报错信息。 SlopeCraftL doesn't give further details. - + 错误码:%1,详情:%2 Error code: %1, details: %2 - + %1 生成失败,%2 Failed to generate %1, %2 @@ -1546,38 +1538,38 @@ Details: Failed to query system memory usage - + 保存颜色表 Save palette - - + + 保存颜色表失败 Failed to save colormap image - + 分配内存失败 Failed to allocate memory for image - + 无法生成文件 %1 Failed to generate %1 - + 保存测试文件 Save testing file - + 输出测试文件失败 Failed to save testing file - + 保存测试文件 %1 时出现错误。详细信息: %2 An error occured when saving test file %1. Details: diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 54c6dc5c..62c1a806 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -867,14 +867,6 @@ If you select a block in "Avaliable blocks" page, the other page will 这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - - %1 - -这不是一个致命错误,您可以选择其他的显卡,或者只使用 CPU 计算。点击 Ignore 将忽略这个错误,点击 Close 将关闭 VisualCraft - %1 - -This is not a fatal error, you can use other GPUs or your CPU instead. Click Ignore will ignore this error, or click Close to close VisualCraft - 创建 GPU 平台失败,平台序号为%1,设备序号为%2 diff --git a/utilities/BlockListManager/others/BlockListManager_en_US.ts b/utilities/BlockListManager/others/BlockListManager_en_US.ts index c28a4f78..469601a4 100644 --- a/utilities/BlockListManager/others/BlockListManager_en_US.ts +++ b/utilities/BlockListManager/others/BlockListManager_en_US.ts @@ -43,24 +43,24 @@ Unable to read zip archive "%1", it might be deleted accidentally. - + 无法删除方块列表 "%1",没有加载同名的方块列表。已加载:%2 Failed to load block list \"%1\", no block list for such name. Loaded: %2 - - + + 加载预设错误 Failed to load preset - + 预设文件包含的基色数量 (%1) 与实际情况 (%2) 不符 There 're %1 basecolors in the preset file, while actually there are %2 basecolors - + 预设中为基色%1指定的方块 id 是"%2",没有找到这个方块 id Block "%2" is assigned to base color %1, but failed to find a block with such id From 7306a56a8cfc800579446b190a2395aa04e7ba8e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 29 Oct 2025 15:18:55 +0800 Subject: [PATCH 1087/1123] Update Read me Signed-off-by: ToKiNoBug --- README-en.md | 6 +++--- README.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README-en.md b/README-en.md index 0c725371..e73d8cb0 100644 --- a/README-en.md +++ b/README-en.md @@ -8,7 +8,7 @@

- + @@ -16,8 +16,8 @@
- - + +

diff --git a/README.md b/README.md index 29b1c871..557a920d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

- + @@ -15,8 +15,8 @@
- - + +

From e6c4192af1f08d802bca488010a4a5ec004aae72 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 7 Nov 2025 14:29:40 +0800 Subject: [PATCH 1088/1123] [CI] Try to fix macOS build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 4 +++- .github/workflows/macos-build-x64.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index c8228959..02a60d5b 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -37,7 +37,7 @@ jobs: - name: Install dependencies run: | - brew install llvm boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip + brew install llvm lld boost ninja libpng xsimd p7zip libzip zstd xz eigen boost tl-expected magic_enum fmt sevenzip - name: Check clang run: /opt/homebrew/opt/llvm/bin/clang -v @@ -65,6 +65,8 @@ jobs: - name: Build run: | cd build + export LDFLAGS="-L/opt/homebrew/opt/llvm/lib" + export CPPFLAGS="-I/opt/homebrew/opt/llvm/include" cmake --build . --parallel # - name: CPack # run: | diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index b99c43d2..c16279ae 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -34,7 +34,7 @@ jobs: # brew upgrade - name: Install LLVM clang run: | - brew install llvm + brew install llvm lld - name: Check clang run: /usr/local/opt/llvm/bin/clang -v - name: echo matrix variables (build_type = ${{ matrix.build_type }}) @@ -80,6 +80,8 @@ jobs: - name: Build run: | cd build + export LDFLAGS="-L/usr/local/opt/llvm/lib" + export CPPFLAGS="-I/usr/local/opt/llvm/include" cmake --build . --parallel # - name: CPack # run: | From fc20725158ccfbdbeebb7b1bca7cc7ea235d73f2 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 26 Nov 2025 20:56:54 +0800 Subject: [PATCH 1089/1123] Remove usage of fmt from VCL, SCL and utilities Signed-off-by: ToKiNoBug --- SlopeCraftL/CMakeLists.txt | 16 +- SlopeCraftL/SlopeCraftL.cpp | 2 +- SlopeCraftL/block_list.cpp | 44 +- SlopeCraftL/color_table.cpp | 16 +- SlopeCraftL/converted_image.cpp | 18 +- SlopeCraftL/structure_3D.cpp | 20 +- VisualCraftL/BlockStateList.cpp | 4 +- VisualCraftL/CMakeLists.txt | 12 +- VisualCraftL/ParseResourcePack_blocks.cpp | 432 +++++++++--------- VisualCraftL/ParseResourcePack_json.cpp | 42 +- VisualCraftL/ParseResourcePack_png.cpp | 14 +- VisualCraftL/ResourcePack.cpp | 40 +- VisualCraftL/Resource_tree.cpp | 14 +- VisualCraftL/TokiVC.cpp | 26 +- VisualCraftL/TokiVC_build.cpp | 10 +- VisualCraftL/TokiVC_export_test.cpp | 4 +- VisualCraftL/TokiVC_flagdiagram.cpp | 6 +- VisualCraftL/VCL_internal.h | 3 +- VisualCraftL/VisualCraftL.cpp | 18 +- cmake/optional_deps/kompute.cmake | 2 - cmake/required_deps/fmtlib.cmake | 41 -- utilities/FlatDiagram/CMakeLists.txt | 4 +- utilities/FlatDiagram/FlatDiagram.cpp | 10 +- .../StatMemory/others/test_stat_memory.cpp | 14 +- 24 files changed, 380 insertions(+), 432 deletions(-) delete mode 100644 cmake/required_deps/fmtlib.cmake diff --git a/SlopeCraftL/CMakeLists.txt b/SlopeCraftL/CMakeLists.txt index ed39b771..17e1b737 100644 --- a/SlopeCraftL/CMakeLists.txt +++ b/SlopeCraftL/CMakeLists.txt @@ -2,7 +2,6 @@ project(SlopeCraft_SlopeCraftL VERSION ${SlopeCraft_version} LANGUAGES CXX) find_package(ZLIB 1.2.11 REQUIRED) find_package(OpenMP REQUIRED) -find_package(fmt REQUIRED) find_package(Eigen3 REQUIRED) find_package(Heu REQUIRED) find_package(Boost COMPONENTS iostreams OPTIONAL_COMPONENTS multi_array CONFIG REQUIRED) @@ -63,16 +62,20 @@ set(SlopeCraft_SCL_sources blocklist.h ) -# add this definations to both targets -add_definitions(-DSLOPECRAFTL_LIBRARY) - -add_library(SlopeCraftL SHARED ${SlopeCraft_SCL_sources}) +add_library(SlopeCraftL SHARED + ${SlopeCraft_SCL_sources} + ${Slope_SCL_internal_headers} +) include(GenerateExportHeader) generate_export_header(SlopeCraftL BASE_NAME SCL EXPORT_FILE_NAME SlopeCraftL_export.h) # add_library(SlopeCraftL_C SHARED ${SlopeCraft_SCL_sources}) target_compile_features(SlopeCraftL PRIVATE cxx_std_23) +target_compile_definitions(SlopeCraftL PRIVATE + SLOPECRAFTL_LIBRARY +) +target_compile_options(SlopeCraftL PRIVATE ${SlopeCraft_vectorize_flags}) target_precompile_headers(SlopeCraftL PRIVATE ${SlopeCraft_SCL_internal_headers}) target_include_directories(SlopeCraftL PUBLIC $ @@ -97,7 +100,6 @@ set(SlopeCraft_SCL_link_libs ZLIB::ZLIB OpenMP::OpenMP_CXX - fmt::fmt Eigen3::Eigen Heu::Genetic Boost::iostreams @@ -111,8 +113,6 @@ set(SlopeCraft_SCL_link_libs # link to dependents target_link_libraries(SlopeCraftL PRIVATE $) -target_compile_options(SlopeCraftL PRIVATE ${SlopeCraft_vectorize_flags}) - if (CMAKE_SYSTEM_NAME MATCHES "Linux") target_compile_options(SlopeCraftL PRIVATE "-fvisibility=hidden" "-fPIC") endif () diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 47d1e58b..7acebb4b 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -20,7 +20,7 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include +#include #include #include #include diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp index b6cdbc60..572a5b3e 100644 --- a/SlopeCraftL/block_list.cpp +++ b/SlopeCraftL/block_list.cpp @@ -21,7 +21,7 @@ General Public License for more details. bilibili:https://space.bilibili.com/351429231 */ -#include +#include #include #include #include @@ -42,7 +42,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( mc_block ret; const int basecolor = jo.at("baseColor"); if (basecolor < 0 || basecolor >= 64) { - throw std::runtime_error{fmt::format("invalid base color: {}", basecolor)}; + throw std::runtime_error{std::format("invalid base color: {}", basecolor)}; } ret.id = jo.at("id"); @@ -74,7 +74,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( if (jo.contains("stackSize")) { const int val = jo.at("stackSize"); if (val <= 0 or val > 64) { - throw std::runtime_error{fmt::format("Invalid stack size: {}", val)}; + throw std::runtime_error{std::format("Invalid stack size: {}", val)}; } ret.stackSize = val; } @@ -86,13 +86,13 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( for (auto ver : need_stone) { if (not ver.is_number_integer()) { throw std::runtime_error{ - fmt::format("needStone must be boolean or array of versions, but " + std::format("needStone must be boolean or array of versions, but " "found non-integer element in array")}; } const int ver_int = ver; if (ver_int < static_cast(SCL_gameVersion::MC12) or ver_int > static_cast(SCL_maxAvailableVersion())) { - throw std::runtime_error{fmt::format( + throw std::runtime_error{std::format( "Found invalid version {} in version list of needStone", ver_int)}; } @@ -100,7 +100,7 @@ std::pair parse_block(const nlohmann::json &jo) noexcept( } } else { throw std::runtime_error{ - fmt::format("needStone must be boolean or array of versions")}; + std::format("needStone must be boolean or array of versions")}; } } @@ -140,13 +140,13 @@ tl::expected parse_meta_info( } catch (const std::exception &e) { return tl::make_unexpected( - fmt::format("Failed to parse \"metainfo.json\": {}", e.what())); + std::format("Failed to parse \"metainfo.json\": {}", e.what())); } return ret; } return tl::make_unexpected( - fmt::format("Failed to extract \"metainfo.json\": {}", res.error())); + std::format("Failed to extract \"metainfo.json\": {}", res.error())); } block_list_create_result parse_block_list(zip_t *archive) noexcept { @@ -163,7 +163,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { zip_name_locate(archive, filename, ZIP_FL_UNCHANGED); if (index_i < 0) { return tl::make_unexpected( - fmt::format("File \"{}\" doesn't exist in archive", filename)); + std::format("File \"{}\" doesn't exist in archive", filename)); } const uint64_t index = uint64_t(index_i); @@ -171,7 +171,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { error_code = zip_stat_index(archive, index, ZIP_FL_UNCHANGED, &stat); if (error_code != ZIP_ER_OK) { return tl::make_unexpected( - fmt::format("Failed to get size of file \"{}\" in archive: \"{}\", " + std::format("Failed to get size of file \"{}\" in archive: \"{}\", " "error code = {}", filename, zip_strerror(archive), error_code)); } @@ -182,14 +182,14 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { auto file = zip_fopen(archive, filename, ZIP_FL_UNCHANGED); if (file == nullptr) { return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive : \"{}\" ", + std::format("Failed to extract \"{}\" from archive : \"{}\" ", filename, zip_strerror(archive))); } const int64_t read_bytes = zip_fread(file, dest.data(), dest.size()); if (read_bytes != int64_t(file_size)) { return tl::make_unexpected( - fmt::format("Failed to extract \"{}\" from archive, expected " + std::format("Failed to extract \"{}\" from archive, expected " "{} bytes, but extracted {} bytes : \"{}\" ", filename, file_size, read_bytes, zip_strerror(archive))); } @@ -210,7 +210,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { // metainfo.json exists in the archive auto mi_res = parse_meta_info(extract_file, buffer); if (not mi_res) { - fmt::format_to(std::back_inserter(warnings), + std::format_to(std::back_inserter(warnings), "metainfo.json exist in the archive, but failed to " "parse it: {}\n", mi_res.error()); @@ -229,7 +229,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { njson jo = njson::parse(buffer, nullptr, true, true); if (not jo.is_array()) { return {tl::make_unexpected( - fmt::format("Json should contain an array directly")), + std::format("Json should contain an array directly")), warnings}; } @@ -243,7 +243,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { bl.blocks().emplace(std::make_unique(block), version); } catch (const std::exception &e) { - return {tl::make_unexpected(fmt::format( + return {tl::make_unexpected(std::format( "Failed to parse block at index {}:\n{}", idx, e.what())), warnings}; } @@ -251,7 +251,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { } catch (const std::exception &e) { return {tl::make_unexpected( - fmt::format("nlohmann json exception : {}", e.what())), + std::format("nlohmann json exception : {}", e.what())), warnings}; } // load images @@ -261,7 +261,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { auto err = extract_file(pair.first->imageFilename.c_str(), buffer); if (not err) { warnings += - fmt::format("{}, required by {}", err.error(), pair.first->id); + std::format("{}, required by {}", err.error(), pair.first->id); continue; } } @@ -272,7 +272,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { warnings += warns; if (!result) { - fmt::format_to(std::back_insert_iterator{warnings}, + std::format_to(std::back_insert_iterator{warnings}, "Failed to load image \"{}\" because \"{}\"\n", pair.first->getImageFilename(), result.error()); // for (uint8_t byte : buffer) { @@ -283,7 +283,7 @@ block_list_create_result parse_block_list(zip_t *archive) noexcept { } auto image_size = result.value(); if (image_size.rows != 16 || image_size.cols != 16) { - fmt::format_to(std::back_insert_iterator{warnings}, + std::format_to(std::back_insert_iterator{warnings}, "{} has invalid shape, expected 16x16, but found {} " "rows x {} cols.\n", pair.first->getImageFilename(), image_size.rows, @@ -305,7 +305,7 @@ block_list_create_result create_block_list_from_file( std::unique_ptr archive{ zip_open(zip_path, ZIP_RDONLY | ZIP_CHECKCONS, &error_code)}; if (error_code not_eq ZIP_ER_OK or archive == nullptr) { - auto ret = tl::make_unexpected(fmt::format( + auto ret = tl::make_unexpected(std::format( "Failed to open archive \"{}\" : \"{}\" libzip error code = {}", zip_path, zip_strerror(archive.get()), error_code)); return {ret, warnings}; @@ -320,7 +320,7 @@ block_list_create_result create_block_list_from_buffer( zip_source_t *const source = zip_source_buffer_create(buffer.data(), buffer.size_bytes(), 0, &err); if (source == nullptr) { - return {tl::make_unexpected(fmt::format("Failed to create zip_source_t: {}", + return {tl::make_unexpected(std::format("Failed to create zip_source_t: {}", zip_error_strerror(&err))), {}}; } @@ -330,7 +330,7 @@ block_list_create_result create_block_list_from_buffer( if (archive == nullptr) { zip_source_free(source); return {tl::make_unexpected( - fmt::format("Failed to open zip, zip_err = {}, sys_err = {}", + std::format("Failed to open zip, zip_err = {}, sys_err = {}", err.zip_err, err.sys_err)), {}}; } diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index de19db55..4eaf29f9 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -2,7 +2,7 @@ // Created by joseph on 4/15/24. // -#include +#include #include #include "SCLDefines.h" #include "color_table.h" @@ -110,7 +110,7 @@ std::optional color_table_impl::create( } if (!result.allowed->apply_allowed(*SlopeCraft::basic_colorset, m_index)) { - std::string msg = fmt::format( + std::string msg = std::format( "Too few usable color(s) : only {} colors\nAvaliable base color(s) : ", result.allowed->color_count()); @@ -220,7 +220,7 @@ uint64_t color_table_impl::hash() const noexcept { std::filesystem::path color_table_impl::self_cache_dir( const char *cache_root_dir) const noexcept { - return fmt::format("{}/{:x}", cache_root_dir, this->hash()); + return std::format("{}/{:x}", cache_root_dir, this->hash()); } std::filesystem::path color_table_impl::convert_task_cache_filename( @@ -228,7 +228,7 @@ std::filesystem::path color_table_impl::convert_task_cache_filename( const char *cache_root_dir) const noexcept { auto self_cache_dir = this->self_cache_dir(cache_root_dir); self_cache_dir.append("convert"); - self_cache_dir.append(fmt::format( + self_cache_dir.append(std::format( "{:x}", converted_image_impl::convert_task_hash(original_img, option))); return self_cache_dir; } @@ -252,11 +252,11 @@ std::string color_table_impl::save_convert_cache( auto err = dynamic_cast(cvted).save_cache(filename); if (!err.empty()) { - return fmt::format("Failed to save cache to file \"{}\": {}", + return std::format("Failed to save cache to file \"{}\": {}", filename.string(), err); } } catch (const std::exception &e) { - return fmt::format("Caught exception: {}", e.what()); + return std::format("Caught exception: {}", e.what()); } return {}; @@ -296,7 +296,7 @@ std::filesystem::path color_table_impl::build_task_cache_filename( auto path = this->self_cache_dir(cache_root_dir); path.append("build"); - path.append(fmt::format("{:x}", hash_u64)); + path.append(std::format("{:x}", hash_u64)); return path; } @@ -446,7 +446,7 @@ std::string color_table_impl::impl_generate_test_schematic( if (not ok) { auto &err = ok.error(); - return fmt::format( + return std::format( "Failed to export structure file {}, error code = {}, detail: {}", filename, int(err.first), err.second); } else { diff --git a/SlopeCraftL/converted_image.cpp b/SlopeCraftL/converted_image.cpp index 00f90e14..312107e9 100644 --- a/SlopeCraftL/converted_image.cpp +++ b/SlopeCraftL/converted_image.cpp @@ -2,7 +2,7 @@ // Created by joseph on 4/17/24. // -#include +#include #include #include #include "SCLDefines.h" @@ -87,13 +87,13 @@ bool converted_image_impl::export_map_data( for (int r = 0; r < rows; r++) { const std::array offset = {r * 128, c * 128}; std::filesystem::path current_filename = dir; - current_filename.append(fmt::format("map_{}.dat", currentIndex)); + current_filename.append(std::format("map_{}.dat", currentIndex)); NBT::NBTWriter MapFile; if (!MapFile.open(current_filename.string().c_str())) { option.ui.report_error(errorFlag::EXPORT_MAP_DATA_FAILURE, - fmt::format("Failed to create nbt file {}", + std::format("Failed to create nbt file {}", current_filename.string()) .c_str()); fail_count += 1; @@ -121,7 +121,7 @@ bool converted_image_impl::export_map_data( break; } - static const std::string ExportedBy = fmt::format( + static const std::string ExportedBy = std::format( "Exported by SlopeCraft {}, developed by TokiNoBug", SC_VERSION_STR); MapFile.writeString("ExportedBy", ExportedBy.data()); MapFile.writeCompound("data"); @@ -217,7 +217,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { "vanilla map.\n Map contents (map color matrix in col-major) :\n["; for (int c = 0; c < map_color.cols(); c++) { for (int r = 0; r < map_color.rows(); r++) { - fmt::format_to(std::back_insert_iterator{msg}, "{},", map_color(r, c)); + std::format_to(std::back_insert_iterator{msg}, "{},", map_color(r, c)); } msg += ";\n"; } @@ -255,7 +255,7 @@ converted_image_impl::height_info(const build_options &option) const noexcept { if (!success) { option.ui.report_error( SCL_errorFlag::LOSSYCOMPRESS_FAILED, - fmt::format("Failed to compress the 3D structure at column {}. You " + std::format("Failed to compress the 3D structure at column {}. You " "have required that max height <= {}, but SlopeCraft " "is only able to this column to max height = {}.", c, option.max_allowed_height, HL.maxHeight()) @@ -440,7 +440,7 @@ bool converted_image_impl::get_map_command( const int map_cols = this->map_cols(); if (map_rows <= 0 or map_cols <= 0) { std::string err_msg = - fmt::format("Invalid map size: {} rows, {} cols", map_rows, map_cols); + std::format("Invalid map size: {} rows, {} cols", map_rows, map_cols); option.destination->write(err_msg.c_str(), err_msg.size()); return false; } @@ -454,7 +454,7 @@ bool converted_image_impl::get_map_command( std::string name; if (option.set_name_as_index) - name = fmt::format("{{\"text\":\"[{},{}]\"}}", r, c); + name = std::format("{{\"text\":\"[{},{}]\"}}", r, c); nbt::tag_compound result; nbt::tag_compound tag; @@ -506,7 +506,7 @@ bool converted_image_impl::get_map_command( const std::string item_id = chest_all_in_one.at("id").as().get(); - option.destination->write(fmt::format("/give @p {}", item_id).c_str()); + option.destination->write(std::format("/give @p {}", item_id).c_str()); erase_if("Count"); erase_if("count"); erase_if("id"); diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index f0926cd8..cd989e33 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -1,7 +1,7 @@ // // Created by joseph on 4/17/24. // -#include +#include #include #include #include @@ -22,7 +22,7 @@ std::optional structure_3D_impl::create( if (option.max_allowed_height < 14) { option.ui.report_error( errorFlag::MAX_ALLOWED_HEIGHT_LESS_THAN_14, - fmt::format("Max allowed height should be >= 14, but found {}", + std::format("Max allowed height should be >= 14, but found {}", option.max_allowed_height) .c_str()); return std::nullopt; @@ -78,7 +78,7 @@ std::optional structure_3D_impl::create( const uint64_t bytes_required = shape[0] * shape[1] * shape[2]; option.ui.report_error( errorFlag::MEMORY_ALLOCATE_FAILED, - fmt::format("Failed to allocate memory for this structure, " + std::format("Failed to allocate memory for this structure, " "required {} GiB. The exception says: \"{}\"", double(bytes_required) / (uint64_t{1} << 30), e.what()) .c_str()); @@ -110,11 +110,11 @@ std::optional structure_3D_impl::create( fixed_opt.main_progressbar.add(cvted.size()); - // fmt::println("{} rows, {} cols", cvted.rows(), cvted.cols()); + // std::println("{} rows, {} cols", cvted.rows(), cvted.cols()); // Common blocks for (int64_t r = -1; r < int64_t(cvted.rows()); r++) { for (int64_t c = 0; c < int64_t(cvted.cols()); c++) { - // fmt::println("r = {}, c = {}", r, c); + // std::println("r = {}, c = {}", r, c); const int cur_base_color = base_color(r + 1, c); if (cur_base_color == 12 || cur_base_color == 0) { // water or air @@ -305,7 +305,7 @@ bool structure_3D_impl::export_flat_diagram( if (table.map_type() != SCL_mapTypes::Flat) { option.ui.report_error( SCL_errorFlag::EXPORT_FLAT_DIAGRAM_ON_WRONG_MAP_TYPE, - fmt::format( + std::format( "We can only export flat diagram for flat maps, but found {}", magic_enum::enum_name(table.map_type())) .c_str()); @@ -341,7 +341,7 @@ bool structure_3D_impl::export_flat_diagram( } option.ui.report_error( errorFlag::EXPORT_FLAT_DIAGRAM_FAILURE, - fmt::format("SlopeCraftL internal error. Failed to find block image " + std::format("SlopeCraftL internal error. Failed to find block image " "for \"{}\". " "In the 3d structure, the corresponding block idx is " "{}.\nThe whole " @@ -404,7 +404,7 @@ void load(archive &ar, Eigen::ArrayXX &mat) { ar(rows, cols); if (rows < 0 || cols < 0) { throw std::runtime_error{ - fmt::format("Found negative shape when deserializing " + std::format("Found negative shape when deserializing " "Eigen::ArrayXX, {} rows and {} cols", rows, cols)}; } @@ -438,7 +438,7 @@ std::string structure_3D_impl::save_cache( } } catch (const std::exception &e) { - return fmt::format("Caught exception: {}", e.what()); + return std::format("Caught exception: {}", e.what()); } return {}; @@ -458,7 +458,7 @@ tl::expected structure_3D_impl::load_cache( bia(ret); } } catch (const std::exception &e) { - return tl::make_unexpected(fmt::format("Caught exception: {}", e.what())); + return tl::make_unexpected(std::format("Caught exception: {}", e.what())); } return ret; diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index bc6be30e..d3e93825 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -231,7 +231,7 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { ifs.close(); } catch (std::exception &e) { std::string msg = - fmt::format("Failed to parse {}, detail : {}", filename, e.what()); + std::format("Failed to parse {}, detail : {}", filename, e.what()); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -240,7 +240,7 @@ bool VCL_block_state_list::add(std::string_view filename) noexcept { auto vb = parse_block(pair.value()); if (not vb) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse {}, : invalid value for block state {} : {}", filename, pair.key().c_str(), to_string(pair.value())); ::VCL_report(VCL_report_type_t::error, msg.c_str()); diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index 08afc56f..fff3c3fb 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.20) project(VisualCraftL VERSION ${SlopeCraft_version} LANGUAGES C CXX) -set(CMAKE_CXX_STANDARD 20) - set(VCL_enable_internal_test OFF) include(config_versions.cmake) @@ -77,7 +75,6 @@ add_library(VisualCraftL_static STATIC find_package(ZLIB 1.2.11 REQUIRED) find_package(libzip 1.7.0 REQUIRED) -find_package(fmt 10.0.0 REQUIRED) set(VCL_include_dirs ${SlopeCraft_Nlohmann_json_include_dir} @@ -103,7 +100,6 @@ set(VCL_link_libs PNG::PNG ${VCL_libzip_additions} Schem - fmt::fmt ProcessBlockId ) @@ -111,11 +107,11 @@ target_link_libraries(VisualCraftL PRIVATE $) target_link_libraries(VisualCraftL_static PUBLIC ${VCL_link_libs}) # message(STATUS "ret = " ${ret}) -target_compile_definitions(VisualCraftL PRIVATE "-DVISUALCRAFTL_BUILD") -target_compile_definitions(VisualCraftL_static PRIVATE "-DVISUALCRAFTL_BUILD") +target_compile_definitions(VisualCraftL PRIVATE VISUALCRAFTL_BUILD) +target_compile_definitions(VisualCraftL_static PRIVATE VISUALCRAFTL_BUILD) -target_compile_features(VisualCraftL PRIVATE cxx_std_20) -target_compile_features(VisualCraftL_static PUBLIC cxx_std_20) +target_compile_features(VisualCraftL PRIVATE cxx_std_23) +target_compile_features(VisualCraftL_static PUBLIC cxx_std_23) target_compile_options(VisualCraftL PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_options(VisualCraftL_static PRIVATE ${SlopeCraft_vectorize_flags}) diff --git a/VisualCraftL/ParseResourcePack_blocks.cpp b/VisualCraftL/ParseResourcePack_blocks.cpp index 479b27a5..7c5b0c6c 100644 --- a/VisualCraftL/ParseResourcePack_blocks.cpp +++ b/VisualCraftL/ParseResourcePack_blocks.cpp @@ -28,20 +28,20 @@ using Array3f = ::Eigen::Array3f; ray_t::ray_t(const face_idx f) { switch (f) { - case face_idx::face_down: - case face_idx::face_up: - abc = {0, 1, 0}; - break; - - case face_idx::face_north: - case face_idx::face_south: - abc = {0, 0, 1}; - break; - - case face_idx::face_east: - case face_idx::face_west: - abc = {1, 0, 0}; - break; + case face_idx::face_down: + case face_idx::face_up: + abc = {0, 1, 0}; + break; + + case face_idx::face_north: + case face_idx::face_south: + abc = {0, 0, 1}; + break; + + case face_idx::face_east: + case face_idx::face_west: + abc = {1, 0, 0}; + break; } } @@ -53,43 +53,43 @@ plane_t element::plane(face_idx fi) const noexcept { Array3f pos_max = this->_to.max(this->_from); switch (fi) { - case face_y_pos: - point = {0.5, pos_max[1], 0.5}; - break; - case face_y_neg: - point = {0.5, pos_min[1], 0.5}; - break; - - case face_x_pos: - point = {pos_max[0], 0.5, 0.5}; - break; - case face_x_neg: - point = {pos_min[0], 0.5, 0.5}; - break; - - case face_z_pos: - point = {0.5, 0.5, pos_max[2]}; - break; - case face_z_neg: - point = {0.5, 0.5, pos_min[2]}; - break; + case face_y_pos: + point = {0.5, pos_max[1], 0.5}; + break; + case face_y_neg: + point = {0.5, pos_min[1], 0.5}; + break; + + case face_x_pos: + point = {pos_max[0], 0.5, 0.5}; + break; + case face_x_neg: + point = {pos_min[0], 0.5, 0.5}; + break; + + case face_z_pos: + point = {0.5, 0.5, pos_max[2]}; + break; + case face_z_neg: + point = {0.5, 0.5, pos_min[2]}; + break; } switch (fi) { - case face_y_pos: - case face_y_neg: - norm = {0, 1, 0}; - break; - - case face_x_pos: - case face_x_neg: - norm = {1, 0, 0}; - break; - - case face_z_pos: - case face_z_neg: - norm = {0, 0, 1}; - break; + case face_y_pos: + case face_y_neg: + norm = {0, 1, 0}; + break; + + case face_x_pos: + case face_x_neg: + norm = {1, 0, 0}; + break; + + case face_z_pos: + case face_z_neg: + norm = {0, 0, 1}; + break; } return plane_t(norm, point); @@ -126,8 +126,7 @@ Array3f crossover_point(const plane_t &plane, const ray_t &ray) noexcept { void element::intersect_points( const face_idx f, const ray_t &ray, std::vector *const dest) const noexcept { - if (dest == nullptr) - return; + if (dest == nullptr) return; // const Array3f &start_point = ray.x0y0z0; /* switch (f) { @@ -154,31 +153,30 @@ void element::intersect_points( } */ - if (this->face(f).is_hidden) - return; + if (this->face(f).is_hidden) return; switch (f) { - case face_x_neg: - case face_x_pos: - if (this->y_range_abs() * this->z_range_abs() < 1e-4f) { - // VCL_report(VCL_report_type_t::information, "yz range skip"); - return; - } - break; - case face_y_neg: - case face_y_pos: - if (this->x_range_abs() * this->z_range_abs() < 1e-4f) { - // VCL_report(VCL_report_type_t::information, "xz range skip"); - return; - } - break; - case face_z_neg: - case face_z_pos: - if (this->x_range_abs() * this->y_range_abs() < 1e-4f) { - // VCL_report(VCL_report_type_t::information, "xy range skip"); - return; - } - break; + case face_x_neg: + case face_x_pos: + if (this->y_range_abs() * this->z_range_abs() < 1e-4f) { + // VCL_report(VCL_report_type_t::information, "yz range skip"); + return; + } + break; + case face_y_neg: + case face_y_pos: + if (this->x_range_abs() * this->z_range_abs() < 1e-4f) { + // VCL_report(VCL_report_type_t::information, "xz range skip"); + return; + } + break; + case face_z_neg: + case face_z_pos: + if (this->x_range_abs() * this->y_range_abs() < 1e-4f) { + // VCL_report(VCL_report_type_t::information, "xy range skip"); + return; + } + break; } intersect_point intersect{1e9f, {0, 0}, nullptr}; @@ -186,8 +184,7 @@ void element::intersect_points( coordinate = crossover_point(this->plane(f), ray); // printf("\nelement::intersect_points : coordinate = [%f, %f, // %f]",coordinate[0], coordinate[1], coordinate[2]); - if (!this->is_not_outside(coordinate)) - return; + if (!this->is_not_outside(coordinate)) return; intersect.face_ptr = &this->face(f); @@ -205,73 +202,73 @@ void element::intersect_points( // #warning compute uv here switch (f) { - case face_idx::face_up: - uv_start = {min_pos[0], max_pos[1], min_pos[2]}; - // uv_end=max_pos; - - // here u <-> x+ - intersect.uv[0] = (coordinate[0] - uv_start[0]) / this->x_range_abs(); - // here v<-> z+ - intersect.uv[1] = (coordinate[2] - uv_start[2]) / this->z_range_abs(); - /* - printf("\nelement::intersect_points : face = up, uv_start = [%f, %f, %f], - " "uv = [%f, %f] ", uv_start[0], uv_start[1], uv_start[2], - intersect.uv[0], intersect.uv[1]); - - */ - - break; - - case face_idx::face_down: - uv_start = {max_pos[0], min_pos[1], max_pos[2]}; - { - Array3f uv_end = {min_pos[0], min_pos[1], min_pos[2]}; - // here u <-> x+ - intersect.uv[0] = (coordinate[0] - uv_end[0]) / this->x_range_abs(); - // here v <-> z- - intersect.uv[1] = (uv_start[2] - coordinate[2]) / this->z_range_abs(); - } - break; - - case face_idx::face_east: - // uv_start=max_pos; - uv_start = {max_pos[0], max_pos[1], max_pos[2]}; - // uv_end = {max_pos[0], min_pos[1], min_pos[2]}; - // here u <-> z- - intersect.uv[0] = (uv_start[2] - coordinate[2]) / this->z_range_abs(); - // here v <-> y- - intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); - break; - - case face_idx::face_west: - uv_start = {min_pos[0], max_pos[1], min_pos[2]}; - // uv_end = {min_pos[0], min_pos[1], max_pos[2]}; - - // here u <-> z+ - intersect.uv[0] = (coordinate[2] - uv_start[2]) / this->z_range_abs(); - // here v <-> y- - intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); - break; - - case face_idx::face_south: - uv_start = {min_pos[0], max_pos[1], max_pos[2]}; - // uv_end = {max_pos[0], min_pos[1], max_pos[2]}; - - // here u <-> x+ - intersect.uv[0] = (coordinate[0] - uv_start[0]) / this->x_range_abs(); - // here v <-> y- - intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); - break; - - case face_idx::face_north: - uv_start = {max_pos[0], max_pos[0], min_pos[0]}; - // uv_end = min_pos; - - // here u <-> x- - intersect.uv[0] = (uv_start[0] - coordinate[0]) / this->x_range_abs(); - // here v <-> y- - intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); - break; + case face_idx::face_up: + uv_start = {min_pos[0], max_pos[1], min_pos[2]}; + // uv_end=max_pos; + + // here u <-> x+ + intersect.uv[0] = (coordinate[0] - uv_start[0]) / this->x_range_abs(); + // here v<-> z+ + intersect.uv[1] = (coordinate[2] - uv_start[2]) / this->z_range_abs(); + /* + printf("\nelement::intersect_points : face = up, uv_start = [%f, %f, %f], + " "uv = [%f, %f] ", uv_start[0], uv_start[1], uv_start[2], + intersect.uv[0], intersect.uv[1]); + + */ + + break; + + case face_idx::face_down: + uv_start = {max_pos[0], min_pos[1], max_pos[2]}; + { + Array3f uv_end = {min_pos[0], min_pos[1], min_pos[2]}; + // here u <-> x+ + intersect.uv[0] = (coordinate[0] - uv_end[0]) / this->x_range_abs(); + // here v <-> z- + intersect.uv[1] = (uv_start[2] - coordinate[2]) / this->z_range_abs(); + } + break; + + case face_idx::face_east: + // uv_start=max_pos; + uv_start = {max_pos[0], max_pos[1], max_pos[2]}; + // uv_end = {max_pos[0], min_pos[1], min_pos[2]}; + // here u <-> z- + intersect.uv[0] = (uv_start[2] - coordinate[2]) / this->z_range_abs(); + // here v <-> y- + intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); + break; + + case face_idx::face_west: + uv_start = {min_pos[0], max_pos[1], min_pos[2]}; + // uv_end = {min_pos[0], min_pos[1], max_pos[2]}; + + // here u <-> z+ + intersect.uv[0] = (coordinate[2] - uv_start[2]) / this->z_range_abs(); + // here v <-> y- + intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); + break; + + case face_idx::face_south: + uv_start = {min_pos[0], max_pos[1], max_pos[2]}; + // uv_end = {max_pos[0], min_pos[1], max_pos[2]}; + + // here u <-> x+ + intersect.uv[0] = (coordinate[0] - uv_start[0]) / this->x_range_abs(); + // here v <-> y- + intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); + break; + + case face_idx::face_north: + uv_start = {max_pos[0], max_pos[0], min_pos[0]}; + // uv_end = min_pos; + + // here u <-> x- + intersect.uv[0] = (uv_start[0] - coordinate[0]) / this->x_range_abs(); + // here v <-> y- + intersect.uv[1] = (uv_start[1] - coordinate[1]) / this->y_range_abs(); + break; } for (auto &uv : intersect.uv) { @@ -279,25 +276,25 @@ void element::intersect_points( } switch (intersect.face_ptr->rot) { - case face_rot::face_rot_0: - break; - case face_rot::face_rot_90: { - float temp_u = intersect.uv[0]; - intersect.uv[0] = intersect.uv[1]; - intersect.uv[1] = 1 - temp_u; - } break; - - case face_rot::face_rot_180: - intersect.uv[0] = 1 - intersect.uv[0]; - intersect.uv[1] = 1 - intersect.uv[1]; - break; - - case face_rot::face_rot_270: { - float temp_u = intersect.uv[0]; - intersect.uv[0] = 1 - intersect.uv[1]; - intersect.uv[1] = temp_u; - break; - } + case face_rot::face_rot_0: + break; + case face_rot::face_rot_90: { + float temp_u = intersect.uv[0]; + intersect.uv[0] = intersect.uv[1]; + intersect.uv[1] = 1 - temp_u; + } break; + + case face_rot::face_rot_180: + intersect.uv[0] = 1 - intersect.uv[0]; + intersect.uv[1] = 1 - intersect.uv[1]; + break; + + case face_rot::face_rot_270: { + float temp_u = intersect.uv[0]; + intersect.uv[0] = 1 - intersect.uv[1]; + intersect.uv[1] = temp_u; + break; + } } intersect.distance = (coordinate - ray.x0y0z0).square().sum(); @@ -328,29 +325,29 @@ void model::projection_image(face_idx fidx, // set the origin point of a ray switch (fidx) { - case face_idx::face_up: - ray.x0y0z0 = {c + 0.5f, 128.0f, r + 0.5f}; - break; - case face_idx::face_down: - ray.x0y0z0 = {c + 0.5f, -128.0f, 15.5f - r}; - break; - - case face_idx::face_east: - // r->y-, c->z-,x=128 - ray.x0y0z0 = {128.0f, 15.5f - r, 15.5f - c}; - break; - case face_idx::face_west: - // r->y-, c->z+, x=-128 - ray.x0y0z0 = {-128.0f, 15.5f - r, c + 0.5f}; - break; - case face_idx::face_south: - // r->y-, c->x+, z=128 - ray.x0y0z0 = {c + 0.5f, 15.5f - r, 128.0f}; - break; - case face_idx::face_north: - // r->y-, c->x-, z=-128 - ray.x0y0z0 = {15.5f - c, 15.5f - r, -128.0f}; - break; + case face_idx::face_up: + ray.x0y0z0 = {c + 0.5f, 128.0f, r + 0.5f}; + break; + case face_idx::face_down: + ray.x0y0z0 = {c + 0.5f, -128.0f, 15.5f - r}; + break; + + case face_idx::face_east: + // r->y-, c->z-,x=128 + ray.x0y0z0 = {128.0f, 15.5f - r, 15.5f - c}; + break; + case face_idx::face_west: + // r->y-, c->z+, x=-128 + ray.x0y0z0 = {-128.0f, 15.5f - r, c + 0.5f}; + break; + case face_idx::face_south: + // r->y-, c->x+, z=128 + ray.x0y0z0 = {c + 0.5f, 15.5f - r, 128.0f}; + break; + case face_idx::face_north: + // r->y-, c->x-, z=-128 + ray.x0y0z0 = {15.5f - c, 15.5f - r, -128.0f}; + break; } for (const element &ele : this->elements) { @@ -364,7 +361,7 @@ void model::projection_image(face_idx fidx, } if constexpr (false) { std::string msg = - fmt::format("num of intersects : {}", intersects.size()); + std::format("num of intersects : {}", intersects.size()); VCL_report(VCL_report_type_t::information, msg.c_str()); } @@ -386,8 +383,7 @@ void model::projection_image(face_idx fidx, // printf("\n0x%08X + 0x%08X -> ", color, ip.color()); color = ComposeColor_background_half_transparent(color, ip.color()); // printf("0x%08X; ", color); - if (getA(color) >= 255) - break; + if (getA(color) >= 255) break; } // printf(";"); @@ -421,20 +417,20 @@ Eigen::Array3f block_model::rotate_x(const Eigen::Array3f &pos, Eigen::Array3f diff_after = diff_before; switch (x_rot) { - case face_rot::face_rot_0: - return pos; - case face_rot::face_rot_90: - diff_after[y_idx] = diff_before[z_idx]; - diff_after[z_idx] = -diff_before[y_idx]; - break; - case face_rot::face_rot_180: - diff_after[y_idx] = -diff_before[y_idx]; - diff_after[z_idx] = -diff_before[z_idx]; - break; - case face_rot::face_rot_270: - diff_after[y_idx] = -diff_before[z_idx]; - diff_after[z_idx] = diff_before[y_idx]; - break; + case face_rot::face_rot_0: + return pos; + case face_rot::face_rot_90: + diff_after[y_idx] = diff_before[z_idx]; + diff_after[z_idx] = -diff_before[y_idx]; + break; + case face_rot::face_rot_180: + diff_after[y_idx] = -diff_before[y_idx]; + diff_after[z_idx] = -diff_before[z_idx]; + break; + case face_rot::face_rot_270: + diff_after[y_idx] = -diff_before[z_idx]; + diff_after[z_idx] = diff_before[y_idx]; + break; } return diff_after + center; } @@ -447,21 +443,21 @@ Eigen::Array3f block_model::rotate_y(const Eigen::Array3f &pos, Eigen::Array3f diff_after = diff_before; switch (y_rot) { - case face_rot::face_rot_0: - return pos; - - case face_rot::face_rot_90: - diff_after[x_idx] = -diff_before[z_idx]; - diff_after[z_idx] = diff_before[x_idx]; - break; - case face_rot::face_rot_180: - diff_after[x_idx] = -diff_before[x_idx]; - diff_after[z_idx] = -diff_before[z_idx]; - break; - case face_rot::face_rot_270: - diff_after[x_idx] = diff_before[z_idx]; - diff_after[z_idx] = -diff_before[x_idx]; - break; + case face_rot::face_rot_0: + return pos; + + case face_rot::face_rot_90: + diff_after[x_idx] = -diff_before[z_idx]; + diff_after[z_idx] = diff_before[x_idx]; + break; + case face_rot::face_rot_180: + diff_after[x_idx] = -diff_before[x_idx]; + diff_after[z_idx] = -diff_before[z_idx]; + break; + case face_rot::face_rot_270: + diff_after[x_idx] = diff_before[z_idx]; + diff_after[z_idx] = -diff_before[x_idx]; + break; } return diff_after + center; @@ -472,7 +468,7 @@ element block_model::element::rotate(face_rot x_rot, element ret; if constexpr (false) { std::string msg = - fmt::format("this->_from = [{}, {}, {}], this->_to = [{}, {}, {}]", + std::format("this->_from = [{}, {}, {}], this->_to = [{}, {}, {}]", this->_from[0], this->_from[1], this->_from[2], this->_to[0], this->_to[1], this->_to[2]); @@ -492,7 +488,7 @@ element block_model::element::rotate(face_rot x_rot, } if constexpr (false) { - std::string msg = fmt::format("f = [{}, {}, {}], t = [{}, {}, {}]", f[0], + std::string msg = std::format("f = [{}, {}, {}], t = [{}, {}, {}]", f[0], f[1], f[2], t[0], t[1], t[2]); VCL_report(VCL_report_type_t::information, msg.c_str()); } diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index 301cfa45..22652b29 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -238,7 +238,7 @@ bool resource_json::parse_block_state( obj.contains("multipart") && obj.at("multipart").is_array(); if (has_variant == has_multipart) { - std::string msg = fmt::format( + std::string msg = std::format( "Function parse_block_state failed to parse json : " "has_variant = {}, has_multipart = {}.", has_variant, has_multipart); @@ -288,7 +288,7 @@ bool parse_block_state_list(std::string_view str, state_list *const sl, if (!blkid::process_state_list({str.data(), str.data() + str.size()}, &buffer.attributes, nullptr)) { - std::string msg = fmt::format( + std::string msg = std::format( " Function parse_block_state_list failed to parse block state " "list : {}", str); @@ -326,7 +326,7 @@ model_store_t json_to_model(const njson &obj) noexcept { if (!block_model::is_0_90_180_270(val)) { std::string msg; - msg = fmt::format( + msg = std::format( "Invalid x rotation value : {}. Invalid values : 0, 90, 180, 270.", val); VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -340,7 +340,7 @@ model_store_t json_to_model(const njson &obj) noexcept { const int val = obj.at("y"); if (!block_model::is_0_90_180_270(val)) { std::string msg; - msg = fmt::format( + msg = std::format( "Invalid y rotation value : {}. Invalid values : 0, 90, 180, 270.", val); VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -365,7 +365,7 @@ bool parse_block_state_variant(const njson::object_t &obj, for (auto pair : variants.items()) { if (!pair.value().is_structured()) { - std::string msg = fmt::format( + std::string msg = std::format( "Function parse_block_state_variant failed to parse json : " "value for key \"{}\" is not an object or array.", pair.key()); @@ -375,7 +375,7 @@ bool parse_block_state_variant(const njson::object_t &obj, } if (pair.value().is_array() && pair.value().size() <= 0) { - std::string msg = fmt::format( + std::string msg = std::format( "Function parse_block_state_variant failed to parse json : " "value for key \"{}\" is an empty array.", pair.key().data()); @@ -387,7 +387,7 @@ bool parse_block_state_variant(const njson::object_t &obj, (pair.value().is_object()) ? (pair.value()) : (pair.value().at(0)); if ((!obj.contains("model")) || (!obj.at("model").is_string())) { - std::string msg = fmt::format( + std::string msg = std::format( "Function parse_block_state_variant failed to parse json : no " "valid value for key \"model\""); @@ -401,7 +401,7 @@ bool parse_block_state_variant(const njson::object_t &obj, if (!parse_block_state_list(pair.key(), &p.first, buffer)) { std::string msg = - fmt::format("Failed to parse block state list : {}", pair.key()); + std::format("Failed to parse block state list : {}", pair.key()); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -545,7 +545,7 @@ bool parse_block_state_multipart(const njson::object_t &obj, const njson &multiparts = obj.at("multipart"); if (!multiparts.is_array()) { - std::string msg = fmt::format("Fatal error : multipart must be an array."); + std::string msg = std::format("Fatal error : multipart must be an array."); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -563,7 +563,7 @@ bool parse_block_state_multipart(const njson::object_t &obj, const njson &apply = part.at("apply"); mpp.apply_blockmodel = parse_multipart_apply(apply); } catch (const std::exception &err) { - std::string msg = fmt::format( + std::string msg = std::format( "An error occurred when parsing the value of apply. Details : {}", err.what()); ::VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -583,7 +583,7 @@ bool parse_block_state_multipart(const njson::object_t &obj, mpp.criteria_variant = parse_multipart_when(when); } catch (const std::exception &err) { - std::string msg = fmt::format( + std::string msg = std::format( "\nFatal error : failed to parse \"when\" for a multipart blockstate " "file. Details : {}\n", err.what()); @@ -796,7 +796,7 @@ bool parse_single_model_json(const char *const json_beg, { auto fidx_opt = string_to_face_idx(temp.key()); if (not fidx_opt) { - std::string msg = fmt::format( + std::string msg = std::format( "Error while parsing block model json : invalid key {} " "doesn't refer to any face.", temp.key()); @@ -835,7 +835,7 @@ bool parse_single_model_json(const char *const json_beg, auto cullface_fidx = string_to_face_idx(cullface_temp); if (not cullface_fidx) { - std::string msg = fmt::format("Invalid value for cullface : {}", + std::string msg = std::format("Invalid value for cullface : {}", cullface_temp); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -993,7 +993,7 @@ bool inherit_recrusively(std::string_view childname, auto it = temp_models.find(child.parent); if (it == temp_models.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to inherit. Undefined reference to model {}, " "required by {}.", child.parent.data(), childname.data()); @@ -1018,7 +1018,7 @@ bool inherit_recrusively(std::string_view childname, // dereference_texture_name(child.textures); if (!success) { - std::string msg = fmt::format("Failed to inherit. Child : {}, parent : {}.", + std::string msg = std::format("Failed to inherit. Child : {}, parent : {}.", childname.data(), child.parent.data()); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -1071,7 +1071,7 @@ bool resource_pack::add_block_models( (const char *)file.second.data() + file.second.file_size(), &bmjt); if (!ok) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse assets/minecraft/models/block/{}.", file.first); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -1095,7 +1095,7 @@ bool resource_pack::add_block_models( const bool ok = inherit_recrusively(model.first, model.second, temp_models); if (!ok) { model.second.parent = "INVALID"; - std::string msg = fmt::format( + std::string msg = std::format( "Failed to inherit model {}. This model will be " "skipped, but it may cause further errors.", model.first); @@ -1167,14 +1167,14 @@ bool resource_pack::add_block_models( skip_this_model = true; continue; } - std::string msg = fmt::format( + std::string msg = std::format( "Undefined reference to texture \"{}\", required by " "model {} but no such image.\nThe textures are : \n", tface.texture, tmodel.first); for (const auto &pair : tmodel.second.textures) { msg.push_back('{'); std::string temp = - fmt::format("{}, {}\n", pair.first.data(), pair.second.data()); + std::format("{}, {}\n", pair.first.data(), pair.second.data()); msg.append(temp); msg.push_back('}'); } @@ -1199,7 +1199,7 @@ bool resource_pack::add_block_models( for (const auto &ele : pair.second.elements) { for (const auto &face : ele.faces) { if (!face.is_hidden && face.texture == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "Found an error while examining all block models : " "face.texture==nullptr in model {}", pair.first); @@ -1250,7 +1250,7 @@ bool resource_pack::add_block_states( &is_dest_variant); if (!success) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse block state json file " "assets/minecraft/blockstates/{}. This will be " "skipped but may cause further errors.\n", diff --git a/VisualCraftL/ParseResourcePack_png.cpp b/VisualCraftL/ParseResourcePack_png.cpp index 8cbd4cc5..a2ad0aa1 100644 --- a/VisualCraftL/ParseResourcePack_png.cpp +++ b/VisualCraftL/ParseResourcePack_png.cpp @@ -138,7 +138,7 @@ bool parse_png( break; default: png_destroy_read_struct(&png, &info, &info_end); - std::string msg = fmt::format("Unknown color type {}", color_type); + std::string msg = std::format("Unknown color type {}", color_type); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -345,7 +345,7 @@ bool resource_pack::add_textures_direct( const bool success = parse_png(file.second.data(), file.second.file_size(), &img); if (!success || img.size() <= 0) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse png file {} in {}. Png parsing will " "continue but this warning may cause further errors.", file.first, buffer.data()); @@ -355,7 +355,7 @@ bool resource_pack::add_textures_direct( if (is_dynamic) { if (img.rows() % img.cols() != 0) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to process dynamic png file {} in {}. Image " "has {} rows and {} cols, which is not of integer ratio. Png " "parsing will continue but this warning may cause further " @@ -382,7 +382,7 @@ process_dynamic_texture(const Eigen::Arrayfiles.contains(filename.data())) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to find \"assets/minecraft/textures/colormap/{}\". " "File doesn\'t exist.", filename); @@ -441,7 +441,7 @@ bool resource_pack::add_colormap(const zipped_folder &resourece_pack_root, const bool success = parse_png(png.data(), png.file_size(), &img); if (!success) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse \"assets/minecraft/textures/colormap/{}\". " "Not a valid png file.", filename); @@ -450,7 +450,7 @@ bool resource_pack::add_colormap(const zipped_folder &resourece_pack_root, } if (img.rows() != 256 || img.cols() != 256) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to parse assets/minecraft/textures/colormap/{}. " "The rows({}) and cols({}) mismatch with (256,256).", filename, img.rows(), img.cols()); diff --git a/VisualCraftL/ResourcePack.cpp b/VisualCraftL/ResourcePack.cpp index f34071a4..f28722ed 100644 --- a/VisualCraftL/ResourcePack.cpp +++ b/VisualCraftL/ResourcePack.cpp @@ -74,7 +74,7 @@ bool VCL_resource_pack::filter_model_textures( face.texture = it->second; } else { if (is_missing_error) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to filter image pointer {}. Missing in the " "filter and is_missing_error is set to true.", (const void *)face.texture); @@ -213,7 +213,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, buffer_t &buffer) const noexcept { if (!resource_json::process_full_id(block_state_str, nullptr, &buffer.pure_id, &buffer.state_list)) { - std::string msg = fmt::format( + std::string msg = std::format( "invalid full block id that can not be parsed to a list " "of block states : \"{}\"", block_state_str.c_str()); @@ -227,7 +227,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, std::string msg = "statelist = ["; for (const auto &i : buffer.state_list) { - std::string temp = fmt::format("{}={},", i.key.c_str(), i.value.c_str()); + std::string temp = std::format("{}={},", i.key.c_str(), i.value.c_str()); msg.append(temp); } msg.append("]\n"); @@ -245,7 +245,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, if (buffer.pure_id == "air") { return block_model::model{}; } - std::string msg = fmt::format( + std::string msg = std::format( "Undefined reference to block state whose pure block id " "is : \"{}\" and full block id is : \"{}\"\n", buffer.pure_id, block_state_str); @@ -261,7 +261,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, // face_exposed = block_model::invrotate(face_exposed, model.x, model.y); if (model.model_name == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "No block model for full id : \"{}\", this is usually " "because block states mismatch.", block_state_str); @@ -284,7 +284,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, } if (it_model == this->block_models.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to find block model for full id : \"{}\". Detail : " "undefined reference to model named \"{}\".\n", block_state_str.c_str(), model.model_name); @@ -302,20 +302,20 @@ VCL_resource_pack::find_model(const std::string &block_state_str, for (const auto &md : models) { if constexpr (false) { std::string msg = - fmt::format("x_rot = {}, y_rot = {}", int(md.x), int(md.y)); + std::format("x_rot = {}, y_rot = {}", int(md.x), int(md.y)); VCL_report(VCL_report_type_t::information, msg.c_str()); } if (md.model_name == nullptr) { std::string msg = - fmt::format("File = {}, line = {}\n", __FILE__, __LINE__); + std::format("File = {}, line = {}\n", __FILE__, __LINE__); VCL_report(VCL_report_type_t::error, msg.c_str()); return model_with_rotation{nullptr}; } } if (models.size() <= 0) { - std::string msg = fmt::format("File = {}, line = {}\n", __FILE__, __LINE__); + std::string msg = std::format("File = {}, line = {}\n", __FILE__, __LINE__); VCL_report(VCL_report_type_t::error, msg.c_str()); return model_with_rotation{nullptr}; } @@ -338,7 +338,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, it_model = this->block_models.find("block/" + buffer.pure_id); } if (it_model == this->block_models.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to find block model for full id : \"{}\". Detail : " "undefined reference to model named \"{}\".\n", block_state_str.c_str(), models[mdidx].model_name); @@ -347,7 +347,7 @@ VCL_resource_pack::find_model(const std::string &block_state_str, } if constexpr (false) { std::string msg = - fmt::format("merging back model : {}", models[mdidx].model_name); + std::format("merging back model : {}", models[mdidx].model_name); VCL_report(VCL_report_type_t::information, msg.c_str()); } @@ -367,7 +367,7 @@ bool VCL_resource_pack::compute_projection( if (ret.index() == 0) { auto model = std::get<0>(ret); if (model.model_ptr == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "failed to find a block model for full id :\"{}\", " "function find_model returned nullptr\n", block_state_str.c_str()); @@ -395,7 +395,7 @@ bool VCL_resource_pack::override_texture( auto it = this->textures_original.find(path_in_original.data()); if (it == this->textures_original.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to override texture \"{0}\" with given color {1:#x}, the " "original texture \"{0}\" doesn't exist.", path_in_original, standard_color); @@ -406,7 +406,7 @@ bool VCL_resource_pack::override_texture( const auto &img_original = it->second; if (img_original.rows() != 16 || img_original.cols() != 16) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to override texture \"{0}\" with given " "color {1:#x}, the image size of " "original texture \"{0}\" is {2} * {3} instead of 16 * 16", @@ -558,7 +558,7 @@ bool VCL_resource_pack::update_block_model_textures() noexcept { for (auto &pair : this->textures_override) { auto it = this->textures_original.find(pair.first); if (it == this->textures_original.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Internal logical error when invoking function " "\"VCL_resource_pack::update_block_model_textures\" : " "texture \"{}\" is overrided, but failed to find the " @@ -601,7 +601,7 @@ bool VCL_resource_pack::override_required_textures( } if (is_grass == is_foliage) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to override texture for block {} " "because it is both grass and foliage.", blk.full_id_ptr()->c_str()); @@ -611,7 +611,7 @@ bool VCL_resource_pack::override_required_textures( auto model = this->find_model(*blk.full_id_ptr(), buffer); if (model.index() == 0 && std::get<0>(model).model_ptr == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to override texture for block {} because model is not found.", blk.full_id_ptr()->c_str()); VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -654,7 +654,7 @@ bool VCL_resource_pack::override_required_textures( } if (pair.second.name == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to override texture at address {}, because this " "image cannot be found in this->textures_original.", (const void *)(pair.first)); @@ -663,7 +663,7 @@ bool VCL_resource_pack::override_required_textures( } if (pair.second.is_foliage && pair.second.is_grass) { - std::string msg = fmt::format( + std::string msg = std::format( "Texture \"{}\" will is used both as grass and as foliage.", pair.second.name); VCL_report(VCL_report_type_t::warning, msg.c_str()); @@ -677,7 +677,7 @@ bool VCL_resource_pack::override_required_textures( replace_transparent_with_black); if (!success) { std::string msg = - fmt::format("Failed to override texture named {}", pair.second.name); + std::format("Failed to override texture named {}", pair.second.name); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } diff --git a/VisualCraftL/Resource_tree.cpp b/VisualCraftL/Resource_tree.cpp index 991fb2b4..e627da79 100644 --- a/VisualCraftL/Resource_tree.cpp +++ b/VisualCraftL/Resource_tree.cpp @@ -88,7 +88,7 @@ std::optional zipped_folder::from_zip(std::string_view zipname, destfile->__data.resize(stat.size); zip_file_t *const zfile = zip_fopen_index(zip, entry_idx, ZIP_FL_UNCHANGED); if (zfile == NULL) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to open file in zip. index : {}, file name : {}\n", entry_idx, ::zip_get_name(zip, entry_idx, ZIP_FL_ENC_GUESS)); ::VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -109,7 +109,7 @@ std::optional zipped_folder::from_zip( zip_content.data(), zip_content.size_bytes(), 0, &err); if (source == nullptr) { ::VCL_report(VCL_report_type_t::error, - fmt::format("{} may be a broken zip: {}", zipname, + std::format("{} may be a broken zip: {}", zipname, zip_error_strerror(&err)) .c_str()); return std::nullopt; @@ -118,7 +118,7 @@ std::optional zipped_folder::from_zip( zip_t *archive = zip_open_from_source(source, ZIP_RDONLY, &err); if (archive == nullptr) { ::VCL_report(VCL_report_type_t::error, - fmt::format("{} may be a broken zip: {}", zipname, + std::format("{} may be a broken zip: {}", zipname, zip_error_strerror(&err)) .c_str()); zip_source_free(source); @@ -135,20 +135,20 @@ std::optional zipped_folder::from_zip( std::filesystem::path path = (const char8_t *)(zipname).data(); if (zipname.empty()) { std::string msg = - fmt::format("The filename \"{}\" of zip is empty.", zipname); + std::format("The filename \"{}\" of zip is empty.", zipname); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return std::nullopt; } if (!std::filesystem::is_regular_file(path)) { - std::string msg = fmt::format( + std::string msg = std::format( "The filename \"{}\" does not refer to a regular file.", zipname); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return std::nullopt; } if (path.extension() != ".zip") { - std::string msg = fmt::format( + std::string msg = std::format( "The filename \"{}\" extension name is not .zip", zipname); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return std::nullopt; @@ -158,7 +158,7 @@ std::optional zipped_folder::from_zip( zip_t *const zip = zip_open(zipname.data(), ZIP_RDONLY, &errorcode); if (zip == NULL) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to open zip file : {}, error code = {}", zipname, errorcode); ::VCL_report(VCL_report_type_t::error, msg.c_str()); return std::nullopt; diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 636bc746..f0aacc0f 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -101,7 +101,7 @@ bool add_projection_image_for_bsl(const std::vector &bs_list, resource_pack::buffer_t &buff) noexcept { for (VCL_block *blkp : bs_list) { if (blkp->full_id_ptr() == nullptr) { - std::string msg = fmt::format( + std::string msg = std::format( "\nError : a VCL_block do not have full_id. The block names are : " "{}, {}\n", blkp->name_ZH, blkp->name_EN); @@ -111,7 +111,7 @@ bool add_projection_image_for_bsl(const std::vector &bs_list, // { // std::string msg = - // fmt::format("Computing projection image for full id \"{}\"\n", + // std::format("Computing projection image for full id \"{}\"\n", // blkp->full_id_ptr()->c_str()); // VCL_report(VCL_report_type_t::information, msg.c_str()); // } @@ -120,7 +120,7 @@ bool add_projection_image_for_bsl(const std::vector &bs_list, if (!TokiVC::pack.compute_projection(*blkp->full_id_ptr(), TokiVC::exposed_face, img, buff)) { - std::string msg = fmt::format("failed to compute projection for {}.\n", + std::string msg = std::format("failed to compute projection for {}.\n", blkp->full_id_ptr()->c_str()); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -192,7 +192,7 @@ bool add_color_trans_to_trans_recurs( mutlihash_color_blocks &map_color_blocks) noexcept { if (allowed_depth <= 0) { std::string msg = - fmt::format("Invalid value for allowed_depth : {}\n", allowed_depth); + std::format("Invalid value for allowed_depth : {}\n", allowed_depth); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -385,7 +385,7 @@ bool TokiVC::set_resource_no_lock() noexcept { case SCL_gameVersion::ANCIENT: case SCL_gameVersion::FUTURE: { std::string msg = - fmt::format("Invalid MC version : {}\n", int(TokiVC::version)); + std::format("Invalid MC version : {}\n", int(TokiVC::version)); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -452,7 +452,7 @@ bool TokiVC::set_resource_no_lock() noexcept { } // { - // std::string msg = fmt::format("Size of map_color_blocks = {}\n", + // std::string msg = std::format("Size of map_color_blocks = {}\n", // map_color_blocks.size()); // VCL_report(VCL_report_type_t::information, msg.c_str()); // } @@ -467,7 +467,7 @@ bool TokiVC::set_resource_no_lock() noexcept { } // { - // std::string msg = fmt::format("Size of map_color_blocks = {}\n", + // std::string msg = std::format("Size of map_color_blocks = {}\n", // map_color_blocks.size()); // VCL_report(VCL_report_type_t::information, msg.c_str()); // } @@ -479,7 +479,7 @@ bool TokiVC::set_resource_no_lock() noexcept { map_color_blocks, colors_temp, TokiVC::LUT_basic_color_idx_to_blocks); if (colors_temp.size() != TokiVC::LUT_basic_color_idx_to_blocks.size()) { - std::string msg = fmt::format( + std::string msg = std::format( "\nImpossible error : " "colors_temp.size() (aka {}) " "!=TokiVC::LUT_basic_color_idx_to_blocks.size() (aka {})\n", @@ -489,7 +489,7 @@ bool TokiVC::set_resource_no_lock() noexcept { } if (colors_temp.size() >= UINT16_MAX - 1) { - std::string msg = fmt::format( + std::string msg = std::format( "\nError : too much colors. Num of colors should not exceed {}, " "but it is {} now.\n", UINT16_MAX - 1, colors_temp.size()); @@ -579,7 +579,7 @@ bool TokiVC::set_allowed_no_lock( if (counter_air != 1) { std::string msg = - fmt::format("Types of air block is {}, but expected 1.", counter_air); + std::format("Types of air block is {}, but expected 1.", counter_air); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -590,7 +590,7 @@ bool TokiVC::set_allowed_no_lock( std::fill(allowed_list.begin(), allowed_list.end(), 0); // { - // std::string msg = fmt::format("TokiVC::colorset_basic.color_count() = + // std::string msg = std::format("TokiVC::colorset_basic.color_count() = // {} // .", // TokiVC::colorset_basic.color_count()); @@ -690,7 +690,7 @@ bool TokiVC::convert(::SCL_convertAlgo algo, bool dither) noexcept { } if (!this->img_cvter.convert_image(algo, dither, this->imgcvter_prefer_gpu)) { std::string msg = - fmt::format("Failed to convert. detail : {}, error code = {}", + std::format("Failed to convert. detail : {}, error code = {}", this->img_cvter.gpu_resource()->error_detail_v(), this->img_cvter.gpu_resource()->error_code_v()); VCL_report(VCL_report_type_t::error, msg.c_str()); @@ -725,7 +725,7 @@ bool TokiVC::set_gpu_resource(const VCL_GPU_Platform *p, std::pair err; auto gi = gpu_wrapper::gpu_interface::create(platp, devp, err); if (gi == nullptr || !gi->ok_v()) { - err.second = fmt::format("{}, error code = {}", err.second, err.first); + err.second = std::format("{}, error code = {}", err.second, err.first); write_to_string_deliver(err.second, option.error_message); return false; } else { diff --git a/VisualCraftL/TokiVC_build.cpp b/VisualCraftL/TokiVC_build.cpp index cd1856bd..57de96e2 100644 --- a/VisualCraftL/TokiVC_build.cpp +++ b/VisualCraftL/TokiVC_build.cpp @@ -106,7 +106,7 @@ bool TokiVC::build() noexcept { for (size_t di = 0; di < 3; di++) { if (coord[di] < 0 || coord[di] >= range[di]) { std::string msg = - fmt::format("coordinate out of range : {}, {}, {}.\n", coord[0], + std::format("coordinate out of range : {}, {}, {}.\n", coord[0], coord[1], coord[2]); VCL_report(VCL_report_type_t::error, msg.c_str()); } @@ -116,7 +116,7 @@ bool TokiVC::build() noexcept { auto it = TokiVC::blocks_allowed.find(blkp); if (it == TokiVC::blocks_allowed.end()) { - std::string msg = fmt::format( + std::string msg = std::format( "Failed to find VCL_block at address {} named {} in " "allowed blocks. This is an internal error.", (const void *)blkp, blkp->full_id_ptr()->c_str()); @@ -170,7 +170,7 @@ bool TokiVC::export_litematic(const char *localEncoding_filename, &flag, &detail); if (!ok) { - std::string err = fmt::format( + std::string err = std::format( "VisualCraftL failed to export a litematic. Error " "number(SCSL_errorFlag) = {}, detail : {}", int(flag), detail); @@ -196,7 +196,7 @@ bool TokiVC::export_structure(const char *localEncoding_TargetName, localEncoding_TargetName, is_air_structure_void, &flag, &detail); if (!ok) { - std::string err = fmt::format( + std::string err = std::format( "VisualCraftL failed to export a structure. Error " "number(SCSL_errorFlag) = {}, detail : {}", int(flag), detail); @@ -237,7 +237,7 @@ bool TokiVC::export_WESchem(const char *localEncoding_fileName, const bool ok = this->schem.export_WESchem(localEncoding_fileName, info, &flag, &detail); if (!ok) { - std::string err = fmt::format( + std::string err = std::format( "VisualCraftL failed to export a WorldEdit schem. Error " "number(SCSL_errorFlag) = {}, detail : {}", int(flag), detail); diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index 02efacd8..f9035c5a 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -137,7 +137,7 @@ bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { { libSchem::litematic_info info; info.litename_utf8 = - fmt::format("Testing litematic for 1.{}", int(TokiVC::version)); + std::format("Testing litematic for 1.{}", int(TokiVC::version)); info.author_utf8 = "VisualCraftL"; info.destricption_utf8 = "This litematic is generated by VisualCraft."; @@ -145,7 +145,7 @@ bool TokiVC::export_test_litematic_no_lock(const char *filename) noexcept { if (not res) { auto &err = res.error(); auto msg = - fmt::format("Failed to export {} because {}, detail: {}\n", filename, + std::format("Failed to export {} because {}, detail: {}\n", filename, magic_enum::enum_name(err.first), err.second); VCL_report(VCL_report_type_t::warning, msg.c_str(), true); return false; diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index 8a148ad1..51e7cbe2 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -186,7 +186,7 @@ bool TokiVC::export_flag_diagram(const char *png_filename, if (fp == nullptr) { std::string msg = - fmt::format("fopen failed to create png file {}.", png_filename); + std::format("fopen failed to create png file {}.", png_filename); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; } @@ -195,7 +195,7 @@ bool TokiVC::export_flag_diagram(const char *png_filename, png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (png == nullptr) { fclose(fp); - std::string msg = fmt::format( + std::string msg = std::format( "fopen failed to create png struct for png file {}.", png_filename); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; @@ -206,7 +206,7 @@ bool TokiVC::export_flag_diagram(const char *png_filename, png_destroy_write_struct(&png, &png_info); fclose(fp); std::string msg = - fmt::format("fopen failed to create png info struct for png file {}.", + std::format("fopen failed to create png info struct for png file {}.", png_filename); VCL_report(VCL_report_type_t::error, msg.c_str()); return false; diff --git a/VisualCraftL/VCL_internal.h b/VisualCraftL/VCL_internal.h index b4e70e86..9b87511f 100644 --- a/VisualCraftL/VCL_internal.h +++ b/VisualCraftL/VCL_internal.h @@ -24,8 +24,7 @@ This file is part of SlopeCraft. #define SLOPECRAFT_VISUALCRAFTL_VCL_INTERNAL_H #include "VisualCraftL.h" -#include -// #include +#include void VCL_report(VCL_report_type_t, const char *, bool flush = false) noexcept; diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index f8ed00de..42defbbf 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -99,7 +99,7 @@ VCL_EXPORT_FUN VCL_resource_pack *VCL_create_resource_pack( std::optional zf_opt = zipped_folder::from_zip(filename); if (not zf_opt) { - std::string msg = fmt::format("Failed to parse {}\n", filename); + std::string msg = std::format("Failed to parse {}\n", filename); VCL_report(VCL_report_type_t::error, msg.c_str(), true); } return zf_opt; @@ -142,7 +142,7 @@ VCL_create_resource_pack_from_buffers(const size_t zip_count, file_contents[0].size}); if (not zf_opt) { VCL_report(VCL_report_type_t::error, - fmt::format("Failed to parse {}\n", zip_file_names[0]).c_str(), + std::format("Failed to parse {}\n", zip_file_names[0]).c_str(), true); return nullptr; } @@ -156,7 +156,7 @@ VCL_create_resource_pack_from_buffers(const size_t zip_count, if (not zf_opt) { VCL_report( VCL_report_type_t::error, - fmt::format("Failed to parse {}\n", zip_file_names[idx]).c_str(), + std::format("Failed to parse {}\n", zip_file_names[idx]).c_str(), true); return nullptr; } @@ -943,14 +943,14 @@ VCL_EXPORT_FUN void VCL_display_model(const VCL_model *md) { msg.append("elements :[\n"); for (const auto &ele : mdp->elements) { msg.append(" {\n"); - msg.append(fmt::format(" from : [{}, {}, {}]\n", ele._from[0], + msg.append(std::format(" from : [{}, {}, {}]\n", ele._from[0], ele._from[1], ele._from[2])); - msg.append(fmt::format(" to : [{}, {}, {}]\n", ele._to[0], ele._to[1], + msg.append(std::format(" to : [{}, {}, {}]\n", ele._to[0], ele._to[1], ele._to[2])); msg.append(" faces : [\n"); for (const block_model::face_t &face : ele.faces) { msg.append(" {"); - msg.append(fmt::format( + msg.append(std::format( "uv_start=[{},{}],uv_end=[{},{}],rot={},is_hidden={},texture={}", face.uv_start[0], face.uv_start[1], face.uv_end[0], face.uv_end[1], int(face.rot) * 10, face.is_hidden, (const void *)face.texture)); @@ -1508,7 +1508,7 @@ VCL_EXPORT VCL_preset *VCL_load_preset(const char *filename, block_ids = std::move(nj.at("block_ids")); block_classes = std::move(nj.at("block_classes")); } catch (std::exception &e) { - auto err = fmt::format("Exception occurred when parsing {}, detail: {}", + auto err = std::format("Exception occurred when parsing {}, detail: {}", filename, e.what()); write_to_string_deliver(err, error); return nullptr; @@ -1523,7 +1523,7 @@ VCL_EXPORT VCL_preset *VCL_load_preset(const char *filename, for (auto &pair : block_classes.items()) { auto cls = magic_enum::enum_cast(pair.key()); if (!cls.has_value()) { - auto err = fmt::format( + auto err = std::format( "Invalid block class \"{}\" can not be converted to " "VCL_block_class_t", pair.key()); @@ -1554,7 +1554,7 @@ VCL_EXPORT bool VCL_save_preset(const VCL_preset *p, const char *filename, std::ofstream ofs{filename}; if (!ofs) { - write_to_string_deliver(fmt::format("Failed to open/create {}", filename), + write_to_string_deliver(std::format("Failed to open/create {}", filename), error); return false; } diff --git a/cmake/optional_deps/kompute.cmake b/cmake/optional_deps/kompute.cmake index 24c18f8d..bbc90070 100644 --- a/cmake/optional_deps/kompute.cmake +++ b/cmake/optional_deps/kompute.cmake @@ -1,5 +1,3 @@ -include(${CMAKE_CURRENT_LIST_DIR}/../required_deps/fmtlib.cmake) - find_package(Vulkan REQUIRED) set(KOMPUTE_OPT_USE_BUILT_IN_FMT OFF) diff --git a/cmake/required_deps/fmtlib.cmake b/cmake/required_deps/fmtlib.cmake deleted file mode 100644 index 37e9cdca..00000000 --- a/cmake/required_deps/fmtlib.cmake +++ /dev/null @@ -1,41 +0,0 @@ -cmake_minimum_required(VERSION 3.14) - -set(SC_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - -set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) - -find_package(fmt 9.1.0 QUIET) - -if (NOT ${fmt_FOUND}) - include(FetchContent) - FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG "10.1.1" - OVERRIDE_FIND_PACKAGE - EXCLUDE_FROM_ALL - - # QUIET false - # FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/3rdParty - # FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS FIND_PACKAGE_ARGS find_fmt_args - ) - - message(STATUS "Downaloding......") - - FetchContent_MakeAvailable(fmt) - find_package(fmt REQUIRED) -endif () - -set(CMAKE_CXX_FLAGS ${SC_CMAKE_CXX_FLAGS}) -unset(SC_CMAKE_CXX_FLAGS) - -if (${MSVC}) - # enable c++ exceptions - add_compile_options("/EHsc") - - # target_compile_options(fmt::fmt INTERFACE "/EHsc") -endif () - -# message(STATUS "fmt_POPULATED = " ) - -# message(STATUS "find_fmt_args = " ${find_fmt_args}) diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index 53ee38d1..f15200a2 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -13,5 +13,5 @@ target_link_libraries(FlatDiagram ColorManip PNG::PNG Eigen3::Eigen - fmt::fmt) -target_compile_features(FlatDiagram PUBLIC cxx_std_20) \ No newline at end of file +) +target_compile_features(FlatDiagram PUBLIC cxx_std_23) \ No newline at end of file diff --git a/utilities/FlatDiagram/FlatDiagram.cpp b/utilities/FlatDiagram/FlatDiagram.cpp index 5298ba43..07858372 100644 --- a/utilities/FlatDiagram/FlatDiagram.cpp +++ b/utilities/FlatDiagram/FlatDiagram.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include void libFlatDiagram::reverse_color(uint32_t *ptr, size_t num_pixels) noexcept { // this can be vertorized by compiler optimization @@ -76,14 +76,14 @@ std::string libFlatDiagram::export_flat_diagram( FILE *fp = fopen(png_filename.data(), "wb"); if (fp == nullptr) { - return fmt::format("fopen failed to create png file {}.", png_filename); + return std::format("fopen failed to create png file {}.", png_filename); } png_struct *png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (png == nullptr) { fclose(fp); - return fmt::format("fopen failed to create png struct for png file {}.", + return std::format("fopen failed to create png struct for png file {}.", png_filename); } @@ -91,7 +91,7 @@ std::string libFlatDiagram::export_flat_diagram( if (png_info == nullptr) { png_destroy_write_struct(&png, &png_info); fclose(fp); - return fmt::format( + return std::format( "fopen failed to create png info struct for png file {}.", png_filename); } @@ -145,7 +145,7 @@ std::string libFlatDiagram::export_flat_diagram( } } } catch (const std::exception &e) { - return fmt::format("Exception occurred while writing flat diagram: {}", + return std::format("Exception occurred while writing flat diagram: {}", e.what()); } diff --git a/utilities/StatMemory/others/test_stat_memory.cpp b/utilities/StatMemory/others/test_stat_memory.cpp index a7495055..1b0434b9 100644 --- a/utilities/StatMemory/others/test_stat_memory.cpp +++ b/utilities/StatMemory/others/test_stat_memory.cpp @@ -1,7 +1,7 @@ #include "stat_memory.h" #include -#include -#include +#include +#include int main() { int fail_count = 0; @@ -9,10 +9,10 @@ int main() { const auto sys_info = get_system_memory_info(); if (sys_info) { const auto &val = sys_info.value(); - fmt::print("System free memory: {}\n", val.free); - fmt::print("System total memory: {}\n", val.total); + std::print("System free memory: {}\n", val.free); + std::print("System total memory: {}\n", val.total); } else { - fmt::print("Failed to get system memory info:\n{}\n", sys_info.error()); + std::print("Failed to get system memory info:\n{}\n", sys_info.error()); fail_count++; } } @@ -20,9 +20,9 @@ int main() { const auto self_info = get_self_memory_info(); if (self_info) { const auto &val = self_info.value(); - fmt::print("Memory used by this process: \"{}\"\n", val.used); + std::print("Memory used by this process: \"{}\"\n", val.used); } else { - fmt::print("Failed to get self memory info:\n{}\n", self_info.error()); + std::print("Failed to get self memory info:\n{}\n", self_info.error()); fail_count++; } From 60bbc910fe38134e403e708e7215512148cbfc0f Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 26 Nov 2025 21:00:06 +0800 Subject: [PATCH 1090/1123] Remove usage of fmt Signed-off-by: ToKiNoBug --- SlopeCraft/CMakeLists.txt | 2 -- SlopeCraft/main.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/SlopeCraft/CMakeLists.txt b/SlopeCraft/CMakeLists.txt index b0564079..ab7a15c6 100644 --- a/SlopeCraft/CMakeLists.txt +++ b/SlopeCraft/CMakeLists.txt @@ -9,7 +9,6 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools Network REQUIRED) find_package(magic_enum REQUIRED) -find_package(fmt REQUIRED) find_package(tl-expected REQUIRED) set(SlopeCraft_rc_files) @@ -83,7 +82,6 @@ target_link_libraries(SlopeCraft PRIVATE Qt6::Widgets Qt6::Network magic_enum::magic_enum - fmt::fmt tl::expected SlopeCraftL diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index cec2bba5..b834159a 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include From ba637bd7423e1f91004b0f660db0d017edb92406 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 28 Nov 2025 11:05:35 +0800 Subject: [PATCH 1091/1123] Remove using fmtlib Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 4 +-- VisualCraftL/Resource_tree.cpp | 4 +-- utilities/FlatDiagram/CMakeLists.txt | 1 - utilities/GPUWrapper/CMakeLists.txt | 5 +-- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 3 +- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 10 +++--- utilities/GPUWrapper/OpenCL/OCLWrapper.h | 2 +- utilities/GPUWrapper/Vulkan/CMakeLists.txt | 5 +-- utilities/GPUWrapper/Vulkan/GPU_interface.cpp | 33 ++++++++--------- utilities/Schem/CMakeLists.txt | 2 -- utilities/Schem/Schem.cpp | 24 ++++++------- utilities/Schem/entity.cpp | 6 ++-- utilities/Schem/mushroom.cpp | 6 ++-- utilities/StatMemory/CMakeLists.txt | 3 +- .../StatMemory/stat_memory_src/linux.cpp | 12 +++---- utilities/libpngReader/CMakeLists.txt | 3 +- utilities/libpngReader/libpng_reader.cpp | 6 ++-- vccl/CMakeLists.txt | 3 +- vccl/vccl.cpp | 12 +++---- vccl/vccl_parse_default.cpp | 36 +++++++++---------- 20 files changed, 87 insertions(+), 93 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 4eaf29f9..88c6d74e 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -167,14 +167,14 @@ const mc_block *color_table_impl::find_block_for_index( blkid::char_range pure_id_range; // invalid block id - if (!blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { + if (not blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { return nullptr; } std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; auto mush_type_opt = lsi::pureid_to_type(pure_id); - if (!mush_type_opt.has_value()) { + if (not mush_type_opt.has_value()) { return nullptr; } diff --git a/VisualCraftL/Resource_tree.cpp b/VisualCraftL/Resource_tree.cpp index e627da79..c9d93b8e 100644 --- a/VisualCraftL/Resource_tree.cpp +++ b/VisualCraftL/Resource_tree.cpp @@ -22,10 +22,10 @@ This file is part of SlopeCraft. #include "Resource_tree.h" -#include -#include +#include #include #include +#include #include "VCL_internal.h" diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index f15200a2..94a75f93 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -1,7 +1,6 @@ project(ColorManip VERSION ${SlopeCraft_version} LANGUAGES C CXX) find_package(Eigen3 REQUIRED) -find_package(fmt REQUIRED) add_library(FlatDiagram STATIC FlatDiagram.h diff --git a/utilities/GPUWrapper/CMakeLists.txt b/utilities/GPUWrapper/CMakeLists.txt index 0167c58e..359c35a3 100644 --- a/utilities/GPUWrapper/CMakeLists.txt +++ b/utilities/GPUWrapper/CMakeLists.txt @@ -4,10 +4,7 @@ add_library(GPUInterface STATIC GPU_interface.h) target_include_directories(GPUInterface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_features(GPUInterface PUBLIC cxx_std_20) - -find_package(fmt REQUIRED) -target_link_libraries(GPUInterface PUBLIC fmt::fmt) +target_compile_features(GPUInterface PUBLIC cxx_std_23) if (${LINUX}) set_target_properties(GPUInterface PROPERTIES TARGET_INDENPENDENT_CODE TRUE) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 02e2708f..2a780b78 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -25,7 +25,8 @@ target_link_libraries(GPUInterface PUBLIC OpenCL::OpenCL ColorManip_cl_rc - Eigen3::Eigen) + Eigen3::Eigen +) message(STATUS "OpenCL_INCLUDE_DIR = ${OpenCL_INCLUDE_DIR}") message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}") diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index ec673b88..190418c0 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -22,11 +22,11 @@ This file is part of SlopeCraft. #include "OCLWrapper.h" #include "../GPU_interface.h" +#include +#include #include -#include #include -#include extern "C" { extern const unsigned char ColorManip_cl_rc[]; @@ -152,9 +152,9 @@ void ocl_warpper::ocl_resource::init_resource() noexcept { this->device, &ec_get_build_log); if (ec_get_build_log == CL_SUCCESS) { this->err_msg = - fmt::format("Failed to build program. Build log:\n{}", build_log); + std::format("Failed to build program. Build log:\n{}", build_log); } else { - this->err_msg = fmt::format( + this->err_msg = std::format( "Failed to build program, and then failed to retrieve build log with " "error code {}", ec_get_build_log); @@ -341,7 +341,7 @@ cl::Kernel *ocl_warpper::ocl_resource::kernel_by_algo( default: return nullptr; } - return nullptr; + // return nullptr; } void ocl_warpper::ocl_resource::set_task( diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.h b/utilities/GPUWrapper/OpenCL/OCLWrapper.h index acbf5694..79afb209 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.h +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.h @@ -30,7 +30,7 @@ This file is part of SlopeCraft. #include "../GPU_interface.h" #include -#include +#include #include #include diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index fec0d629..1383dd42 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -13,8 +13,9 @@ target_link_libraries(GPUInterface PUBLIC Vulkan::Vulkan kompute::kompute Eigen3::Eigen - tl::expected) -target_compile_features(GPUInterface PRIVATE cxx_std_20) + tl::expected +) +target_compile_features(GPUInterface PRIVATE cxx_std_23) get_target_property(glslc_exe Vulkan::glslc LOCATION) message(STATUS "glslc found at ${glslc_exe}") diff --git a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp index ffafbdfc..2154c5a9 100644 --- a/utilities/GPUWrapper/Vulkan/GPU_interface.cpp +++ b/utilities/GPUWrapper/Vulkan/GPU_interface.cpp @@ -1,14 +1,15 @@ -#include -#include -#include +#include +#include #include #include #include #include #include -#include #include +#include +#include +#include #include #include "GPUWrapper/GPU_interface.h" @@ -88,7 +89,7 @@ create_vk_instance() noexcept { return instance; } catch (const std::exception& e) { - fmt::print("Failed to create vulkan instance, exception details: {}", + std::print("Failed to create vulkan instance, exception details: {}", e.what()); return nullptr; } @@ -202,7 +203,7 @@ device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, try { devices = plat.instance->enumeratePhysicalDevices(); } catch (const std::exception& e) { - fmt::println("Failed to enumerate physical devices, detail: {}", e.what()); + std::println("Failed to enumerate physical devices, detail: {}", e.what()); set_error_code(ec, error_code::create_physical_device_failure); return nullptr; } @@ -259,7 +260,7 @@ device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, result->device = std::make_shared(phy_device.createDevice(dci)); } catch (const std::exception& e) { - fmt::println("Failed to create logical device, details: {}", e.what()); + std::println("Failed to create logical device, details: {}", e.what()); set_error_code(ec, error_code::create_logical_device_failure); delete result; return nullptr; @@ -269,11 +270,11 @@ device_wrapper* device_wrapper::create(gpu_wrapper::platform_wrapper* pw, set_error_code(ec, error_code::ok); return result; } catch (const std::exception& e) { - fmt::println("Failed to create logical device because {}", e.what()); + std::println("Failed to create logical device because {}", e.what()); set_error_code(ec, error_code::create_logical_device_failure); return nullptr; } catch (...) { - fmt::println("Failed to create logical device because unknown exception."); + std::println("Failed to create logical device because unknown exception."); set_error_code(ec, error_code::create_logical_device_failure); return nullptr; } @@ -375,7 +376,7 @@ class gpu_impl : public gpu_interface { } catch (const std::exception& e) { this->error.code = error_code::manager_set_colorset_failure; this->error.message = - fmt::format("Failed to set colorset, detail: {}", e.what()); + std::format("Failed to set colorset, detail: {}", e.what()); } } @@ -391,7 +392,7 @@ class gpu_impl : public gpu_interface { } catch (const std::exception& e) { this->error.code = error_code::manager_set_tasks_failure; this->error.message = - fmt::format("Failed to set tasks, detail: {}", e.what()); + std::format("Failed to set tasks, detail: {}", e.what()); } } @@ -401,15 +402,15 @@ class gpu_impl : public gpu_interface { } catch (const std::exception& e) { this->error.code = error_code::manager_wait_failure; this->error.message = - fmt::format("Failed to wait for results, detail: {}", e.what()); + std::format("Failed to wait for results, detail: {}", e.what()); } - // fmt::println("Computation result: ["); + // std::println("Computation result: ["); // for (uint32_t i = 0; i < this->task_count; i++) { - // fmt::println("\t[task {}, result idx = {}, result diff = {}]", i, + // std::println("\t[task {}, result idx = {}, result diff = {}]", i, // this->result_idx->data()[i], // this->result_diff->data()[i]); // } - // fmt::println("]"); + // std::println("]"); } void execute_v(::SCL_convertAlgo algo, bool wait) noexcept final { @@ -440,7 +441,7 @@ class gpu_impl : public gpu_interface { } catch (const std::exception& e) { this->error.code = error_code::manager_execute_failure; this->error.message = - fmt::format("Failed to execute computation, detail: {}", e.what()); + std::format("Failed to execute computation, detail: {}", e.what()); } } diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 6a2b503c..323d0cdb 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -19,7 +19,6 @@ target_compile_features(Schem PUBLIC cxx_std_14) find_package(Eigen3 REQUIRED) find_package(cereal REQUIRED) -find_package(fmt REQUIRED) find_package(magic_enum REQUIRED) find_package(Boost CONFIG) @@ -29,7 +28,6 @@ target_link_libraries(Schem PUBLIC NBTWriter Eigen3::Eigen cereal::cereal - fmt::fmt magic_enum::magic_enum NBTWriter ) diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 5fdbcde0..22571063 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -27,7 +27,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include #include #include "Schem.h" @@ -56,7 +56,7 @@ std::string Schem::check_size() const noexcept { std::string Schem::check_size(int64_t x, int64_t y, int64_t z) noexcept { if (x < 0 || y < 0 || z < 0) { - return fmt::format( + return std::format( "Size in one or more dimensions is negative. x= {}, y= {}, z= {}", x, y, z); } @@ -196,7 +196,7 @@ Schem::split_by_block_size( for (size_t blk_idx = 0; blk_idx < xyz_block_len[dim].size(); blk_idx++) { const auto block_len = xyz_block_len[dim][blk_idx]; if (block_len <= 0) { - return tl::make_unexpected(fmt::format( + return tl::make_unexpected(std::format( "Found non-positive block length in dim = {}, block index = {}", dim, blk_idx)); } @@ -209,7 +209,7 @@ Schem::split_by_block_size( cur_block_start_index = cur_block_end_index; } if (block_len_sum[dim] not_eq shape[dim]) { - return tl::make_unexpected(fmt::format( + return tl::make_unexpected(std::format( "The sum of block length of dim {} is {}, which is not identical " "to shape on this dim({}), ", dim, block_len_sum[dim], shape[dim])); @@ -399,7 +399,7 @@ tl::expected> Schem::pre_check( // wrong extension return tl::make_unexpected(std::make_pair( SCL_errorFlag::EXPORT_SCHEM_WRONG_EXTENSION, - fmt::format("The filename extension must be \"{}\".", extension))); + std::format("The filename extension must be \"{}\".", extension))); } // check for invalid blocks { @@ -407,7 +407,7 @@ tl::expected> Schem::pre_check( if (this->have_invalid_block(&pos[0], &pos[1], &pos[2])) { return tl::make_unexpected(std::make_pair( SCL_errorFlag::EXPORT_SCHEM_HAS_INVALID_BLOCKS, - fmt::format("The first invalid block is at x={}, y={}, z={}", pos[0], + std::format("The first invalid block is at x={}, y={}, z={}", pos[0], pos[1], pos[2]))); } } @@ -429,7 +429,7 @@ Schem::export_litematic(std::string_view filename, if (!lite.open(filename.data())) { return tl::make_unexpected( std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, - fmt::format("Failed to open file: {}", filename))); + std::format("Failed to open file: {}", filename))); } lite.writeCompound("Metadata"); @@ -567,7 +567,7 @@ Schem::export_litematic(std::string_view filename, lite.close(); return tl::make_unexpected(std::make_pair( SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION, - fmt::format("Unknown major game version! Only 1.12 to 1.19 is " + std::format("Unknown major game version! Only 1.12 to 1.19 is " "supported, but given value {}", int(this->MC_major_ver)))); } @@ -617,7 +617,7 @@ Schem::export_structure(std::string_view filename, if (!file.open(filename.data())) { return tl::make_unexpected( std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, - fmt::format("Failed to open file {}", filename))); + std::format("Failed to open file {}", filename))); } file.writeListHead("size", NBT::Int, 3); @@ -752,7 +752,7 @@ Schem::export_structure(std::string_view filename, file.close(); return tl::make_unexpected(std::make_pair( SCL_errorFlag::UNKNOWN_MAJOR_GAME_VERSION, - fmt::format("Unknown major game version! Only 1.12 to 1.21 is " + std::format("Unknown major game version! Only 1.12 to 1.21 is " "supported, but given value {}", (int)this->MC_major_ver))); } @@ -784,7 +784,7 @@ tl::expected> Schem::export_WESchem( if (not file.open(filename.data())) { return tl::make_unexpected( std::make_pair(SCL_errorFlag::EXPORT_SCHEM_FAILED_TO_CREATE_FILE, - fmt::format("Failed to open file {}", filename))); + std::format("Failed to open file {}", filename))); } auto write_version = [&]() { // data version @@ -915,7 +915,7 @@ libSchem::Schem::remove_unused_ids() noexcept { for (const ele_t blkid : *this) { if (blkid >= this->palette_size()) [[unlikely]] { return tl::make_unexpected( - fmt::format("The scheme required block with id = {}, but the block " + std::format("The scheme required block with id = {}, but the block " "palette has only {} blocks", blkid, this->palette_size())); } diff --git a/utilities/Schem/entity.cpp b/utilities/Schem/entity.cpp index 8b97dab1..9e912ebc 100644 --- a/utilities/Schem/entity.cpp +++ b/utilities/Schem/entity.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include "entity.h" @@ -69,7 +69,7 @@ tl::expected libSchem::item_frame::dump( bytes += destination.writeFloat("ItemDropChance", this->item_drop_chance); if (this->item_rotation < 0 or this->item_rotation > 7) { return tl::make_unexpected( - fmt::format("Invalid item rotation {}, expected in range [0,7]", + std::format("Invalid item rotation {}, expected in range [0,7]", int(this->item_rotation))); } bytes += destination.writeByte("ItemRotation", this->item_rotation); @@ -79,7 +79,7 @@ tl::expected libSchem::item_frame::dump( auto res_item = this->item_->dump(destination, data_version); if (not res_item) { return tl::make_unexpected( - fmt::format("Failed to dump item fields: {}", res_item.error())); + std::format("Failed to dump item fields: {}", res_item.error())); } bytes += res_item.value(); bytes += destination.endCompound(); diff --git a/utilities/Schem/mushroom.cpp b/utilities/Schem/mushroom.cpp index 846ff449..1d3a56a5 100644 --- a/utilities/Schem/mushroom.cpp +++ b/utilities/Schem/mushroom.cpp @@ -1,5 +1,5 @@ #include "mushroom.h" -#include +#include #include #include #include @@ -35,7 +35,7 @@ lsi::mushroom_state::mushroom_state(std::array _stoma) : m_is_stoma{_stoma} {} std::string lsi::mushroom_state::to_block_state_list() const noexcept { - return fmt::format("up={},down={},north={},south={},east={},west={}", + return std::format("up={},down={},north={},south={},east={},west={}", m_is_stoma[0], m_is_stoma[1], m_is_stoma[2], m_is_stoma[3], m_is_stoma[4], m_is_stoma[5]); } @@ -126,7 +126,7 @@ std::string_view lsi::mushroom_block::pureid() const noexcept { std::string lsi::mushroom_block::id(bool with_namespacename) const noexcept { std::string_view nsn = (with_namespacename ? "minecraft::" : ""); - return fmt::format("{}{}[{}]", nsn, this->pureid(), + return std::format("{}{}[{}]", nsn, this->pureid(), m_state.to_block_state_list()); } diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index faa0578b..2c126006 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -7,8 +7,7 @@ set(CMAKE_AUTORCC ON) add_library(StatMemory STATIC stat_memory.h) find_package(tl-expected REQUIRED) -find_package(fmt REQUIRED) -target_link_libraries(StatMemory PUBLIC tl::expected fmt::fmt) +target_link_libraries(StatMemory PUBLIC tl::expected) target_include_directories(StatMemory PUBLIC $) target_compile_features(StatMemory PUBLIC cxx_std_23) # Set source file by system diff --git a/utilities/StatMemory/stat_memory_src/linux.cpp b/utilities/StatMemory/stat_memory_src/linux.cpp index 714b0db6..0b7de0f1 100644 --- a/utilities/StatMemory/stat_memory_src/linux.cpp +++ b/utilities/StatMemory/stat_memory_src/linux.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -23,7 +23,7 @@ tl::expected, std::string> parse_linux_file( FILE* fd = fopen(filename, "r"); if (fd == nullptr) { return tl::make_unexpected( - fmt::format("Failed to read \"{}\", fopen returned NULL", filename)); + std::format("Failed to read \"{}\", fopen returned NULL", filename)); } std::array buf; while (true) { @@ -50,7 +50,7 @@ tl::expected, std::string> parse_linux_file( if (idx_of_colon == line_sv.npos) { // Failed to parse this line, skip it. continue; // return tl::make_unexpected( - // fmt::format("Failed to parse \"{}\" from {}", line_sv, + // std::format("Failed to parse \"{}\" from {}", line_sv, // filename)); } @@ -130,7 +130,7 @@ get_system_memory_info() noexcept { [[nodiscard]] tl::expected get_self_memory_info() noexcept { const int64_t pid = getpid(); - const std::string file = fmt::format("/proc/{}/status", pid); + const std::string file = std::format("/proc/{}/status", pid); auto fields = parse_linux_file(file.c_str(), [](std::string_view line) { return not line.starts_with("VmSize"); }); @@ -143,12 +143,12 @@ get_self_memory_info() noexcept { if (it not_eq val.end()) { const int64_t used_memory = it->second; if (used_memory < 0) { - return tl::make_unexpected(fmt::format( + return tl::make_unexpected(std::format( "VmSize from {} is negative(the value is {})", file, used_memory)); } return self_memory_usage{uint64_t(used_memory)}; } return tl::make_unexpected( - fmt::format("Failed to parse field VmSize from {}", file)); + std::format("Failed to parse field VmSize from {}", file)); } diff --git a/utilities/libpngReader/CMakeLists.txt b/utilities/libpngReader/CMakeLists.txt index 22600d16..d47d06ff 100644 --- a/utilities/libpngReader/CMakeLists.txt +++ b/utilities/libpngReader/CMakeLists.txt @@ -3,10 +3,9 @@ add_library(libpng_reader STATIC libpng_reader.h) find_package(tl-expected REQUIRED) -find_package(fmt REQUIRED) find_package(PNG REQUIRED) target_compile_features(libpng_reader PUBLIC cxx_std_23) -target_link_libraries(libpng_reader PUBLIC tl::expected fmt::fmt PNG::PNG) +target_link_libraries(libpng_reader PUBLIC tl::expected PNG::PNG) target_include_directories(libpng_reader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index e22ec7fb..01fe99a6 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -4,7 +4,7 @@ #include "libpng_reader.h" #include -#include +#include struct read_buffer_wrapper { const void *data; @@ -32,7 +32,7 @@ parse_png_into_argb32(std::span encoded, std::string warnings{}; if (encoded.size() < 8) { return { - tl::make_unexpected(fmt::format( + tl::make_unexpected(std::format( "File is too small ({} bytes) to be possible PNG", encoded.size())), warnings}; } @@ -129,7 +129,7 @@ parse_png_into_argb32(std::span encoded, default: png_destroy_read_struct(&png, &info, &info_end); return {tl::make_unexpected( - fmt::format("Unknown color type {}", color_type)), + std::format("Unknown color type {}", color_type)), warnings}; } // cout << ")\n"; diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index 0dda0002..08c2f107 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -17,7 +17,6 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 COMPONENTS Widgets LinguistTools REQUIRED) -find_package(fmt REQUIRED) find_package(magic_enum REQUIRED) qt_add_executable(vccl @@ -29,7 +28,7 @@ qt_add_executable(vccl ${vccl_win_sources} ) -target_link_libraries(vccl PRIVATE VisualCraftL Qt6::Core Qt6::Gui fmt::fmt magic_enum::magic_enum) +target_link_libraries(vccl PRIVATE VisualCraftL Qt6::Core Qt6::Gui magic_enum::magic_enum) target_include_directories(vccl PRIVATE ${cli11_include_dir} ${SlopeCraft_Nlohmann_json_include_dir}) find_package(OpenMP REQUIRED) diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 5ace058f..87143801 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -29,7 +29,7 @@ This file is part of SlopeCraft. #include #include -#include +#include using std::cout, std::endl; @@ -181,11 +181,11 @@ int main(int argc, char **argv) { CLI11_PARSE(app, argc, argv); if (show_config) { - fmt::println("Version : {}", SC_VERSION_STR); - fmt::println("Build type : {}", CMAKE_BUILD_TYPE); - fmt::println("GPU API : {}", SC_GPU_API); - fmt::println("Vectorize : {}", SC_VECTORIZE); - fmt::println("Gprof : {}", SC_GPROF); + std::println("Version : {}", SC_VERSION_STR); + std::println("Build type : {}", CMAKE_BUILD_TYPE); + std::println("GPU API : {}", SC_GPU_API); + std::println("Vectorize : {}", SC_VECTORIZE); + std::println("Gprof : {}", SC_GPROF); return 0; } diff --git a/vccl/vccl_parse_default.cpp b/vccl/vccl_parse_default.cpp index 3783f95c..57607f40 100644 --- a/vccl/vccl_parse_default.cpp +++ b/vccl/vccl_parse_default.cpp @@ -24,7 +24,7 @@ This file is part of SlopeCraft. #include #include #include -#include +#include #include #include @@ -227,7 +227,7 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - fmt::print( + std::print( "Parsing resource pack and block state list in {} miliseconds.\n", wt * 1000); } @@ -241,23 +241,23 @@ int run(const inputs &input) noexcept { } if (input.show_color_num) { - fmt::println("{} colors avaliable.", VCL_get_allowed_colors(nullptr, 0)); + std::println("{} colors avaliable.", VCL_get_allowed_colors(nullptr, 0)); } if (input.export_test_lite) { - std::string filename = fmt::format("{}test_all_blocks_mc={}.litematic", + std::string filename = std::format("{}test_all_blocks_mc={}.litematic", input.prefix, int(input.version)); wt = omp_get_wtime(); if (!VCL_export_test_litematic(filename.c_str())) { - fmt::print("Failed to export test litematic \"{}\"\n", filename); + std::print("Failed to export test litematic \"{}\"\n", filename); return __LINE__; } wt = omp_get_wtime() - wt; if (input.benchmark) { - fmt::print("Exported \"{}\" in {} seconds.\n", filename, wt); + std::print("Exported \"{}\" in {} seconds.\n", filename, wt); } } @@ -274,7 +274,7 @@ int run(const inputs &input) noexcept { QImage img(QString::fromLocal8Bit(img_filename.c_str())); if (img.isNull()) { - fmt::print("Failed to open image {}\n", img_filename); + std::print("Failed to open image {}\n", img_filename); VCL_destroy_kernel(kernel); return __LINE__; } @@ -302,7 +302,7 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - fmt::print("Converted {} pixels in {} seconds.\n", + std::print("Converted {} pixels in {} seconds.\n", img.height() * img.width(), wt); } @@ -318,7 +318,7 @@ int run(const inputs &input) noexcept { const bool ok = img.save(QString::fromLocal8Bit(dst_name_str.c_str())); if (!ok) { - fmt::print("Failed to save image {}\n", dst_name_str); + std::print("Failed to save image {}\n", dst_name_str); return __LINE__; } // cout << dst_path << endl; @@ -340,14 +340,14 @@ int run(const inputs &input) noexcept { option.split_line_col_margin = input.flat_diagram_splitline_margin_col; wtime[layer] = omp_get_wtime(); if (!kernel->export_flag_diagram(dst_name_str.c_str(), option, layer)) { - fmt::print("Failed to export flat diagram {}\n", dst_name_str); + std::print("Failed to export flat diagram {}\n", dst_name_str); return __LINE__; } wtime[layer] = omp_get_wtime() - wtime[layer]; } if (input.benchmark) { - fmt::print("Export flatdiagram containing {} images in ", input.layers); + std::print("Export flatdiagram containing {} images in ", input.layers); for (int i = 0; i < input.layers; i++) { cout << wtime[i] << ", "; } @@ -367,7 +367,7 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (input.benchmark) { - fmt::print("Built {} blocks in {} seconds.\n", kernel->xyz_size(), wt); + std::print("Built {} blocks in {} seconds.\n", kernel->xyz_size(), wt); } if (input.make_litematic) { @@ -380,12 +380,12 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - fmt::println("Failed to export {}.", filename); + std::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - fmt::println("Export litematic with {} blocks in {} seconds.", + std::println("Export litematic with {} blocks in {} seconds.", kernel->xyz_size(), wt); } } @@ -400,12 +400,12 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - fmt::println("Failed to export {}.", filename); + std::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - fmt::print("Export WE schem with {} blocks in {} seconds.\n", + std::print("Export WE schem with {} blocks in {} seconds.\n", kernel->xyz_size(), wt); } } @@ -420,12 +420,12 @@ int run(const inputs &input) noexcept { wt = omp_get_wtime() - wt; if (!success) { - fmt::println("Failed to export {}.", filename); + std::println("Failed to export {}.", filename); return __LINE__; } if (input.benchmark) { - fmt::print( + std::print( "Export vanilla structure file with {} blocks in {} seconds.\n", kernel->xyz_size(), wt); } From 1d94f3b5fa634773236023530c0f0eabb3aaf9f6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Fri, 28 Nov 2025 14:03:15 +0800 Subject: [PATCH 1092/1123] Fix vccl build Signed-off-by: ToKiNoBug --- vccl/vccl.cpp | 2 +- vccl/vccl_parse_default.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 87143801..5f2d3e03 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -29,7 +29,7 @@ This file is part of SlopeCraft. #include #include -#include +#include using std::cout, std::endl; diff --git a/vccl/vccl_parse_default.cpp b/vccl/vccl_parse_default.cpp index 57607f40..b1a09982 100644 --- a/vccl/vccl_parse_default.cpp +++ b/vccl/vccl_parse_default.cpp @@ -20,13 +20,13 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include "vccl_internal.h" -#include -#include #include -#include +#include #include #include +#include +#include +#include "vccl_internal.h" void cb_progress_range_set(void *, int, int, int) {} void cb_progress_add(void *, int) {} From 0d54305427f7920c236130d23d442aa7444ccf93 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 17:01:35 +0800 Subject: [PATCH 1093/1123] Fix SCL export flat diagram (#142 Signed-off-by: ToKiNoBug --- SlopeCraftL/color_table.cpp | 131 +++++++++++++++++++++++------------ SlopeCraftL/color_table.h | 14 +++- SlopeCraftL/mc_block.cpp | 15 ++++ SlopeCraftL/mc_block.h | 27 +++++++- SlopeCraftL/structure_3D.cpp | 22 ++++-- 5 files changed, 158 insertions(+), 51 deletions(-) diff --git a/SlopeCraftL/color_table.cpp b/SlopeCraftL/color_table.cpp index 88c6d74e..ce053754 100644 --- a/SlopeCraftL/color_table.cpp +++ b/SlopeCraftL/color_table.cpp @@ -151,57 +151,67 @@ std::vector color_table_impl::block_id_list( } const mc_block *color_table_impl::find_block_for_index( - int idx, std::string_view blkid) const noexcept { - if (idx < 0) { + std::string_view blkid) const noexcept { + if (blkid.empty()) { return nullptr; } - - if (idx < (int)this->blocks.size()) { - // assert(this->blocks[idx].id == blkid); - return &this->blocks[idx]; - } - - // the block must be mushroom - namespace lsi = libSchem::internal; - using lsi::mushroom_type; - blkid::char_range pure_id_range; // invalid block id if (not blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { return nullptr; } - - std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; - - auto mush_type_opt = lsi::pureid_to_type(pure_id); - if (not mush_type_opt.has_value()) { - return nullptr; - } - - uint8_t expected_basecolor = 0; - switch (mush_type_opt.value()) { - case mushroom_type::red: - expected_basecolor = 28; - break; - case mushroom_type::brown: - expected_basecolor = 10; - break; - case mushroom_type::stem: - expected_basecolor = 3; - break; - } - - const auto *blkp = this->find_block_for_index(expected_basecolor, {}); - - if (blkp == nullptr) { - return nullptr; - } - - if (lsi::pureid_to_type(pure_id) != mush_type_opt) { - return nullptr; - } - - return blkp; + std::string_view pure_id{pure_id_range}; + + // if (idx < 0) { + // return nullptr; + // } + // + // if (idx < (int)this->blocks.size()) { + // // assert(this->blocks[idx].id == blkid); + // return &this->blocks[idx]; + // } + // + // // the block must be mushroom + // namespace lsi = libSchem::internal; + // using lsi::mushroom_type; + // + // blkid::char_range pure_id_range; + // // invalid block id + // if (not blkid::process_blk_id(blkid, nullptr, &pure_id_range, nullptr)) { + // return nullptr; + // } + // + // std::string_view pure_id{pure_id_range.begin(), pure_id_range.end()}; + // + // auto mush_type_opt = lsi::pureid_to_type(pure_id); + // if (not mush_type_opt.has_value()) { + // return nullptr; + // } + // + // uint8_t expected_basecolor = 0; + // switch (mush_type_opt.value()) { + // case mushroom_type::red: + // expected_basecolor = 28; + // break; + // case mushroom_type::brown: + // expected_basecolor = 10; + // break; + // case mushroom_type::stem: + // expected_basecolor = 3; + // break; + // } + // + // const auto *blkp = this->find_block_for_index(expected_basecolor, {}); + // + // if (blkp == nullptr) { + // return nullptr; + // } + // + // if (lsi::pureid_to_type(pure_id) != mush_type_opt) { + // return nullptr; + // } + // + // return blkp; } uint64_t color_table_impl::hash() const noexcept { @@ -454,6 +464,39 @@ std::string color_table_impl::impl_generate_test_schematic( } } +std::expected +color_table_impl::build_indexer() const noexcept { + color_table_searching_index indexer; + for (const auto &blk : this->blocks) { + auto info_opt = blk.detail_info(this->mc_version()); + if (not info_opt) { + return std::unexpected{std::format("Found invalid block id: \"{}\"", + blk.idForVersion(this->mc_version()))}; + } + indexer.block_LUT.emplace(info_opt.value(), &blk); + } + + return indexer; +} + +const mc_block *color_table_searching_index::find( + std::string_view id) const noexcept { + using namespace blkid; + char_range namespace_, pure_id; + if (not process_blk_id(id, &namespace_, &pure_id, nullptr)) { + return nullptr; + } + const block_detail_info detail{ + .id_namespace{namespace_}, + .pure_id{pure_id}, + }; + auto it = this->block_LUT.find(detail); + if (it == this->block_LUT.end()) { + return nullptr; + } + return it->second; +} + std::array LUT_map_color_to_ARGB() noexcept { const auto &basic = *SlopeCraft::basic_colorset; std::array ret; diff --git a/SlopeCraftL/color_table.h b/SlopeCraftL/color_table.h index b5117d2d..8f0d9a04 100644 --- a/SlopeCraftL/color_table.h +++ b/SlopeCraftL/color_table.h @@ -7,13 +7,20 @@ #include #include -#include +#include +#include #include "SlopeCraftL.h" #include "SCLDefines.h" #include "mc_block.h" #include "string_deliver.h" #include "converted_image.h" +struct color_table_searching_index { + std::unordered_map block_LUT; + + [[nodiscard]] const mc_block *find(std::string_view id) const noexcept; +}; + class color_table_impl : public SlopeCraft::color_table { public: std::shared_ptr allowed{new colorset_allowed_t}; @@ -55,7 +62,7 @@ class color_table_impl : public SlopeCraft::color_table { bool contain_air) const noexcept; [[nodiscard]] const mc_block *find_block_for_index( - int index, std::string_view block_id) const noexcept; + std::string_view block_id) const noexcept; [[nodiscard]] uint64_t hash() const noexcept; @@ -134,6 +141,9 @@ class color_table_impl : public SlopeCraft::color_table { std::string impl_generate_test_schematic( std::string_view filename, const test_blocklist_options &option) const noexcept; + + [[nodiscard]] std::expected + build_indexer() const noexcept; }; [[nodiscard]] std::array LUT_map_color_to_ARGB() noexcept; diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index ce2d8eeb..eacbd290 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -23,6 +23,8 @@ This file is part of SlopeCraft. #include "mc_block.h" #include "blocklist.h" +#include "process_block_id.h" + mc_block::mc_block() { // id = ""; // version = 0; @@ -36,6 +38,19 @@ mc_block::mc_block() { // wallUseable=true; } +std::optional mc_block::detail_info( + SCL_gameVersion current_version) const { + using namespace blkid; + char_range namespace_name; + char_range pure_id; + const bool ok = blkid::process_blk_id(this->idForVersion(current_version), + &namespace_name, &pure_id, nullptr); + if (not ok) { + return std::nullopt; + } + return block_detail_info{.id_namespace{namespace_name}, .pure_id{pure_id}}; +} + void mc_block_interface::clear() noexcept { setBurnable(false); setDoGlow(false); diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index 2301ec20..085f348d 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -24,18 +24,40 @@ This file is part of SlopeCraft. #define SIMPLEBLOCK_H #include +#include #include #include #include #include #include +#include #include "SCLDefines.h" using namespace SlopeCraft; -#include typedef std::vector stringList; +struct block_detail_info { + std::string_view id_namespace; + std::string_view pure_id; + + [[nodiscard]] inline bool operator==( + const block_detail_info &b) const noexcept { + return (this->id_namespace == b.id_namespace) and + (this->pure_id == b.pure_id); + } +}; + +template <> +struct std::hash { + [[nodiscard]] static inline size_t operator()( + const block_detail_info &info) noexcept { + size_t hash = std::hash{}(info.id_namespace); + hash ^= std::hash{}(info.pure_id); + return hash; + } +}; + class mc_block : public ::SlopeCraft::mc_block_interface { public: mc_block(); @@ -54,6 +76,9 @@ class mc_block : public ::SlopeCraft::mc_block_interface { bool burnable{false}; uint8_t stackSize{64}; + [[nodiscard]] std::optional detail_info( + SCL_gameVersion current_version) const; + const char *getId() const noexcept override { return id.data(); }; uint8_t getVersion() const noexcept override { return version; }; const char *getIdOld() const noexcept override { return idOld.data(); }; diff --git a/SlopeCraftL/structure_3D.cpp b/SlopeCraftL/structure_3D.cpp index cd989e33..e047bda1 100644 --- a/SlopeCraftL/structure_3D.cpp +++ b/SlopeCraftL/structure_3D.cpp @@ -324,14 +324,28 @@ bool structure_3D_impl::export_flat_diagram( std::vector> img_list_rmj; img_list_rmj.reserve(this->schem.palette_size()); + color_table_searching_index block_indexer; + { + auto indexer_opt = + dynamic_cast(table_).build_indexer(); + if (not indexer_opt) { + option.ui.report_error( + errorFlag::EXPORT_FLAT_DIAGRAM_FAILURE, + std::format("SlopeCraftL internal error. {}", indexer_opt.error()) + .c_str()); + return false; + } + block_indexer = std::move(indexer_opt.value()); + } for (size_t pblkid = 0; pblkid < this->schem.palette_size(); pblkid++) { - if (pblkid == 0) { + if (pblkid == 0) { // air img_list_rmj.emplace_back(); img_list_rmj[0].setZero(); continue; } std::string_view id = this->schem.palette()[pblkid]; - const mc_block *blkp = table.find_block_for_index(pblkid - 1, id); + const mc_block *blkp = block_indexer.find(id); + // const mc_block *blkp = table.find_block_for_index(pblkid - 1, id); if (blkp == nullptr) { std::string blkid_full; blkid_full.reserve(64 * 2048); @@ -357,8 +371,8 @@ bool structure_3D_impl::export_flat_diagram( auto block_at_callback = [this, &img_list_rmj]( int64_t r, int64_t c) -> libFlatDiagram::block_img_ref_t { - if (r < 0 || c < 0 || r >= this->schem.z_range() || - c >= this->schem.x_range()) { + if (r < 0 or c < 0 or r >= this->schem.z_range() or + c >= this->schem.x_range()) { // out of range return libFlatDiagram::block_img_ref_t{img_list_rmj.at(0).data()}; } From 1eea38ba4194ca12d9928c1434a383b1acb11d75 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 17:06:00 +0800 Subject: [PATCH 1094/1123] Fix vccl build Signed-off-by: ToKiNoBug --- vccl/vccl.cpp | 1 + vccl/vccl_parse_default.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 5f2d3e03..349ee30f 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -30,6 +30,7 @@ This file is part of SlopeCraft. #include #include +#include using std::cout, std::endl; diff --git a/vccl/vccl_parse_default.cpp b/vccl/vccl_parse_default.cpp index b1a09982..9363d693 100644 --- a/vccl/vccl_parse_default.cpp +++ b/vccl/vccl_parse_default.cpp @@ -23,6 +23,7 @@ This file is part of SlopeCraft. #include #include #include +#include #include #include #include From 8eb28baedabbe4fe7641dbc266e36972a57c66bd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 17:06:15 +0800 Subject: [PATCH 1095/1123] Fix linux build with kompute Signed-off-by: ToKiNoBug --- .github/workflows/linux-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9ba0d7f1..b4c229b1 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -63,7 +63,7 @@ jobs: - name: Install Vulkan SDK if: matrix.gpu_api == 'Vulkan' run: | - sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools + sudo apt install vulkan-tools libvulkan1 libvulkan-dev glslang-tools libfmt-dev cd .. wget https://sdk.lunarg.com/sdk/download/1.3.275.0/linux/vulkansdk-linux-x86_64-1.3.275.0.tar.xz tar xf vulkansdk-linux-x86_64-1.3.275.0.tar.xz From 077a5b8640428d8c768332715052e8b5dbd2846e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 17:51:08 +0800 Subject: [PATCH 1096/1123] VCL: use FlatDiagram library Signed-off-by: ToKiNoBug --- VisualCraft/VCWind_export.cpp | 2 +- VisualCraftL/CMakeLists.txt | 1 + VisualCraftL/TokiVC.h | 7 +- VisualCraftL/TokiVC_flagdiagram.cpp | 255 ++++++---------------------- VisualCraftL/VisualCraftL.h | 8 +- 5 files changed, 60 insertions(+), 213 deletions(-) diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 4b33a69c..090da8f1 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -278,7 +278,7 @@ bool VCWind::export_converted(const QString &converted_image_dest_path, bool VCWind::export_flatdiagram(const QString &diagram_dest) noexcept { const QStringList qsl = diagram_dest.split(';'); - if (qsl.size() != VCL_get_max_block_layers()) { + if (qsl.size() not_eq VCL_get_max_block_layers()) { const auto ret = QMessageBox::critical( this, VCWind::tr("平面示意图输入错误"), VCWind::tr("应输入%1个以\";\"分隔的文件名,但实际上输入了%" diff --git a/VisualCraftL/CMakeLists.txt b/VisualCraftL/CMakeLists.txt index fff3c3fb..5a81a831 100644 --- a/VisualCraftL/CMakeLists.txt +++ b/VisualCraftL/CMakeLists.txt @@ -101,6 +101,7 @@ set(VCL_link_libs ${VCL_libzip_additions} Schem ProcessBlockId + FlatDiagram ) target_link_libraries(VisualCraftL PRIVATE $) diff --git a/VisualCraftL/TokiVC.h b/VisualCraftL/TokiVC.h index dc0a97c7..7188e469 100644 --- a/VisualCraftL/TokiVC.h +++ b/VisualCraftL/TokiVC.h @@ -105,9 +105,10 @@ class TokiVC : public VCL_Kernel { void converted_image(uint32_t *dest, int64_t *rows, int64_t *cols, bool write_dest_row_major) const noexcept override; - void flag_diagram(uint32_t *image_u8c3_rowmajor, const flag_diagram_option &, - int layer_idx, int64_t *rows_required_dest, - int64_t *cols_required_dest) const noexcept override; + // void flag_diagram(uint32_t *image_u8c3_rowmajor, const flag_diagram_option + // &, + // int layer_idx, int64_t *rows_required_dest, + // int64_t *cols_required_dest) const noexcept override; bool export_flag_diagram(const char *png_filename, const flag_diagram_option &, int layer_idx) const noexcept override; diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index 51e7cbe2..419205ac 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -57,112 +57,7 @@ void ARGB_to_AGBR(uint32_t *ptr, size_t num_pixels) noexcept { } } -void TokiVC::draw_flag_diagram_to_memory(uint32_t *image_u8c3_rowmajor, - const flag_diagram_option &opt, - int layer_idx) const noexcept { - Eigen::Map map( - image_u8c3_rowmajor, (opt.row_end - opt.row_start) * 16, - this->cols() * 16); - - memset(image_u8c3_rowmajor, 0, - (opt.row_end - opt.row_start) * 16 * this->img_cvter.cols() * 16 * - sizeof(uint32_t)); - - /*s constexpr int size_of_u32_per_vec = 32 / sizeof(uint32_t); - - const bool is_dst_aligned = - (reinterpret_cast(image_u8c3_rowmajor) % 32) == 0; - - */ - // copy block images - for (int64_t r = opt.row_start; r < opt.row_end; r++) { - const int r_pixel_beg = (r - opt.row_start) * 16; - for (int64_t c = 0; c < this->cols(); c++) { - const int c_pixel_beg = c * 16; - const uint16_t current_color_idx = this->img_cvter.color_id(r, c); - - const auto &variant = - TokiVC::LUT_basic_color_idx_to_blocks[current_color_idx]; - const VCL_block *blkp = nullptr; - if (variant.index() == 0) { - if (layer_idx == 0) { - blkp = std::get<0>(variant); - } - } else { - const auto &vec = std::get<1>(variant); - - if (layer_idx < (int)vec.size()) { - blkp = vec[layer_idx]; - } - } - - if (blkp == nullptr) { - map.block<16, 16>(r_pixel_beg, c_pixel_beg).fill(0x00'FF'FF'FF); - continue; - } - /* - const bool is_src_aligned = - (reinterpret_cast( - blkp->project_image_on_exposed_face.data()) % - 32) == 0; - const bool is_aligned = is_dst_aligned && is_src_aligned; - */ - - map.block<16, 16>(r_pixel_beg, c_pixel_beg) = - blkp->project_image_on_exposed_face; - } - } - - for (int64_t br = opt.row_start; br < opt.row_end; br++) { - if ((opt.split_line_row_margin > 0) && - (br % opt.split_line_row_margin == 0)) { - const int64_t pr = (br - opt.row_start) * 16; - - reverse_color(&map(pr, 0), map.cols()); - } - } - - for (int64_t bc = 0; bc < this->img_cvter.cols(); bc++) { - if ((opt.split_line_col_margin > 0) && - (bc % opt.split_line_col_margin == 0)) { - const int64_t pc = bc * 16; - - for (int64_t pr = 0; pr < map.rows(); pr++) { - map(pr, pc) = reverse_color(map(pr, pc)); - } - } - } -} - -void TokiVC::flag_diagram(uint32_t *image_u8c3_rowmajor, - const flag_diagram_option &opt, int layer_idx, - int64_t *rows_required_dest, - int64_t *cols_required_dest) const noexcept { - if (this->_step < ::VCL_Kernel_step::VCL_wait_for_build) { - VCL_report(VCL_report_type_t::error, - "Trying to export flag diagram without image converted."); - return; - } - - std::shared_lock lkgd(TokiVC_internal::global_lock); - - if (rows_required_dest != nullptr) { - *rows_required_dest = (opt.row_end - opt.row_start) * 16; - } - - if (cols_required_dest != nullptr) { - *cols_required_dest = this->img_cvter.cols() * 16; - } - - if (image_u8c3_rowmajor == nullptr) { - return; - } - - this->draw_flag_diagram_to_memory(image_u8c3_rowmajor, opt, layer_idx); -} - -#include -#include +#include bool TokiVC::export_flag_diagram(const char *png_filename, const flag_diagram_option &opt, @@ -174,111 +69,61 @@ bool TokiVC::export_flag_diagram(const char *png_filename, } std::shared_lock lkgd(TokiVC_internal::global_lock); + std::array, 4> txt{ + std::make_pair( + "Title", "Flat diagram generated by VisualCraftL."), + std::make_pair("Software", "VisualCraftL"), + std::make_pair( + "Description", + "This image is a flat diagram created by VisualCraftL which is is a " + "subproject of SlopeCraft, developed by TokiNoBug."), + std::make_pair( + "Comment", + "SlopeCraft is a free software published " + "under GPLv3 license. You can find " + "its repository at https://github.com/SlopeCraft/SlopeCraft")}; this->img_cvter.ui.rangeSet(0, this->img_cvter.rows(), 0); + const libFlatDiagram::fd_option fdopt{ + .row_start = opt.row_start, + .row_end = opt.row_end, + .cols = this->cols(), + .split_line_row_margin = opt.split_line_row_margin, + .split_line_col_margin = opt.split_line_col_margin, + .png_compress_level = opt.png_compress_level, + .png_compress_memory_level = opt.png_compress_memory_level, + }; + Eigen::Array empty_image; + empty_image.fill(0x00'FF'FF'FF); + auto get_block_image = [&](int64_t r, + int64_t c) -> libFlatDiagram::block_img_ref_t { + const uint16_t current_color_idx = this->img_cvter.color_id(r, c); + + const auto &variant = + TokiVC::LUT_basic_color_idx_to_blocks[current_color_idx]; + const VCL_block *blkp = nullptr; + if (variant.index() == 0) { + if (layer_idx == 0) { + blkp = std::get<0>(variant); + } + } else { + const auto &vec = std::get<1>(variant); - const int64_t rows_capacity_by_blocks = 64; - - block_model::EImgRowMajor_t buffer(rows_capacity_by_blocks * 16, - this->img_cvter.cols() * 16); - - FILE *fp = fopen(png_filename, "wb"); - - if (fp == nullptr) { - std::string msg = - std::format("fopen failed to create png file {}.", png_filename); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - png_struct *png = - png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (png == nullptr) { - fclose(fp); - std::string msg = std::format( - "fopen failed to create png struct for png file {}.", png_filename); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - png_info *png_info = png_create_info_struct(png); - if (png_info == nullptr) { - png_destroy_write_struct(&png, &png_info); - fclose(fp); - std::string msg = - std::format("fopen failed to create png info struct for png file {}.", - png_filename); - VCL_report(VCL_report_type_t::error, msg.c_str()); - return false; - } - - png_init_io(png, fp); - - png_set_compression_level(png, opt.png_compress_level); - - png_set_compression_mem_level(png, opt.png_compress_memory_level); - - // png_set_text_compression_level(png, 8); - - png_set_IHDR(png, png_info, this->img_cvter.cols() * 16, - 16 * (opt.row_end - opt.row_start), 8, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, png_info); - - { - std::array, 4> txt{ - std::make_pair( - "Title", "Flat diagram generated by VisualCraftL."), - std::make_pair("Software", "VisualCraftL"), - std::make_pair( - "Description", - "This image is a flat diagram created by VisualCraftL, which is is " - "a subproject of SlopeCraft, developed by TokiNoBug."), - std::make_pair( - "Comment", - "SlopeCraft is a free software published " - "under GPLv3 license. You can find " - "its repository at https://github.com/SlopeCraft/SlopeCraft")}; - - std::array png_txts; - - for (size_t i = 0; i < txt.size(); i++) { - png_txts[i].compression = -1; - png_txts[i].key = txt[i].first.data(); - png_txts[i].text = txt[i].second.data(); - // png.txts[i].key = + if (layer_idx < (int)vec.size()) { + blkp = vec[layer_idx]; + } } + if (c == 0) + this->img_cvter.ui.rangeSet(0, this->img_cvter.rows(), r - opt.row_start); - png_set_text(png, png_info, png_txts.data(), png_txts.size()); - } - - for (int64_t ridx = opt.row_start; ridx < opt.row_end; - ridx += rows_capacity_by_blocks) { - const int64_t rows_this_time = - std::min(opt.row_end - ridx, rows_capacity_by_blocks); - memset(buffer.data(), 0xFF, buffer.size() * sizeof(uint32_t)); - this->draw_flag_diagram_to_memory( - buffer.data(), - {opt.lib_version, ridx, ridx + rows_this_time, - opt.split_line_row_margin, opt.split_line_col_margin}, - layer_idx); - - ARGB_to_AGBR(buffer.data(), - rows_this_time * 16 * this->img_cvter.cols() * 16); - - for (int64_t pix_r = 0; pix_r < rows_this_time * 16; pix_r++) { - png_write_row(png, reinterpret_cast(&buffer(pix_r, 0))); + if (blkp == nullptr) { + return libFlatDiagram::block_img_ref_t{empty_image.data()}; } - - this->img_cvter.ui.rangeSet(0, this->img_cvter.rows(), - ridx - opt.row_start); - } - - png_write_end(png, png_info); - - png_destroy_write_struct(&png, &png_info); - fclose(fp); + return libFlatDiagram::block_img_ref_t{ + blkp->project_image_on_exposed_face.data()}; + }; + const auto err_string = libFlatDiagram::export_flat_diagram( + png_filename, fdopt, get_block_image, txt); this->img_cvter.ui.rangeSet(0, this->img_cvter.rows(), this->img_cvter.rows()); diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index 3c7ca0f1..c7dffe0e 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -250,10 +250,10 @@ class VCL_Kernel { int png_compress_memory_level{8}; }; - virtual void flag_diagram(uint32_t *image_u8c3_rowmajor, - const flag_diagram_option &, int layer_idx, - int64_t *rows_required_dest, - int64_t *cols_required_dest) const noexcept = 0; + // virtual void flag_diagram(uint32_t *image_u8c3_rowmajor, + // const flag_diagram_option &, int layer_idx, + // int64_t *rows_required_dest, + // int64_t *cols_required_dest) const noexcept = 0; virtual bool export_flag_diagram(const char *png_filename, const flag_diagram_option &, int layer_idx) const noexcept = 0; From c2566cf0b2f1ba350bf4d43c144ccd5a439bbfa4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 18:03:54 +0800 Subject: [PATCH 1097/1123] VC: Fix image corruption Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 6 +++--- VisualCraft/VCWind_export.cpp | 10 +++++----- VisualCraftL/TokiVC.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 011a246e..53670dd4 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -698,7 +698,7 @@ void VCWind::on_tb_remove_images_clicked() noexcept { void VCWind::setup_image(const QImage &img) noexcept { this->setup_allowed_colorset(); bool ok = this->kernel->set_image( - img.width(), img.height(), + img.height(), img.width(), reinterpret_cast(img.scanLine(0)), true); if (!ok) { const auto ret = QMessageBox::critical( @@ -763,11 +763,11 @@ void VCWind::show_image(decltype(image_cache)::iterator it) noexcept { return; } - QImage img(rows, cols, QImage::Format_ARGB32); + QImage img(cols, rows, QImage::Format_ARGB32); memset(img.scanLine(0), 0xFF, img.sizeInBytes()); this->kernel->converted_image(reinterpret_cast(img.scanLine(0)), - nullptr, nullptr, true); + nullptr, nullptr, false); it->second.second = img; this->ui->lable_converted->setPixmap(QPixmap::fromImage(img)); diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 090da8f1..e4237d1b 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -400,11 +400,11 @@ void VCWind::on_pb_execute_clicked() noexcept { QImage new_img(it->second.first.width(), it->second.first.height(), QImage::Format_ARGB32); this->kernel->converted_image((uint32_t *)new_img.scanLine(0), nullptr, - nullptr, true); + nullptr, false); it->second.second = new_img; - if (!converted_image_dest_path.isEmpty()) { - if (!this->export_converted(converted_image_dest_path, new_img)) { + if (not converted_image_dest_path.isEmpty()) { + if (not this->export_converted(converted_image_dest_path, new_img)) { continue; } } @@ -413,8 +413,8 @@ void VCWind::on_pb_execute_clicked() noexcept { ->setText( QStringLiteral("%1 %").arg(100.0f * task_finished / task_num)); - if (!diagram_dest.isEmpty()) { - if (!this->export_flatdiagram(diagram_dest)) { + if (not diagram_dest.isEmpty()) { + if (not this->export_flatdiagram(diagram_dest)) { continue; } task_finished++; diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index f0aacc0f..56669d4d 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -710,7 +710,7 @@ void TokiVC::converted_image(uint32_t *dest, int64_t *rows, int64_t *cols, // constexpr size_t sz = sizeof(decltype(this->img_cvter)::TokiColor_t); - this->img_cvter.converted_image(dest, rows, cols, not write_dest_row_major); + this->img_cvter.converted_image(dest, rows, cols, write_dest_row_major); } bool TokiVC::set_gpu_resource(const VCL_GPU_Platform *p, From a907d3d5a584651927ce7c2b92a0f59efed17d32 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 18:07:03 +0800 Subject: [PATCH 1098/1123] [CI]: Use gcc15.2.0 for windows (mingw) Signed-off-by: ToKiNoBug --- .github/workflows/windows-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 4a00fa4f..2043201f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -202,7 +202,7 @@ jobs: echo "short_sha = $short_sha" echo "SHORT_SHA=$short_sha" >> $env:GITHUB_ENV - - name: Filter perl-related pathes from env:path, and append directory of gcc13 to path + - name: Filter perl-related pathes from env:path, and append directory of gcc15 to path run: | $basedir=(pwd).path.replace("\\","/") $exclude_key_words="perl","Strawberry" @@ -227,8 +227,8 @@ jobs: - name: Download mingw64 and extract run: | cmd - curl -JL -o bin/gcc13.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/13.2.0-rt_v11-rev1/x86_64-13.2.0-release-posix-seh-ucrt-rt_v11-rev1.7z" - 7z x -obin bin/gcc13.7z + curl -JL -o bin/gcc15.7z "https://github.com/niXman/mingw-builds-binaries/releases/download/15.2.0-rt_v13-rev0/x86_64-15.2.0-release-posix-seh-ucrt-rt_v13-rev0.7z" + 7z x -obin bin/gcc15.7z exit # gcc installation dir: bin/mingw64 # gcc.exe: bin/mingw64/bin/gcc.exe From 7c01320f3166b133e2f2b1ecdcb4f242297268bd Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 18:10:15 +0800 Subject: [PATCH 1099/1123] [CI]: Use mac-15 Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-arm64.yml | 2 +- .github/workflows/macos-build-x64.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos-build-arm64.yml b/.github/workflows/macos-build-arm64.yml index 02a60d5b..1f1cca78 100644 --- a/.github/workflows/macos-build-arm64.yml +++ b/.github/workflows/macos-build-arm64.yml @@ -8,7 +8,7 @@ on: jobs: clang: - runs-on: macos-14 + runs-on: macos-15 strategy: matrix: build_type: [ Debug, Release ] diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index c16279ae..c4530e08 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -8,7 +8,7 @@ on: jobs: clang: - runs-on: macos-13 + runs-on: macos-15 strategy: matrix: build_type: [ Debug, Release ] From 93297b88506037117a7303a51ec7ccae62fb7fd1 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:12:04 +0800 Subject: [PATCH 1100/1123] [CI]: Fix linux build Signed-off-by: ToKiNoBug --- utilities/libpngReader/libpng_reader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index 01fe99a6..50484be3 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -5,6 +5,7 @@ #include "libpng_reader.h" #include #include +#include struct read_buffer_wrapper { const void *data; From fd3ae46d07a6428137afa6236897588f0f21de2a Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:14:01 +0800 Subject: [PATCH 1101/1123] [CI]: Try to fix mingw build Signed-off-by: ToKiNoBug --- utilities/StatMemory/others/test_stat_memory.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utilities/StatMemory/others/test_stat_memory.cpp b/utilities/StatMemory/others/test_stat_memory.cpp index 1b0434b9..fe6bcbeb 100644 --- a/utilities/StatMemory/others/test_stat_memory.cpp +++ b/utilities/StatMemory/others/test_stat_memory.cpp @@ -9,10 +9,10 @@ int main() { const auto sys_info = get_system_memory_info(); if (sys_info) { const auto &val = sys_info.value(); - std::print("System free memory: {}\n", val.free); - std::print("System total memory: {}\n", val.total); + std::println("System free memory: {}", val.free); + std::println("System total memory: {}", val.total); } else { - std::print("Failed to get system memory info:\n{}\n", sys_info.error()); + std::println("Failed to get system memory info:\n{}", sys_info.error()); fail_count++; } } @@ -20,9 +20,9 @@ int main() { const auto self_info = get_self_memory_info(); if (self_info) { const auto &val = self_info.value(); - std::print("Memory used by this process: \"{}\"\n", val.used); + std::println("Memory used by this process: \"{}\"", val.used); } else { - std::print("Failed to get self memory info:\n{}\n", self_info.error()); + std::println("Failed to get self memory info:\n{}", self_info.error()); fail_count++; } From c70c1e5dbf6e3dfb98ab30d887fbdde6f35bad7b Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:15:54 +0800 Subject: [PATCH 1102/1123] Delete libSCGUI Signed-off-by: ToKiNoBug --- utilities/libSCGUI/CMakeLists.txt | 9 --- utilities/libSCGUI/libSCGUI.cpp | 123 ------------------------------ utilities/libSCGUI/libSCGUI.h | 59 -------------- 3 files changed, 191 deletions(-) delete mode 100644 utilities/libSCGUI/CMakeLists.txt delete mode 100644 utilities/libSCGUI/libSCGUI.cpp delete mode 100644 utilities/libSCGUI/libSCGUI.h diff --git a/utilities/libSCGUI/CMakeLists.txt b/utilities/libSCGUI/CMakeLists.txt deleted file mode 100644 index 8634c045..00000000 --- a/utilities/libSCGUI/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -project(SlopeCraft_libSCGUI VERSION ${SlopeCraft_version} LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 20) - -include_directories(${CMAKE_SOURCE_DIR}/utilities/libAbstractGUI - ${CMAKE_SOURCE_DIR}/SlopeCraftL) - -add_library(SCGUI STATIC libSCGUI.h libSCGUI.cpp) - -target_link_libraries(SCGUI PRIVATE AbstractGUI SlopeCraftL) \ No newline at end of file diff --git a/utilities/libSCGUI/libSCGUI.cpp b/utilities/libSCGUI/libSCGUI.cpp deleted file mode 100644 index 83d2e355..00000000 --- a/utilities/libSCGUI/libSCGUI.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#include "libSCGUI.h" -#include "libAbstractGUI.h" -#include "libSCGUI/libSCGUI.h" - -// #include - -using namespace libSCGUI; -using namespace libAbstractGUI; -using std::string, std::vector, std::string_view; - -void SCGUI::on_load_image_clicked() noexcept { - - const vector image_files = callback_get_open_filenames( - "Select one or multiple images", prev_dir, "*.png;;*.jpg;;*.jpeg;;*.bmp"); - - if (image_files.size() <= 0) { - return; - } - - if (image_files.size() == 1) { - string_view filename = image_files.front(); - - if (filename.size() <= 0) { - return; - } - int img_rows = 0, img_cols = 0; - callback_read_image_from_file(filename, nullptr, 0, &img_rows, &img_cols, - nullptr); - - if (img_rows <= 0 || img_cols <= 0) { - // the image seems to be broken. - return; - } - bool is_row_major = false; - uint32_t *buffer = - (uint32_t *)malloc(sizeof(uint32_t) * img_rows * img_cols); - callback_read_image_from_file(filename, buffer, - sizeof(uint32_t) * img_rows * img_cols, - &img_rows, &img_cols, &is_row_major); - // change the storage order to col-major - if (is_row_major) { - for (int r = 0; r < img_rows; r++) { - for (int c = 0; c < img_cols; c++) { - std::swap(buffer[r * img_cols + c], buffer[c * img_rows + r]); - } - } - } - - kernel->setRawImage(buffer, img_rows, img_cols); - callback_set_image(label_show_raw_image, buffer, img_rows, img_cols, - is_row_major); - callback_set_image(label_show_image_before_convert, buffer, img_rows, - img_cols, is_row_major); - free(buffer); - } - -#warning batch op not finished yet. -} - -void cb_progress_range_set(void *libAbstractGUI_progress_bar_ptr, int min, - int max, int val) { - callback_set_progress_bar( - *reinterpret_cast(libAbstractGUI_progress_bar_ptr), min, - max, val); -} -void cb_progress_add(void *libAbstractGUI_progress_bar_ptr, int delta) { - int min, max, val; - callback_get_progress_bar( - *reinterpret_cast(libAbstractGUI_progress_bar_ptr), &min, - &max, &val); - callback_set_progress_bar( - *reinterpret_cast(libAbstractGUI_progress_bar_ptr), min, - max, val + delta); -} - -void SCGUI::on_convert_clicked(const ::SCL_convertAlgo algo, - const bool dither) noexcept { - callback_set_freezed(main_window, true); - kernel->setWindPtr(&progressbar_convert_image); - kernel->setProgressRangeSet(cb_progress_range_set); - kernel->setProgressAdd(cb_progress_add); - - kernel->convert(algo, dither); - refreash_converted_image(); - callback_set_freezed(main_window, false); -} - -void SCGUI::refreash_raw_image() noexcept {} - -void SCGUI::refreash_converted_image() noexcept { - int rows = 0, cols = 0; - kernel->getConvertedImage(&rows, &cols, nullptr); - - uint32_t *buffer = (uint32_t *)malloc(sizeof(uint32_t) * rows * cols); - - kernel->getConvertedImage(nullptr, nullptr, buffer); - - callback_set_image(label_show_image_after_convert, buffer, rows, cols, false); - - free(buffer); -} \ No newline at end of file diff --git a/utilities/libSCGUI/libSCGUI.h b/utilities/libSCGUI/libSCGUI.h deleted file mode 100644 index 7a315125..00000000 --- a/utilities/libSCGUI/libSCGUI.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright © 2021-2023 TokiNoBug -This file is part of SlopeCraft. - - SlopeCraft is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SlopeCraft 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SlopeCraft. If not, see . - - Contact with me: - github:https://github.com/SlopeCraft/SlopeCraft - bilibili:https://space.bilibili.com/351429231 -*/ - -#ifndef SLOPECRAFT_UTILITIES_LIBSCGUI_LIBSCGUI_H -#define SLOPECRAFT_UTILITIES_LIBSCGUI_LIBSCGUI_H - -#include - -#include - -namespace libSCGUI { -class SCGUI { -private: - ::SlopeCraft::Kernel *kernel; - ::std::string prev_dir = ""; - -public: - libAbstractGUI::abstract_widget main_window; - libAbstractGUI::label label_show_raw_image; - // these 2 labels are about image conversion, actually they can be equal. - libAbstractGUI::label label_show_image_before_convert; - libAbstractGUI::label label_show_image_after_convert; - - libAbstractGUI::progress_bar progressbar_convert_image; - -public: - SCGUI() { kernel = ::SlopeCraft::Kernel::create(); } - -public: - void on_load_image_clicked() noexcept; - void on_convert_clicked(const ::SCL_convertAlgo, const bool dither) noexcept; - void refreash_raw_image() noexcept; - void refreash_converted_image() noexcept; - - void on_build3D_clicked() noexcept; - void on_export3D_clicked() noexcept; -}; -} // namespace libSCGUI - -#endif // SLOPECRAFT_UTILITIES_LIBSCGUI_LIBSCGUI_H \ No newline at end of file From f4716274acf5bd3e7632f280ef45f003ade023d4 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:22:29 +0800 Subject: [PATCH 1103/1123] [CI] Fix linux build Signed-off-by: ToKiNoBug --- utilities/libpngReader/libpng_reader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index 50484be3..4a75a034 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -5,7 +5,7 @@ #include "libpng_reader.h" #include #include -#include +#include struct read_buffer_wrapper { const void *data; From ece819d4da33d91bb9dbba085137c35baa4d8d73 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:30:44 +0800 Subject: [PATCH 1104/1123] Try to fix mingw build Signed-off-by: ToKiNoBug --- utilities/StatMemory/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 2c126006..80142783 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -22,10 +22,12 @@ else () message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") endif () -add_executable(test_stat_memory others/test_stat_memory.cpp) -target_link_libraries(test_stat_memory PRIVATE StatMemory) -add_test(NAME stat_memory - COMMAND test_stat_memory) +if (NOT ${MINGW}) + add_executable(test_stat_memory others/test_stat_memory.cpp) + target_link_libraries(test_stat_memory PRIVATE StatMemory) + add_test(NAME stat_memory + COMMAND test_stat_memory) +endif () find_package(Qt6 COMPONENTS Widgets REQUIRED) add_library(MemoryPolicyDialog STATIC From f52953a205f6ad22a0f74ae02a24083759e6e3ba Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sun, 14 Dec 2025 22:38:26 +0800 Subject: [PATCH 1105/1123] Try to fix linux and macos-intel build Signed-off-by: ToKiNoBug --- .github/workflows/macos-build-x64.yml | 4 ++-- cmake/required_deps/libnbt++.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos-build-x64.yml b/.github/workflows/macos-build-x64.yml index c4530e08..6b076431 100644 --- a/.github/workflows/macos-build-x64.yml +++ b/.github/workflows/macos-build-x64.yml @@ -36,7 +36,7 @@ jobs: run: | brew install llvm lld - name: Check clang - run: /usr/local/opt/llvm/bin/clang -v + run: /opt/homebrew/opt/llvm/bin/clang -v - name: echo matrix variables (build_type = ${{ matrix.build_type }}) run: | echo $BUILD_TYPE @@ -76,7 +76,7 @@ jobs: - name: Check PATH run: echo $PATH - name: Configure CMake - run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON + run: cmake -S . -B ./build -G "Ninja" -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_INSTALL_PREFIX=./build/install -DSlopeCraft_GPU_API=$GPU_API -DSlopeCraft_vectorize=$VECTORIZE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH="$HOME/Downloads/Qt6.6.0-appleclang-static-x86_64;/System/Volumes/Data/usr/local/Cellar;/opt/homebrew" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DSlopeCraft_macdeployqt_flags_install="-no-plugins" -DKOMPUTE_OPT_DISABLE_VULKAN_VERSION_CHECK=ON - name: Build run: | cd build diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 18bbf886..9bb4c3e1 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -23,6 +23,6 @@ find_package(libnbt++ REQUIRED) target_link_libraries(nbt++ ZLIB::ZLIB) target_compile_features(nbt++ PUBLIC cxx_std_20) -if (${MSVC}) - target_compile_options(nbt++ PRIVATE /std:c++20) +if (${LINUX}) + set_target_properties(nbt++ POSITION_INDEPENDENT_CODE ON) endif () \ No newline at end of file From 7839e1d2268c3eea62d74532317bd069b1a42e76 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 Dec 2025 09:09:35 +0800 Subject: [PATCH 1106/1123] Try to fix linux build Signed-off-by: ToKiNoBug --- cmake/required_deps/libnbt++.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/required_deps/libnbt++.cmake b/cmake/required_deps/libnbt++.cmake index 9bb4c3e1..e9183953 100644 --- a/cmake/required_deps/libnbt++.cmake +++ b/cmake/required_deps/libnbt++.cmake @@ -24,5 +24,7 @@ find_package(libnbt++ REQUIRED) target_link_libraries(nbt++ ZLIB::ZLIB) target_compile_features(nbt++ PUBLIC cxx_std_20) if (${LINUX}) - set_target_properties(nbt++ POSITION_INDEPENDENT_CODE ON) + set_target_properties(nbt++ PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) endif () \ No newline at end of file From a05cb03de4c58cb35085de6da4221ab667fd8072 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 Dec 2025 09:40:55 +0800 Subject: [PATCH 1107/1123] Fix mingw build Signed-off-by: ToKiNoBug --- utilities/BlockListManager/BlockListManager.cpp | 2 +- utilities/StatMemory/CMakeLists.txt | 13 ++++++++----- vccl/CMakeLists.txt | 4 ++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/utilities/BlockListManager/BlockListManager.cpp b/utilities/BlockListManager/BlockListManager.cpp index 8f97e240..0bc69f83 100644 --- a/utilities/BlockListManager/BlockListManager.cpp +++ b/utilities/BlockListManager/BlockListManager.cpp @@ -100,7 +100,7 @@ BlockListManager::impl_addblocklist(const QByteArray &file_content) noexcept { base_colors.resize(bli->size()); blockps.resize(bli->size()); - const size_t size_2 = + const size_t size_2 [[maybe_unused]] = bli->get_blocks(blockps.data(), base_colors.data(), blockps.size()); assert(size_2 == base_colors.size() and base_colors.size() == blockps.size()); diff --git a/utilities/StatMemory/CMakeLists.txt b/utilities/StatMemory/CMakeLists.txt index 80142783..04e72d55 100644 --- a/utilities/StatMemory/CMakeLists.txt +++ b/utilities/StatMemory/CMakeLists.txt @@ -22,11 +22,14 @@ else () message(FATAL_ERROR "Unsupported system ${CMAKE_SYSTEM_NAME}, not windows, linux or macos") endif () -if (NOT ${MINGW}) - add_executable(test_stat_memory others/test_stat_memory.cpp) - target_link_libraries(test_stat_memory PRIVATE StatMemory) - add_test(NAME stat_memory - COMMAND test_stat_memory) +add_executable(test_stat_memory others/test_stat_memory.cpp) +target_link_libraries(test_stat_memory PRIVATE StatMemory) +add_test(NAME stat_memory + COMMAND test_stat_memory) + +if (${MINGW}) + # Link this to fix std::print under mingw (gcc>=14) + target_link_libraries(test_stat_memory PRIVATE stdc++exp) endif () find_package(Qt6 COMPONENTS Widgets REQUIRED) diff --git a/vccl/CMakeLists.txt b/vccl/CMakeLists.txt index 08c2f107..48ffa87a 100644 --- a/vccl/CMakeLists.txt +++ b/vccl/CMakeLists.txt @@ -55,6 +55,10 @@ if (${WIN32}) add_dependencies(SC_create_all_symlinks SC_create_symlink_VCCL) endif () +if (${MINGW}) + # Link this to fix std::print under mingw (gcc>=14) + target_link_libraries(vccl PRIVATE stdc++exp) +endif () include(install.cmake) include(add_test_vccl.cmake) \ No newline at end of file From 4b2253cc556c33a10574c810fcbf144b07e85a02 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 15 Dec 2025 09:53:24 +0800 Subject: [PATCH 1108/1123] Add -fPIC on static libs for linux build Signed-off-by: ToKiNoBug --- utilities/CMakeLists.txt | 4 ++++ utilities/ColorManip/CMakeLists.txt | 3 --- utilities/ExternalConverters/GAConverter/CMakeLists.txt | 3 --- utilities/FlatDiagram/CMakeLists.txt | 2 +- utilities/GPUWrapper/OpenCL/CMakeLists.txt | 8 -------- utilities/GPUWrapper/Vulkan/CMakeLists.txt | 4 ---- utilities/MCDataVersion/CMakeLists.txt | 4 ---- utilities/MapImageCvter/CMakeLists.txt | 4 ---- utilities/NBTWriter/CMakeLists.txt | 6 ------ utilities/ProcessBlockId/CMakeLists.txt | 4 ---- utilities/Schem/CMakeLists.txt | 4 ---- utilities/libpngReader/CMakeLists.txt | 1 - 12 files changed, 5 insertions(+), 42 deletions(-) diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index 83f78a0b..bbfde7be 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -1,5 +1,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +if (${LINUX}) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif () + add_subdirectory(MCDataVersion) add_subdirectory(version_set) add_subdirectory(GPUWrapper) diff --git a/utilities/ColorManip/CMakeLists.txt b/utilities/ColorManip/CMakeLists.txt index bb11bc06..7bc954ff 100644 --- a/utilities/ColorManip/CMakeLists.txt +++ b/utilities/ColorManip/CMakeLists.txt @@ -44,9 +44,6 @@ target_link_libraries(ColorManip PUBLIC # target_compile_options(ColorManip BEFORE PUBLIC "-std=c++17") target_compile_options(ColorManip PRIVATE ${SlopeCraft_vectorize_flags}) -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(ColorManip PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () # ColorManip links to GPUInterface target_link_libraries(ColorManip PUBLIC GPUInterface) diff --git a/utilities/ExternalConverters/GAConverter/CMakeLists.txt b/utilities/ExternalConverters/GAConverter/CMakeLists.txt index 52d69220..5c978372 100644 --- a/utilities/ExternalConverters/GAConverter/CMakeLists.txt +++ b/utilities/ExternalConverters/GAConverter/CMakeLists.txt @@ -29,8 +29,5 @@ target_link_libraries(GAConverter PUBLIC OpenMP::OpenMP_CXX Eigen3::Eigen Heu::G target_compile_features(GAConverter PRIVATE cxx_std_23) -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(GAConverter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () # target_compile_options(GAConverter BEFORE PUBLIC "-std=c++17") \ No newline at end of file diff --git a/utilities/FlatDiagram/CMakeLists.txt b/utilities/FlatDiagram/CMakeLists.txt index 94a75f93..155dbb88 100644 --- a/utilities/FlatDiagram/CMakeLists.txt +++ b/utilities/FlatDiagram/CMakeLists.txt @@ -13,4 +13,4 @@ target_link_libraries(FlatDiagram PNG::PNG Eigen3::Eigen ) -target_compile_features(FlatDiagram PUBLIC cxx_std_23) \ No newline at end of file +target_compile_features(FlatDiagram PUBLIC cxx_std_23) diff --git a/utilities/GPUWrapper/OpenCL/CMakeLists.txt b/utilities/GPUWrapper/OpenCL/CMakeLists.txt index 2a780b78..072774e9 100644 --- a/utilities/GPUWrapper/OpenCL/CMakeLists.txt +++ b/utilities/GPUWrapper/OpenCL/CMakeLists.txt @@ -9,10 +9,6 @@ target_sources(GPUInterface PRIVATE GPU_interface.cpp) -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () - # convert ColorDiff.cl to a resource file (not windows rc). It is generated by ResourceCreator.cmake (3rd party cmake lib) add_resource_config_time(ColorManip_cl_rc ColorDiff.cl) @@ -51,10 +47,6 @@ endif () target_compile_definitions(GPUInterface PUBLIC SLOPECRAFT_HAVE_OPENCL) -if (${LINUX}) - set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () - find_program(clang_exe NAMES "clang") if (clang_exe) set(binfile ${CMAKE_CURRENT_BINARY_DIR}/ColorDiff.bc) diff --git a/utilities/GPUWrapper/Vulkan/CMakeLists.txt b/utilities/GPUWrapper/Vulkan/CMakeLists.txt index 1383dd42..20ac7149 100644 --- a/utilities/GPUWrapper/Vulkan/CMakeLists.txt +++ b/utilities/GPUWrapper/Vulkan/CMakeLists.txt @@ -31,10 +31,6 @@ execute_process(COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${sh add_resource_config_time(VkComputeShaderSPIRV_rc ${shader_filename}) target_link_libraries(GPUInterface PRIVATE VkComputeShaderSPIRV_rc) -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(GPUInterface PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () - set(shader_test_filename "${CMAKE_CURRENT_BINARY_DIR}/compute_test.spv") add_custom_target(GPUInterface_shader_test ALL COMMAND ${glslc_exe} -fshader-stage=compute compute.glsl -o ${shader_test_filename} diff --git a/utilities/MCDataVersion/CMakeLists.txt b/utilities/MCDataVersion/CMakeLists.txt index 5764c101..748169ef 100644 --- a/utilities/MCDataVersion/CMakeLists.txt +++ b/utilities/MCDataVersion/CMakeLists.txt @@ -11,7 +11,3 @@ target_link_libraries(MCDataVersion PUBLIC magic_enum::magic_enum) target_compile_features(MCDataVersion PRIVATE cxx_std_20) target_include_directories(MCDataVersion INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(MCDataVersion PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () \ No newline at end of file diff --git a/utilities/MapImageCvter/CMakeLists.txt b/utilities/MapImageCvter/CMakeLists.txt index a6e53aa8..cc52f0f6 100644 --- a/utilities/MapImageCvter/CMakeLists.txt +++ b/utilities/MapImageCvter/CMakeLists.txt @@ -23,7 +23,3 @@ target_include_directories(MapImageCvter PRIVATE "${CMAKE_BINARY_DIR}/SlopeCraft target_compile_options(MapImageCvter PRIVATE ${SlopeCraft_vectorize_flags}) target_compile_features(MapImageCvter PUBLIC cxx_std_23) - -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(MapImageCvter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () \ No newline at end of file diff --git a/utilities/NBTWriter/CMakeLists.txt b/utilities/NBTWriter/CMakeLists.txt index 754c7e53..c720478a 100644 --- a/utilities/NBTWriter/CMakeLists.txt +++ b/utilities/NBTWriter/CMakeLists.txt @@ -12,9 +12,3 @@ add_library(NBTWriter NBTWriter.cpp) target_link_libraries(NBTWriter PUBLIC ZLIB::ZLIB) - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set_target_properties(NBTWriter PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif() - -# target_compile_options(NBTWriter BEFORE PUBLIC -std=c++17) diff --git a/utilities/ProcessBlockId/CMakeLists.txt b/utilities/ProcessBlockId/CMakeLists.txt index 0c8f058e..92056b0b 100644 --- a/utilities/ProcessBlockId/CMakeLists.txt +++ b/utilities/ProcessBlockId/CMakeLists.txt @@ -12,7 +12,3 @@ add_executable(test_process_block_id test_process_blk_id.cpp) target_link_libraries(test_process_block_id PRIVATE ProcessBlockId) - -if(${LINUX}) - set_target_properties(ProcessBlockId PROPERTIES POSITION_INDEPENDENT_CODE ON) -endif() \ No newline at end of file diff --git a/utilities/Schem/CMakeLists.txt b/utilities/Schem/CMakeLists.txt index 323d0cdb..2b90a74c 100644 --- a/utilities/Schem/CMakeLists.txt +++ b/utilities/Schem/CMakeLists.txt @@ -35,7 +35,3 @@ if (TARGET Boost::multi_array) target_link_libraries(Schem PUBLIC Boost::multi_array) endif () target_link_libraries(Schem PUBLIC MCDataVersion ProcessBlockId) - -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - set_target_properties(Schem PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -endif () \ No newline at end of file diff --git a/utilities/libpngReader/CMakeLists.txt b/utilities/libpngReader/CMakeLists.txt index d47d06ff..e367e985 100644 --- a/utilities/libpngReader/CMakeLists.txt +++ b/utilities/libpngReader/CMakeLists.txt @@ -5,7 +5,6 @@ add_library(libpng_reader STATIC find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) - target_compile_features(libpng_reader PUBLIC cxx_std_23) target_link_libraries(libpng_reader PUBLIC tl::expected PNG::PNG) target_include_directories(libpng_reader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file From afe479d2939f5adecf83a8008705b359ae2b96bb Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Dec 2025 09:30:40 +0800 Subject: [PATCH 1109/1123] VCL: use resource pack of 1.21.11 Signed-off-by: ToKiNoBug --- VisualCraft/vc-config.json | 2 +- cmake/required_deps/vanilla_zips.cmake | 2 +- vccl/vccl-config.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VisualCraft/vc-config.json b/VisualCraft/vc-config.json index ff343083..1317190c 100644 --- a/VisualCraft/vc-config.json +++ b/VisualCraft/vc-config.json @@ -38,7 +38,7 @@ ], [ 21, - "./Blocks_VCL/Vanilla_1_21_5.zip" + "./Blocks_VCL/Vanilla_1_21_11.zip" ] ], "default_block_state_list": [ diff --git a/cmake/required_deps/vanilla_zips.cmake b/cmake/required_deps/vanilla_zips.cmake index 82275662..ff6dd728 100644 --- a/cmake/required_deps/vanilla_zips.cmake +++ b/cmake/required_deps/vanilla_zips.cmake @@ -8,7 +8,7 @@ set(VCL_zip_names "Vanilla_1_18_2.zip" "Vanilla_1_19_3.zip" "Vanilla_1_20_6.zip" - "Vanilla_1_21_5.zip" + "Vanilla_1_21_11.zip" ) #https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/Vanilla_1_20_1.zip set(VCL_url_prefix "https://github.com/SlopeCraft/VisualCraft-binaries/releases/download/resource-packs/") diff --git a/vccl/vccl-config.json b/vccl/vccl-config.json index ff343083..1317190c 100644 --- a/vccl/vccl-config.json +++ b/vccl/vccl-config.json @@ -38,7 +38,7 @@ ], [ 21, - "./Blocks_VCL/Vanilla_1_21_5.zip" + "./Blocks_VCL/Vanilla_1_21_11.zip" ] ], "default_block_state_list": [ From 4893322a9b96d41b3fe7228a480d455d5fad2b50 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Tue, 16 Dec 2025 11:00:14 +0800 Subject: [PATCH 1110/1123] VCL: update to 1.21.11 Signed-off-by: ToKiNoBug --- VisualCraftL/ResourcePack.cpp | 3 + VisualCraftL/VCL_blocks_fixed.json | 145 ++++++++++++++++++++++-- VisualCraftL/VisualCraftL.cpp | 10 +- VisualCraftL/VisualCraftL.h | 3 +- utilities/MCDataVersion/MCDataVersion.h | 11 ++ 5 files changed, 161 insertions(+), 11 deletions(-) diff --git a/VisualCraftL/ResourcePack.cpp b/VisualCraftL/ResourcePack.cpp index f28722ed..c695cf3b 100644 --- a/VisualCraftL/ResourcePack.cpp +++ b/VisualCraftL/ResourcePack.cpp @@ -545,6 +545,9 @@ uint32_t VCL_resource_pack::standard_color( if (biome == VCL_biome_t::cherry_grove) { return 0xFF'90'81'4d; } + if (biome == VCL_biome_t::pale_garden) { + return 0xFF'87'8d'76; + } return default_result; } diff --git a/VisualCraftL/VCL_blocks_fixed.json b/VisualCraftL/VCL_blocks_fixed.json index a1724c27..1b338655 100644 --- a/VisualCraftL/VCL_blocks_fixed.json +++ b/VisualCraftL/VCL_blocks_fixed.json @@ -941,13 +941,38 @@ "version": 19, "is_foliage": true }, + // Cherry, azalea(and flowering), pale leaves don't use coloring mechanism, so is_foliage is set to false "minecraft:cherry_leaves[distance=7,persistent=true]": { "burnable": true, "class": "leaves", "nameEN": "Cherry leaves", "nameZH": "樱花树叶", "version": 20, - "is_foliage": true + "is_foliage": false + }, + "minecraft:azalea_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "nameEN": "Azalea leaves", + "nameZH": "杜鹃树叶", + "version": 17, + "is_foliage": false + }, + "minecraft:flowering_azalea_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "nameEN": "Flowering azalea leaves", + "nameZH": "盛开杜鹃树叶", + "version": 17, + "is_foliage": false + }, + "minecraft:pale_oak_leaves[distance=7,persistent=true]": { + "burnable": true, + "class": "leaves", + "nameEN": "Pale oak leaves", + "nameZH": "苍白树叶", + "version": 21, + "is_foliage": false }, "minecraft:blue_ice": { "class": "natural", @@ -1230,6 +1255,42 @@ ], "reproducible": false }, + "minecraft:resin_block": { + "class": "natural", + "nameEN": "Resin block", + "nameZH": "树脂块", + "version": 21 + }, + "minecraft:resin_bricks": { + "class": "natural", + "nameEN": "Resin bricks", + "nameZH": "树脂砖块", + "version": 21 + }, + "minecraft:chiseled_resin_bricks": { + "class": "natural", + "nameEN": "Chiseled resin bricks", + "nameZH": "雕纹树脂砖块", + "version": 21 + }, + "minecraft:pale_moss_block": { + "class": "natural", + "nameEN": "Pale Moss Block", + "nameZH": "苍白苔藓块", + "version": 21, + "burnable": true + }, + // Currently VCl is not able to process these carpet files. Comment them out + // "minecraft:pale_moss_carpet": { + // "class": "natural", + // "nameEN": "Pale moss carpet", + // "nameZH": "苍白苔藓地毯", + // "version": 21, + // "burnable": true, + // "faces": [ + // "up" + // ] + // }, "minecraft:crimson_nylium": { "class": "nether", "endermanPickable": true, @@ -1885,6 +1946,13 @@ "nameZH": "扭曲木板", "version": 16 }, + "minecraft:pale_oak_planks": { + "burnable": true, + "class": "planks", + "nameEN": "Pale oak plank", + "nameZH": "苍白木板", + "version": 21 + }, "minecraft:honey_block": { "class": "redstone", "nameEN": "Honey block", @@ -2389,6 +2457,12 @@ "nameZH": "雕纹凝灰岩砖", "version": 21 }, + "minecraft:polished_tuff": { + "class": "stone", + "nameEN": "Polished tuff", + "nameZH": "磨制凝灰岩", + "version": 21 + }, "minecraft:calcite": { "class": "stone", "nameEN": "Calcite", @@ -4228,12 +4302,67 @@ "south" ], "burnable": true + }, + "minecraft:pale_oak_wood[axis=y]": { + "class": "wood", + "nameEN": "Pale oak log (Y axis)", + "nameZH": "苍白原木 (Y 轴)", + "version": 21, + "burnable": true + }, + "minecraft:pale_oak_wood[axis=x]": { + "class": "wood", + "nameEN": "Pale oak log (X axis)", + "nameZH": "苍白原木 (X 轴)", + "version": 21, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:pale_oak_wood[axis=z]": { + "class": "wood", + "nameEN": "Pale oak log (Z axis)", + "nameZH": "苍白原木 (Z 轴)", + "version": 21, + "faces": [ + "north", + "south" + ], + "burnable": true + }, + "minecraft:stripped_pale_oak_wood[axis=y]": { + "class": "wood", + "nameEN": "Pale oak log (Y axis)", + "nameZH": "去皮苍白原木 (Y 轴)", + "version": 21, + "burnable": true + }, + "minecraft:stripped_pale_oak_wood[axis=x]": { + "class": "wood", + "nameEN": "Pale oak log (X axis)", + "nameZH": "去皮苍白原木 (X 轴)", + "version": 21, + "faces": [ + "east", + "west", + "up", + "down" + ], + "burnable": true + }, + "minecraft:stripped_pale_oak_wood[axis=z]": { + "class": "wood", + "nameEN": "Pale oak log (Z axis)", + "nameZH": "去皮苍白原木 (Z 轴)", + "version": 21, + "faces": [ + "north", + "south" + ], + "burnable": true } - /*, - "minecraft:beacon": { - "nameEN": "Beacon", - "nameZH": "信标", - "class": "others", - "version": "all" - }*/ } \ No newline at end of file diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 42defbbf..1859e9ab 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1178,6 +1178,8 @@ VCL_EXPORT_FUN VCL_biome_info VCL_get_biome_info(VCL_biome_t biome) { return VCL_biome_info{0.5, 0.5}; case VCL_biome_t::cherry_grove: return VCL_biome_info{0.5, 0.8}; + case VCL_biome_t::pale_garden: + return VCL_biome_info{0.7, 0.8}; } return VCL_biome_info{NAN, NAN}; } @@ -1314,8 +1316,10 @@ const char *VCL_biome_name_ZH(VCL_biome_t b) noexcept { return "末地荒地"; case VCL_biome_t::cherry_grove: return "樱花树林"; + case VCL_biome_t::pale_garden: + return "苍白花园"; } - return "Unamed"; + return "未命名"; } const char *VCL_biome_name_EN(VCL_biome_t b) noexcept { @@ -1448,9 +1452,11 @@ const char *VCL_biome_name_EN(VCL_biome_t b) noexcept { return "End Barrens"; case VCL_biome_t::cherry_grove: return "Cherry Grove"; + case VCL_biome_t::pale_garden: + return "Pale garden"; } - return "Unamed"; + return "Unnamed"; } VCL_EXPORT_FUN const char *VCL_biome_name(VCL_biome_t biome, uint8_t is_ZH) { diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index c7dffe0e..25c2561a 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -163,7 +163,8 @@ enum class VCL_biome_t : uint16_t { end_midlands = 60, small_end_islands = 61, end_barrens = 62, - cherry_grove = 63 + cherry_grove = 63, + pale_garden = 64, }; /** diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index a83c67a0..d4c2e179 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -30,6 +30,17 @@ This file is part of SlopeCraft. namespace MCDataVersion { enum class MCDataVersion_t : int { + Java_1_21_11 = 4671, + Java_1_21_11__rc3 = 4670, + Java_1_21_11__rc2 = 4669, + Java_1_21_11__rc1 = 4668, + Java_1_21_11__pre5 = 4667, + Java_1_21_11__pre4 = 4666, + Java_1_21_11__pre3 = 4665, + Java_1_21_11__pre2 = 4664, + Java_1_21_11__pre1 = 4663, + Snapshot_25w46a = 4662, + Snapshot_25w45a = 4660, Snapshot_25w44a = 4659, Snapshot_25w43a = 4655, Snapshot_25w42a = 4654, From 7f97a7d3c36a4ab0399fffeda53b08479f1052e6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 21 Jan 2026 09:41:48 +0800 Subject: [PATCH 1111/1123] Fix cmake format error in zstd.cmake Signed-off-by: ToKiNoBug --- cmake/required_deps/zstd.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/required_deps/zstd.cmake b/cmake/required_deps/zstd.cmake index ac459ba5..125f0f20 100644 --- a/cmake/required_deps/zstd.cmake +++ b/cmake/required_deps/zstd.cmake @@ -43,7 +43,7 @@ elseif (TARGET zstd::libzstd_static) set(SC_zstd_target_name "zstd::libzstd_static") elseif (TARGET zstd_manually_imported) set(SC_zstd_target_name "zstd_manually_imported") -elseif () +else () message(FATAL_ERROR "No zstd library target imported.") endif () message(STATUS "Found zstd: ${SC_zstd_target_name}") \ No newline at end of file From 6014efa3926c8402aaaa29f09443b7a94852ef50 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 21 Jan 2026 10:45:57 +0800 Subject: [PATCH 1112/1123] Add flexible API for libpngReader Signed-off-by: ToKiNoBug --- utilities/libpngReader/CMakeLists.txt | 5 +-- utilities/libpngReader/libpng_reader.cpp | 51 ++++++++++++++++-------- utilities/libpngReader/libpng_reader.h | 9 ++++- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/utilities/libpngReader/CMakeLists.txt b/utilities/libpngReader/CMakeLists.txt index e367e985..9a4b5add 100644 --- a/utilities/libpngReader/CMakeLists.txt +++ b/utilities/libpngReader/CMakeLists.txt @@ -2,9 +2,8 @@ add_library(libpng_reader STATIC libpng_reader.cpp libpng_reader.h) -find_package(tl-expected REQUIRED) find_package(PNG REQUIRED) target_compile_features(libpng_reader PUBLIC cxx_std_23) -target_link_libraries(libpng_reader PUBLIC tl::expected PNG::PNG) -target_include_directories(libpng_reader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file +target_link_libraries(libpng_reader PUBLIC PNG::PNG) +target_include_directories(libpng_reader INTERFACE $) \ No newline at end of file diff --git a/utilities/libpngReader/libpng_reader.cpp b/utilities/libpngReader/libpng_reader.cpp index 4a75a034..678faa19 100644 --- a/utilities/libpngReader/libpng_reader.cpp +++ b/utilities/libpngReader/libpng_reader.cpp @@ -2,10 +2,12 @@ // Created by Joseph on 2024/4/8. // -#include "libpng_reader.h" -#include #include #include +#include +#include + +#include "libpng_reader.h" struct read_buffer_wrapper { const void *data; @@ -27,13 +29,27 @@ void png_callback_read_data_from_memory(png_struct *png, png_byte *data, ioptr->offset += read_length; } -std::tuple, std::string> +std::tuple, std::string> parse_png_into_argb32(std::span encoded, std::vector &pixels) noexcept { + std::function allocator = + [&pixels](const image_info &info) { + pixels.resize(static_cast(info.rows) * + static_cast(info.cols)); + return pixels.data(); + }; + + return parse_png_into_argb32_flex(encoded, allocator); +} + +std::tuple, std::string> +parse_png_into_argb32_flex( + std::span encoded, + const std::function allocator) noexcept { std::string warnings{}; if (encoded.size() < 8) { return { - tl::make_unexpected(std::format( + std::unexpected(std::format( "File is too small ({} bytes) to be possible PNG", encoded.size())), warnings}; } @@ -41,27 +57,25 @@ parse_png_into_argb32(std::span encoded, png_struct *png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { - return {tl::make_unexpected("Failed to create png read struct."), - warnings}; + return {std::unexpected("Failed to create png read struct."), warnings}; } png_info *info = png_create_info_struct(png); if (info == NULL) { png_destroy_read_struct(&png, &info, NULL); - return {tl::make_unexpected("Failed to create png info struct."), - warnings}; + return {std::unexpected("Failed to create png info struct."), warnings}; } png_info *info_end = png_create_info_struct(png); if (info_end == NULL) { png_destroy_read_struct(&png, &info, &info_end); - return {tl::make_unexpected("Failed to create png info_end struct."), + return {std::unexpected("Failed to create png info_end struct."), warnings}; } { const auto compare_result = png_sig_cmp(encoded.data(), 0, 8); if (compare_result not_eq 0) { - return {tl::make_unexpected("Not a png file."), warnings}; + return {std::unexpected("Not a png file."), warnings}; } } @@ -129,20 +143,23 @@ parse_png_into_argb32(std::span encoded, break; default: png_destroy_read_struct(&png, &info, &info_end); - return {tl::make_unexpected( - std::format("Unknown color type {}", color_type)), - warnings}; + return { + std::unexpected(std::format("Unknown color type {}", color_type)), + warnings}; } // cout << ")\n"; // #warning here - pixels.resize(height * width); + const auto img_info = image_info{height, width}; + uint32_t *const pixels_data = allocator(img_info); + assert(pixels_data not_eq nullptr); + // pixels.resize(height * width); // img->resize(height, width); std::vector row_ptrs; row_ptrs.resize(height); for (int r = 0; r < int(height); r++) { - row_ptrs[r] = reinterpret_cast(pixels.data() + r * width); + row_ptrs[r] = reinterpret_cast(pixels_data + r * width); } png_read_image(png, row_ptrs.data()); @@ -166,8 +183,8 @@ parse_png_into_argb32(std::span encoded, // png_destroy_info_struct(png, &info); png_destroy_read_struct(&png, &info, &info_end); - return {image_info{height, width}, warnings}; + return {img_info, warnings}; } catch (const std::exception &e) { - return {tl::make_unexpected(e.what()), warnings}; + return {std::unexpected(e.what()), warnings}; } } diff --git a/utilities/libpngReader/libpng_reader.h b/utilities/libpngReader/libpng_reader.h index 2761f216..1f923a09 100644 --- a/utilities/libpngReader/libpng_reader.h +++ b/utilities/libpngReader/libpng_reader.h @@ -6,9 +6,10 @@ #define SLOPECRAFT_LIBPNG_READER_H #include -#include +#include #include #include +#include #include #include @@ -17,8 +18,12 @@ struct image_info { uint32_t cols{0}; }; -[[nodiscard]] std::tuple, std::string> +[[nodiscard]] std::tuple, std::string> parse_png_into_argb32(std::span png_file_in_bytes, std::vector& pixels_row_major) noexcept; +[[nodiscard]] std::tuple, std::string> +parse_png_into_argb32_flex( + std::span png_file_in_bytes, + const std::function allocator) noexcept; #endif // SLOPECRAFT_LIBPNG_READER_H From 170e648fa2c639110d34f2f82faa5d0a05e210dc Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 21 Jan 2026 12:10:11 +0800 Subject: [PATCH 1113/1123] Fix reading very large image Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 2 +- SlopeCraft/main.cpp | 6 +++++- VisualCraft/VCWind.cpp | 3 +-- VisualCraft/main.cpp | 7 +++++-- vccl/vccl.cpp | 10 ++++++---- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index 8b2f9436..a06c66b0 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -40,7 +40,7 @@ void SCWind::on_pb_add_image_clicked() noexcept { if (!task_res) { auto ret = QMessageBox::critical( this, tr("打开图像失败"), - tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") + tr("无法打开图像 %1。\n详细信息: %2") .arg(filename, task_res.error()), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); diff --git a/SlopeCraft/main.cpp b/SlopeCraft/main.cpp index b834159a..8846296c 100644 --- a/SlopeCraft/main.cpp +++ b/SlopeCraft/main.cpp @@ -1,6 +1,9 @@ #include -#include +#include +#include +#include #include +#include #include #include "SCWind.h" #include "VersionDialog.h" @@ -9,6 +12,7 @@ int main(int argc, char** argv) { QApplication qapp(argc, argv); QDir::setCurrent(QCoreApplication::applicationDirPath()); + QImageReader::setAllocationLimit(INT32_MAX); SCWind wind; diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 53670dd4..586465ca 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -650,8 +650,7 @@ void VCWind::on_tb_add_images_clicked() noexcept { const auto ret = QMessageBox::warning( this, VCWind::tr("读取图片失败"), VCWind::tr("无法读取图片%" - "1。图片可能是不支持的格式,或者已经损坏" - "。图像过大也可能导致此错误。") + "1。图片可能是不支持的格式,或者已经损坏。") .arg(filename), QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, QMessageBox::StandardButton::Close}, diff --git a/VisualCraft/main.cpp b/VisualCraft/main.cpp index a0e3c54d..2b577183 100644 --- a/VisualCraft/main.cpp +++ b/VisualCraft/main.cpp @@ -20,12 +20,14 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ -#include +#include +#include #include #include +#include #include #include -#include +#include #include "CallbackFunctions.h" #include "VCWind.h" @@ -39,6 +41,7 @@ bool parse_config_json(QString &err) noexcept; int main(int argc, char **argv) { QApplication qapp(argc, argv); QDir::setCurrent(QCoreApplication::applicationDirPath()); + QImageReader::setAllocationLimit(INT32_MAX); ::is_language_ZH = QLocale::system().uiLanguages().contains("zh"); diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 349ee30f..6741f623 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -20,17 +20,18 @@ This file is part of SlopeCraft. bilibili:https://space.bilibili.com/351429231 */ +#include +#include +#include #include #include -#include "vccl_internal.h" #include +#include +#include "vccl_internal.h" #include #include - #include -#include -#include using std::cout, std::endl; @@ -236,6 +237,7 @@ int main(int argc, char **argv) { } QCoreApplication qapp(argc, argv); + QImageReader::setAllocationLimit(INT32_MAX); if (input.list_supported_formats) { list_supported_formats(); qapp.quit(); From c2513845bca8cf5adf6c04947674584614efed75 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 21 Jan 2026 12:13:07 +0800 Subject: [PATCH 1114/1123] Update translations Signed-off-by: ToKiNoBug --- SlopeCraft/others/SlopeCraft_en_US.ts | 8 +++++++- VisualCraft/others/VisualCraft_en_US.ts | 16 ++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index 63dc153f..d8947827 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -1060,7 +1060,6 @@ Click Ok to ignore, and click Close to exit SlopeCraft. Failed to open image - 无法打开图像 %1。常见原因:图像尺寸太大。 详细信息: %2 @@ -1072,6 +1071,13 @@ Detailed information: %2 请选择将被替换的图像 Please images to be replaced + + + 无法打开图像 %1。 +详细信息: %2 + Failed to open image %1 . +Details: %2 + 必须先选择一个或多个图像,然后才能替换它们。 diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 62c1a806..0e5abd65 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -689,22 +689,22 @@ If you select a block in "Avaliable blocks" page, the other page will Biomes - + VisualCraftL 动态库版本不匹配 The version of VisualCraftL shared lib mismatch - + 界面程序编译时使用的 VisualCraftL 版本为%1,而 VisualCraftL 动态库的版本为%2。通常这是因为动态库版本过低。 The version of VisualCraftL at compile-time is %1, while that at runtime is %2. Usually it is because the version of VisualCraftL shared lib is too old. - + 加载配置文件失败。 Failed to load configuration file. - + 无法加载配置文件"./vc-config.json"。 %1 Failed to load configuration file "./vc-config.json'. @@ -788,16 +788,16 @@ If you select a block in "Avaliable blocks" page, the other page will - 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。图像过大也可能导致此错误。 - Failed to load image %1 . The image may be of unsupported format, or has been screwed up. A tooooo large image may also cause this error. + 无法读取图片%1。图片可能是不支持的格式,或者已经损坏。 + Failed to read image %1 . Unsupported format or broken image. - + 设置图片失败 Failed to set image - + 这个错误不应该发生的,可能是你点儿背。 This error is considered to be impossible. From fd850033eec821fa4cbf7546132bbd89fd1036ff Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Wed, 21 Jan 2026 12:55:29 +0800 Subject: [PATCH 1115/1123] Fix VCWind image preview Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 22 +++++++++++++--------- VisualCraft/VCWind.h | 1 - VisualCraft/VCWind.ui | 14 ++------------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 586465ca..06ffa687 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -736,10 +736,21 @@ SCL_convertAlgo VCWind::current_selected_algo() const noexcept { } void VCWind::show_image(decltype(image_cache)::iterator it) noexcept { - this->ui->label_raw_image->setPixmap(QPixmap::fromImage(it->second.first)); + const int margin_pixels = 8; + const auto margin = QMargins{0, 0, margin_pixels, margin_pixels}; + this->ui->label_raw_image->setPixmap( + QPixmap::fromImage(it->second.first) + .scaled(this->ui->label_raw_image->size().shrunkBy(margin), + Qt::KeepAspectRatio, Qt::FastTransformation)); if (!it->second.second.isNull()) { - this->ui->lable_converted->setPixmap(QPixmap::fromImage(it->second.second)); + auto raw_pixmap = QPixmap::fromImage(it->second.second); + const auto size = this->ui->lable_converted->size().shrunkBy(margin); + qDebug() << "size = " << size; + // for (int i = 0; i < 1; i++) { + this->ui->lable_converted->setPixmap( + raw_pixmap.scaled(size, Qt::KeepAspectRatio, Qt::FastTransformation)); + // } return; } @@ -808,13 +819,6 @@ void VCWind::clear_convert_cache() noexcept { } } -void VCWind::on_cb_show_raw_size_stateChanged(int state) noexcept { - bool autoscale = (state == 0); - - this->ui->label_raw_image->setScaledContents(autoscale); - this->ui->lable_converted->setScaledContents(autoscale); -} - void VCWind::on_cb_show_raw_stateChanged(int state) noexcept { if (state) { this->ui->label_raw_image->show(); diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index ee2d30c2..7c4f0435 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -285,7 +285,6 @@ class VCWind : public QMainWindow { void on_tb_remove_images_clicked() noexcept; // auto connected - void on_cb_show_raw_size_stateChanged(int state) noexcept; void on_cb_show_raw_stateChanged(int state) noexcept; void on_cb_show_converted_stateChanged(int state) noexcept; void on_lw_image_files_itemClicked(QListWidgetItem *item) noexcept; diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index ed62b423..3453fa3f 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -457,7 +457,7 @@ 0 0 - 885 + 881 305 @@ -497,16 +497,6 @@ - true - - - - - - - 显示原始尺寸 - - false @@ -629,7 +619,7 @@ - true + false From 8343119387795c0a6a98341fc85507c2ce37d84c Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 24 Jan 2026 14:16:57 +0800 Subject: [PATCH 1116/1123] Update version number Signed-off-by: ToKiNoBug --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19093f63..d7830624 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) # set version ----------------------------------------------------------------- -set(SlopeCraft_version 5.3.2) +set(SlopeCraft_version 5.3.3) # set basic project attributes ------------------------------------------------ project(SlopeCraft VERSION ${SlopeCraft_version} LANGUAGES C CXX) From dd09eddfe57b22601a3fa9ebf5f345b7dbf8fc5e Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 24 Jan 2026 14:31:32 +0800 Subject: [PATCH 1117/1123] Update copyright info to 2026 Signed-off-by: ToKiNoBug --- MapViewer/MapViewerWind.cpp | 2 +- MapViewer/MapViewerWind.h | 2 +- MapViewer/main.cpp | 3 +- MapViewer/processMapFiles.cpp | 19 +++--- MapViewer/processMapFiles.h | 4 +- MapViewer/resource_manually.cpp | 3 +- SlopeCraft/AiCvterParameterDialog.cpp | 2 +- SlopeCraft/AiCvterParameterDialog.h | 2 +- SlopeCraft/others/SlopeCraft.rc.in | 58 +++++++--------- SlopeCraftL/SlopeCraftL.cpp | 2 +- SlopeCraftL/SlopeCraftL.h | 2 +- SlopeCraftL/color_source.cpp | 2 +- SlopeCraftL/height_line.cpp | 2 +- SlopeCraftL/image_preprocess.cpp | 2 +- SlopeCraftL/lossy_compressor.cpp | 2 +- SlopeCraftL/mc_block.cpp | 2 +- SlopeCraftL/optimize_chain.cpp | 2 +- SlopeCraftL/others/SlopeCraftL.rc.in | 57 +++++++--------- VisualCraft/BiomeBrowser.cpp | 2 +- VisualCraft/BlockBrowser.cpp | 2 +- VisualCraft/BlockBrowser.h | 2 +- VisualCraft/BlockSelector.cpp | 7 +- VisualCraft/BlockSelector.h | 24 +++---- VisualCraft/BlockSelectorCriteria.cpp | 2 +- VisualCraft/CallbackFunctions.cpp | 2 +- VisualCraft/CallbackFunctions.h | 6 +- VisualCraft/ColorBrowser.cpp | 2 +- VisualCraft/ColorBrowser.h | 8 +-- VisualCraft/VCWind.cpp | 2 +- VisualCraft/VCWind.h | 2 +- VisualCraft/VCWind_export.cpp | 2 +- VisualCraft/VCWind_gpu.cpp | 2 +- VisualCraft/VCWind_select.cpp | 2 +- VisualCraft/VCWind_subwindows.cpp | 2 +- VisualCraft/VC_block_class.cpp | 2 +- VisualCraft/VC_block_class.h | 12 ++-- VisualCraft/main.cpp | 2 +- VisualCraft/others/VisualCraft.rc.in | 58 +++++++--------- VisualCraftL/BlockStateList.cpp | 2 +- VisualCraftL/BlockStateList.h | 2 +- VisualCraftL/DirectionHandler.hpp | 67 ++++++++++--------- VisualCraftL/ParseResourcePack_blocks.cpp | 2 +- VisualCraftL/ParseResourcePack_json.cpp | 2 +- VisualCraftL/ParseResourcePack_png.cpp | 2 +- VisualCraftL/ResourcePack.cpp | 2 +- VisualCraftL/Resource_tree.cpp | 2 +- VisualCraftL/Resource_tree.h | 2 +- VisualCraftL/TokiVC.cpp | 2 +- VisualCraftL/TokiVC.h | 2 +- VisualCraftL/TokiVC_build.cpp | 2 +- VisualCraftL/TokiVC_export_test.cpp | 2 +- VisualCraftL/TokiVC_flagdiagram.cpp | 2 +- VisualCraftL/VisualCraftL.cpp | 2 +- VisualCraftL/VisualCraftL.h | 2 +- VisualCraftL/VisualCraftL_global.h | 2 +- VisualCraftL/others/VisualCraftL.rc.in | 57 +++++++--------- imageCutter/CutterWind.cpp | 15 ++--- imageCutter/CutterWind.h | 10 +-- imageCutter/main.cpp | 3 +- tests/test_libSchem/test_libSchem.cpp | 2 +- utilities/BlockListManager/BLM_preset.cpp | 2 +- utilities/ColorManip/CIEDE00.cpp | 12 ++-- utilities/ColorManip/ColorCvt.cpp | 16 ++--- utilities/ColorManip/ColorDiff.cpp | 2 +- utilities/ColorManip/colorset_maptical.hpp | 2 +- utilities/ColorManip/imageConvert.hpp | 2 +- utilities/ColorManip/newColorSet.hpp | 2 +- utilities/ColorManip/newTokiColor.hpp | 2 +- .../GAConverter/GAConverter.cpp | 2 +- .../GAConverter/GAConverter.h | 2 +- .../GAConverter/GACvterDefines.hpp | 2 +- .../GAConverter/sortColor.cpp | 2 +- .../GAConverter/sortColor.h | 2 +- .../ExternalConverters/GAConverter/uiPack.h | 2 +- utilities/GPUWrapper/GPU_interface.h | 2 +- utilities/GPUWrapper/OpenCL/ColorDiff.cl | 2 +- utilities/GPUWrapper/OpenCL/GPU_interface.cpp | 2 +- utilities/GPUWrapper/OpenCL/OCLWrapper.cpp | 2 +- utilities/GPUWrapper/OpenCL/OCLWrapper.h | 2 +- utilities/MCDataVersion/MCDataVersion.cpp | 2 +- utilities/MCDataVersion/MCDataVersion.h | 2 +- utilities/MapImageCvter/MapImageCvter.cpp | 2 +- utilities/MapImageCvter/MapImageCvter.h | 2 +- utilities/NBTWriter/NBTWriter.cpp | 5 +- utilities/SC_version_buildtime.h.in | 2 +- utilities/Schem/Schem.cpp | 2 +- utilities/Schem/Schem.h | 2 +- utilities/Schem/bit_shrink.cpp | 2 +- utilities/Schem/bit_shrink.h | 2 +- utilities/VersionDialog/VersionDialog.cpp | 2 +- utilities/VersionDialog/VersionDialog.h | 2 +- vccl/vccl.cpp | 2 +- vccl/vccl_internal.h | 5 +- vccl/vccl_parse_default.cpp | 2 +- 94 files changed, 267 insertions(+), 328 deletions(-) diff --git a/MapViewer/MapViewerWind.cpp b/MapViewer/MapViewerWind.cpp index 5de96e40..a68bc704 100644 --- a/MapViewer/MapViewerWind.cpp +++ b/MapViewer/MapViewerWind.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/MapViewer/MapViewerWind.h b/MapViewer/MapViewerWind.h index 87fd9f14..b816913a 100644 --- a/MapViewer/MapViewerWind.h +++ b/MapViewer/MapViewerWind.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/MapViewer/main.cpp b/MapViewer/main.cpp index b4f19e75..b2c0b632 100644 --- a/MapViewer/main.cpp +++ b/MapViewer/main.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -30,7 +30,6 @@ This file is part of SlopeCraft. #include int main(int argc, char *argv[]) { - QApplication a(argc, argv); QTranslator translator; diff --git a/MapViewer/processMapFiles.cpp b/MapViewer/processMapFiles.cpp index 8c0dcf59..8a0108dc 100644 --- a/MapViewer/processMapFiles.cpp +++ b/MapViewer/processMapFiles.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -51,8 +51,9 @@ bool uncompress_map_file(const char *filename, std::vector *const dest, *error_info = "Failed to open map data file "; *error_info += filename; *error_info += ", the file may be invalid."; - *error_info += "\nThis error may also be caused by non-English " - "characters in the filename of path."; + *error_info += + "\nThis error may also be caused by non-English " + "characters in the filename of path."; } return false; } @@ -110,8 +111,9 @@ const uint8_t *find_color_begin(const std::vector &inflated, } if (error_info != nullptr) { - *error_info = "Failed to find map data array named color. The map data " - "file may be invalid."; + *error_info = + "Failed to find map data array named color. The map data " + "file may be invalid."; } // cout<<"failed to find feature"< *const dest, std::string *const error_info) { - if (filename == nullptr || strlen(filename) <= 0) { - if (error_info != nullptr) - *error_info = "Invalid input : filename"; + if (error_info != nullptr) *error_info = "Invalid input : filename"; return false; } if (dest == nullptr) { - if (error_info != nullptr) - *error_info = "Invalid input : dest"; + if (error_info != nullptr) *error_info = "Invalid input : dest"; return false; } diff --git a/MapViewer/processMapFiles.h b/MapViewer/processMapFiles.h index 2acf3faf..86fe3401 100644 --- a/MapViewer/processMapFiles.h +++ b/MapViewer/processMapFiles.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -38,4 +38,4 @@ bool process_map_file( Eigen::Array *const dest, std::string *const error_info); -#endif // PROCESSMAPFILES_H +#endif // PROCESSMAPFILES_H diff --git a/MapViewer/resource_manually.cpp b/MapViewer/resource_manually.cpp index 10745e98..a9ef67fa 100644 --- a/MapViewer/resource_manually.cpp +++ b/MapViewer/resource_manually.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -23,7 +23,6 @@ This file is part of SlopeCraft. #include #include - extern const uint8_t data_unknown_base_color[]; extern const size_t png_size; diff --git a/SlopeCraft/AiCvterParameterDialog.cpp b/SlopeCraft/AiCvterParameterDialog.cpp index da86b948..660785fc 100644 --- a/SlopeCraft/AiCvterParameterDialog.cpp +++ b/SlopeCraft/AiCvterParameterDialog.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraft/AiCvterParameterDialog.h b/SlopeCraft/AiCvterParameterDialog.h index 91cda1b7..ed594cf1 100644 --- a/SlopeCraft/AiCvterParameterDialog.h +++ b/SlopeCraft/AiCvterParameterDialog.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraft/others/SlopeCraft.rc.in b/SlopeCraft/others/SlopeCraft.rc.in index d6ba2ea6..014200e1 100644 --- a/SlopeCraft/others/SlopeCraft.rc.in +++ b/SlopeCraft/others/SlopeCraft.rc.in @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -22,40 +22,30 @@ This file is part of SlopeCraft. #include -IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/SlopeCraftIconNew.ico" +IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/SlopeCraftIconNew.ico" -VS_VERSION_INFO VERSIONINFO - FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - FILEFLAGSMASK 0x3fL + VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, + @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, + 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, + @PROJECT_VERSION_PATCH @, + 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000404b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "Minecraft Map Pixel Art Tool\0" - VALUE "FileVersion", "@PROJECT_VERSION@.0\0" - VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2023\0" - VALUE "OriginalFilename", "SlopeCraft.exe\0" - VALUE "ProductName", "SlopeCraft\0" - VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" - VALUE "InternalName", "SlopeCraft\0" - VALUE "Comments", "Main program of SlopeCraft\0" - VALUE "LegalTrademarks", "Published under GPLv3 license\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0004, 1200 - END - END - + FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN + BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE + "CompanyName", + "\0" VALUE "FileDescription", + "Minecraft Map Pixel Art Tool\0" VALUE "FileVersion", + "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", + "Copyright TokiNoBug 2021-2023\0" VALUE "OriginalFilename", + "SlopeCraft.exe\0" VALUE "ProductName", + "SlopeCraft\0" VALUE "ProductVersion", + "@PROJECT_VERSION@.0\0" VALUE "InternalName", + "SlopeCraft\0" VALUE "Comments", + "Main program of SlopeCraft\0" VALUE "LegalTrademarks", + "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE + "Translation", + 0x0004, 1200 END END diff --git a/SlopeCraftL/SlopeCraftL.cpp b/SlopeCraftL/SlopeCraftL.cpp index 7acebb4b..413e2569 100644 --- a/SlopeCraftL/SlopeCraftL.cpp +++ b/SlopeCraftL/SlopeCraftL.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/SlopeCraftL.h b/SlopeCraftL/SlopeCraftL.h index c97154dc..e8aab3e4 100644 --- a/SlopeCraftL/SlopeCraftL.h +++ b/SlopeCraftL/SlopeCraftL.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/color_source.cpp b/SlopeCraftL/color_source.cpp index a170ef62..51033dac 100644 --- a/SlopeCraftL/color_source.cpp +++ b/SlopeCraftL/color_source.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/height_line.cpp b/SlopeCraftL/height_line.cpp index ef6b8d0e..a51d89cc 100644 --- a/SlopeCraftL/height_line.cpp +++ b/SlopeCraftL/height_line.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/image_preprocess.cpp b/SlopeCraftL/image_preprocess.cpp index 8d7bbf1f..fbbf48c5 100644 --- a/SlopeCraftL/image_preprocess.cpp +++ b/SlopeCraftL/image_preprocess.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/lossy_compressor.cpp b/SlopeCraftL/lossy_compressor.cpp index 43968024..fa982968 100644 --- a/SlopeCraftL/lossy_compressor.cpp +++ b/SlopeCraftL/lossy_compressor.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/mc_block.cpp b/SlopeCraftL/mc_block.cpp index eacbd290..70ae5f30 100644 --- a/SlopeCraftL/mc_block.cpp +++ b/SlopeCraftL/mc_block.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/optimize_chain.cpp b/SlopeCraftL/optimize_chain.cpp index 908d1c4d..a9630871 100644 --- a/SlopeCraftL/optimize_chain.cpp +++ b/SlopeCraftL/optimize_chain.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/others/SlopeCraftL.rc.in b/SlopeCraftL/others/SlopeCraftL.rc.in index 6b440d44..bcc5d773 100644 --- a/SlopeCraftL/others/SlopeCraftL.rc.in +++ b/SlopeCraftL/others/SlopeCraftL.rc.in @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -22,39 +22,28 @@ This file is part of SlopeCraft. #include -VS_VERSION_INFO VERSIONINFO - FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, + @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, + 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, + @PROJECT_VERSION_PATCH @, + 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000404b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "SlopeCraft Library\0" - VALUE "FileVersion", "@PROJECT_VERSION@.0\0" - VALUE "LegalCopyright", "TokiNoBug\0" - VALUE "OriginalFilename", "SlopeCraftL.dll\0" - VALUE "ProductName", "SlopeCraftL\0" - VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" - VALUE "InternalName", "SlopeCraftL\0" - VALUE "Comments", "\0" - VALUE "LegalTrademarks", "Published under GPLv3 license\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0004, 1200 - END - END -/* End of Version info */ - + FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN + BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE + "CompanyName", + "\0" VALUE "FileDescription", "SlopeCraft Library\0" VALUE "FileVersion", + "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", + "TokiNoBug\0" VALUE "OriginalFilename", + "SlopeCraftL.dll\0" VALUE "ProductName", + "SlopeCraftL\0" VALUE "ProductVersion", + "@PROJECT_VERSION@.0\0" VALUE "InternalName", + "SlopeCraftL\0" VALUE "Comments", "\0" VALUE "LegalTrademarks", + "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE + "Translation", + 0x0004, + 1200 END END + /* End of Version info */ diff --git a/VisualCraft/BiomeBrowser.cpp b/VisualCraft/BiomeBrowser.cpp index febc9fb4..fb4b7614 100644 --- a/VisualCraft/BiomeBrowser.cpp +++ b/VisualCraft/BiomeBrowser.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/BlockBrowser.cpp b/VisualCraft/BlockBrowser.cpp index 01b99745..366a79f1 100644 --- a/VisualCraft/BlockBrowser.cpp +++ b/VisualCraft/BlockBrowser.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/BlockBrowser.h b/VisualCraft/BlockBrowser.h index 7677ea3b..b5126710 100644 --- a/VisualCraft/BlockBrowser.h +++ b/VisualCraft/BlockBrowser.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/BlockSelector.cpp b/VisualCraft/BlockSelector.cpp index 193288ae..295457ce 100644 --- a/VisualCraft/BlockSelector.cpp +++ b/VisualCraft/BlockSelector.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -89,9 +89,8 @@ void BlockSelector::when_criteria_changed() noexcept { BlockSelector::tr("匹配到%1个方块").arg(count)); } -std::function -BlockSelector::match_functor() const noexcept { - +std::function BlockSelector::match_functor() + const noexcept { bs_criteria cr; for (auto bsc : this->criterias) { diff --git a/VisualCraft/BlockSelector.h b/VisualCraft/BlockSelector.h index 955db838..13729ae9 100644 --- a/VisualCraft/BlockSelector.h +++ b/VisualCraft/BlockSelector.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -33,10 +33,10 @@ class BlockSelectorCriteria; namespace Ui { class BlockSelector; class BlockSelectorCriteria; -} // namespace Ui +} // namespace Ui class bs_criteria { -public: + public: struct alignas(4) statement { bool logic_is_and{true}; VCL_block_attribute_t key; @@ -50,21 +50,21 @@ class bs_criteria { class BlockSelector : public QWidget { Q_OBJECT -private: + private: Ui::BlockSelector *ui; std::vector criterias; -public: + public: BlockSelector(QWidget *parent); ~BlockSelector(); -private: + private: void update_criteria_roles() noexcept; std::function match_functor() const noexcept; -private slots: + private slots: void emplace_back() noexcept; void remove_one(BlockSelectorCriteria *) noexcept; @@ -77,16 +77,16 @@ private slots: class BlockSelectorCriteria : public QWidget { Q_OBJECT -private: + private: Ui::BlockSelectorCriteria *ui; -signals: + signals: void options_changed(); void append(); void remove(BlockSelectorCriteria *); -public: + public: BlockSelectorCriteria(QWidget *parent); ~BlockSelectorCriteria(); @@ -94,10 +94,10 @@ class BlockSelectorCriteria : public QWidget { void update_criteria(bs_criteria &cr) const noexcept; -private slots: + private slots: // auto connected void on_tb_append_clicked() noexcept; void on_tb_remove_clicked() noexcept; }; -#endif // SLOPECRAFT_VISUALCRAFT_BLOCKSELECTOR_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_BLOCKSELECTOR_H \ No newline at end of file diff --git a/VisualCraft/BlockSelectorCriteria.cpp b/VisualCraft/BlockSelectorCriteria.cpp index ef51bb55..8a972b0c 100644 --- a/VisualCraft/BlockSelectorCriteria.cpp +++ b/VisualCraft/BlockSelectorCriteria.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/CallbackFunctions.cpp b/VisualCraft/CallbackFunctions.cpp index 6690a059..f096fb22 100644 --- a/VisualCraft/CallbackFunctions.cpp +++ b/VisualCraft/CallbackFunctions.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/CallbackFunctions.h b/VisualCraft/CallbackFunctions.h index 3a959a04..f57ee691 100644 --- a/VisualCraft/CallbackFunctions.h +++ b/VisualCraft/CallbackFunctions.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -31,6 +31,6 @@ void callback_receive_report(VCL_report_type_t, const char *msg, bool flush) noexcept; extern QWidget *wind; -} // namespace VC_callback +} // namespace VC_callback -#endif // SLOPECRAFT_VISUALCRAFT_CALLBACKFUNCTIONS_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_CALLBACKFUNCTIONS_H \ No newline at end of file diff --git a/VisualCraft/ColorBrowser.cpp b/VisualCraft/ColorBrowser.cpp index 6eab7738..0d78f3b5 100644 --- a/VisualCraft/ColorBrowser.cpp +++ b/VisualCraft/ColorBrowser.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/ColorBrowser.h b/VisualCraft/ColorBrowser.h index 701151c6..c6e0f8ab 100644 --- a/VisualCraft/ColorBrowser.h +++ b/VisualCraft/ColorBrowser.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -34,14 +34,14 @@ class ColorBrowser; class ColorBrowser : public QWidget { Q_OBJECT -private: + private: Ui::ColorBrowser *ui; // private_class_setup_chart *thread{nullptr}; void setup_table(const uint16_t *const color_id_list, const size_t color_count) noexcept; -public: + public: explicit ColorBrowser(QWidget *parent); ~ColorBrowser(); @@ -51,4 +51,4 @@ class ColorBrowser : public QWidget { // void setup_table_threaded() noexcept; }; -#endif // SLOPECRAFT_VISUALCRAFT_COLORBROWSER_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_COLORBROWSER_H \ No newline at end of file diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 06ffa687..51b3da41 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VCWind.h b/VisualCraft/VCWind.h index 7c4f0435..09a9fd8a 100644 --- a/VisualCraft/VCWind.h +++ b/VisualCraft/VCWind.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index e4237d1b..61401cec 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VCWind_gpu.cpp b/VisualCraft/VCWind_gpu.cpp index b0d1d7be..5aff1419 100644 --- a/VisualCraft/VCWind_gpu.cpp +++ b/VisualCraft/VCWind_gpu.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VCWind_select.cpp b/VisualCraft/VCWind_select.cpp index 687f286f..a8378e99 100644 --- a/VisualCraft/VCWind_select.cpp +++ b/VisualCraft/VCWind_select.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VCWind_subwindows.cpp b/VisualCraft/VCWind_subwindows.cpp index 978daeec..f8a07e0a 100644 --- a/VisualCraft/VCWind_subwindows.cpp +++ b/VisualCraft/VCWind_subwindows.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VC_block_class.cpp b/VisualCraft/VC_block_class.cpp index 01af0b2d..fb429964 100644 --- a/VisualCraft/VC_block_class.cpp +++ b/VisualCraft/VC_block_class.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/VC_block_class.h b/VisualCraft/VC_block_class.h index 5029340b..3c8a70a9 100644 --- a/VisualCraft/VC_block_class.h +++ b/VisualCraft/VC_block_class.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -36,11 +36,11 @@ class QCheckBox; class VC_block_class : public QGroupBox { Q_OBJECT -private: + private: Ui::VC_block_class *ui; std::vector> blocks; -public: + public: explicit VC_block_class(QWidget *parent); ~VC_block_class(); @@ -54,12 +54,12 @@ class VC_block_class : public QGroupBox { QCheckBox *chbox_enabled() noexcept; -private: + private: void erase_blocks() noexcept; void set_state_for_all(bool checked) noexcept; -private slots: + private slots: }; -#endif // SLOPECRAFT_VISUALCRAFT_VC_BLOCK_CLASS_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFT_VC_BLOCK_CLASS_H \ No newline at end of file diff --git a/VisualCraft/main.cpp b/VisualCraft/main.cpp index 2b577183..57cbeddc 100644 --- a/VisualCraft/main.cpp +++ b/VisualCraft/main.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/others/VisualCraft.rc.in b/VisualCraft/others/VisualCraft.rc.in index 6bdd831c..1961634a 100644 --- a/VisualCraft/others/VisualCraft.rc.in +++ b/VisualCraft/others/VisualCraft.rc.in @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -22,40 +22,30 @@ This file is part of SlopeCraft. #include -IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/VisualCraft.ico" +IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/VisualCraft.ico" -VS_VERSION_INFO VERSIONINFO - FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 - FILEFLAGSMASK 0x3fL + VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, + @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, + 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, + @PROJECT_VERSION_PATCH @, + 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000404b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "Minecraft Pixel Art Tool\0" - VALUE "FileVersion", "@PROJECT_VERSION@.0\0" - VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2023\0" - VALUE "OriginalFilename", "VisualCraft.exe\0" - VALUE "ProductName", "VisualCraft\0" - VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" - VALUE "InternalName", "VisualCraft\0" - VALUE "Comments", "Main program of VisualCraft\0" - VALUE "LegalTrademarks", "Published under GPLv3 license\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0004, 1200 - END - END - + FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN + BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE + "CompanyName", + "\0" VALUE "FileDescription", + "Minecraft Pixel Art Tool\0" VALUE "FileVersion", + "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", + "Copyright TokiNoBug 2021-2023\0" VALUE "OriginalFilename", + "VisualCraft.exe\0" VALUE "ProductName", + "VisualCraft\0" VALUE "ProductVersion", + "@PROJECT_VERSION@.0\0" VALUE "InternalName", + "VisualCraft\0" VALUE "Comments", + "Main program of VisualCraft\0" VALUE "LegalTrademarks", + "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE + "Translation", + 0x0004, 1200 END END diff --git a/VisualCraftL/BlockStateList.cpp b/VisualCraftL/BlockStateList.cpp index d3e93825..43f2a696 100644 --- a/VisualCraftL/BlockStateList.cpp +++ b/VisualCraftL/BlockStateList.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/BlockStateList.h b/VisualCraftL/BlockStateList.h index 07ff3ae1..bb59f6fa 100644 --- a/VisualCraftL/BlockStateList.h +++ b/VisualCraftL/BlockStateList.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/DirectionHandler.hpp b/VisualCraftL/DirectionHandler.hpp index 2e5c97c0..06478ede 100644 --- a/VisualCraftL/DirectionHandler.hpp +++ b/VisualCraftL/DirectionHandler.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -26,28 +26,29 @@ This file is part of SlopeCraft. #include "VisualCraftL.h" #include -template class dir_handler { -private: +template +class dir_handler { + private: std::array size_xyz{0, 0, 0}; VCL_face_t map_face; -public: + public: dir_handler() = delete; dir_handler(VCL_face_t __face, int_t rows, int_t cols, int_t depth) : map_face(__face) { switch (this->map_face) { - case VCL_face_t::face_north: - case VCL_face_t::face_south: - this->size_xyz = {cols, rows, depth}; - return; - case VCL_face_t::face_east: - case VCL_face_t::face_west: - this->size_xyz = {depth, rows, cols}; - return; - case VCL_face_t::face_up: - case VCL_face_t::face_down: - this->size_xyz = {cols, depth, rows}; - return; + case VCL_face_t::face_north: + case VCL_face_t::face_south: + this->size_xyz = {cols, rows, depth}; + return; + case VCL_face_t::face_east: + case VCL_face_t::face_west: + this->size_xyz = {depth, rows, cols}; + return; + case VCL_face_t::face_up: + case VCL_face_t::face_down: + this->size_xyz = {cols, depth, rows}; + return; } abort(); } @@ -76,34 +77,34 @@ return this->coord_when_vertical(r, c, depth); return this->coord_when_no_rot(r, c, depth); } -private: + private: std::array coord_when_no_rot(int_t r, int_t c, int_t depth) const noexcept { switch (this->map_face) { - case VCL_face_t::face_east: - return {this->size_xyz[idx_x] - depth - 1, this->size_xyz[idx_y] - r - 1, - this->size_xyz[idx_z] - c - 1}; + case VCL_face_t::face_east: + return {this->size_xyz[idx_x] - depth - 1, + this->size_xyz[idx_y] - r - 1, this->size_xyz[idx_z] - c - 1}; - case VCL_face_t::face_west: - return {depth, this->size_xyz[idx_y] - r - 1, c}; + case VCL_face_t::face_west: + return {depth, this->size_xyz[idx_y] - r - 1, c}; - case VCL_face_t::face_north: - return {this->size_xyz[idx_x] - c - 1, this->size_xyz[idx_y] - r - 1, - depth}; + case VCL_face_t::face_north: + return {this->size_xyz[idx_x] - c - 1, this->size_xyz[idx_y] - r - 1, + depth}; - case VCL_face_t::face_south: - return {c, this->size_xyz[idx_y] - r - 1, - this->size_xyz[idx_z] - depth - 1}; + case VCL_face_t::face_south: + return {c, this->size_xyz[idx_y] - r - 1, + this->size_xyz[idx_z] - depth - 1}; - case VCL_face_t::face_up: - return {c, this->size_xyz[idx_y] - depth - 1, r}; + case VCL_face_t::face_up: + return {c, this->size_xyz[idx_y] - depth - 1, r}; - case VCL_face_t::face_down: - return {c, depth, this->size_xyz[idx_z] - r - 1}; + case VCL_face_t::face_down: + return {c, depth, this->size_xyz[idx_z] - r - 1}; } abort(); return {}; } }; -#endif // SLOPECRAFT_VISUALCRAFTL_DIRECTION_HANDLER_H \ No newline at end of file +#endif // SLOPECRAFT_VISUALCRAFTL_DIRECTION_HANDLER_H \ No newline at end of file diff --git a/VisualCraftL/ParseResourcePack_blocks.cpp b/VisualCraftL/ParseResourcePack_blocks.cpp index 7c5b0c6c..ef6f97a3 100644 --- a/VisualCraftL/ParseResourcePack_blocks.cpp +++ b/VisualCraftL/ParseResourcePack_blocks.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/ParseResourcePack_json.cpp b/VisualCraftL/ParseResourcePack_json.cpp index 22652b29..4962f9c3 100644 --- a/VisualCraftL/ParseResourcePack_json.cpp +++ b/VisualCraftL/ParseResourcePack_json.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/ParseResourcePack_png.cpp b/VisualCraftL/ParseResourcePack_png.cpp index a2ad0aa1..f8450507 100644 --- a/VisualCraftL/ParseResourcePack_png.cpp +++ b/VisualCraftL/ParseResourcePack_png.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/ResourcePack.cpp b/VisualCraftL/ResourcePack.cpp index c695cf3b..30c60c2a 100644 --- a/VisualCraftL/ResourcePack.cpp +++ b/VisualCraftL/ResourcePack.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/Resource_tree.cpp b/VisualCraftL/Resource_tree.cpp index c9d93b8e..c758e197 100644 --- a/VisualCraftL/Resource_tree.cpp +++ b/VisualCraftL/Resource_tree.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/Resource_tree.h b/VisualCraftL/Resource_tree.h index b14dde60..2cf8952e 100644 --- a/VisualCraftL/Resource_tree.h +++ b/VisualCraftL/Resource_tree.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/TokiVC.cpp b/VisualCraftL/TokiVC.cpp index 56669d4d..7dc080ee 100644 --- a/VisualCraftL/TokiVC.cpp +++ b/VisualCraftL/TokiVC.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/TokiVC.h b/VisualCraftL/TokiVC.h index 7188e469..9562e779 100644 --- a/VisualCraftL/TokiVC.h +++ b/VisualCraftL/TokiVC.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/TokiVC_build.cpp b/VisualCraftL/TokiVC_build.cpp index 57de96e2..a4993785 100644 --- a/VisualCraftL/TokiVC_build.cpp +++ b/VisualCraftL/TokiVC_build.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/TokiVC_export_test.cpp b/VisualCraftL/TokiVC_export_test.cpp index f9035c5a..10f9b2d1 100644 --- a/VisualCraftL/TokiVC_export_test.cpp +++ b/VisualCraftL/TokiVC_export_test.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/TokiVC_flagdiagram.cpp b/VisualCraftL/TokiVC_flagdiagram.cpp index 419205ac..f8b396d2 100644 --- a/VisualCraftL/TokiVC_flagdiagram.cpp +++ b/VisualCraftL/TokiVC_flagdiagram.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/VisualCraftL.cpp b/VisualCraftL/VisualCraftL.cpp index 1859e9ab..6b266c6d 100644 --- a/VisualCraftL/VisualCraftL.cpp +++ b/VisualCraftL/VisualCraftL.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/VisualCraftL.h b/VisualCraftL/VisualCraftL.h index 25c2561a..d1cc2de3 100644 --- a/VisualCraftL/VisualCraftL.h +++ b/VisualCraftL/VisualCraftL.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/VisualCraftL_global.h b/VisualCraftL/VisualCraftL_global.h index 8896b51d..07a39c04 100644 --- a/VisualCraftL/VisualCraftL_global.h +++ b/VisualCraftL/VisualCraftL_global.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/others/VisualCraftL.rc.in b/VisualCraftL/others/VisualCraftL.rc.in index 5dcc5bf4..b84215c9 100644 --- a/VisualCraftL/others/VisualCraftL.rc.in +++ b/VisualCraftL/others/VisualCraftL.rc.in @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -22,39 +22,28 @@ This file is part of SlopeCraft. #include -VS_VERSION_INFO VERSIONINFO - FILEVERSION @VisualCraftL_VERSION_MAJOR@,@VisualCraftL_VERSION_MINOR@,@VisualCraftL_VERSION_PATCH@,0 - PRODUCTVERSION @VisualCraftL_VERSION_MAJOR@,@VisualCraftL_VERSION_MINOR@,@VisualCraftL_VERSION_PATCH@,0 - FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO FILEVERSION @VisualCraftL_VERSION_MAJOR @, + @VisualCraftL_VERSION_MINOR @, @VisualCraftL_VERSION_PATCH @, + 0 PRODUCTVERSION @VisualCraftL_VERSION_MAJOR @, + @VisualCraftL_VERSION_MINOR @, @VisualCraftL_VERSION_PATCH @, + 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000404b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "VisualCraft Library\0" - VALUE "FileVersion", "@VisualCraftL_VERSION@.0\0" - VALUE "LegalCopyright", "TokiNoBug\0" - VALUE "OriginalFilename", "VisualCraftL.dll\0" - VALUE "ProductName", "VisualCraftL\0" - VALUE "ProductVersion", "@VisualCraftL_VERSION@.0\0" - VALUE "InternalName", "VisualCraftL\0" - VALUE "Comments", "\0" - VALUE "LegalTrademarks", "Published under GPLv3\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0004, 1200 - END - END -/* End of Version info */ - + FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN + BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE + "CompanyName", + "\0" VALUE "FileDescription", "VisualCraft Library\0" VALUE "FileVersion", + "@VisualCraftL_VERSION@.0\0" VALUE "LegalCopyright", + "TokiNoBug\0" VALUE "OriginalFilename", + "VisualCraftL.dll\0" VALUE "ProductName", + "VisualCraftL\0" VALUE "ProductVersion", + "@VisualCraftL_VERSION@.0\0" VALUE "InternalName", + "VisualCraftL\0" VALUE "Comments", "\0" VALUE "LegalTrademarks", + "Published under GPLv3\0" END END BLOCK "VarFileInfo" BEGIN VALUE + "Translation", + 0x0004, + 1200 END END + /* End of Version info */ diff --git a/imageCutter/CutterWind.cpp b/imageCutter/CutterWind.cpp index 146086e6..cb35730c 100644 --- a/imageCutter/CutterWind.cpp +++ b/imageCutter/CutterWind.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -52,8 +52,7 @@ CutterWind::~CutterWind() { delete ui; } void CutterWind::loadImg() { QString path = QFileDialog::getOpenFileName( this, tr("选择图片"), "", tr("图片(*.png *.bmp *.jpg *.tif)")); - if (path.isEmpty()) - return; + if (path.isEmpty()) return; img.load(path); img = img.convertToFormat(QImage::Format_ARGB32); @@ -87,14 +86,12 @@ void CutterWind::updateImg() const { void CutterWind::saveImg() { QString name = QFileDialog::getSaveFileName( this, tr("保存图片"), "", tr("图片(*.png *.bmp *.jpg *.tif)")); - if (name.isEmpty()) - return; + if (name.isEmpty()) return; img.save(name); } void CutterWind::resizeImg() { - Qt::AspectRatioMode arm = Qt::AspectRatioMode(ui->boxAspectRatioMode->currentData().toInt()); Qt::TransformationMode tm = @@ -112,8 +109,7 @@ void CutterWind::cutImg() { QString dir = QFileDialog::getExistingDirectory(this, tr("选择输出文件夹"), ""); - if (dir.isEmpty()) - return; + if (dir.isEmpty()) return; dir = dir.replace("\\\\", "/"); dir = dir.replace('\\', '/'); @@ -133,8 +129,7 @@ void CutterWind::cutImg() { for (int rOffset = 0; rOffset < 128; rOffset++) { const int imgR = rOffset + 128 * mapR; const uint32_t *src = nullptr; - if (imgR < imgRN) - src = (const uint32_t *)img.constScanLine(imgR); + if (imgR < imgRN) src = (const uint32_t *)img.constScanLine(imgR); uint32_t *dst = (uint32_t *)part.scanLine(rOffset); diff --git a/imageCutter/CutterWind.h b/imageCutter/CutterWind.h index 77c04835..b49f962c 100644 --- a/imageCutter/CutterWind.h +++ b/imageCutter/CutterWind.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -35,16 +35,16 @@ QT_END_NAMESPACE class CutterWind : public QMainWindow { Q_OBJECT -public: + public: CutterWind(QWidget *parent = nullptr); ~CutterWind(); -private slots: + private slots: void loadImg(); void saveImg(); void cutImg(); -private: + private: void updateImg() const; void resizeImg(); QImage img; @@ -52,4 +52,4 @@ private slots: QString rawFileSuffix; Ui::CutterWind *ui; }; -#endif // CUTTERWIND_H +#endif // CUTTERWIND_H diff --git a/imageCutter/main.cpp b/imageCutter/main.cpp index c57ed02a..3d3ff13d 100644 --- a/imageCutter/main.cpp +++ b/imageCutter/main.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -31,7 +31,6 @@ This file is part of SlopeCraft. #include int main(int argc, char *argv[]) { - QApplication a(argc, argv); QTranslator translator; diff --git a/tests/test_libSchem/test_libSchem.cpp b/tests/test_libSchem/test_libSchem.cpp index e4a00049..060a6338 100644 --- a/tests/test_libSchem/test_libSchem.cpp +++ b/tests/test_libSchem/test_libSchem.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/BlockListManager/BLM_preset.cpp b/utilities/BlockListManager/BLM_preset.cpp index c9c70814..366178d6 100644 --- a/utilities/BlockListManager/BLM_preset.cpp +++ b/utilities/BlockListManager/BLM_preset.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/CIEDE00.cpp b/utilities/ColorManip/CIEDE00.cpp index 0e13976d..c40c7973 100644 --- a/utilities/ColorManip/CIEDE00.cpp +++ b/utilities/ColorManip/CIEDE00.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ This file is part of SlopeCraft. #include "ColorManip.h" #include -#define deg2rad(deg) ((deg)*M_PI / 180.0) -#define rad2deg(rad) ((rad)*180.0 / M_PI) +#define deg2rad(deg) ((deg) * M_PI / 180.0) +#define rad2deg(rad) ((rad) * 180.0 / M_PI) const float kL = 1.0; const float kC = 1.0; const float kH = 1.0; @@ -47,15 +47,13 @@ float Lab00_diff(float L1, float a1, float b1, float L2, float a2, h1p = 0; else h1p = std::atan2(b1, a1p); - if (h1p < 0) - h1p += 2 * M_PI; + if (h1p < 0) h1p += 2 * M_PI; if (b2 == 0 && a2p == 0) h2p = 0; else h2p = std::atan2(b2, a2p); - if (h2p < 0) - h2p += 2 * M_PI; + if (h2p < 0) h2p += 2 * M_PI; float dLp = L2 - L1; float dCp = C2p - C1p; diff --git a/utilities/ColorManip/ColorCvt.cpp b/utilities/ColorManip/ColorCvt.cpp index 6578fcc6..9025dc99 100644 --- a/utilities/ColorManip/ColorCvt.cpp +++ b/utilities/ColorManip/ColorCvt.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -30,7 +30,7 @@ This file is part of SlopeCraft. static constexpr float threshold = 1e-10f; -#define deg2rad(deg) ((deg)*M_PI / 180.0) +#define deg2rad(deg) ((deg) * M_PI / 180.0) ARGB ComposeColor(const ARGB top, const ARGB back) noexcept { int red = (getR(top) * getA(top) + getR(back) * (255 - getA(top))) / 255; @@ -47,11 +47,9 @@ ARGB ComposeColor_background_half_transparent(const ARGB top, if (alpha_back <= 0) { return top; } - if (alpha_top <= 0) - return back; + if (alpha_top <= 0) return back; - if (alpha_top >= 255) - return top; + if (alpha_top >= 255) return top; // int result_alpha = alpha_top + alpha_back - alpha_back * alpha_top / // 255; @@ -227,10 +225,8 @@ void Lab2XYZ(float L, float a, float b, float &X, float &Y, float &Z) noexcept { } inline float squeeze01(float t) noexcept { - if (t < 0.0) - return 0.0f; - if (t > 1.0) - return 1.0f; + if (t < 0.0) return 0.0f; + if (t > 1.0) return 1.0f; return t; } diff --git a/utilities/ColorManip/ColorDiff.cpp b/utilities/ColorManip/ColorDiff.cpp index 3dc3f8d4..25163fa6 100644 --- a/utilities/ColorManip/ColorDiff.cpp +++ b/utilities/ColorManip/ColorDiff.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/colorset_maptical.hpp b/utilities/ColorManip/colorset_maptical.hpp index 4c9ab3dc..f55f8ab8 100644 --- a/utilities/ColorManip/colorset_maptical.hpp +++ b/utilities/ColorManip/colorset_maptical.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/imageConvert.hpp b/utilities/ColorManip/imageConvert.hpp index 96a63c56..741b39da 100644 --- a/utilities/ColorManip/imageConvert.hpp +++ b/utilities/ColorManip/imageConvert.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/newColorSet.hpp b/utilities/ColorManip/newColorSet.hpp index e70d1177..48c2704c 100644 --- a/utilities/ColorManip/newColorSet.hpp +++ b/utilities/ColorManip/newColorSet.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/newTokiColor.hpp b/utilities/ColorManip/newTokiColor.hpp index 3bb46928..6b6dafd4 100644 --- a/utilities/ColorManip/newTokiColor.hpp +++ b/utilities/ColorManip/newTokiColor.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.cpp b/utilities/ExternalConverters/GAConverter/GAConverter.cpp index f1ad91a3..4a9b25f4 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.cpp +++ b/utilities/ExternalConverters/GAConverter/GAConverter.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/GAConverter.h b/utilities/ExternalConverters/GAConverter/GAConverter.h index a3166d16..f7111153 100644 --- a/utilities/ExternalConverters/GAConverter/GAConverter.h +++ b/utilities/ExternalConverters/GAConverter/GAConverter.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp index c023536a..cce96e97 100644 --- a/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp +++ b/utilities/ExternalConverters/GAConverter/GACvterDefines.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/sortColor.cpp b/utilities/ExternalConverters/GAConverter/sortColor.cpp index cfc11dc8..fd8db067 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.cpp +++ b/utilities/ExternalConverters/GAConverter/sortColor.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/sortColor.h b/utilities/ExternalConverters/GAConverter/sortColor.h index 4bd8bd3e..8bd8610a 100644 --- a/utilities/ExternalConverters/GAConverter/sortColor.h +++ b/utilities/ExternalConverters/GAConverter/sortColor.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/GAConverter/uiPack.h b/utilities/ExternalConverters/GAConverter/uiPack.h index c2cd22f3..edab976c 100644 --- a/utilities/ExternalConverters/GAConverter/uiPack.h +++ b/utilities/ExternalConverters/GAConverter/uiPack.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/GPUWrapper/GPU_interface.h b/utilities/GPUWrapper/GPU_interface.h index 4732113b..36050d40 100644 --- a/utilities/GPUWrapper/GPU_interface.h +++ b/utilities/GPUWrapper/GPU_interface.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/GPUWrapper/OpenCL/ColorDiff.cl b/utilities/GPUWrapper/OpenCL/ColorDiff.cl index be851441..4d126397 100644 --- a/utilities/GPUWrapper/OpenCL/ColorDiff.cl +++ b/utilities/GPUWrapper/OpenCL/ColorDiff.cl @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/GPUWrapper/OpenCL/GPU_interface.cpp b/utilities/GPUWrapper/OpenCL/GPU_interface.cpp index 2178d281..685ab0ac 100644 --- a/utilities/GPUWrapper/OpenCL/GPU_interface.cpp +++ b/utilities/GPUWrapper/OpenCL/GPU_interface.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp index 190418c0..f0ded588 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/GPUWrapper/OpenCL/OCLWrapper.h b/utilities/GPUWrapper/OpenCL/OCLWrapper.h index 79afb209..22cc375a 100644 --- a/utilities/GPUWrapper/OpenCL/OCLWrapper.h +++ b/utilities/GPUWrapper/OpenCL/OCLWrapper.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/MCDataVersion/MCDataVersion.cpp b/utilities/MCDataVersion/MCDataVersion.cpp index f7dc882a..dcac823e 100644 --- a/utilities/MCDataVersion/MCDataVersion.cpp +++ b/utilities/MCDataVersion/MCDataVersion.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/MCDataVersion/MCDataVersion.h b/utilities/MCDataVersion/MCDataVersion.h index d4c2e179..4b1e53ff 100644 --- a/utilities/MCDataVersion/MCDataVersion.h +++ b/utilities/MCDataVersion/MCDataVersion.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/MapImageCvter/MapImageCvter.cpp b/utilities/MapImageCvter/MapImageCvter.cpp index 823a7ae0..288350b7 100644 --- a/utilities/MapImageCvter/MapImageCvter.cpp +++ b/utilities/MapImageCvter/MapImageCvter.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/MapImageCvter/MapImageCvter.h b/utilities/MapImageCvter/MapImageCvter.h index 9b9c4b58..e63f86c0 100644 --- a/utilities/MapImageCvter/MapImageCvter.h +++ b/utilities/MapImageCvter/MapImageCvter.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/NBTWriter/NBTWriter.cpp b/utilities/NBTWriter/NBTWriter.cpp index d46e0e3f..0be0d782 100644 --- a/utilities/NBTWriter/NBTWriter.cpp +++ b/utilities/NBTWriter/NBTWriter.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -24,11 +24,9 @@ This file is part of SlopeCraft. #include #include - using namespace NBT::internal; bool NBTWriterBase_nocompress::open(const char *newFileName) noexcept { - if (file != nullptr) { return false; } @@ -54,7 +52,6 @@ bool NBTWriterBase_nocompress::open(const char *newFileName) noexcept { } bool NBTWriterBase_gzip::open(const char *newFileName) noexcept { - if (this->file != nullptr) { return false; } diff --git a/utilities/SC_version_buildtime.h.in b/utilities/SC_version_buildtime.h.in index 5e3a5ce0..84eeedf1 100644 --- a/utilities/SC_version_buildtime.h.in +++ b/utilities/SC_version_buildtime.h.in @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/Schem/Schem.cpp b/utilities/Schem/Schem.cpp index 22571063..c055f02d 100644 --- a/utilities/Schem/Schem.cpp +++ b/utilities/Schem/Schem.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/Schem/Schem.h b/utilities/Schem/Schem.h index 6315d7c5..d010fea1 100644 --- a/utilities/Schem/Schem.h +++ b/utilities/Schem/Schem.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/Schem/bit_shrink.cpp b/utilities/Schem/bit_shrink.cpp index bba31adb..f4724285 100644 --- a/utilities/Schem/bit_shrink.cpp +++ b/utilities/Schem/bit_shrink.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/Schem/bit_shrink.h b/utilities/Schem/bit_shrink.h index 09285334..db442687 100644 --- a/utilities/Schem/bit_shrink.h +++ b/utilities/Schem/bit_shrink.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/VersionDialog/VersionDialog.cpp b/utilities/VersionDialog/VersionDialog.cpp index 479a2fa7..b627d5f0 100644 --- a/utilities/VersionDialog/VersionDialog.cpp +++ b/utilities/VersionDialog/VersionDialog.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/VersionDialog/VersionDialog.h b/utilities/VersionDialog/VersionDialog.h index 61cefb26..56b4ec72 100644 --- a/utilities/VersionDialog/VersionDialog.h +++ b/utilities/VersionDialog/VersionDialog.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/vccl/vccl.cpp b/vccl/vccl.cpp index 6741f623..6c43b6b2 100644 --- a/vccl/vccl.cpp +++ b/vccl/vccl.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/vccl/vccl_internal.h b/vccl/vccl_internal.h index 1022d058..3984dfdf 100644 --- a/vccl/vccl_internal.h +++ b/vccl/vccl_internal.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -31,7 +31,6 @@ This file is part of SlopeCraft. #include struct inputs { - // resource std::vector zips; std::vector jsons; @@ -98,4 +97,4 @@ int list_gpu(); void list_supported_formats() noexcept; -#endif // #ifndef SLOPECRAFT_VCCL_INTERNAL_H \ No newline at end of file +#endif // #ifndef SLOPECRAFT_VCCL_INTERNAL_H \ No newline at end of file diff --git a/vccl/vccl_parse_default.cpp b/vccl/vccl_parse_default.cpp index 9363d693..d53a97e2 100644 --- a/vccl/vccl_parse_default.cpp +++ b/vccl/vccl_parse_default.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify From fc35600fdad82da0db8ece57b6a95282c674daae Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 31 Jan 2026 10:04:04 +0800 Subject: [PATCH 1118/1123] Update copyright info to 2026 Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 2 +- SlopeCraft/others/SlopeCraft_en_US.ts | 4 ++-- SlopeCraftL/SCLDefines.h | 2 +- SlopeCraftL/block_list.cpp | 2 +- SlopeCraftL/height_line.h | 2 +- SlopeCraftL/lossy_compressor.h | 2 +- SlopeCraftL/mc_block.h | 2 +- SlopeCraftL/optimize_chain.h | 2 +- SlopeCraftL/prim_glass_builder.cpp | 2 +- SlopeCraftL/prim_glass_builder.h | 2 +- SlopeCraftL/water_item.h | 2 +- VisualCraft/BiomeBrowser.h | 10 ++++---- VisualCraft/main.cpp | 2 +- VisualCraftL/ParseResourcePack.h | 2 +- VisualCraftL/VCL_internal.h | 2 +- VisualCraftL/tests/SCL_json_cvt.cpp | 5 +--- VisualCraftL/tests/VCL_json_sort.cpp | 24 +++++++++---------- VisualCraftL/tests/itest_VCL_rotate.cpp | 2 +- VisualCraftL/tests/test_VCL_blockstate.cpp | 2 +- VisualCraftL/tests/test_VCL_model.cpp | 2 +- VisualCraftL/tests/test_VCL_project_image.cpp | 2 +- VisualCraftL/tests/test_VCL_version.cpp | 3 +-- VisualCraftL/tests/test_block_class.cpp | 3 +-- tests/test_SlopeCraftL/test_SlopeCraftL.cpp | 2 +- utilities/ColorManip/ColorManip.h | 2 +- utilities/ColorManip/colorset_optical.hpp | 2 +- .../ExternalConverterStaticInterface.h | 2 +- utilities/NBTWriter/NBTWriter.h | 2 +- utilities/SC_GlobalEnums.h | 2 +- utilities/SC_aligned_alloc.hpp | 4 ++-- utilities/uiPack/uiPack.h | 14 +++++------ 31 files changed, 53 insertions(+), 60 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index a06c66b0..ee6db5ed 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -907,7 +907,7 @@ void SCWind::on_ac_about_triggered() noexcept { info += tr("本软件遵循 GPL-3.0 及以后版本 (GPL-3.0 or later) 协议开放源码。"); info += "\n\n"; info += - tr("Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, " + tr("Copyright © 2021-2026 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, " "iXOR Technology, Mifan-T, 以及贡献者). 版权所有"); QMessageBox::information(this, tr("关于 SlopeCraft"), info); } diff --git a/SlopeCraft/others/SlopeCraft_en_US.ts b/SlopeCraft/others/SlopeCraft_en_US.ts index d8947827..b392d9e3 100644 --- a/SlopeCraft/others/SlopeCraft_en_US.ts +++ b/SlopeCraft/others/SlopeCraft_en_US.ts @@ -1302,8 +1302,8 @@ Click Ignore to skip, Retry to retry and Cancel to cancel - Copyright © 2021-2023 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 - Copyright © 2021-2023 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. + Copyright © 2021-2026 SlopeCraft 开发者 (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, 以及贡献者). 版权所有 + Copyright © 2021-2026 SlopeCraft Developers (TokiNoBug, AbrasiveBoar, iXOR Technology, Mifan-T, and contributors). All rights reserved. diff --git a/SlopeCraftL/SCLDefines.h b/SlopeCraftL/SCLDefines.h index 3be45c82..8df58367 100644 --- a/SlopeCraftL/SCLDefines.h +++ b/SlopeCraftL/SCLDefines.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/block_list.cpp b/SlopeCraftL/block_list.cpp index 572a5b3e..644fd0a4 100644 --- a/SlopeCraftL/block_list.cpp +++ b/SlopeCraftL/block_list.cpp @@ -1,5 +1,5 @@ /* -Copyright © 2021-2023 TokiNoBug +Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/height_line.h b/SlopeCraftL/height_line.h index 86ec7515..f2ce8a81 100644 --- a/SlopeCraftL/height_line.h +++ b/SlopeCraftL/height_line.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/lossy_compressor.h b/SlopeCraftL/lossy_compressor.h index 0a69e3be..971e59e3 100644 --- a/SlopeCraftL/lossy_compressor.h +++ b/SlopeCraftL/lossy_compressor.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/mc_block.h b/SlopeCraftL/mc_block.h index 085f348d..e5ea09cb 100644 --- a/SlopeCraftL/mc_block.h +++ b/SlopeCraftL/mc_block.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/optimize_chain.h b/SlopeCraftL/optimize_chain.h index 8eacba32..75f4b6d1 100644 --- a/SlopeCraftL/optimize_chain.h +++ b/SlopeCraftL/optimize_chain.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/prim_glass_builder.cpp b/SlopeCraftL/prim_glass_builder.cpp index 662486bb..89ae942c 100644 --- a/SlopeCraftL/prim_glass_builder.cpp +++ b/SlopeCraftL/prim_glass_builder.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/prim_glass_builder.h b/SlopeCraftL/prim_glass_builder.h index 6b038ab8..2956e4cc 100644 --- a/SlopeCraftL/prim_glass_builder.h +++ b/SlopeCraftL/prim_glass_builder.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/SlopeCraftL/water_item.h b/SlopeCraftL/water_item.h index d1eb2a58..4bbe1ecd 100644 --- a/SlopeCraftL/water_item.h +++ b/SlopeCraftL/water_item.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraft/BiomeBrowser.h b/VisualCraft/BiomeBrowser.h index da7eb952..49620178 100644 --- a/VisualCraft/BiomeBrowser.h +++ b/VisualCraft/BiomeBrowser.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -30,17 +30,17 @@ class BiomeBrowser; class BiomeBrowser : public QWidget { Q_OBJECT -private: + private: Ui::BiomeBrowser *ui; -public: + public: BiomeBrowser(QWidget *parent); ~BiomeBrowser(); -private: + private: VCL_biome_t biome_selected() const noexcept; bool is_grass_selected() const noexcept; -private slots: + private slots: void when_biome_changed() noexcept; void refresh_colormap() noexcept; }; \ No newline at end of file diff --git a/VisualCraft/main.cpp b/VisualCraft/main.cpp index 57cbeddc..69cafe95 100644 --- a/VisualCraft/main.cpp +++ b/VisualCraft/main.cpp @@ -112,7 +112,7 @@ int main(int argc, char **argv) { VCL_set_report_callback(VC_callback::callback_receive_report); wind.setWindowTitle( - QStringLiteral("VisualCraft v%1 Copyright © 2021-2023 TokiNoBug") + QStringLiteral("VisualCraft v%1 Copyright © 2021-2026 TokiNoBug") .arg(SC_VERSION_STR)); wind.show(); diff --git a/VisualCraftL/ParseResourcePack.h b/VisualCraftL/ParseResourcePack.h index 5555ca38..ee65c2d9 100644 --- a/VisualCraftL/ParseResourcePack.h +++ b/VisualCraftL/ParseResourcePack.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/VCL_internal.h b/VisualCraftL/VCL_internal.h index 9b87511f..410012a0 100644 --- a/VisualCraftL/VCL_internal.h +++ b/VisualCraftL/VCL_internal.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/tests/SCL_json_cvt.cpp b/VisualCraftL/tests/SCL_json_cvt.cpp index 124927ce..66f34424 100644 --- a/VisualCraftL/tests/SCL_json_cvt.cpp +++ b/VisualCraftL/tests/SCL_json_cvt.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -29,7 +29,6 @@ using std::cout, std::endl; using njson = nlohmann::json; njson &get_scl_block_list(njson &scl) noexcept { - if (scl.contains("FixedBlocks") && scl.at("FixedBlocks").is_array()) { return scl.at("FixedBlocks"); } @@ -39,14 +38,12 @@ njson &get_scl_block_list(njson &scl) noexcept { void try_copy_trait(std::string_view trait_name, const njson &obj_scl, njson &obj_vcl) { - if (obj_scl.contains(trait_name)) { obj_vcl.emplace(trait_name, obj_scl.at(trait_name)); } } int main(int argc, char **argv) { - if (argc != 3) { cout << "Usage : SCL_json_cvt [SCL json file] [VCL json file]" << endl; return 1; diff --git a/VisualCraftL/tests/VCL_json_sort.cpp b/VisualCraftL/tests/VCL_json_sort.cpp index 7334d64f..6f0dc0de 100644 --- a/VisualCraftL/tests/VCL_json_sort.cpp +++ b/VisualCraftL/tests/VCL_json_sort.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -82,17 +82,17 @@ int main(int argc, char **argv) { } switch (block_class) { - case VCL_block_class_t::concrete: - // case VCL_block_class_t::concrete_powder: - case VCL_block_class_t::glazed_terracotta: - case VCL_block_class_t::wool: - case VCL_block_class_t::shulker_box: - case VCL_block_class_t::terracotta: - it.value()["background"] = true; - break; - - default: - break; + case VCL_block_class_t::concrete: + // case VCL_block_class_t::concrete_powder: + case VCL_block_class_t::glazed_terracotta: + case VCL_block_class_t::wool: + case VCL_block_class_t::shulker_box: + case VCL_block_class_t::terracotta: + it.value()["background"] = true; + break; + + default: + break; } } diff --git a/VisualCraftL/tests/itest_VCL_rotate.cpp b/VisualCraftL/tests/itest_VCL_rotate.cpp index 2aa44a71..38b45318 100644 --- a/VisualCraftL/tests/itest_VCL_rotate.cpp +++ b/VisualCraftL/tests/itest_VCL_rotate.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/tests/test_VCL_blockstate.cpp b/VisualCraftL/tests/test_VCL_blockstate.cpp index 54eac48e..bc72f29b 100644 --- a/VisualCraftL/tests/test_VCL_blockstate.cpp +++ b/VisualCraftL/tests/test_VCL_blockstate.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/tests/test_VCL_model.cpp b/VisualCraftL/tests/test_VCL_model.cpp index fd983389..311dc925 100644 --- a/VisualCraftL/tests/test_VCL_model.cpp +++ b/VisualCraftL/tests/test_VCL_model.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/tests/test_VCL_project_image.cpp b/VisualCraftL/tests/test_VCL_project_image.cpp index c7a149db..92c08821 100644 --- a/VisualCraftL/tests/test_VCL_project_image.cpp +++ b/VisualCraftL/tests/test_VCL_project_image.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/VisualCraftL/tests/test_VCL_version.cpp b/VisualCraftL/tests/test_VCL_version.cpp index 8faa39b8..bd7f947c 100644 --- a/VisualCraftL/tests/test_VCL_version.cpp +++ b/VisualCraftL/tests/test_VCL_version.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -26,7 +26,6 @@ This file is part of SlopeCraft. #include int main() { - std::string_view ver_str_1 = VCL_version_string(); std::string ver_str_2; diff --git a/VisualCraftL/tests/test_block_class.cpp b/VisualCraftL/tests/test_block_class.cpp index 02654f52..a20dd187 100644 --- a/VisualCraftL/tests/test_block_class.cpp +++ b/VisualCraftL/tests/test_block_class.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -25,7 +25,6 @@ This file is part of SlopeCraft. #include int main(int, char **) { - const char *arr[] = {"wood", "planks", "leaves", diff --git a/tests/test_SlopeCraftL/test_SlopeCraftL.cpp b/tests/test_SlopeCraftL/test_SlopeCraftL.cpp index 02fec93e..54bcd40c 100644 --- a/tests/test_SlopeCraftL/test_SlopeCraftL.cpp +++ b/tests/test_SlopeCraftL/test_SlopeCraftL.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/ColorManip.h b/utilities/ColorManip/ColorManip.h index 19e0f9fc..2ba5ce30 100644 --- a/utilities/ColorManip/ColorManip.h +++ b/utilities/ColorManip/ColorManip.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ColorManip/colorset_optical.hpp b/utilities/ColorManip/colorset_optical.hpp index 8b4fa58d..81a3a752 100644 --- a/utilities/ColorManip/colorset_optical.hpp +++ b/utilities/ColorManip/colorset_optical.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/ExternalConverters/ExternalConverterStaticInterface.h b/utilities/ExternalConverters/ExternalConverterStaticInterface.h index c9f66a95..28f964cc 100644 --- a/utilities/ExternalConverters/ExternalConverterStaticInterface.h +++ b/utilities/ExternalConverters/ExternalConverterStaticInterface.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/NBTWriter/NBTWriter.h b/utilities/NBTWriter/NBTWriter.h index 18c02433..db7e6d25 100644 --- a/utilities/NBTWriter/NBTWriter.h +++ b/utilities/NBTWriter/NBTWriter.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/SC_GlobalEnums.h b/utilities/SC_GlobalEnums.h index 630d01bd..cf0cbaef 100644 --- a/utilities/SC_GlobalEnums.h +++ b/utilities/SC_GlobalEnums.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify diff --git a/utilities/SC_aligned_alloc.hpp b/utilities/SC_aligned_alloc.hpp index 3d16d092..f490cf47 100644 --- a/utilities/SC_aligned_alloc.hpp +++ b/utilities/SC_aligned_alloc.hpp @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -41,4 +41,4 @@ inline void SC_aligned_free(void *ptr) noexcept { #endif } -#endif // SLOPECRAFT_UTITILITIES_ALIGNED_ALLOC_HPP \ No newline at end of file +#endif // SLOPECRAFT_UTITILITIES_ALIGNED_ALLOC_HPP \ No newline at end of file diff --git a/utilities/uiPack/uiPack.h b/utilities/uiPack/uiPack.h index 7c60d3e8..46f4ad59 100644 --- a/utilities/uiPack/uiPack.h +++ b/utilities/uiPack/uiPack.h @@ -1,5 +1,5 @@ /* - Copyright © 2021-2023 TokiNoBug + Copyright © 2021-2026 TokiNoBug This file is part of SlopeCraft. SlopeCraft is free software: you can redistribute it and/or modify @@ -24,20 +24,18 @@ This file is part of SlopeCraft. #define SCL_UIPACK_UIPACK_H struct uiPack { -public: + public: void *_uiPtr{nullptr}; void (*progressRangeSet)(void *, int, int, int){nullptr}; void (*progressAdd)(void *, int){nullptr}; -public: + public: inline void rangeSet(int a, int b, int c) const noexcept { - if (progressRangeSet != nullptr) - progressRangeSet(_uiPtr, a, b, c); + if (progressRangeSet != nullptr) progressRangeSet(_uiPtr, a, b, c); } inline void add(int d) const noexcept { - if (progressAdd != nullptr) - progressAdd(_uiPtr, d); + if (progressAdd != nullptr) progressAdd(_uiPtr, d); } }; -#endif // SCL_UIPACK_UIPACK_H +#endif // SCL_UIPACK_UIPACK_H From 05299e1fde9582e4864a90cba49c05e67159c981 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 31 Jan 2026 10:08:10 +0800 Subject: [PATCH 1119/1123] Fix .rc changes Signed-off-by: ToKiNoBug --- SlopeCraft/others/SlopeCraft.rc.in | 56 +++++++++++++++----------- SlopeCraftL/others/SlopeCraftL.rc.in | 55 +++++++++++++++---------- VisualCraft/others/VisualCraft.rc.in | 56 +++++++++++++++----------- VisualCraftL/others/VisualCraftL.rc.in | 55 +++++++++++++++---------- 4 files changed, 132 insertions(+), 90 deletions(-) diff --git a/SlopeCraft/others/SlopeCraft.rc.in b/SlopeCraft/others/SlopeCraft.rc.in index 014200e1..0ac37af6 100644 --- a/SlopeCraft/others/SlopeCraft.rc.in +++ b/SlopeCraft/others/SlopeCraft.rc.in @@ -22,30 +22,40 @@ This file is part of SlopeCraft. #include -IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/SlopeCraftIconNew.ico" +IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/SlopeCraftIconNew.ico" - VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, - @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, - 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, - @PROJECT_VERSION_PATCH @, - 0 FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN - BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE - "CompanyName", - "\0" VALUE "FileDescription", - "Minecraft Map Pixel Art Tool\0" VALUE "FileVersion", - "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", - "Copyright TokiNoBug 2021-2023\0" VALUE "OriginalFilename", - "SlopeCraft.exe\0" VALUE "ProductName", - "SlopeCraft\0" VALUE "ProductVersion", - "@PROJECT_VERSION@.0\0" VALUE "InternalName", - "SlopeCraft\0" VALUE "Comments", - "Main program of SlopeCraft\0" VALUE "LegalTrademarks", - "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE - "Translation", - 0x0004, 1200 END END + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000404b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Minecraft Map Pixel Art Tool\0" + VALUE "FileVersion", "@PROJECT_VERSION@.0\0" + VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2026\0" + VALUE "OriginalFilename", "SlopeCraft.exe\0" + VALUE "ProductName", "SlopeCraft\0" + VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" + VALUE "InternalName", "SlopeCraft\0" + VALUE "Comments", "Main program of SlopeCraft\0" + VALUE "LegalTrademarks", "Published under GPLv3 license\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0004, 1200 + END + END + diff --git a/SlopeCraftL/others/SlopeCraftL.rc.in b/SlopeCraftL/others/SlopeCraftL.rc.in index bcc5d773..bbd10fdb 100644 --- a/SlopeCraftL/others/SlopeCraftL.rc.in +++ b/SlopeCraftL/others/SlopeCraftL.rc.in @@ -22,28 +22,39 @@ This file is part of SlopeCraft. #include -VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, - @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, - 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, - @PROJECT_VERSION_PATCH @, - 0 FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN - BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE - "CompanyName", - "\0" VALUE "FileDescription", "SlopeCraft Library\0" VALUE "FileVersion", - "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", - "TokiNoBug\0" VALUE "OriginalFilename", - "SlopeCraftL.dll\0" VALUE "ProductName", - "SlopeCraftL\0" VALUE "ProductVersion", - "@PROJECT_VERSION@.0\0" VALUE "InternalName", - "SlopeCraftL\0" VALUE "Comments", "\0" VALUE "LegalTrademarks", - "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE - "Translation", - 0x0004, - 1200 END END - /* End of Version info */ + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000404b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "SlopeCraft Library\0" + VALUE "FileVersion", "@PROJECT_VERSION@.0\0" + VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2026\0" + VALUE "OriginalFilename", "SlopeCraftL.dll\0" + VALUE "ProductName", "SlopeCraftL\0" + VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" + VALUE "InternalName", "SlopeCraftL\0" + VALUE "Comments", "\0" + VALUE "LegalTrademarks", "Published under GPLv3 license\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0004, 1200 + END + END +/* End of Version info */ + diff --git a/VisualCraft/others/VisualCraft.rc.in b/VisualCraft/others/VisualCraft.rc.in index 1961634a..87c66194 100644 --- a/VisualCraft/others/VisualCraft.rc.in +++ b/VisualCraft/others/VisualCraft.rc.in @@ -22,30 +22,40 @@ This file is part of SlopeCraft. #include -IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/VisualCraft.ico" +IDI_ICON1 ICON "@CMAKE_CURRENT_SOURCE_DIR@/others/VisualCraft.ico" - VS_VERSION_INFO VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR @, - @PROJECT_VERSION_MINOR @, @PROJECT_VERSION_PATCH @, - 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR @, @PROJECT_VERSION_MINOR @, - @PROJECT_VERSION_PATCH @, - 0 FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN - BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE - "CompanyName", - "\0" VALUE "FileDescription", - "Minecraft Pixel Art Tool\0" VALUE "FileVersion", - "@PROJECT_VERSION@.0\0" VALUE "LegalCopyright", - "Copyright TokiNoBug 2021-2023\0" VALUE "OriginalFilename", - "VisualCraft.exe\0" VALUE "ProductName", - "VisualCraft\0" VALUE "ProductVersion", - "@PROJECT_VERSION@.0\0" VALUE "InternalName", - "VisualCraft\0" VALUE "Comments", - "Main program of VisualCraft\0" VALUE "LegalTrademarks", - "Published under GPLv3 license\0" END END BLOCK "VarFileInfo" BEGIN VALUE - "Translation", - 0x0004, 1200 END END + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000404b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Minecraft Pixel Art Tool\0" + VALUE "FileVersion", "@PROJECT_VERSION@.0\0" + VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2026\0" + VALUE "OriginalFilename", "VisualCraft.exe\0" + VALUE "ProductName", "VisualCraft\0" + VALUE "ProductVersion", "@PROJECT_VERSION@.0\0" + VALUE "InternalName", "VisualCraft\0" + VALUE "Comments", "Main program of VisualCraft\0" + VALUE "LegalTrademarks", "Published under GPLv3 license\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0004, 1200 + END + END + diff --git a/VisualCraftL/others/VisualCraftL.rc.in b/VisualCraftL/others/VisualCraftL.rc.in index b84215c9..dc788e2e 100644 --- a/VisualCraftL/others/VisualCraftL.rc.in +++ b/VisualCraftL/others/VisualCraftL.rc.in @@ -22,28 +22,39 @@ This file is part of SlopeCraft. #include -VS_VERSION_INFO VERSIONINFO FILEVERSION @VisualCraftL_VERSION_MAJOR @, - @VisualCraftL_VERSION_MINOR @, @VisualCraftL_VERSION_PATCH @, - 0 PRODUCTVERSION @VisualCraftL_VERSION_MAJOR @, - @VisualCraftL_VERSION_MINOR @, @VisualCraftL_VERSION_PATCH @, - 0 FILEFLAGSMASK 0x3fL +VS_VERSION_INFO VERSIONINFO + FILEVERSION @VisualCraftL_VERSION_MAJOR@,@VisualCraftL_VERSION_MINOR@,@VisualCraftL_VERSION_PATCH@,0 + PRODUCTVERSION @VisualCraftL_VERSION_MAJOR@,@VisualCraftL_VERSION_MINOR@,@VisualCraftL_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0x0L #endif - FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN - BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000404b0" BEGIN VALUE - "CompanyName", - "\0" VALUE "FileDescription", "VisualCraft Library\0" VALUE "FileVersion", - "@VisualCraftL_VERSION@.0\0" VALUE "LegalCopyright", - "TokiNoBug\0" VALUE "OriginalFilename", - "VisualCraftL.dll\0" VALUE "ProductName", - "VisualCraftL\0" VALUE "ProductVersion", - "@VisualCraftL_VERSION@.0\0" VALUE "InternalName", - "VisualCraftL\0" VALUE "Comments", "\0" VALUE "LegalTrademarks", - "Published under GPLv3\0" END END BLOCK "VarFileInfo" BEGIN VALUE - "Translation", - 0x0004, - 1200 END END - /* End of Version info */ + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000404b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "VisualCraft Library\0" + VALUE "FileVersion", "@VisualCraftL_VERSION@.0\0" + VALUE "LegalCopyright", "Copyright TokiNoBug 2021-2026\0" + VALUE "OriginalFilename", "VisualCraftL.dll\0" + VALUE "ProductName", "VisualCraftL\0" + VALUE "ProductVersion", "@VisualCraftL_VERSION@.0\0" + VALUE "InternalName", "VisualCraftL\0" + VALUE "Comments", "\0" + VALUE "LegalTrademarks", "Published under GPLv3\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0004, 1200 + END + END +/* End of Version info */ + From 9d86075f0f87f0a55fd060b9521b2dd2694826b6 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Sat, 31 Jan 2026 10:15:51 +0800 Subject: [PATCH 1120/1123] lupdate Signed-off-by: ToKiNoBug --- VisualCraft/others/VisualCraft_en_US.ts | 131 ++++++++++++------------ imageCutter/imageCutter_en_US.ts | 16 +-- 2 files changed, 71 insertions(+), 76 deletions(-) diff --git a/VisualCraft/others/VisualCraft_en_US.ts b/VisualCraft/others/VisualCraft_en_US.ts index 0e5abd65..c3596a71 100644 --- a/VisualCraft/others/VisualCraft_en_US.ts +++ b/VisualCraft/others/VisualCraft_en_US.ts @@ -379,312 +379,307 @@ If you select a block in "Avaliable blocks" page, the other page will Select images - - 显示原始尺寸 - Original size - - - + 调色算法 Convertion algorithm - + 抖动 Dithering - + 显示原图 Display original - + 显示转化后图像 Display converted + - 导出 Export - + 图像 Image - + 大小(行,列) Size (rows, cols) - + 生成litematica Litematica file - + 生成结构方块文件 Structure file - + 生成WE原理图 WE schem file - + 生成转化后图像 Converted image - + 生成平面示意图 Flat diagram - + 进度 Progress - + 导出类型 Export type - + litematic投影 Litematica - + 原版结构方块文件 Vanilla structure - + WorldEdit原理图 WorldEdit schematic - + 转化后图像 Converted image - + 平面示意图 Flat diagram - + 开始执行 Start - + 设置导出位置 Set export directory - + 平面示意图(*.png) Flat diagram(*.png) - + png压缩级别: png compress level: - - + + 方块 blocks - - + + 间距: margin: - + 垂直分隔线 Vertical split line - + 水平分隔线 Horizontal split line - + png压缩内存级别: png compress memory level: - + 联系开发者 Contact developer - + 关于VisualCraft About VisualCraft - + 反馈bug Report bugs - - + + Github仓库 Github repository - + bilibili ? bilibili - + 生成测试投影 Generate testing litematic - + 查看所有颜色 Browse all colors - + 查看可用颜色 Browse avaliable colors - + 检查更新 Check updates - + 刷新警告信息 Flush warnings - + 使用教程 Tutorial - + 原版结构方块文件(*.nbt) Vanilla structure(*.nbt) - + 用结构空位表示空气 Use structure void as air - + Litematica投影(*.litematic) Litematica file (*.litematic) - + 导出选项 Export options - + 区域名称 Region name - + 投影名称(非文件名) Schematic name(not file name) - + WorldEdit原理图(*.schem) (仅1.13+) WorldEdit schematic(*schem) (1.13+ only) - + 名称(非文件名) Name (not file name) - + 需要的mod名(一行一个,默认为空) Required mods (one mod in one line) - + 显卡设置 GPU settings - + 计算设置 Computation settings - + CPU线程数: CPU threads: - + 选择计算设备 Select compute device - + 测试 Test - + 查看 Browse - + 资源 Resources - + 关于 About - + 方块 Blocks - + 加载资源 Load resources - + 设置可用的方块 Set avaliable blocks - + 生物群系 Biomes diff --git a/imageCutter/imageCutter_en_US.ts b/imageCutter/imageCutter_en_US.ts index 741fdf64..8ff4e6df 100644 --- a/imageCutter/imageCutter_en_US.ts +++ b/imageCutter/imageCutter_en_US.ts @@ -10,7 +10,7 @@ - + cols @@ -21,7 +21,7 @@ - + 图片尺寸(方块): Image size (blocks) : @@ -62,7 +62,7 @@ - + 保存图片 Save image @@ -97,28 +97,28 @@ Select image - + 打开图片失败 Failed to load image - + 图片格式损坏,或者图片过于巨大。 The image might be damaged, or it's too huge. - + 行 , rows, - + 选择输出文件夹 Select output directory - + 图片(*.png *.bmp *.jpg *.tif) From 584b4e10be449305057a1d6b29cf2adf45dea876 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 23 Feb 2026 21:15:25 +0800 Subject: [PATCH 1121/1123] SC: Fix sizing policy Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind.ui | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/SlopeCraft/SCWind.ui b/SlopeCraft/SCWind.ui index f0979762..65fc90d1 100644 --- a/SlopeCraft/SCWind.ui +++ b/SlopeCraft/SCWind.ui @@ -384,7 +384,7 @@ 导入图像并转化 - + @@ -472,6 +472,12 @@ + + + 0 + 0 + + 删除 @@ -486,6 +492,12 @@ + + + 0 + 0 + + 添加 @@ -496,6 +508,12 @@ true + + + 0 + 0 + + 显示缩略图 @@ -506,6 +524,12 @@ + + + 0 + 0 + + 替换 From 929f6120b4c04155a2d4e3891aec92e6c5dec840 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 23 Feb 2026 21:20:11 +0800 Subject: [PATCH 1122/1123] VC: Fix resizing Signed-off-by: ToKiNoBug --- VisualCraft/VCWind.cpp | 3 ++- VisualCraft/VCWind.ui | 56 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/VisualCraft/VCWind.cpp b/VisualCraft/VCWind.cpp index 51b3da41..bf0ba3c6 100644 --- a/VisualCraft/VCWind.cpp +++ b/VisualCraft/VCWind.cpp @@ -780,7 +780,8 @@ void VCWind::show_image(decltype(image_cache)::iterator it) noexcept { nullptr, nullptr, false); it->second.second = img; - this->ui->lable_converted->setPixmap(QPixmap::fromImage(img)); + const auto size = this->ui->lable_converted->size().shrunkBy(margin); + this->ui->lable_converted->setPixmap(QPixmap::fromImage(img).scaled(size, Qt::KeepAspectRatio, Qt::FastTransformation)); } void VCWind::on_lw_image_files_itemClicked(QListWidgetItem *item) noexcept { diff --git a/VisualCraft/VCWind.ui b/VisualCraft/VCWind.ui index 3453fa3f..8e74358f 100644 --- a/VisualCraft/VCWind.ui +++ b/VisualCraft/VCWind.ui @@ -474,7 +474,7 @@ 选择图片 - + @@ -486,8 +486,8 @@ - 0 - 0 + 1 + 1 @@ -523,6 +523,12 @@ + + + 0 + 0 + + 抖动 @@ -530,6 +536,12 @@ + + + 0 + 0 + + HSV @@ -537,6 +549,12 @@ + + + 0 + 0 + + RGB @@ -547,6 +565,12 @@ + + + 0 + 0 + + Lab00(CIEDE00) @@ -554,6 +578,12 @@ + + + 0 + 0 + + RGB+ @@ -561,6 +591,12 @@ + + + 0 + 0 + + Lab94(CIEDE94) @@ -568,6 +604,12 @@ + + + 0 + 0 + + XYZ @@ -579,9 +621,9 @@ - + 0 - 0 + 1 @@ -608,8 +650,8 @@ - 0 - 0 + 1 + 1 From 0668e2fd04e3fe182b5af3d7753eb715b20cf267 Mon Sep 17 00:00:00 2001 From: ToKiNoBug Date: Mon, 23 Feb 2026 21:32:47 +0800 Subject: [PATCH 1123/1123] SC & VC: remove redundant Close and abort Signed-off-by: ToKiNoBug --- SlopeCraft/SCWind_slots.cpp | 19 ++---- VisualCraft/ColorBrowser.cpp | 28 ++------ VisualCraft/VCWind_export.cpp | 122 ++++++++++++---------------------- 3 files changed, 54 insertions(+), 115 deletions(-) diff --git a/SlopeCraft/SCWind_slots.cpp b/SlopeCraft/SCWind_slots.cpp index ee6db5ed..b1cf8789 100644 --- a/SlopeCraft/SCWind_slots.cpp +++ b/SlopeCraft/SCWind_slots.cpp @@ -38,18 +38,13 @@ void SCWind::on_pb_add_image_clicked() noexcept { auto task_res = cvt_task::load(filename); if (!task_res) { - auto ret = QMessageBox::critical( + auto ret [[maybe_unused]] = QMessageBox::critical( this, tr("打开图像失败"), tr("无法打开图像 %1。\n详细信息: %2") .arg(filename, task_res.error()), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}); + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}); - if (ret == QMessageBox::Ignore) { - continue; - } else { - abort(); - } + continue; } auto task = std::move(task_res.value()); @@ -120,18 +115,14 @@ void SCWind::on_pb_replace_image_clicked() noexcept { auto task_res = cvt_task::load(file); if (!task_res) { - auto ret = QMessageBox::critical( + auto ret[[maybe_unused]] = QMessageBox::critical( this, tr("打开图像失败"), tr("无法打开图像 %1。常见原因:图像尺寸太大。\n详细信息: %2") .arg(file, task_res.error()), QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, QMessageBox::StandardButton::Ignore}); - if (ret == QMessageBox::Ignore) { - return; - } else { - abort(); - } + return; } for (const auto &qmi : selected) { this->tasks[qmi.row()] = std::move(task_res.value()); diff --git a/VisualCraft/ColorBrowser.cpp b/VisualCraft/ColorBrowser.cpp index 0d78f3b5..3cc5d49e 100644 --- a/VisualCraft/ColorBrowser.cpp +++ b/VisualCraft/ColorBrowser.cpp @@ -131,7 +131,7 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, color_id_list[idx], pair.first.data(), &pair.second); if (num <= 0) { - const auto ret = QMessageBox::warning( + const auto ret[[maybe_unused]] = QMessageBox::warning( this, ColorBrowser::tr("获取颜色表失败"), ColorBrowser::tr( "在尝试获取第%1个颜色(color_id = " @@ -140,18 +140,12 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, .arg(idx) .arg(color_id_list[idx]) .arg(num), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, - QMessageBox::StandardButton::Close}, + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, QMessageBox::StandardButton::Ignore); - if (ret == QMessageBox::StandardButton::Close) { - abort(); - return; - } else { // ignore the error pair.first.resize(0); continue; - } } pair.first.resize(num); @@ -169,19 +163,13 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, VCL_model *const model = VCL_get_block_model(pair.first, VCL_get_resource_pack()); if (model == nullptr) { - const auto ret = QMessageBox::warning( + const auto ret[[maybe_unused]] = QMessageBox::warning( this, ColorBrowser::tr("计算投影图像失败"), ColorBrowser::tr("在尝试获取方块 \"%1\" 的方块模型时出现错误。") .arg(QString::fromUtf8(VCL_get_block_id(pair.first))), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, - QMessageBox::StandardButton::Close}, + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, QMessageBox::StandardButton::Ignore); - if (ret == QMessageBox::StandardButton::Close) { - abort(); - return; - } - pair.second = std::move(proj); continue; } @@ -196,15 +184,9 @@ void ColorBrowser::setup_table(const uint16_t *const color_id_list, ColorBrowser::tr( "成功获取到方块 \"%1\" 的方块模型,但计算投影图像失败。") .arg(QString::fromUtf8(VCL_get_block_id(pair.first))), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore, - QMessageBox::StandardButton::Close}, + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, QMessageBox::StandardButton::Ignore); - if (ret == QMessageBox::StandardButton::Close) { - abort(); - return; - } - pair.second = std::move(proj); VCL_destroy_block_model(model); continue; diff --git a/VisualCraft/VCWind_export.cpp b/VisualCraft/VCWind_export.cpp index 61401cec..9d78d6cd 100644 --- a/VisualCraft/VCWind_export.cpp +++ b/VisualCraft/VCWind_export.cpp @@ -176,15 +176,11 @@ bool VCWind::export_lite(const QString &lite_dest, VCWind::tr("VisualCraftL 不能为图像\"%1\"生成投影文件\"%2\"。") .arg(image_filename) .arg(lite_dest), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Ignore) { - return false; - } else { - abort(); - return false; - } + QMessageBox::StandardButtons{ + QMessageBox::StandardButton::Ignore + }, + QMessageBox::StandardButton::Ignore); + return false; } return true; } @@ -200,15 +196,11 @@ bool VCWind::export_structure(const QString &nbt_dest, VCWind::tr("VisualCraftL 不能为图像\"%1\"生成结构方块文件\"%2\"。") .arg(image_filename) .arg(nbt_dest), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Ignore) { - return false; - } else { - abort(); - return false; - } + QMessageBox::StandardButtons{ + QMessageBox::StandardButton::Ignore + }, + QMessageBox::StandardButton::Ignore); + return false; } return true; } @@ -237,21 +229,17 @@ bool VCWind::export_schem(const QString &schem_dest, this->ui->pte_weschem_name->toPlainText().toUtf8().data(), mods_charp.data(), mods_charp.size()); if (!success) { - const auto ret = QMessageBox::critical( - this, VCWind::tr("导出 World Edit 原理图失败"), - VCWind::tr( - "VisualCraftL 不能为图像\"%1\"生成 World Edit 原理图\"%2\"。") - .arg(image_filename) - .arg(schem_dest), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Ignore) { - return false; - } else { - abort(); + const auto ret[[maybe_unused]] = QMessageBox::critical( + this, VCWind::tr("导出 World Edit 原理图失败"), + VCWind::tr( + "VisualCraftL 不能为图像\"%1\"生成 World Edit 原理图\"%2\"。") + .arg(image_filename) + .arg(schem_dest), + QMessageBox::StandardButtons{ + QMessageBox::StandardButton::Ignore + }, + QMessageBox::StandardButton::Ignore); return false; - } } return true; } @@ -260,18 +248,12 @@ bool VCWind::export_converted(const QString &converted_image_dest_path, const QImage &new_img) noexcept { bool success = new_img.save(converted_image_dest_path); if (!success) { - const auto ret = QMessageBox::critical( - this, VCWind::tr("保存转化后图像失败"), - VCWind::tr("QImage 未能生成\"%1\"。").arg(converted_image_dest_path), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Ignore) { + const auto ret [[maybe_unused]] = QMessageBox::critical( + this, VCWind::tr("保存转化后图像失败"), + VCWind::tr("QImage 未能生成\"%1\"。").arg(converted_image_dest_path), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, + QMessageBox::StandardButton::Ignore); return false; - } else { - abort(); - return false; - } } return true; } @@ -279,20 +261,15 @@ bool VCWind::export_converted(const QString &converted_image_dest_path, bool VCWind::export_flatdiagram(const QString &diagram_dest) noexcept { const QStringList qsl = diagram_dest.split(';'); if (qsl.size() not_eq VCL_get_max_block_layers()) { - const auto ret = QMessageBox::critical( - this, VCWind::tr("平面示意图输入错误"), - VCWind::tr("应输入%1个以\";\"分隔的文件名,但实际上输入了%" - "2 个。\n您输入的%2个文件名是:\n%3") - .arg(VCL_get_max_block_layers()) - .arg(qsl.size()) - .arg(diagram_dest), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}); - if (ret == QMessageBox::StandardButton::Ignore) { + const auto ret [[maybe_unused]] = QMessageBox::critical( + this, VCWind::tr("平面示意图输入错误"), + VCWind::tr("应输入%1个以\";\"分隔的文件名,但实际上输入了%" + "2 个。\n您输入的%2个文件名是:\n%3") + .arg(VCL_get_max_block_layers()) + .arg(qsl.size()) + .arg(diagram_dest), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}); return false; - } - abort(); - return false; } VCL_Kernel::flag_diagram_option option; @@ -320,19 +297,14 @@ bool VCWind::export_flatdiagram(const QString &diagram_dest) noexcept { qsl[l].toLocal8Bit().data(), option, l); if (!ok) { - const auto ret = QMessageBox::critical( - this, VCWind::tr("导出平面示意图失败"), - VCWind::tr("尝试为原图生成第%1个平面示意图(%2)时出现了错误。") - .arg(l) - .arg(qsl[l]), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}); - - if (ret == QMessageBox::StandardButton::Ignore) { + const auto ret [[maybe_unused]] = QMessageBox::critical( + this, VCWind::tr("导出平面示意图失败"), + VCWind::tr("尝试为原图生成第%1个平面示意图(%2)时出现了错误。") + .arg(l) + .arg(qsl[l]), + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}); + return false; - } - abort(); - return true; } } @@ -431,19 +403,13 @@ void VCWind::on_pb_execute_clicked() noexcept { success = this->kernel->build(); if (!success) { - const auto ret = QMessageBox::critical( - this, VCWind::tr("构建三维结构失败"), + const auto ret[[maybe_unused]] = QMessageBox::critical( + this, VCWind::tr("构建三维结构失败"), VCWind::tr("VisualCraftL 不能为图像\"%1\"构建三维结构。") .arg(image_filename), - QMessageBox::StandardButtons{QMessageBox::StandardButton::Close, - QMessageBox::StandardButton::Ignore}, - QMessageBox::StandardButton::Close); - if (ret == QMessageBox::StandardButton::Ignore) { + QMessageBox::StandardButtons{QMessageBox::StandardButton::Ignore}, + QMessageBox::StandardButton::Ignore); continue; - } else { - abort(); - return; - } } task_finished++; this->ui->tw_build->item(r, VCWind::export_col_progress)