diff --git a/.github/workflows/all-builds.yml b/.github/workflows/all-builds.yml index 2596ad4..dedf9a8 100644 --- a/.github/workflows/all-builds.yml +++ b/.github/workflows/all-builds.yml @@ -6,9 +6,9 @@ on: workflow_dispatch: jobs: - Build-Qtk: + Qtk: env: - CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=ON -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=OFF + CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=ON -DQTK_PLUGINS=OFF -DQTK_EXAMPLE=ON strategy: fail-fast: false matrix: @@ -16,10 +16,13 @@ jobs: include: - os: ubuntu-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) - os: windows-latest cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG + flags: '' - os: macos-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) runs-on: ${{ matrix.os }} steps: @@ -44,33 +47,24 @@ jobs: sudo apt update -y sudo apt install libxcb-cursor0 -y - - name: Configure Qtk Application (Windows) - if: matrix.os == 'windows-latest' + - name: Configure Qtk Application shell: bash run: cmake -B build/ ${{ matrix.cmake }} - - name: Build Qtk Application (Windows) - if: matrix.os == 'windows-latest' + - name: Build Qtk Application shell: bash - run: cmake --build build/ --config Release + run: cmake --build build/ --config Release --target qtk_gui ${{ matrix.flags }} - # OSX / Linux - - - name: Configure Qtk Application (OSX / Linux) + - name: Build Qtk Example if: matrix.os != 'windows-latest' shell: bash - run: cmake -B build/ ${{ matrix.cmake }} - - - name: Build Qtk Application (OSX / Linux) - if: matrix.os != 'windows-latest' - shell: bash - run: cmake --build build/ --config Release --target qtk_app -- -j $(nproc) + run: cmake --build build/ --config Release --target qtk_example ${{ matrix.flags }} # Packaging - name: Install Qtk Application shell: bash - run: cmake --install build/ --config Release --prefix=$(pwd)/install --component qtk + run: cmake --install build/ --config Release --component qtk_gui - name: Package Qtk Application shell: bash @@ -87,7 +81,7 @@ jobs: if: matrix.os == 'ubuntu-latest' uses: actions/upload-artifact@v3 with: - name: qtk-app-${{ matrix.os }} + name: qtk-gui-${{ matrix.os }} path: | build/packages/*.deb @@ -102,7 +96,7 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/upload-artifact@v3 with: - name: qtk-app-${{ matrix.os }} + name: qtk-gui-${{ matrix.os }} path: | build/packages/*.exe @@ -117,14 +111,14 @@ jobs: if: matrix.os == 'macos-latest' uses: actions/upload-artifact@v3 with: - name: qtk-app-${{ matrix.os }} + name: qtk-gui-${{ matrix.os }} path: | build/packages/*.tar.gz - name: Upload Qtk install directory uses: actions/upload-artifact@v3 with: - name: qtk-app-${{ matrix.os }}-install + name: qtk-gui-${{ matrix.os }}-installdir path: install/* # TODO: Enable after trimming resources. @@ -142,9 +136,9 @@ jobs: # build/packages/* # !build/packages/_CPack_Packages/* - Build-Qtk-Library: + Qtk-Library: env: - CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=OFF + CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=OFF -DQTK_PLUGINS=OFF -DQTK_EXAMPLE=OFF strategy: fail-fast: false matrix: @@ -152,10 +146,13 @@ jobs: include: - os: ubuntu-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) - os: windows-latest cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG + flags: '' - os: macos-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) runs-on: ${{ matrix.os }} steps: @@ -174,33 +171,19 @@ jobs: with: args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1 - - name: Configure Qtk Library (Windows) - if: matrix.os == 'windows-latest' + - name: Configure Qtk Library shell: bash run: cmake -B build/ ${{ matrix.cmake }} - - name: Build Qtk Library (Windows) - if: matrix.os == 'windows-latest' + - name: Build Qtk Library shell: bash - run: cmake --build build/ --config Release - - # OSX / Linux - - - name: Configure Qtk Library (OSX / Linux) - if: matrix.os != 'windows-latest' - shell: bash - run: cmake -B build/ ${{ matrix.cmake }} - - - name: Build Qtk Library (OSX / Linux) - if: matrix.os != 'windows-latest' - shell: bash - run: cmake --build build/ --config Release --target qtk_library -- -j $(nproc) + run: cmake --build build/ --config Release --target qtk_library -- ${{ matrix.flags }} # Packaging - name: Install Qtk Library shell: bash - run: cmake --install build/ --config Release --prefix=$(pwd)/install --component libqtk + run: cmake --install build/ --config Release --prefix=$(pwd)/install --component qtk_library - name: Package Qtk Library shell: bash @@ -255,12 +238,12 @@ jobs: uses: actions/upload-artifact@v3 if: always() with: - name: libqtk-${{ matrix.os }}-install + name: libqtk-${{ matrix.os }}-installdir path: install/* - Build-Qtk-Plugins: + Qtk-Plugins: env: - CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=OFF -DQTK_INSTALL_PLUGINS=ON + CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=OFF -DQTK_PLUGINS=ON -DQTK_EXAMPLE=OFF strategy: fail-fast: false matrix: @@ -268,10 +251,13 @@ jobs: include: - os: ubuntu-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) - os: windows-latest cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG + flags: '' - os: macos-latest cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG + flags: -j $(nproc) runs-on: ${{ matrix.os }} steps: @@ -282,43 +268,27 @@ jobs: with: version: '6.5.0' - # Windows - - name: Chocolatey Action if: matrix.os == 'windows-latest' uses: crazy-max/ghaction-chocolatey@v2 with: args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1 - - name: Configure Qtk Plugins (Windows) - if: matrix.os == 'windows-latest' + - name: Configure Qtk Plugins shell: bash run: cmake -B build/ ${{ matrix.cmake }} - - name: Build Qtk Plugins (Windows) - if: matrix.os == 'windows-latest' + - name: Build Qtk Plugins shell: bash - run: cmake --build build/ --config Release --target qtk_collection - - # OSX / Linux - - - name: Configure Qtk Plugins (OSX / Linux) - if: matrix.os != 'windows-latest' - shell: bash - run: cmake -B build/ ${{ matrix.cmake }} - - - name: Build Qtk Plugins (OSX / Linux) - if: matrix.os != 'windows-latest' - shell: bash - run: cmake --build build/ --config Release --target qtk_collection -- -j $(nproc) + run: cmake --build build/ --config Release --target qtk_plugins -- ${{ matrix.flags }} # Packaging - name: Install Qtk Plugins shell: bash - run: cmake --install build/ --config Release --prefix=$(pwd)/install --component collection + run: cmake --install build/ --config Release --component qtk_plugins - Build-Qtk-Assimp-Targets: + Qtk-Assimp-Targets: strategy: fail-fast: false matrix: @@ -352,7 +322,7 @@ jobs: - name: Configure Qtk shell: bash - run: cmake -B build/ ${{ matrix.cmake }} -DQTK_ENABLE_CCACHE=OFF + run: cmake -B build/ ${{ matrix.cmake }} -DQTK_CCACHE=OFF - name: Build Qtk shell: bash diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8568d35..fd01ba9 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -21,8 +21,8 @@ jobs: - name: Build Qtk run: | - cmake -B build -DQTK_UPDATE_SUBMODULES=OFF -DQTK_ENABLE_CCACHE=OFF - cmake --build build + cmake -B build -DQTK_SUBMODULES=OFF -DQTK_CCACHE=OFF -DQTK_PLUGINS=OFF -DQTK_GUI=ON + cmake --build build --target qtk_gui -- -j $(nproc) - uses: cpp-linter/cpp-linter-action@v2 id: linter diff --git a/CMakeLists.txt b/CMakeLists.txt index 57cc0a2..e3a573a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,14 +46,13 @@ include(GNUInstallDirs) # Options ################################################################################ option(QTK_DEBUG "Enable debugger" OFF) -option(QTK_UPDATE_SUBMODULES "Update external project (assimp) submodule" OFF) -option(QTK_BUILD_GUI "Build the Qtk desktop application" ON) -option(QTK_INSTALL_LIBRARY "Install libqtk to CMAKE_INSTALL_PREFIX path." ON) -option(QTK_INSTALL_PLUGINS "Install Qtk plugin collection to Qt Creator." OFF) -option(QTK_BUILD_EXAMPLE "Build the Qtk example desktop application" ON) -option(QTK_ENABLE_CCACHE "Enable ccache" ON) +option(QTK_SUBMODULES "Update external project (assimp) submodule" OFF) +option(QTK_GUI "Build the Qtk desktop application" ON) +option(QTK_PLUGINS "Install Qtk plugins to Qt Creator path." OFF) +option(QTK_EXAMPLE "Build the Qtk example desktop application" ON) +option(QTK_CCACHE "Enable ccache" ON) -if (QTK_ENABLE_CCACHE) +if (QTK_CCACHE) set(CMAKE_CXX_COMPILER_LAUNCHER ccache) endif() @@ -61,28 +60,41 @@ endif() option(QTK_PREFIX_QTCREATOR "Install Qtk to Qt Creator. Untested." OFF) # Option for bringing your own assimp installation; Otherwise not needed -# + If assimp is available system-wide we can just set QTK_UPDATE_SUBMODULES OFF +# + If assimp is available system-wide we can just set QTK_SUBMODULES OFF option( QTK_ASSIMP_NEW_INTERFACE "Use the assimp::assimp interface (WIN / OSX)" OFF ) -if(NOT QTK_DEBUG) - set(CMAKE_BUILD_TYPE Release) -else() +if(QTK_DEBUG OR CMAKE_BUILD_TYPE MATCHES "^[Dd][Ee][Bb][Uu][Gg]$") + set(QTK_DEBUG ON) set(CMAKE_BUILD_TYPE Debug) +else() + set(QTK_DEBUG OFF) + set(CMAKE_BUILD_TYPE Release) endif() # This should be set to your Qt6 installation directory. -set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64" CACHE PATH "Path to Qt6 install.") +set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/lib/cmake" CACHE PATH "Path to Qt6 install.") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install") +endif () + +set(QTK_RESOURCES "${CMAKE_SOURCE_DIR}/resources") +set(QTK_OSX_ICONS ${CMAKE_SOURCE_DIR}/resources/icons/osx/kilroy.icns) + +# Print all QTK options and their values at the end of configuration. +get_cmake_property(VAR_NAMES VARIABLES) +list(FILTER VAR_NAMES INCLUDE REGEX "^Q[tT][kK]_.*$") +list(SORT VAR_NAMES) + +################################################################################ +# External Dependencies +################################################################################ # Point CMAKE_PREFIX_PATH to Qt6 install directory # If Qtk is built within Qt Creator this is not required. list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") -if (QTK_PREFIX_QTCREATOR) - # TODO: This might be a bit strange and needs more testing. - set(CMAKE_INSTALL_PREFIX "${QT_INSTALL_DIR}") -endif() set( QT_CREATOR_DIR @@ -133,8 +145,32 @@ if(NOT Qt6_FOUND) ) endif() +# +# To use custom plugins, set QT_PLUGIN_PATH environment variable before running designer +# Or, we can install plugins to the designer for use across all projects. +# Qt Creator on linux will look here for widget plugins in the integrated designer +# /home/shaun/Qt/Tools/QtCreator/lib/Qt/lib +# Qt Designer will use the following path on linux +# /home/shaun/Qt/6.5.0/gcc_64/plugins/designer/ +# We can use this path after find_package(Qt6) to install our plugins on all systems +# ${QT6_INSTALL_PREFIX}/${QT6_INSTALL_PLUGINS}/designer +# And run designer at ${QT6_INSTALL_PREFIX}/bin/designer +# Use cmake -DQTK_PLUGIN_INSTALL_DIR=/some/path to override this install path +set( + QTK_PLUGIN_INSTALL_DIR + "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_PLUGINS}/designer" CACHE PATH + "Path to install Qtk plugin collection." +) +# See cmake configure output for values of these variables on your system +set( + VAR_PATHS + CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX QTK_PLUGIN_INSTALL_DIR QT6_INSTALL_PREFIX + QT_INSTALL_DIR +) +list(APPEND VAR_NAMES QT6_INSTALL_PLUGINS) + # Find Assimp. -if(QTK_UPDATE_SUBMODULES) +if(QTK_SUBMODULES) # Required to statically link. add_compile_options(-fPIC) set(BUILD_SHARED_LIBS OFF CACHE STRING "Build static assimp libs" FORCE) @@ -166,8 +202,18 @@ endif() ################################################################################ add_subdirectory(src) -if(QTK_BUILD_EXAMPLE) +if(QTK_EXAMPLE) # Create a namespaced alias for linking with qtk_library in the example. add_library(${PROJECT_NAME}::qtk_library ALIAS qtk_library) - add_subdirectory(example-app) + add_subdirectory(example-app EXCLUDE_FROM_ALL) endif() + +foreach(VAR_NAME IN LISTS VAR_NAMES VAR_PATHS) + if(VAR_NAME IN_LIST VAR_PATHS) + # Print absolute if variable is path + get_filename_component(VAR_REALPATH "${${VAR_NAME}}" REALPATH) + message(STATUS "[Qtk] ${VAR_NAME}=${VAR_REALPATH}") + else() + message(STATUS "[Qtk] ${VAR_NAME}=${${VAR_NAME}}") + endif() +endforeach() diff --git a/README.md b/README.md index a1302b0..079218b 100644 --- a/README.md +++ b/README.md @@ -48,80 +48,51 @@ your system, **version 6.5.0** or later. Be sure to take note of the Qt6 installation directory, as we will need it to correctly set our `CMAKE_PREFIX_PATH` in the next steps. +If you are building on **Windows / Mac**, consider setting +the `-DASSIMP_NEW_INTERFACE` build flag. + If the build is configured with all options enabled, we can subsequently install individual components as needed with cmake. ```bash -cmake -B build-all/ -DQTK_BUILD_GUI=ON -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=ON -``` +sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache libgl1-mesa-dev libglvnd-dev -y +git clone https://github.com/shaunrd0/qtk +cd qtk +# Configure the build with all components enabled +cmake -B build-all -DQTK_GUI=ON -DQTK_PLUGINS=ON -DQTK_EXAMPLE=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 +# Build all targets +cmake --build build-all/ +```` + +By default, the build will not initialize Assimp as a git submodule and build +from source. +We can turn this on by setting the `-DQTK_SUBMODULES=ON` flag when running +CMake. +Building using this option will fetch and build Assimp for us, but builds will +take longer as a result. +Using `-DQTK_SUBMODULES=ON` supports providing assimp on cross-platform builds ( +Windows / Mac / Linux) and may be easier +to configure. ```bash -# Install libqtk only -cmake --install build-all/ --prefix=$(pwd)/install --component libqtk --- Install configuration: "Release" --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkConfig.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkConfigVersion.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkTargets.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/cmake/Qtk/QtkTargets-release.cmake --- Up-to-date: /home/shaun/Code/qtk/install/lib/static/libqtk_library.a --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/camera3d.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/input.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/meshrenderer.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/model.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/modelmesh.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/object.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkapi.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkiostream.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/qtkiosystem.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/scene.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/shape.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/skybox.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/texture.h --- Up-to-date: /home/shaun/Code/qtk/install/include/qtk/transform3D.h - -# Install Qtk widget collection to use Qt Designer -cmake --install build-all/ --prefix=$(pwd)/install --component collection --- Install configuration: "Release" --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_library.a --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_plugin_library.a --- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/plugins/designer/libqtk_collection.so - -# Install Qtk desktop application (output removed) -cmake --install build-all/ --prefix=$(pwd)/install --component qtk +cmake -B build-all -DQTK_GUI=ON -DQTK_PLUGINS=ON -DQTK_EXAMPLE=ON -DQTK_SUBMODULES=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 ``` #### Qtk GUI -Once Qt6 is installed, to build and run `qtk` on Ubuntu - - ```bash -sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache -y -git clone https://github.com/shaunrd0/qtk -cmake -S qtk/ -B qtk/build/ -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -cmake --build qtk/build/ -j $(nproc --ignore=2) -./qtk/build/bin/qtk-main -``` - -By default, the build will not initialize Assimp as a git submodule and build -from source. -We can turn this on by setting the `-DQTK_UPDATE_SUBMODULES=ON` flag when -running CMake. -Building using this option will fetch and build Assimp for us, but builds will -take longer as a result. -Using `-DQTK_UPDATE_SUBMODULES=ON` supports providing assimp on cross-platform -builds (Windows / Mac / Linux) and may be easier to configure. - -```bash -cmake -S qtk/ -B qtk/build/ -DQTK_UPDATE_SUBMODULES=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -cmake --build qtk/build/ -j $(nproc --ignore=2) -./qtk/build/bin/qtk-main +cmake --build build-all/ --target qtk_gui -- -j $(nproc) +# Install Qtk desktop application (output removed) +# Installation prefix path must be absolute, since Qtk uses Qt deploy tools. +cmake --install build-all/ --component qtk_gui --prefix=$(pwd)/install +./install/bin/qtk_gui ``` If any errors are encountered loading plugins, we can debug plugin loading by setting the following environment variable - ```bash -QT_DEBUG_PLUGINS=1 ./qtk-main +QT_DEBUG_PLUGINS=1 ./install/bin/qtk_gui ``` #### Qtk Library @@ -131,12 +102,10 @@ We can install this library on a system path or a custom path and then set `CMAKE_PREFIX_PATH` to point to this location when building an application using libqtk. -Below is an example of installing on a system path. - ```bash -cmake -S qtk/ -B qtk/build/ -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_PLUGINS=OFF -DQTK_DEBUG=OFF -cmake --build qtk/build/ -j $(nproc --ignore=2) -sudo cmake --install . --prefix=/usr/local +# Install libqtk only +cmake --build build-all/ --target qtk_library -- -j $(nproc) +cmake --install build-all/ --component qtk_library --prefix=/usr/local -- Install configuration: "Release" -- Installing: /usr/local/lib/cmake/Qtk/QtkConfig.cmake -- Installing: /usr/local/lib/cmake/Qtk/QtkConfigVersion.cmake @@ -175,9 +144,14 @@ interfaces. To build and install the Qtk plugin collection - ```bash -cmake -S /path/to/qtk -B /path/to/qtk/build -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64 -DQTK_INSTALL_PLUGINS=ON -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=OFF -cmake --build /path/to/qtk/build -cmake --install /path/to/qtk/build +cmake --build build-all/ --target qtk_plugins -- -j $(nproc) +# Install Qtk widget collection to use Qt Designer +# The path here should be initialized during build configuration, so no need for --prefix +cmake --install build-all/ --component qtk_plugins +-- Install configuration: "Release" +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_library.a +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_plugin_library.a +-- Up-to-date: /home/shaun/Qt/6.5.0/gcc_64/../../Tools/QtCreator/lib/Qt/plugins/designer/libqtk_collection.so ``` To uninstall after a previous installation, we can run the following command @@ -187,16 +161,22 @@ from the root of the repository. xargs rm < build/install_manifest.txt ``` -#### Windows / MacOS +#### Qtk Example -If you are building on **Windows / Mac**, consider setting -the `-DASSIMP_NEW_INTERFACE` build flag. +There is a simple example of using libqtk in the [example-app/](example-app) +directory. The example can be built standalone using `find_package` or as a +target within any qtk build. ```bash -cmake -S qtk/ -B qtk/build/ -DASSIMP_NEW_INTERFACE=ON -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64;/path/to/assimp/ -cmake --build qtk/build/ -j $(nproc --ignore=2) +# Build the example from a configured qtk build tree +cmake --build build-all/ --target qtk_example -- -j $(nproc) +cmake --install build-all/ --component qtk_example --prefix=install +./install/bin/qtk_example ``` +See the README in the [example-app/](example-app) subdirectory for instructions +on standalone builds. + ### Controls You can fly around the scene if you hold the right mouse button and use WASD. @@ -253,7 +233,7 @@ CLion automatically. # Move to the root of the repo cd qtk # Build -cmake -B build && cmake --build build +cmake -B build && cmake --build build -- -j $(nproc) clang-tidy -p build/ --fix --config-file=.clang-tidy src/*.cpp src/*.h app/*.cpp app/*.h ``` @@ -261,7 +241,7 @@ Last we need to run `clang-format`, this can be done with the command directly. This will reformat all the code in the repository. ```bash -clang-format -i --style=file:.clang-format src/*.cpp src/*.h app/*.cpp app/*.h +clang-format -i --style=file:.clang-format src/app/*.cpp src/app/*.h src/qtk/*.cpp src/qtk/*.h example-app/*.cpp example-app/*.h ``` `clang-format` can be run with git integration (or CLion if you prefer). @@ -320,12 +300,8 @@ Any of the above options can be appended with `--trace-expand` to debug package generation issues. The contents of all packages will depend on how the build was configured. -If we are generating packages for *only* libqtk, we -set `-DQTK_INSTALL_LIBRARY=ON` -during the cmake configuration step. To generate packages for Qtk desktop application, we should -set `-DQTK_BUILD_GUI=ON`, and optionally `-DQTK_INSTALL_LIBRARY=ON` if we would -like to bundle libqtk with the desktop application. +set `-DQTK_GUI=ON`. If this option is not set we will only package libqtk. The NSIS installer will allow component-specific path modification for all of these installation components through a GUI install application. diff --git a/cmake/include/git_submodule.cmake b/cmake/include/git_submodule.cmake index 26274e2..33f2f03 100644 --- a/cmake/include/git_submodule.cmake +++ b/cmake/include/git_submodule.cmake @@ -10,7 +10,7 @@ find_package(Git) # _PATH: Path to git submodule location that we want to update # + submodule_update(extern/assimp) function(submodule_update _PATH) - if (NOT QTK_UPDATE_SUBMODULES) + if (NOT QTK_SUBMODULES) return() endif() diff --git a/cmake/templates/Config.cmake.in b/cmake/templates/Config.cmake.in index 8026caa..cd8a459 100644 --- a/cmake/templates/Config.cmake.in +++ b/cmake/templates/Config.cmake.in @@ -2,8 +2,12 @@ include("${CMAKE_CURRENT_LIST_DIR}/QtkTargets.cmake") -set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_app") +set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_gui") set_and_check(QTK_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include") set_and_check(QTK_LIBRARIES "${PACKAGE_PREFIX_DIR}/lib") +set_and_check(Qtk_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_gui") +set_and_check(Qtk_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include") +set_and_check(Qtk_LIBRARIES "${PACKAGE_PREFIX_DIR}/lib") + check_required_components(Qtk) diff --git a/example-app/CMakeLists.txt b/example-app/CMakeLists.txt index 673b8a3..fb92b2c 100644 --- a/example-app/CMakeLists.txt +++ b/example-app/CMakeLists.txt @@ -22,7 +22,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") endif() # If you did not install Qtk on a system path, point cmake to installation. -set(QTK_PATH /usr/local CACHE PATH "Path to installation of Qtk") +set( + QTK_PATH ../build/install/lib/cmake/Qtk + CACHE PATH "Path to installation of Qtk" + FORCE +) # If you did not install Qt6 on a system path, point cmake to installation. set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/" CACHE PATH "Path to Qt6") @@ -40,12 +44,6 @@ project( list(APPEND CMAKE_PREFIX_PATH "${QTK_PATH}") list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") -# Allow add_subdirectory on this project to use target ALIAS if available. -# If this example project is opened standalone we will use find_package. -if(NOT TARGET Qtk::qtk_library) - find_package(Qtk 0.2 REQUIRED) -endif() - # Print all QTK variables if (NOT Qtk_IS_TOP_LEVEL) get_cmake_property(VAR_NAMES VARIABLES) @@ -56,6 +54,12 @@ if (NOT Qtk_IS_TOP_LEVEL) endforeach() endif() +# Allow add_subdirectory on this project to use target ALIAS if available. +# If this example project is opened standalone we will use find_package. +if(NOT TARGET Qtk::qtk_library) + find_package(Qtk 0.2 REQUIRED) +endif() + find_package(Qt6 COMPONENTS Core Widgets OpenGLWidgets REQUIRED) set( @@ -65,6 +69,28 @@ set( examplewidget.cpp examplewidget.h ) -add_executable(example_app ${EXAMPLE_SOURCES}) -target_link_libraries(example_app PUBLIC Qt6::Widgets Qt6::OpenGLWidgets Qt6::Core) -target_link_libraries(example_app PUBLIC Qtk::qtk_library) +configure_file( + #[[INPUT]] "${CMAKE_CURRENT_SOURCE_DIR}/resources.h.in" + #[[OUTPUT]] "${CMAKE_CURRENT_BINARY_DIR}/resources.h" + @ONLY +) + +qt_add_executable(qtk_example ${EXAMPLE_SOURCES}) +target_link_libraries(qtk_example PUBLIC Qt6::Widgets Qt6::OpenGLWidgets Qt6::Core) +target_link_libraries(qtk_example PUBLIC Qtk::qtk_library) +target_include_directories(qtk_example PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + +install( + TARGETS qtk_example + COMPONENT qtk_example + BUNDLE DESTINATION . + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + RUNTIME DESTINATION bin +) +qt_generate_deploy_app_script( + TARGET qtk_example + OUTPUT_SCRIPT QTK_EXAMPLE_DEPLOY_SCRIPT + NO_UNSUPPORTED_PLATFORM_ERROR +) +install(SCRIPT ${QTK_EXAMPLE_DEPLOY_SCRIPT} COMPONENT qtk_example) diff --git a/example-app/README.md b/example-app/README.md index 9dccf95..500ee10 100644 --- a/example-app/README.md +++ b/example-app/README.md @@ -62,11 +62,12 @@ custom installation directory. ```bash cmake -S /path/to/qtk/example-app/ -B /path/to/qtk/example-app/build -DQTK_PATH=/path/to/qtk/install/ -cmake --build /path/to/qtk/example-app/build +cmake --build /path/to/qtk/example-app/build --target qtk_example -- -j $(nproc) +cmake --install build/ --component qtk_example ``` After this, we can run the example application - ```bash -./path/to/qtk/example-app/build/bin/example +./path/to/qtk/example-app/build/install/bin/example ``` diff --git a/example-app/examplescene.cpp b/example-app/examplescene.cpp index 8e14f36..e812e79 100644 --- a/example-app/examplescene.cpp +++ b/example-app/examplescene.cpp @@ -7,6 +7,7 @@ ##############################################################################*/ #include "examplescene.h" +#include using namespace Qtk; @@ -23,8 +24,10 @@ void ExampleScene::init() { setSkybox(skybox); auto spartan = new Model( - "spartan", "/home/kapper/Code/qtk/resources/models/spartan/spartan.obj"); + "spartan", std::string(QTK_EXAMPLE_SOURCE_DIR) + + "/../resources/models/spartan/spartan.obj"); addObject(spartan); + spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f); auto mesh = addObject( new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ARRAYS))); diff --git a/example-app/resources.h.in b/example-app/resources.h.in new file mode 100644 index 0000000..14e4c24 --- /dev/null +++ b/example-app/resources.h.in @@ -0,0 +1,6 @@ +#ifndef QTK_RESOURCES_H_IN_H +#define QTK_RESOURCES_H_IN_H + +#define QTK_EXAMPLE_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@" + +#endif // QTK_RESOURCES_H_IN_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 982c95f..29e4e48 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,14 +13,14 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - COMPONENT libqtk + COMPONENT qtk_library DESTINATION lib/cmake/${PROJECT_NAME} ) install( EXPORT qtk_export FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME}:: - COMPONENT libqtk + COMPONENT qtk_library DESTINATION lib/cmake/${PROJECT_NAME} ) # System install for qtk_library @@ -28,53 +28,45 @@ install( TARGETS qtk_library # Associate qtk_library target with qtk-export EXPORT qtk_export - COMPONENT libqtk + COMPONENT qtk_library FILE_SET HEADERS DESTINATION include INCLUDES DESTINATION include LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib/static + ARCHIVE DESTINATION lib RUNTIME DESTINATION bin ) # Qtk Application -if(QTK_BUILD_GUI OR QTK_INSTALL_PLUGINS) +if(QTK_GUI OR QTK_PLUGINS) add_subdirectory(app) endif() -if(QTK_INSTALL_PLUGINS) - # Optionally install custom Qtk plugins for Qt Designer. +if(QTK_PLUGINS) install( - TARGETS qtk_library qtk_plugin_library - COMPONENT collection - LIBRARY DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" - ARCHIVE DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" - RUNTIME DESTINATION "${QTK_PLUGIN_LIBRARY_DIR}" - ) - install( - TARGETS qtk_collection - COMPONENT collection + TARGETS qtk_plugins qtk_library qtk_plugin_library + COMPONENT qtk_plugins LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" ARCHIVE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" ) endif() -if(QTK_BUILD_GUI) +if(QTK_GUI) install( - TARGETS qtk_app - COMPONENT qtk + TARGETS qtk_gui + COMPONENT qtk_gui BUNDLE DESTINATION . LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib/static + ARCHIVE DESTINATION lib RUNTIME DESTINATION bin ) qt_generate_deploy_app_script( - TARGET qtk_app + TARGET qtk_gui OUTPUT_SCRIPT QTK_DEPLOY_SCRIPT NO_UNSUPPORTED_PLATFORM_ERROR ) - install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk) + install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk_gui) if(WIN32) if(MSVC AND TARGET Qt6::qmake) @@ -87,7 +79,7 @@ if(QTK_BUILD_GUI) ) file(TO_NATIVE_PATH "${QT6_INSTALL_PREFIX}/bin" QT6_INSTALL_PREFIX) - set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_app.vcxproj.user") + set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_gui.vcxproj.user") file(WRITE ${VSUSER_FILE} "\n") file(APPEND ${VSUSER_FILE} "\n") file(APPEND ${VSUSER_FILE} " \n") @@ -124,7 +116,7 @@ set(CPACK_THREADS 0) set(CPACK_PACKAGE_INSTALL_DIRECTORY "Qtk") # Remove any assimp components if defined by submodule. -if (QTK_UPDATE_SUBMODULES) +if (QTK_SUBMODULES) get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS) list(FILTER CPACK_COMPONENTS_ALL EXCLUDE REGEX .*assimp.*) list(REMOVE_ITEM CPACK_COMPONENTS_ALL Unspecified) @@ -136,7 +128,7 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) # https://nsis.sourceforge.io/Reference/CreateShortCut set( CPACK_NSIS_CREATE_ICONS_EXTRA - "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_app.exe'" + "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_gui.exe'" ) set( CPACK_NSIS_DELETE_ICONS_EXTRA @@ -152,7 +144,7 @@ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) # OSX set(CPACK_BUNDLE_NAME ${PROJECT_NAME}) -set(CPACK_BUNDLE_PLIST $/Info.plist) +set(CPACK_BUNDLE_PLIST $/Info.plist) set(CPACK_BUNDLE_ICON ${QTK_OSX_ICONS}) # Platform defaults for source bundles. diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 6bbfcb6..5f85378 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -33,32 +33,32 @@ target_sources( target_link_libraries(qtk_plugin_library PUBLIC Qt6::UiPlugin qtk_library) ################################################################################ -# Qtk Widget Collection Plugin +# Qtk Widget Plugins ################################################################################ # Create a Qt Designer plugin for a collection of widgets from our library. -qt_add_plugin(qtk_collection SHARED) +qt_add_plugin(qtk_plugins SHARED) target_sources( - qtk_collection PRIVATE + qtk_plugins PRIVATE widgetplugincollection.cpp widgetplugincollection.h widgetplugin.cpp widgetplugin.h ) -target_link_libraries(qtk_collection PUBLIC qtk_plugin_library) +target_link_libraries(qtk_plugins PUBLIC qtk_plugin_library) ################################################################################ # Final Qtk Application ################################################################################ set( - QTK_APP_SOURCES + QTK_GUI_SOURCES qtkscene.cpp qtkscene.h main.cpp ) -qt_add_executable(qtk_app ${QTK_APP_SOURCES}) -target_link_libraries(qtk_app PRIVATE qtk_plugin_library) +qt_add_executable(qtk_gui ${QTK_GUI_SOURCES}) +target_link_libraries(qtk_gui PRIVATE qtk_plugin_library) set_target_properties( - qtk_app PROPERTIES + qtk_gui PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE MACOSX_BUNDLE_BUNDLE_NAME Qtk diff --git a/src/app/qtkwidget.cpp b/src/app/qtkwidget.cpp index 4fd448e..afdb7ac 100644 --- a/src/app/qtkwidget.cpp +++ b/src/app/qtkwidget.cpp @@ -10,6 +10,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -29,22 +34,8 @@ QtkWidget::QtkWidget(QWidget * parent) : QtkWidget(parent, "QtkWidget") {} QtkWidget::QtkWidget(QWidget * parent, const QString & name) : QtkWidget(parent, name, Q_NULLPTR) {} -QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) : - QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR), - mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) { - setAcceptDrops(true); - setScene(scene); - setObjectName(name); - QSurfaceFormat format; - format.setRenderableType(QSurfaceFormat::OpenGL); - format.setProfile(QSurfaceFormat::CoreProfile); - format.setVersion(4, 6); - // Set the number of samples used for glEnable(GL_MULTISAMPLING) - format.setSamples(4); - // Set the size of the depth bufer for glEnable(GL_DEPTH_TEST) - format.setDepthBufferSize(16); - // If QTK_DEBUG is set, enable debug context - format.setOption(QSurfaceFormat::DebugContext); +QtkWidget::QtkWidget(const QSurfaceFormat & format) : + mScene(Q_NULLPTR), mDebugLogger(Q_NULLPTR) { setFormat(format); setFocusPolicy(Qt::ClickFocus); } @@ -198,6 +189,31 @@ void QtkWidget::mouseReleaseEvent(QMouseEvent * event) { Input::registerMouseRelease(event->button()); } +void QtkWidget::keyPressEvent(QKeyEvent * event) { + if(event->isAutoRepeat()) { + // Do not repeat input while a key is held down + event->ignore(); + } else { + Input::registerKeyPress(event->key()); + } +} + +void QtkWidget::keyReleaseEvent(QKeyEvent * event) { + if(event->isAutoRepeat()) { + event->ignore(); + } else { + Input::registerKeyRelease(event->key()); + } +} + +void QtkWidget::mousePressEvent(QMouseEvent * event) { + Input::registerMousePress(event->button()); +} + +void QtkWidget::mouseReleaseEvent(QMouseEvent * event) { + Input::registerMouseRelease(event->button()); +} + void QtkWidget::update() { updateCameraInput(); @@ -283,6 +299,44 @@ void QtkWidget::messageLogged(const QOpenGLDebugMessage & msg) { void QtkWidget::teardownGL() { /* Nothing to teardown yet... */ } +void QtkWidget::updateCameraInput() { + Input::update(); + // Camera Transformation + if(Input::buttonPressed(Qt::RightButton)) { + static const float transSpeed = 0.1f; + static const float rotSpeed = 0.5f; + + // Handle rotations + Scene::getCamera().getTransform().rotate( + -rotSpeed * Input::mouseDelta().x(), Camera3D::LocalUp); + Scene::getCamera().getTransform().rotate( + -rotSpeed * Input::mouseDelta().y(), Scene::getCamera().getRight()); + + // Handle translations + QVector3D translation; + if(Input::keyPressed(Qt::Key_W)) { + translation += Scene::getCamera().getForward(); + } + if(Input::keyPressed(Qt::Key_S)) { + translation -= Scene::getCamera().getForward(); + } + if(Input::keyPressed(Qt::Key_A)) { + translation -= Scene::getCamera().getRight(); + } + if(Input::keyPressed(Qt::Key_D)) { + translation += Scene::getCamera().getRight(); + } + if(Input::keyPressed(Qt::Key_Q)) { + translation -= Scene::getCamera().getUp() / 2.0f; + } + if(Input::keyPressed(Qt::Key_E)) { + translation += Scene::getCamera().getUp() / 2.0f; + } + Scene::getCamera().getTransform().translate(transSpeed * translation); + } +void QtkWidget::teardownGL() { /* Nothing to teardown yet... */ +} + void QtkWidget::updateCameraInput() { Input::update(); // Camera Transformation diff --git a/src/qtk/CMakeLists.txt b/src/qtk/CMakeLists.txt index 42b9dcc..e67f83b 100644 --- a/src/qtk/CMakeLists.txt +++ b/src/qtk/CMakeLists.txt @@ -68,7 +68,7 @@ target_link_libraries( Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets ) -if(QTK_UPDATE_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE) +if(QTK_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE) target_link_libraries(qtk_library PUBLIC assimp) elseif(ASSIMP_NEW_INTERFACE) target_link_libraries(qtk_library PUBLIC assimp::assimp)