diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml
new file mode 100644
index 0000000..97fd186
--- /dev/null
+++ b/.github/workflows/ci_build.yml
@@ -0,0 +1,96 @@
+name: CI Build
+on: [push, pull_request]
+
+jobs:
+ windows-build:
+ strategy:
+ matrix:
+ cfg:
+ - {
+ os: windows-2019,
+ generator: Visual Studio 16 2019,
+ arch: Win32,
+ str: windows-x86,
+ blender-url: "https://github.com/Hoikas/blender2.7/releases/download/blender2.79_20210808/blender-2.79.0-git20210808.d2e1ea3f63e3-windows32.zip",
+ }
+ - {
+ os: windows-2019,
+ generator: Visual Studio 16 2019,
+ arch: x64,
+ str: windows-x64,
+ blender-url: "https://github.com/Hoikas/blender2.7/releases/download/blender2.79_20210808/blender-2.79.0-git20210808.d2e1ea3f63e3-windows64.zip",
+ }
+
+ env:
+ CMAKE_GENERATOR: ${{ matrix.cfg.generator }}
+ CMAKE_GENERATOR_PLATFORM: ${{ matrix.cfg.arch }}
+
+ runs-on: ${{ matrix.cfg.os }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ path: korman
+
+ - name: Download Blender
+ run: |
+ curl --location "${{ matrix.cfg.blender-url }}" --output blender.zip
+ mkdir blender
+ 7z x blender.zip -oblender -bsp1
+
+ - name: Build Standalone Korman
+ run: |
+ $BlenderSubDir = Split-Path -LeafBase $([System.URI]"${{ matrix.cfg.blender-url }}").Segments[-1]
+ korman/build.ps1 `
+ -Modern `
+ -BlenderDir "${{ github.workspace }}/blender/$BlenderSubDir" `
+ -NoInstaller -NoBlender
+
+ - name: Upload Standalone Korman
+ uses: actions/upload-artifact@v2
+ with:
+ name: korman-standalone-${{ matrix.cfg.str }}
+ path: build/package
+
+ - name: Build Korman+Blender Bundle
+ if: startsWith(github.ref, 'refs/tags')
+ run: |
+ Remove-Item -Recurse -Force build/package
+ korman/build.ps1 -Modern
+
+ - name: Upload Korman+Blender Bundle
+ if: startsWith(github.ref, 'refs/tags')
+ uses: actions/upload-artifact@v2
+ with:
+ name: korman-blender-${{ matrix.cfg.str }}
+ path: build/package
+
+ publish:
+ if: startsWith(github.ref, 'refs/tags')
+ needs: [windows-build]
+ runs-on: windows-2019
+
+ steps:
+ - name: Checkout Korman
+ uses: actions/checkout@v2
+ with:
+ path: korman
+
+ - name: Download Artifacts
+ id: download
+ uses: actions/download-artifact@v2
+ with:
+ path: artifacts
+
+ - name: Publish Release
+ run: |
+ korman/release.ps1 `
+ -Repository "${{ github.repository }}" `
+ -Token "${{ secrets.GITHUB_TOKEN }}" `
+ -UploadDir "${{ steps.download.outputs.download-path }}" `
+ -SubDirs @{
+ "korman-standalone-windows-x86" = "standalone"
+ "korman-standalone-windows-x64" = "standalone"
+ "korman-blender-windows-x86" = "bundled"
+ "korman-blender-windows-x64" = "bundled"
+ }
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..225f71f
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,93 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+cmake_minimum_required(VERSION 3.12)
+
+set(_PROJECT_INFO
+ korman
+ VERSION 0.10
+ DESCRIPTION "Blender plugin for creating ages for Cyan Worlds' proprietary Plasma engine and its open source variant, CyanWorlds.com Engine."
+ LANGUAGES CXX # This should probably be NONE, but we need the compiler for string_theory tests
+)
+project(${_PROJECT_INFO})
+
+include(CMakeDependentOption)
+
+set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
+set(CMAKE_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/install" CACHE PATH "")
+
+# TODO: Maybe use cmake_path (requires CMake 3.21) to ensure Blender_EXECUTABLE is not in the CMAKE_INSTALL_PREFIX?
+# That would indicate that we are installing Korman into the blender we found, so no need to install blender.
+option(korman_INSTALL_BLENDER "Copy Blender as part of the INSTALL target" ON)
+option(korman_INSTALL_SCRIPTS "Copy Korman python scripts as part of the INSTALL target" ON)
+
+# While, yes, we could tie our build process into Blender's, Blender pulls in
+# tons of dependencies and can be quite slow if you start trying to build
+# errthang from source. So, we'll jst let you handle that. Good luck!
+if(NOT "${Blender_PYTHON_VERSION}" OR korman_INSTALL_BLENDER)
+ set(_Blender_REQUIRED "REQUIRED")
+elseif("${Blender_PYTHON_VERSION}" AND NOT "${Blender_PYTHON_VERSION}" MATCHES "^[0-9]+\\.[0-9]+$")
+ message(FATAL_ERROR "Your manually defined Blender python version ($CACHE{Blender_PYTHON_VERSION}) doesn't pass muster.")
+endif()
+find_package(Blender 2.79 EXACT ${_Blender_REQUIRED})
+
+# Gotta do this because libHSPlasma is still using the old broke-ass pre-3.12 find modules.
+set(Python3_FIND_STRATEGY VERSION)
+find_package(Python3 ${Blender_PYTHON_VERSION} EXACT COMPONENTS Development REQUIRED)
+
+include(Dependencies)
+include(Packaging)
+
+if(korman_INSTALL_SCRIPTS)
+ set(korman_INSTALL_SCRIPTS_PATH "${Blender_VERSION}/scripts/addons" CACHE STRING "")
+ install(DIRECTORY
+ "${CMAKE_SOURCE_DIR}/korman"
+ DESTINATION "${korman_INSTALL_SCRIPTS_PATH}"
+ COMPONENT "Korman"
+ FILES_MATCHING
+ PATTERN "*.py"
+ )
+endif()
+
+# When we update to CMake 3.21, it might be worth separating the dependency build
+# and Korman build a little more and using install(TARGETS RUNTIME_DEPENDENCIES). For now,
+# this causes no observable problems and gives a good result, so meh.
+set(korman_INSTALL_BINARY_DIR "${Blender_VERSION}/python/lib/site-packages" CACHE STRING "")
+install(DIRECTORY
+ "${korman_HARVEST_DIR}/bin/"
+ DESTINATION "${korman_INSTALL_BINARY_DIR}"
+ COMPONENT "Korman"
+ FILES_MATCHING
+ PATTERN "*.dll"
+ PATTERN "*.pyd"
+ PATTERN "*.so"
+)
+
+if(korman_INSTALL_BLENDER)
+ get_filename_component(_Blender_PATH "${Blender_EXECUTABLE}" DIRECTORY)
+ install(DIRECTORY
+ "${_Blender_PATH}/"
+ DESTINATION "."
+ COMPONENT "Blender"
+ )
+endif()
+
+if(korman_HARVEST_PYTHON22)
+ install(PROGRAMS
+ "${korman_HARVEST_DIR}/bin/Python-2.2.3.exe"
+ DESTINATION "."
+ COMPONENT "Python22"
+ )
+endif()
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..95a80a0
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,223 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+param(
+ [Parameter(ParameterSetName="classic", Mandatory=$false)]
+ [Parameter(ParameterSetName="modern", Mandatory=$false)]
+ [ValidateSet("Visual Studio 2013", "Visual Studio 2015", "Visual Studio 2017", "Visual Studio 2019", "Visual Studio 2022")]
+ [string]$Generator,
+
+ [Parameter(ParameterSetName="classic", Mandatory=$false)]
+ [Parameter(ParameterSetName="modern", Mandatory=$false)]
+ [string]$BuildDir = "$(Get-Location)/build",
+
+ [Parameter(ParameterSetName="modern", Mandatory=$true)]
+ [ValidateScript({
+ if (Get-Command cpack) {
+ $true
+ } else {
+ throw "Modern requires that CPack be installed and available on the PATH."
+ }
+ })]
+ [switch]$Modern,
+
+ [Parameter(ParameterSetName="classic", Mandatory=$true)]
+ [ValidateScript({
+ if (Get-Command makensis) {
+ $true
+ } else {
+ throw "Classic requires that NSIS be installed and available on the PATH."
+ }
+ })]
+ [switch]$Classic,
+
+ [Parameter(ParameterSetName="classic", Mandatory=$true)]
+ [string]$PythonVersion,
+
+ [Parameter(ParameterSetName="modern")]
+ [ValidateSet("x86", "x64")]
+ [string]$Platform,
+
+ [Parameter(ParameterSetName="modern")]
+ [string]$BlenderDir,
+
+ [Parameter(ParameterSetName="modern")]
+ [switch]$NoInstaller,
+
+ [Parameter(ParameterSetName="modern")]
+ [switch]$NoBlender,
+
+ [Parameter(ParameterSetName="classic")]
+ [Parameter(ParameterSetName="modern")]
+ [switch]$RebuildDeps
+)
+
+# Enable for prod
+$ErrorActionPreference = "Stop"
+
+$Generator_LUT = @{
+ "Visual Studio 2013" = "Visual Studio 12 2013"
+ "Visual Studio 2015" = "Visual Studio 14 2015"
+ "Visual Studio 2017" = "Visual Studio 15 2017"
+ "Visual Studio 2019" = "Visual Studio 16 2019"
+ "Visual Studio 2022" = "Visual Studio 17 2022"
+};
+
+$Platform_LUT = @{
+ "x86" = "Win32"
+ "x64" = "x64"
+}
+
+function Find-CMakeArgument($UserInput, $EnvValue, $LUT, $Default) {
+ if ($UserInput) {
+ return $LUT[$UserInput]
+ }
+ if ($EnvValue) {
+ return $EnvValue
+ }
+ return $Default
+}
+
+function Convert-BoolToCMake($Value) {
+ if ($Value) {
+ "ON"
+ } else {
+ "OFF"
+ }
+}
+
+function Start-KormanBuild($HostGenerator, $TargetPlatform, $OutputDir, $StagingDir) {
+ Write-Host -ForegroundColor Cyan "Configuring Korman with $HostGenerator for $TargetPlatform..."
+ $InstallBlender = Convert-BoolToCMake $(if ($NoBlender) { $false } else { $true })
+ $HarvestPython22 = Convert-BoolToCMake $(if ($NoInstaller) { $false } else { $true })
+ cmake `
+ -G "$HostGenerator" `
+ -A "$TargetPlatform" `
+ -S "$PSScriptRoot" `
+ -B "$OutputDir" `
+ -DBlender_ROOT="$BlenderDir" `
+ -DBlender_PYTHON_VERSION="$PythonVersion" `
+ -Dkorman_EXTERNAL_STAGING_DIR="$StagingDir" `
+ -Dkorman_HARVEST_PYTHON22="$HarvestPython22" `
+ -Dkorman_INSTALL_BLENDER="$InstallBlender" | Write-Host
+ if ($LASTEXITCODE -Ne 0) { throw "Configure failed!" }
+}
+
+function Set-KormanClassicBuild($OutputDir, $Arch) {
+ Write-Host -ForegroundColor Cyan "Setting up classic multi-arch build..."
+ cmake `
+ -B "$OutputDir" `
+ -Dkorman_INSTALL_BLENDER=OFF `
+ -Dkorman_INSTALL_SCRIPTS=OFF `
+ -Dkorman_INSTALL_BINARY_DIR="$PSScriptRoot/installer/Files/$Arch"
+ if ($LASTEXITCODE -Ne 0) { throw "Configure failed!" }
+}
+
+function Complete-KormanBuild($OutputDir) {
+ Write-Host -ForegroundColor Cyan "Aaaand they're off!!!"
+ cmake --build "$OutputDir" --config Release --parallel | Write-Host
+ if ($LASTEXITCODE -Ne 0) { throw "Build failed!" }
+}
+
+function Build-KormanClassicSingleArch($HostGenerator, $TargetPlatform, $OutputDir) {
+ $MyPlatform = $Platform_LUT[$TargetPlatform]
+ $MyBuildDir = "$OutputDir/$TargetPlatform"
+ $CheckBuildDir = Test-Path $MyBuildDir
+ Start-KormanBuild "$HostGenerator" "$MyPlatform" "$MyBuildDir" "$OutputDir/external"
+ Set-KormanClassicBuild "$MyBuildDir" "$TargetPlatform"
+ if (!$CheckBuildDir -Or $RebuildDeps) {
+ Complete-KormanBuild "$MyBuildDir"
+ }
+}
+
+function Build-KormanClassicInstaller() {
+ # Ugh, CMake is nice enough to do this kind of shit for us.
+ New-Item -Path "$PSScriptRoot/installer/Files/x86" -ItemType Directory -Force
+ New-Item -Path "$PSScriptRoot/installer/Files/x64" -ItemType Directory -Force
+
+ # CMake copies the vcredist for us. YAY!
+ Write-Host -ForegroundColor Cyan "Copying sub-installers..."
+ Copy-Item "$BuildDir/x86/harvest/bin/vcredist_x86.exe" "$PSScriptRoot/installer/Files/x86/vcredist_x86.exe"
+ Copy-Item "$BuildDir/x64/harvest/bin/vcredist_x64.exe" "$PSScriptRoot/installer/Files/x64/vcredist_x64.exe"
+ Copy-Item "$BuildDir/x86/harvest/bin/Python-2.2.3.exe" "$PSScriptRoot/installer/Files/x86/Python-2.2.3.exe"
+
+ Write-Host -ForegroundColor Cyan "Determining Build Info..."
+ if (Get-Command git) {
+ Push-Location "$PSScriptRoot"
+ try {
+ $KormanRev = git describe --tags --dirty
+ } finally {
+ Pop-Location
+ }
+ } else {
+ $KormanRev = "untracked"
+ }
+
+ Write-Host -ForegroundColor Cyan "Building NSIS installer..."
+ Push-Location installer
+ try {
+ $PythonDLL = "python$($PythonVersion.Replace('.', '')).dll"
+ makensis /DPYTHON_DLL=$PythonDLL Installer.nsi
+ if ($LASTEXITCODE -Ne 0) { throw "makensis failed!" }
+
+ # Move it into the expected location for a "new" installer.
+ New-Item -Path "$BuildDir/package" -ItemType Directory -Force
+ Move-Item "$PSScriptRoot/installer/korman.exe" "$BuildDir/package/korman-$KormanRev-windows-classic.exe"
+ } finally {
+ Pop-Location
+ }
+}
+
+function Build-KormanModern($HostGenerator, $TargetPlatform, $OutputDir) {
+ $CheckBuildDir = Test-Path $OutputDir
+ Start-KormanBuild "$HostGenerator" "$TargetPlatform" "$OutputDir" "$OutputDir/external"
+ if (!$CheckBuildDir -Or $RebuildDeps) {
+ Complete-KormanBuild "$OutputDir"
+ }
+
+ if ($NoInstaller) {
+ $CPackGenerator = "ZIP"
+ } else {
+ $CPackGenerator = "WIX;ZIP"
+ }
+
+ Push-Location "$BuildDir"
+ try {
+ cpack `
+ -G "$CPackGenerator" `
+ -C Release
+ if ($LASTEXITCODE -Eq 0) {
+ Remove-Item -Recurse -Force "$BuildDir/package/_CPack_Packages"
+ }
+ } finally {
+ Pop-Location
+ }
+}
+
+try {
+ Get-Command cmake | Out-Null
+} catch {
+ throw "CMake must be installed and available on the PATH."
+}
+
+$MyGenerator = Find-CMakeArgument $Generator $Env:CMAKE_GENERATOR $Generator_LUT "Visual Studio 16 2019"
+if ($Classic) {
+ Build-KormanClassicSingleArch "$MyGenerator" x86 "$BuildDir"
+ Build-KormanClassicSingleArch "$MyGenerator" x64 "$BuildDir"
+ Build-KormanClassicInstaller
+} else {
+ $MyPlatform = Find-CMakeArgument $Platform $Env:CMAKE_GENERATOR_PLATFORM $Platform_LUT x64
+ Build-KormanModern "$MyGenerator" "$MyPlatform" "$BuildDir"
+}
diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake
new file mode 100644
index 0000000..34615f3
--- /dev/null
+++ b/cmake/Dependencies.cmake
@@ -0,0 +1,253 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+set(korman_EXTERNAL_STAGING_DIR "${PROJECT_BINARY_DIR}/external" CACHE PATH "External project staging directory")
+mark_as_advanced(korman_EXTERNAL_STAGING_DIR)
+
+set(korman_HARVEST_DIR "${PROJECT_BINARY_DIR}/harvest" CACHE PATH "")
+
+cmake_dependent_option(
+ korman_HARVEST_VCREDIST
+ "Harvest the vcredist executable as part of Korman's build process"
+ ON
+ "MSVC"
+ OFF
+)
+
+cmake_dependent_option(
+ korman_HARVEST_PYTHON22
+ "Harvest (read: download) the Python 2.2.3 installer as part of Korman's build process"
+ ON
+ "WIN32" # If we ever decide to allow NSIS installers, NSIS can run on non-Windows.
+ OFF
+)
+
+# Since we are (ideally) building everything static, inline right here, we can use IPO on
+# all of the static libraries for a uuuuge file size win. Most libs do not do the correct
+# CMake magic to turn this on.
+include(CheckIPOSupported)
+check_ipo_supported(
+ RESULT _IPO_SUPPORTED
+ OUTPUT _IPO_OUTPUT
+)
+message(STATUS "Checking for IPO: ${_IPO_SUPPORTED} ${_IPO_OUTPUT}")
+set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${_IPO_SUPPORTED} CACHE BOOL "")
+
+if(WIN32)
+ set(_BUILD_SYSTEM_LIBS ON)
+else()
+ set(_BUILD_SYSTEM_LIBS OFF)
+endif()
+
+option(korman_BUILD_HSPLASMA "Build libHSPlasma as part of Korman's build process" ON)
+option(korman_BUILD_JPEG "Build libpjeg-turbo as part of Korman's build process" ${_BUILD_SYSTEM_LIBS})
+option(korman_BUILD_OGGVORBIS "Build libogg and libvorbis as part of Korman's build process" ${_BUILD_SYSTEM_LIBS})
+option(korman_BUILD_PNG "Build libpng as part of Korman's build process" ${_BUILD_SYSTEM_LIBS})
+option(korman_BUILD_ZLIB "Build zlib as part of Korman's build process" ${_BUILD_SYSTEM_LIBS})
+option(korman_BUILD_STRING_THEORY "Build string_theory as part of Korman's build process" ON)
+option(korman_BUILD_ALWAYS_UPDATE "Always run the update phase for external dependencies" OFF)
+
+if(korman_BUILD_HSPLASMA)
+ list(APPEND korlib_DEPENDS HSPlasma)
+endif()
+if(korman_BUILD_JPEG)
+ list(APPEND HSPlasma_DEPENDS libjpeg-turbo)
+endif()
+if(korman_BUILD_OGGVORBIS)
+ list(APPEND korlib_DEPENDS libvorbis)
+ list(APPEND libvorbis_DEPENDS libogg)
+endif()
+if(korman_BUILD_STRING_THEORY)
+ list(APPEND HSPlasma_DEPENDS string_theory)
+endif()
+if(korman_BUILD_PNG)
+ list(APPEND HSPlasma_DEPENDS libpng)
+endif()
+if(korman_BUILD_ZLIB)
+ list(APPEND HSPlasma_DEPENDS zlib)
+ list(APPEND libpng_DEPENDS zlib)
+endif()
+
+set(_ExternalProjectCMakeCache
+ -DCMAKE_INSTALL_PREFIX:PATH=${korman_HARVEST_DIR}
+ -DCMAKE_POLICY_DEFAULT_CMP0069:STRING=NEW
+ -DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=${CMAKE_INTERPROCEDURAL_OPTIMIZATION}
+)
+
+include(ExternalProject)
+include(FetchContent)
+
+function(korman_add_external_project TARGET)
+ set(_args ${ARGN})
+
+ if("GIT_REPOSITORY" IN_LIST _args)
+ list(APPEND _args GIT_PROGRESS TRUE)
+ if(NOT "GIT_SHALLOW" IN_LIST _args)
+ list(APPEND _args GIT_SHALLOW TRUE)
+ endif()
+ endif()
+
+ list(FIND _args "CMAKE_CACHE_ARGS" _cache_args_idx)
+ if(_cache_args_idx EQUAL -1)
+ list(APPEND _args CMAKE_CACHE_ARGS ${_ExternalProjectCMakeCache})
+ else()
+ math(EXPR _cache_insert_pos "${_cache_args_idx} + 1")
+ list(INSERT _args ${_cache_insert_pos} ${_ExternalProjectCMakeCache})
+ endif()
+
+ set(_builddir "${korman_EXTERNAL_STAGING_DIR}/${TARGET}/src/build")
+ if(CMAKE_GENERATOR_PLATFORM)
+ string(APPEND _builddir "-${CMAKE_GENERATOR_PLATFORM}")
+ endif()
+
+ list(APPEND _args
+ PREFIX "${korman_EXTERNAL_STAGING_DIR}"
+ BINARY_DIR "${_builddir}"
+ DEPENDS ${${TARGET}_DEPENDS}
+ )
+
+ ExternalProject_Add(${TARGET} ${_args})
+endfunction()
+
+if(korman_BUILD_JPEG)
+ korman_add_external_project(libjpeg-turbo
+ GIT_REPOSITORY "https://github.com/libjpeg-turbo/libjpeg-turbo.git"
+ GIT_TAG 2.1.0
+ CMAKE_CACHE_ARGS
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ -DENABLE_SHARED:BOOL=FALSE
+ -DENABLE_STATIC:BOOL=TRUE
+ -DWITH_CRT_DLL:BOOL=ON # WTF libjpeg-turbo, this is a smell.
+ -DWITH_JAVA:BOOL=FALSE
+ -DWITH_TURBOJPEG:BOOL=FALSE
+ )
+endif()
+
+if(korman_BUILD_OGGVORBIS)
+ korman_add_external_project(libogg
+ GIT_REPOSITORY "https://github.com/xiph/ogg.git"
+ GIT_TAG v1.3.5
+ CMAKE_CACHE_ARGS
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ -DBUILD_TESTING:BOOL=OFF
+ -DINSTALL_DOCS:BOOL=OFF
+ )
+ korman_add_external_project(libvorbis
+ GIT_REPOSITORY "https://github.com/xiph/vorbis.git"
+ GIT_TAG v1.3.7
+ CMAKE_CACHE_ARGS
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ )
+endif()
+
+if(korman_BUILD_STRING_THEORY)
+ # Woe betide us if comaptibility breaks...
+ if(MSVC AND MSVC_VERSION LESS 1900)
+ set(_string_theory_tag 2.4)
+ else()
+ set(_string_theory_tag 3.4)
+ endif()
+
+ korman_add_external_project(string_theory
+ GIT_REPOSITORY "https://github.com/zrax/string_theory.git"
+ GIT_TAG ${_string_theory_tag}
+ CMAKE_CACHE_ARGS
+ -DST_BUILD_TESTS:BOOL=OFF
+ )
+endif()
+
+if(korman_BUILD_ZLIB)
+ # Using zlib-ng instead of zlib because the latter's CMakeLists is a pile of steaming garbage
+ # in that it always produces a shared library if BUILD_SHARED_LIBS=OFF, and bad problems when
+ # `if(UNIX)` -> TRUE. Grrr.
+ korman_add_external_project(zlib
+ #URL
+ # "https://zlib.net/zlib-1.2.11.tar.gz"
+ # "https://sourceforge.net/projects/libpng/files/zlib/1.2.11/zlib-1.2.11.tar.gz/download"
+ #DOWNLOAD_NAME "zlib-1.2.11.tar.gz"
+ #URL_HASH "SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1"
+ GIT_REPOSITORY "https://github.com/zlib-ng/zlib-ng.git"
+ GIT_TAG 2.0.5
+ CMAKE_CACHE_ARGS
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ -DZLIB_COMPAT:BOOL=ON
+ -DZLIB_ENABLE_TESTS:BOOL=OFF
+ )
+endif()
+
+if(korman_BUILD_PNG)
+ korman_add_external_project(libpng
+ URL "https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.gz/download"
+ DOWNLOAD_NAME "libpng-1.6.37.tar.gz"
+ URL_HASH "SHA256=daeb2620d829575513e35fecc83f0d3791a620b9b93d800b763542ece9390fb4"
+ CMAKE_CACHE_ARGS
+ -DBUILD_SHARED_LIBS:BOOL=OFF
+ -DPNG_EXECUTABLES:BOOL=OFF
+ -DPNG_SHARED:BOOL=OFF
+ -DPNG_TESTS:BOOL=OFF
+ )
+endif()
+
+if(korman_BUILD_HSPLASMA)
+ korman_add_external_project(HSPlasma
+ GIT_REPOSITORY "https://github.com/H-uru/libhsplasma.git"
+ # Be sure to increase this as the feature set used by Korman increases
+ GIT_TAG 7871b5def20f7352c93be46316982999ed883777
+ # We can only do shallow checkouts if the above is a branch or tag.
+ GIT_SHALLOW FALSE
+ CMAKE_CACHE_ARGS
+ -DCMAKE_UNITY_BUILD:BOOL=ON
+ -DENABLE_NET:BOOL=OFF
+ -DENABLE_PHYSX:BOOL=OFF
+ -DENABLE_PYTHON:BOOL=ON
+ -DENABLE_TOOLS:BOOL=OFF
+ -DPYTHON_INCLUDE_DIR:PATH=${Python3_INCLUDE_DIRS}
+ -DPYTHON_LIBRARY:FILEPATH=${Python3_LIBRARIES}
+ )
+endif()
+
+korman_add_external_project(korlib
+ SOURCE_DIR "${PROJECT_SOURCE_DIR}/korlib"
+ CMAKE_CACHE_ARGS
+ -Dkorlib_PYTHON_VERSION:STRING=${Blender_PYTHON_VERSION}
+ -DPython3_ROOT:PATH=${Python3_ROOT} # Passthru helper
+)
+
+if(korman_HARVEST_VCREDIST)
+ find_package(VCRedist COMPONENTS Executable REQUIRED)
+ set(_vcredist_destination "${korman_HARVEST_DIR}/bin/${VCRedist_NAME}")
+ add_custom_target(VCRedist
+ ALL
+ COMMAND "${CMAKE_COMMAND}" -E make_directory "${korman_HARVEST_DIR}"
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${VCRedist_EXECUTABLE}" "${_vcredist_destination}"
+ BYPRODUCTS "${_vcredist_destination}"
+ )
+ install(
+ PROGRAMS
+ "${_vcredist_destination}"
+ DESTINATION "."
+ )
+endif()
+
+FetchContent_Declare(Python22
+ URL "https://www.python.org/ftp/python/2.2.3/Python-2.2.3.exe"
+ URL_HASH MD5=d76e774a4169794ae0d7a8598478e69e
+ DOWNLOAD_DIR "${korman_HARVEST_DIR}/bin"
+ DOWNLOAD_NAME "Python-2.2.3.exe"
+ DOWNLOAD_NO_EXTRACT TRUE # Why is this not a flag? Yes, that bit me.
+)
+if(korman_HARVEST_PYTHON22 AND NOT Python22_POPULATED)
+ FetchContent_Populate(Python22)
+endif()
diff --git a/cmake/FindBlender.cmake b/cmake/FindBlender.cmake
new file mode 100644
index 0000000..5aba1e1
--- /dev/null
+++ b/cmake/FindBlender.cmake
@@ -0,0 +1,85 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+# The parens in this env variable give CMake heartburn, so we whisper sweet nothings.
+set(_PROGRAMFILES_X86 "PROGRAMFILES(X86)")
+set(_PROGRAMFILES_X86 "$ENV{${_PROGRAMFILES_X86}}")
+
+find_program(Blender_EXECUTABLE
+ NAMES blender
+ PATHS
+ "${Blender_ROOT}"
+ "$ENV{PROGRAMFILES}/Blender Foundation/Blender"
+ "${_PROGRAMFILES_X86}/Blender Foundation/Blender"
+)
+
+# Hacky? On Windows, we want to make sure that the Blender EXE matches sizeof void*
+# Yes, this has bitten me. If it bites you, the result will be "Import Error: PyHSPlasma is not a
+# valid Win32 application." That's hardly useful...
+if(WIN32 AND EXISTS "${Blender_EXECUTABLE}")
+ find_package(dumpbin)
+ if(dumpbin_FOUND)
+ execute_process(
+ COMMAND "${dumpbin_EXECUTABLE}" /headers "${Blender_EXECUTABLE}"
+ RESULTS_VARIABLE _RETURNCODE
+ OUTPUT_VARIABLE _dumpbin_output
+ ERROR_VARIABLE _dumpbin_error
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE
+ )
+ if(_RETURNCODE EQUAL 0)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_expected_arch "machine \\(x64\\)")
+ else()
+ set(_expected_arch "machine \\(x86\\)")
+ endif()
+ if(NOT "${_dumpbin_output}" MATCHES "${_expected_arch}")
+ unset(Blender_EXECUTABLE CACHE)
+ endif()
+ else()
+ message(WARNING "dumpbin failed ${_dumpbin_error}")
+ endif()
+ else()
+ message(WARNING "dumpbin not found, not verifying blender executable")
+ endif()
+endif()
+
+if(EXISTS "${Blender_EXECUTABLE}")
+ # Starting Blender is noisy on stdout, so all the extra characters will make sure things go right.
+ # https://youtu.be/SlQFIsQ0dbs?t=19
+ set(_Blender_PYTHON_EXPR
+ "import sys; print('!!! OOGABOOGA {}.{} AGOOBAGOO !!!'.format(sys.version_info[0], sys.version_info[1]))"
+ )
+ execute_process(
+ COMMAND "${Blender_EXECUTABLE}" -b --python-expr "${_Blender_PYTHON_EXPR}"
+ RESULTS_VARIABLE _RETURNCODE
+ OUTPUT_VARIABLE _Blender_VERSION_OUTPUT
+ ERROR_VARIABLE _Blender_VERSION_OUTPUT
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE
+ )
+ string(REGEX MATCH [[Blender ([0-9]+\.[0-9]+)]] _match "${_Blender_VERSION_OUTPUT}")
+ set(Blender_VERSION "${CMAKE_MATCH_1}")
+ string(REGEX MATCH [[!!! OOGABOOGA ([0-9]+\.[0-9]+) AGOOBAGOO !!!]] _match "${_Blender_VERSION_OUTPUT}")
+ set(Blender_PYTHON_VERSION "${CMAKE_MATCH_1}")
+endif()
+
+mark_as_advanced(Blender_EXECUTABLE)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Blender
+ REQUIRED_VARS Blender_EXECUTABLE Blender_VERSION Blender_PYTHON_VERSION
+ VERSION_VAR Blender_VERSION
+)
diff --git a/cmake/FindVCRedist.cmake b/cmake/FindVCRedist.cmake
new file mode 100644
index 0000000..98a2272
--- /dev/null
+++ b/cmake/FindVCRedist.cmake
@@ -0,0 +1,120 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if(IN_LIST)
+
+function(_get_subdirectories RESULT DIRECTORY)
+ file(GLOB children INCLUDE_DIRECTORIES RELATIVE "${DIRECTORY}" "${DIRECTORY}/*")
+ foreach(child IN LISTS children)
+ if(IS_DIRECTORY "${DIRECTORY}/${child}")
+ list(APPEND subdirectories "${child}")
+ endif()
+ endforeach()
+ set(${RESULT} ${subdirectories} PARENT_SCOPE)
+endfunction()
+
+# Is this even legal?
+if(NOT VCRedist_FIND_COMPONENTS)
+ set(VCRedist_FIND_COMPONENTS Executable MergeModules)
+endif()
+
+if(MSVC)
+ # The parens in this env variable give CMake heartburn, so we whisper sweet nothings.
+ set(_PROGRAMFILES_X86 "PROGRAMFILES(X86)")
+ set(_PROGRAMFILES_X86 "$ENV{${_PROGRAMFILES_X86}}")
+
+ # TODO: support non visual studio generators
+ set(_vs_install_root "${CMAKE_VS_DEVENV_COMMAND}/../../../")
+ get_filename_component(_vs_install_root "${_vs_install_root}" ABSOLUTE)
+
+ # Valid paths:
+ # 2013, 2015: VC/redist/1033/
+ # 2017, 2019: VC/redist/MSVC//
+ # 2019: VC/redist/MSVC//
+ set(_redist_dir "${_vs_install_root}/VC/redist")
+ _get_subdirectories(_msvc_subdirs "${_redist_dir}/MSVC")
+ foreach(_subdir IN LISTS _msvc_subdirs)
+ list(APPEND _redist_paths "${_redist_dir}/MSVC/${_subdir}")
+ endforeach()
+
+ # These are known, valid locations, so we prefer them first.
+ list(INSERT _redist_paths 0 "${_redist_dir}/1033" "${_redist_dir}/MSVC/v${MSVC_TOOLSET_VERSION}")
+ list(REMOVE_DUPLICATES _redist_paths)
+
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_redist_arch x64)
+ else()
+ set(_redist_arch x86)
+ endif()
+
+ if("Executable" IN_LIST VCRedist_FIND_COMPONENTS)
+ list(APPEND _required_vars "VCRedist_EXECUTABLE")
+
+ find_program(VCRedist_EXECUTABLE
+ NAMES "vcredist_${_redist_arch}" "vc_redist.${_redist_arch}"
+ PATHS ${_redist_paths}
+ )
+
+ mark_as_advanced(VCRedist_EXECUTABLE)
+ set(VCRedist_NAME "vcredist_${_redist_arch}.exe")
+ if(EXISTS "${VCRedist_EXECUTABLE}")
+ set(VCRedist_Executable_FOUND TRUE)
+ endif()
+ endif()
+
+ # Valid Paths:
+ # Visual Studio <= 2015: /Common Files/Merge Modules/
+ # Visual Studio >= 2017: /VC//MergeModules/
+ if("MergeModules" IN_LIST VCRedist_FIND_COMPONENTS)
+ list(APPEND _merge_module_paths "${_PROGRAMFILES_X86}/Common Files" ${_redist_paths})
+ set(_merge_module_suffixes "Merge Modules" "MergeModules")
+
+ # We'll flip it OFF if anything is missing
+ set(VCRedist_MergeModules_FOUND TRUE)
+ function(_find_merge_module MODULE_NAME)
+ string(TOUPPER "${MODULE_NAME}" _module_name_upper)
+ set(VARIABLE "VCRedist_${_module_name_upper}_MERGE_MODULE")
+ find_file(${VARIABLE}
+ NAMES "Microsoft_VC${MSVC_TOOLSET_VERSION}_${MODULE_NAME}_${_redist_arch}.msm"
+ PATHS ${_merge_module_paths}
+ PATH_SUFFIXES ${_merge_module_suffixes}
+ )
+ mark_as_advanced(${VARIABLE})
+ set(_required_vars ${_required_vars} ${VARIABLE} PARENT_SCOPE)
+ if(EXISTS "${${VARIABLE}}")
+ set(VCRedist_MERGE_MODULES ${VCRedist_MERGE_MODULES} "${${VARIABLE}}" PARENT_SCOPE)
+ else()
+ set(VCRedist_MergeModules_FOUND FALSE PARENT_SCOPE)
+ endif()
+ endfunction()
+
+ _find_merge_module(CRT)
+ _find_merge_module(MFC)
+ _find_merge_module(MFCLOC)
+ _find_merge_module(OpenMP)
+ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 110)
+ _find_merge_module(CXXAMP)
+ endif()
+ endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(VCRedist
+ REQUIRED_VARS ${_required_vars} # Optional in CMake 3.18+, but we only require 3.12
+ HANDLE_COMPONENTS
+)
+
+cmake_policy(POP)
diff --git a/cmake/Finddumpbin.cmake b/cmake/Finddumpbin.cmake
new file mode 100644
index 0000000..faf2603
--- /dev/null
+++ b/cmake/Finddumpbin.cmake
@@ -0,0 +1,26 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+
+get_filename_component(_linker_dir "${CMAKE_LINKER}" DIRECTORY)
+find_program(dumpbin_EXECUTABLE
+ NAMES dumpbin
+ PATHS ${_linker_dir}
+)
+
+mark_as_advanced(dumpbin_EXECUTABLE)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(dumpbin REQUIRED_VARS dumpbin_EXECUTABLE)
diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake
new file mode 100644
index 0000000..0f6561a
--- /dev/null
+++ b/cmake/Packaging.cmake
@@ -0,0 +1,121 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+set(CPACK_PACKAGE_NAME Korman)
+set(CPACK_PACKAGE_VENDOR "Guild of Writers")
+set(CPACK_PACKAGE_DIRECTORY "${PROJECT_BINARY_DIR}/package")
+set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/installer/Icon.ico")
+set(CPACK_THREADS 0) # Allows multi-threaded LZMA compression in CMake 3.21+
+
+find_package(Git)
+if(Git_FOUND)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} describe --tags --dirty
+ WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
+ OUTPUT_VARIABLE _korman_rev
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET
+ )
+ string(REGEX REPLACE "[\r\n]" " " _korman_rev "${_korman_rev}")
+else()
+ set(_korman_rev "untracked")
+endif()
+
+# Don't rely on the hardwired version number from project() since this may be some rando
+# git checkout or CI run. Also, apparently CPACK_SYSTEM_NAME is faulty. Stupid CMake.
+if(WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_korman_system "windows64")
+ else()
+ set(_korman_system "windows32")
+ endif()
+else()
+ set(_korman_system "${CMAKE_SYSTEM_NAME}")
+endif()
+set(CPACK_PACKAGE_FILE_NAME "korman-${_korman_rev}-${_korman_system}")
+
+set(CPACK_PACKAGE_CHECKSUM SHA256)
+
+# Generate license file based on the install settings
+if(korman_INSTALL_BINARY_DIR OR korman_INSTALL_SCRIPTS)
+ set(KORMAN_LICENSE "Korman is licensed under the GNU GPLv3.")
+ file(READ "${PROJECT_SOURCE_DIR}/installer/GPLv3.txt" _license)
+ string(APPEND LICENSE_TEXT "${_license}\n")
+endif()
+if(korman_INSTALL_BLENDER)
+ set(BLENDER_LICENSE "Blender is licensed under the GNU GPLv2.")
+ file(READ "${PROJECT_SOURCE_DIR}/installer/GPLv2.txt" _license)
+ string(APPEND LICENSE_TEXT "${_license}\n")
+endif()
+
+configure_file(
+ "${PROJECT_SOURCE_DIR}/installer/license.txt.in"
+ "${PROJECT_BINARY_DIR}/license.txt"
+ @ONLY
+)
+set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_BINARY_DIR}/license.txt")
+install(FILES
+ "${PROJECT_BINARY_DIR}/license.txt"
+ DESTINATION "."
+)
+
+set(CPACK_COMPONENTS_ALL "Korman")
+set(CPACK_COMPONENTS_GROUPING "ALL_COMPONENTS_IN_ONE")
+set(CPACK_COMPONENT_KORMAN_HIDDEN TRUE)
+
+if(korman_INSTALL_BLENDER)
+ list(APPEND CPACK_PACKAGE_EXECUTABLES blender Blender)
+ list(APPEND CPACK_COMPONENTS_ALL "Blender")
+ set(CPACK_COMPONENT_BLENDER_HIDDEN TRUE)
+endif()
+
+if(korman_HARVEST_PYTHON22)
+ list(APPEND CPACK_COMPONENTS_ALL "Python22")
+ set(CPACK_COMPONENT_PYTHON22_HIDDEN TRUE)
+endif()
+
+if(WIN32)
+ # We're not actually going to ship this variant, but better prepared than sorry.
+ if(korman_HARVEST_VCREDIST)
+ set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS
+ "ExecWait \\\"$INSTDIR\\\\${VCRedist_NAME} /q /norestart\\\""
+ )
+ endif()
+
+ set(CPACK_WIX_UPGRADE_GUID 84ef4b1d-27b6-54de-a73b-8fb1beb007ac) # KormanUpgrade
+ # I think this should be randomized by CPack and not hardcoded?
+ #set(CPACK_WIX_PRODUCT_GUID 74e91f5d-6d09-5d7f-a48f-3d0b011ef2df) # KormanProduct
+
+ find_package(VCRedist COMPONENTS MergeModules REQUIRED)
+ configure_file(
+ "${PROJECT_SOURCE_DIR}/installer/WiX.template.in"
+ "${PROJECT_BINARY_DIR}/WiX.template"
+ @ONLY
+ )
+ set(CPACK_WIX_TEMPLATE "${PROJECT_BINARY_DIR}/WiX.template")
+
+ set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/installer/WIX_UI_BANNER.bmp")
+ set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/installer/WIX_UI_DIALOG.bmp")
+
+ set(CPACK_WIX_ROOT_FEATURE_TITLE "Blender for Korman")
+
+ # Great release compression. Change it to "none" to iterate faster.
+ set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:high)
+endif()
+
+set(CPACK_ARCHIVE_THREADS 0)
+
+# Apparently this has to come last. Shaweet.
+include(CPack)
diff --git a/installer/GPLv2.txt b/installer/GPLv2.txt
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/installer/GPLv2.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/installer/WIX_UI_BANNER.bmp b/installer/WIX_UI_BANNER.bmp
new file mode 100644
index 0000000..d71ba76
Binary files /dev/null and b/installer/WIX_UI_BANNER.bmp differ
diff --git a/installer/WIX_UI_BANNER.xcf b/installer/WIX_UI_BANNER.xcf
new file mode 100644
index 0000000..7ebedb6
Binary files /dev/null and b/installer/WIX_UI_BANNER.xcf differ
diff --git a/installer/WIX_UI_DIALOG.bmp b/installer/WIX_UI_DIALOG.bmp
new file mode 100644
index 0000000..1e40294
Binary files /dev/null and b/installer/WIX_UI_DIALOG.bmp differ
diff --git a/installer/WIX_UI_DIALOG.xcf b/installer/WIX_UI_DIALOG.xcf
new file mode 100644
index 0000000..422a0f5
Binary files /dev/null and b/installer/WIX_UI_DIALOG.xcf differ
diff --git a/installer/WiX.template.in b/installer/WiX.template.in
new file mode 100644
index 0000000..8ae7c9a
--- /dev/null
+++ b/installer/WiX.template.in
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ProductIcon.ico
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/license.txt.in b/installer/license.txt.in
new file mode 100644
index 0000000..70848d5
--- /dev/null
+++ b/installer/license.txt.in
@@ -0,0 +1,4 @@
+@KORMAN_LICENSE@
+@BLENDER_LICENSE@
+
+@LICENSE_TEXT@
diff --git a/korlib/CMakeLists.txt b/korlib/CMakeLists.txt
index 283c320..5bb5948 100644
--- a/korlib/CMakeLists.txt
+++ b/korlib/CMakeLists.txt
@@ -1,22 +1,22 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.12)
project(korlib)
+set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/install" CACHE PATH "")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
-# Stolen shamelessly from PyHSPlasma
-find_package(PythonLibs REQUIRED)
-find_package(PythonInterp "3.5" REQUIRED)
+set(korlib_PYTHON_VERSION "" CACHE STRING "Exact Python3 version to find")
+if(korlib_PYTHON_VERSION)
+ set(_Python3_find_version ${korlib_PYTHON_VERSION} EXACT)
+endif()
+set(Python3_FIND_STRATEGY VERSION)
+find_package(Python3 ${_Python3_find_version} COMPONENTS Development REQUIRED)
+
find_package(HSPlasma REQUIRED)
find_package(Ogg REQUIRED)
find_package(OpenGL REQUIRED)
find_package(string_theory REQUIRED)
find_package(Vorbis REQUIRED)
-if(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} MATCHES ".*Clang")
- set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter ${CMAKE_CXX_FLAGS}")
-endif()
-
-# Da files
set(korlib_HEADERS
bumpmap.h
korlib.h
@@ -32,26 +32,13 @@ set(korlib_SOURCES
texture.cpp
)
-include_directories(${HSPlasma_INCLUDE_DIRS})
-include_directories(${Ogg_INCLUDE_DIR})
-include_directories(${OPENGL_INCLUDE_DIR})
-include_directories(${PYTHON_INCLUDE_DIRS})
-include_directories(${STRING_THEORY_INCLUDE_DIRS})
-include_directories(${Vorbis_INCLUDE_DIR})
-
-add_library(_korlib SHARED ${korlib_HEADERS} ${korlib_SOURCES})
-set_target_properties(_korlib PROPERTIES PREFIX "")
-if(NOT WIN32)
- set_target_properties(_korlib PROPERTIES SUFFIX ".so")
-else()
- set_target_properties(_korlib PROPERTIES SUFFIX ".pyd")
-endif()
-target_link_libraries(_korlib HSPlasma ${Ogg_LIBRARIES} ${OPENGL_LIBRARIES}
- ${PYTHON_LIBRARIES} ${STRING_THEORY_LIBRARIES}
- ${Vorbis_LIBRARIES})
-
-install(TARGETS _korlib
- RUNTIME DESTINATION bin
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib
+Python3_add_library(_korlib MODULE ${korlib_HEADERS} ${korlib_SOURCES})
+target_link_libraries(_korlib
+ PRIVATE
+ HSPlasma
+ Ogg::ogg
+ OpenGL::GL
+ string_theory
+ Vorbis::vorbisfile
)
+install(TARGETS _korlib DESTINATION "bin")
diff --git a/korlib/cmake/FindOgg.cmake b/korlib/cmake/FindOgg.cmake
index f3071cd..3b81f85 100644
--- a/korlib/cmake/FindOgg.cmake
+++ b/korlib/cmake/FindOgg.cmake
@@ -1,30 +1,25 @@
-if(Ogg_INCLUDE_DIR AND Ogg_LIBRARY)
- set(Ogg_FIND_QUIETLY TRUE)
-endif()
-
+find_package(Ogg CONFIG QUIET)
-find_path(Ogg_INCLUDE_DIR ogg/ogg.h
- /usr/local/include
- /usr/include
-)
+if(NOT TARGET Ogg::ogg)
+ include(FindPackageHandleStandardArgs)
-find_library(Ogg_LIBRARY NAMES ogg
- PATHS /usr/local/lib /usr/lib
-)
+ find_path(Ogg_INCLUDE_DIR ogg/ogg.h
+ PATHS /usr/local/include /usr/include
+ )
-set(Ogg_LIBRARIES ${Ogg_LIBRARY})
+ find_library(Ogg_LIBRARY
+ NAMES ogg libogg libogg_static
+ PATHS /usr/local/lib /usr/lib
+ )
+ find_package_handle_standard_args(Ogg REQUIRED_VARS Ogg_INCLUDE_DIR Ogg_LIBRARY)
-if(Ogg_INCLUDE_DIR AND Ogg_LIBRARY)
- set(Ogg_FOUND TRUE)
-endif()
-
-if (Ogg_FOUND)
- if(NOT Ogg_FIND_QUIETLY)
- message(STATUS "Found libogg: ${Ogg_INCLUDE_DIR}")
- endif()
-else()
- if(Ogg_FIND_REQUIRED)
- message(FATAL_ERROR "Could not find libogg")
+ if(Ogg_FOUND AND NOT TARGET Ogg::ogg)
+ add_library(Ogg::ogg UNKNOWN IMPORTED)
+ set_target_properties(
+ Ogg::ogg PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES ${Ogg_INCLUDE_DIR}
+ IMPORTED_LOCATION ${Ogg_LIBRARY}
+ )
endif()
endif()
diff --git a/korlib/cmake/FindVorbis.cmake b/korlib/cmake/FindVorbis.cmake
index 428d356..d09a10b 100644
--- a/korlib/cmake/FindVorbis.cmake
+++ b/korlib/cmake/FindVorbis.cmake
@@ -1,37 +1,41 @@
-if(Vorbis_INCLUDE_DIR AND Vorbis_LIBRARY)
- set(Vorbis_FIND_QUIETLY TRUE)
-endif()
-
-
-find_path(Vorbis_INCLUDE_DIR vorbis/codec.h
- /usr/local/include
- /usr/include
-)
-
-find_library(Vorbis_LIBRARY NAMES vorbis
- PATHS /usr/local/lib /usr/lib
-)
-
-find_library(VorbisFile_LIBRARY NAMES vorbisfile
- PATHS /usr/local/lib /usr/lib
-)
-
-set(Vorbis_LIBRARIES
- ${Vorbis_LIBRARY}
- ${VorbisFile_LIBRARY}
-)
-
-
-if(Vorbis_INCLUDE_DIR AND Vorbis_LIBRARY AND VorbisFile_LIBRARY)
- set(Vorbis_FOUND TRUE)
-endif()
-
-if (Vorbis_FOUND)
- if(NOT Vorbis_FIND_QUIETLY)
- message(STATUS "Found libvorbis: ${Vorbis_INCLUDE_DIR}")
+find_package(Vorbis CONFIG QUIET)
+
+if(NOT TARGET Vorbis::vorbis)
+ include(FindPackageHandleStandardArgs)
+
+ find_path(Vorbis_INCLUDE_DIR vorbis/codec.h
+ PATHS /usr/local/include /usr/include
+ )
+
+ find_library(Vorbis_LIBRARY
+ NAMES vorbis libvorbis libvorbis_static
+ PATHS /usr/local/lib /usr/lib
+ )
+
+ find_library(VorbisFile_LIBRARY
+ NAMES vorbisfile libvorbisfile libvorbisfile_static
+ PATHS /usr/local/lib /usr/lib
+ )
+
+ find_package_handle_standard_args(
+ Vorbis REQUIRED_VARS Vorbis_INCLUDE_DIR Vorbis_LIBRARY VorbisFile_LIBRARY
+ )
+
+ if(Vorbis_FOUND AND NOT TARGET Vorbis::vorbis)
+ add_library(Vorbis::vorbis UNKNOWN IMPORTED)
+ set_target_properties(
+ Vorbis::vorbis PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES ${Vorbis_INCLUDE_DIR}
+ IMPORTED_LOCATION ${Vorbis_LIBRARY}
+ )
endif()
-else()
- if(Vorbis_FIND_REQUIRED)
- message(FATAL_ERROR "Could not find libvorbis")
+
+ if(Vorbis_FOUND AND NOT TARGET Vorbis::vorbisfile)
+ add_library(Vorbis::vorbisfile UNKNOWN IMPORTED)
+ set_target_properties(
+ Vorbis::vorbisfile PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES ${Vorbis_INCLUDE_DIR}
+ IMPORTED_LOCATION ${VorbisFile_LIBRARY}
+ )
endif()
endif()
diff --git a/release.ps1 b/release.ps1
new file mode 100644
index 0000000..a579bd6
--- /dev/null
+++ b/release.ps1
@@ -0,0 +1,187 @@
+# This file is part of Korman.
+#
+# Korman 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.
+#
+# Korman 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 Korman. If not, see .
+
+param(
+ [Parameter()]
+ [string]$GitHub = "https://api.github.com",
+
+ [Parameter(Mandatory=$true)]
+ [string]$Repository,
+
+ [Parameter(Mandatory=$true)]
+ [string]$Token,
+
+ [Parameter()]
+ [string]$UploadDir = "$PSScriptRoot/build/package",
+
+ [Parameter()]
+ [hashtable]$SubDirs = @{}
+)
+
+$ErrorActionPreference = "STOP"
+
+$RequestHeaders = @{
+ "Accept" = "application/vnd.github.v3+json"
+ "Authorization" = "token $Token"
+}
+
+function Invoke-GitHubRequest($Method, $Uri, $Body, $ValidResults) {
+ $Result = Invoke-WebRequest `
+ -Uri "$Uri" `
+ -Method "$Method" `
+ -Headers $RequestHeaders `
+ -Body @(ConvertTo-JSON $Body) `
+ -SkipHttpErrorCheck
+ Test-GitHubResult `
+ -Result $Result `
+ -FailureMessage "GitHub API call failed" `
+ -ValidResults $ValidResults
+ try {
+ $Content = ConvertFrom-JSON $Result.Content
+ } catch {
+ $Content = ""
+ }
+ return @{
+ "StatusCode" = $Result.StatusCode
+ "Content" = $Content
+ }
+}
+
+$ContentTypeLUT = @{
+ ".exe" = "application/x-msdownload"
+ ".sha256" = "text/plain"
+ ".zip" = "application/zip"
+}
+
+function Invoke-GitHubUpload($Method, $Uri, $InFile, $ValidResults) {
+ Write-Host "Uploading $InFile -> $Uri"
+
+ # Can't use -InFile per my testing. Gah.
+ $Body = [System.IO.File]::ReadAllBytes($InFile)
+ if ($ContentTypeLUT.Contains($(Split-Path -Extension $InFile))) {
+ $ContentType = $ContentTypeLUT[$(Split-Path -Extension $InFile)]
+ } else {
+ $ContentType = "application/octet-stream"
+ }
+
+ try {
+ $Result = Invoke-WebRequest `
+ -Uri "$Uri" `
+ -Method "$Method" `
+ -Headers $RequestHeaders `
+ -ContentType $ContentType `
+ -Body $Body `
+ -SkipHttpErrorCheck
+ } catch {
+ throw "Uploading to GitHub failed. Check for (and delete any) junked files on the release!"
+ }
+ Test-GitHubResult `
+ -Result $Result `
+ -FailureMessage "GitHub API call failed" `
+ -ValidResults $ValidResults
+}
+
+function Test-GitHubResult($Result, $FailureMessage, $ValidResults) {
+ if (!($ValidResults.Contains($Result.StatusCode))) {
+ Write-Host "bad result $Result"
+ throw "$($FailureMessage): $($Result.StatusCode) $($Result.Content)"
+ }
+}
+
+function Get-KormanRelease() {
+ Write-Host -ForegroundColor Cyan "Finding a GitHub release for $Tag ($CommitSHA)..."
+
+ $ExistingRelease = Invoke-GitHubRequest `
+ -Uri "$GitHub/repos/$Repository/releases/tags/$Tag" `
+ -Method GET `
+ -ValidResults @(200, 404)
+
+ if ($ExistingRelease.StatusCode -Eq 404) {
+ # No matching release, so make a new one.
+ Write-Host -ForegroundColor Cyan "Creating a new (pre-)release..."
+ $NewRelease = Invoke-GitHubRequest `
+ -Uri "$GitHub/repos/$Repository/releases" `
+ -Method POST `
+ -Body @{
+ "name" = "Korman $Tag"
+ "tag_name" = $Tag
+ "target_commitish" = $CommitSHA
+ "prerelease" = $true
+ } `
+ -ValidResults @(201)
+ return $NewRelease.Content
+ } elseif ($ExistingRelease.StatusCode -Eq 200) {
+ Write-Host -ForegroundColor Yellow "Existing release found ($($ExistingRelease.Content.name)) - it will be forced to pre-release status and cleared!"
+ if ($ExistingRelease.Content.prerelease -Ne $false) {
+ Invoke-GitHubRequest `
+ -Uri "$GitHub/repos/$Repository/releases/$($ExistingRelease.Content.id)" `
+ -Method PATCH `
+ -Body @{ "prerelease" = $true } `
+ -ValidResults @(200)
+ }
+ foreach ($Asset in $ExistingRelease.Content.assets) {
+ Write-Host -ForegroundColor Red "Deleting release asset $($Asset.name))"
+ Invoke-GitHubRequest `
+ -Uri $Asset.url `
+ -Method DELETE `
+ -ValidResults @(204)
+ }
+ return $ExistingRelease.Content
+ }
+ throw "???"
+}
+
+function Publish-KormanReleaseAssets($Release) {
+ Write-Host -ForegroundColor Cyan "Finding assets to upload"
+ $Assets = @{}
+ foreach ($Iter in $SubDirs.GetEnumerator()) {
+ foreach ($Item in (Get-ChildItem -File "$UploadDir/$($Iter.Key)")) {
+ $Assets.Add("$($Iter.Value)_$($Item.Name)", $Item.FullName);
+ }
+ }
+ foreach ($Item in (Get-ChildItem -File $UploadDir)) {
+ $Assets.Add($Item.Name, $Item.FullName);
+ }
+
+ # Sigh, stupid GitHub...
+ Write-Host -ForegroundColor Cyan "Uploading $($Assets.Count) asset(s) to GitHub release $($Release.id)"
+ $ss = Select-String -InputObject $Release.upload_url "^(https:\/\/.+){"
+ $UploadURL = $ss.Matches[0].Groups[1]
+ Write-Host "URL: $UploadURL"
+
+ foreach ($Asset in $Assets.GetEnumerator()) {
+ Invoke-GitHubUpload `
+ -Uri "$($UploadURL)?name=$($Asset.Key)" `
+ -Method POST `
+ -InFile $Asset.Value `
+ -ValidResults @(201)
+ }
+}
+
+# Try to determine what the current tag is.
+Push-Location $PSScriptRoot
+try {
+ $Tag = git describe --tags --exact
+ if ($LASTEXITCODE -Ne 0) {
+ Write-Host -ForegroundColor Yellow "This will only work for tagged releases, my friend." | Out-Null
+ Exit 0
+ }
+ $CommitSHA = git rev-parse HEAD
+} finally {
+ Pop-Location
+}
+
+$Release = Get-KormanRelease
+Publish-KormanReleaseAssets $Release