Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Transporter | d0c8316f79 | |
Shaun Reed | ad59d9149e |
|
@ -5,21 +5,27 @@ on:
|
|||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
QT_VERSION: 6.6.0
|
||||
|
||||
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:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
- os: windows-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG
|
||||
flags: ''
|
||||
- os: macos-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -28,7 +34,7 @@ jobs:
|
|||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: '6.5.0'
|
||||
version: ${{ env.QT_VERSION }}
|
||||
|
||||
# Windows
|
||||
|
||||
|
@ -44,33 +50,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 +84,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 +99,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 +114,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 }}-install
|
||||
path: install/*
|
||||
|
||||
# TODO: Enable after trimming resources.
|
||||
|
@ -142,20 +139,23 @@ 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:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
- os: windows-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG
|
||||
flags: ''
|
||||
- os: macos-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -164,7 +164,7 @@ jobs:
|
|||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: '6.5.0'
|
||||
version: ${{ env.QT_VERSION }}
|
||||
|
||||
# Windows
|
||||
|
||||
|
@ -174,33 +174,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
|
||||
|
@ -258,20 +244,23 @@ jobs:
|
|||
name: libqtk-${{ matrix.os }}-install
|
||||
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:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
- os: windows-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG
|
||||
flags: ''
|
||||
- os: macos-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG
|
||||
flags: -j $(nproc)
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -280,9 +269,7 @@ jobs:
|
|||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: '6.5.0'
|
||||
|
||||
# Windows
|
||||
version: ${{ env.QT_VERSION }}
|
||||
|
||||
- name: Chocolatey Action
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
@ -290,44 +277,30 @@ jobs:
|
|||
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:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/
|
||||
- os: macos-latest
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ -DASSIMP_NEW_INTERFACE=ON
|
||||
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -336,7 +309,7 @@ jobs:
|
|||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: '6.5.0'
|
||||
version: ${{ env.QT_VERSION }}
|
||||
|
||||
- name: Install Assimp MacOS
|
||||
if: matrix.os == 'macos-latest'
|
||||
|
@ -352,7 +325,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 -DQTK_ASSIMP_NEW_INTERFACE=ON
|
||||
|
||||
- name: Build Qtk
|
||||
shell: bash
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# CLion
|
||||
**/.idea/**
|
||||
|
||||
# VS Code
|
||||
**/.vscode/**
|
||||
|
||||
# CMake build files
|
||||
**/cmake-build-debug/**
|
||||
**/build/**
|
||||
|
|
101
CMakeLists.txt
101
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,21 +60,30 @@ 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)
|
||||
|
||||
# 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}")
|
||||
|
@ -89,31 +97,13 @@ set(
|
|||
"${QT_INSTALL_DIR}/../../Tools/QtCreator"
|
||||
CACHE PATH "Qt Creator path used to install Qtk plugins for Qt Designer."
|
||||
)
|
||||
# Qt Designer will look in different locations if WIN / Unix.
|
||||
# These paths are for using Qt Designer integrated within Qt Creator.
|
||||
# Standalone Qt Designer may use different paths.
|
||||
if (WIN32)
|
||||
# These paths may be different on windows. I have not tested this.
|
||||
set(QT_PLUGIN_INSTALL_DIR "${QT_CREATOR_DIR}/bin/plugins/designer")
|
||||
set(QT_PLUGIN_LIBRARY_DIR "${QT_CREATOR_DIR}/lib/Qt/lib")
|
||||
else()
|
||||
set(QT_PLUGIN_INSTALL_DIR "${QT_CREATOR_DIR}/lib/Qt/plugins/designer")
|
||||
set(QT_PLUGIN_LIBRARY_DIR "${QT_CREATOR_DIR}/lib/Qt/lib")
|
||||
endif()
|
||||
set(QTK_PLUGIN_LIBRARY_DIR "${QT_PLUGIN_LIBRARY_DIR}")
|
||||
set(QTK_PLUGIN_INSTALL_DIR "${QT_PLUGIN_INSTALL_DIR}")
|
||||
|
||||
message(STATUS "[Qtk] CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
|
||||
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.
|
||||
# Print all QTK options and their values at the end of configuration.
|
||||
# We initialize this list here so that we can append to it as needed.
|
||||
# All variables in this list will be printed at the end of configuration.
|
||||
get_cmake_property(VAR_NAMES VARIABLES)
|
||||
list(FILTER VAR_NAMES INCLUDE REGEX "^Q[tT][kK]_.*$")
|
||||
list(FILTER VAR_NAMES INCLUDE REGEX "^[qQ][tT][kK]_.*$")
|
||||
list(SORT VAR_NAMES)
|
||||
foreach(VAR_NAME ${VAR_NAMES})
|
||||
message(STATUS "[Qtk] ${VAR_NAME}=${${VAR_NAME}}")
|
||||
endforeach()
|
||||
|
||||
################################################################################
|
||||
# External Dependencies
|
||||
|
@ -133,8 +123,33 @@ 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
|
||||
)
|
||||
# Add QT6_INSTALL_PLUGINS to VAR_NAMES so it is printed at end of configuration.
|
||||
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 +181,20 @@ 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()
|
||||
|
||||
# Print all QTK options and their values at the end of configuration. This also
|
||||
# prints any additional variables that we have added to VAR_NAMES and VAR_PATHS.
|
||||
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()
|
||||
|
|
134
README.md
134
README.md
|
@ -40,88 +40,59 @@ and [Qt Creator](https://github.com/qt-creator/qt-creator).
|
|||
Simply open the root `CMakeLists.txt` with either of these editors and
|
||||
configurations will be loaded.
|
||||
|
||||
This project has been ported to **Qt 6.5.0**, which is not yet available in
|
||||
This project has been ported to **Qt 6.6.0**, which is not yet available in
|
||||
Ubuntu apt repositories.
|
||||
To run this project, you will *need* to
|
||||
install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for
|
||||
your system, **version 6.5.0** or later.
|
||||
your system, **version 6.6.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 `-DQTK_ASSIMP_NEW_INTERFACE` cmake build option.
|
||||
|
||||
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 zlib1g-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.6.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.6.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.6.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_library.a
|
||||
-- Up-to-date: /home/shaun/Qt/6.6.0/gcc_64/../../Tools/QtCreator/lib/Qt/lib/libqtk_plugin_library.a
|
||||
-- Up-to-date: /home/shaun/Qt/6.6.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.
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
##############################################################################*/
|
||||
|
||||
#include "examplescene.h"
|
||||
#include <resources.h>
|
||||
|
||||
using namespace Qtk;
|
||||
|
||||
|
@ -22,9 +23,11 @@ void ExampleScene::init() {
|
|||
auto skybox = new Qtk::Skybox("Skybox");
|
||||
setSkybox(skybox);
|
||||
|
||||
auto spartan = new Model(
|
||||
"spartan", "/home/kapper/Code/qtk/resources/models/spartan/spartan.obj");
|
||||
std::string spartanPath = QTK_EXAMPLE_SOURCE_DIR;
|
||||
spartanPath += "/resources/models/spartan/spartan.obj";
|
||||
auto spartan = new Model("spartan", spartanPath.c_str());
|
||||
addObject(spartan);
|
||||
spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f);
|
||||
|
||||
auto mesh = addObject(
|
||||
new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ARRAYS)));
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef QTK_RESOURCES_H_IN_H
|
||||
#define QTK_RESOURCES_H_IN_H
|
||||
|
||||
#define QTK_EXAMPLE_SOURCE_DIR "@CMAKE_SOURCE_DIR@"
|
||||
|
||||
#endif // QTK_RESOURCES_H_IN_H
|
|
@ -1 +1 @@
|
|||
Subproject commit eb328ce69dd7b06977aed125e967a41e835b8431
|
||||
Subproject commit 5d5496f1ad895297cede723b3c96b513263f82ed
|
Binary file not shown.
After Width: | Height: | Size: 3.8 MiB |
|
@ -1,5 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/textures">
|
||||
<file alias="plaster.png">images/plaster.png</file>
|
||||
<file alias="crate.png">images/crate.png</file>
|
||||
<file alias="stone.png">images/stone.png</file>
|
||||
<file alias="wood.png">images/wood.png</file>
|
||||
|
|
|
@ -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} "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
||||
file(APPEND ${VSUSER_FILE} "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n")
|
||||
file(APPEND ${VSUSER_FILE} " <PropertyGroup>\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 $<TARGET_BUNDLE_CONTENT_DIR:qtk_app>/Info.plist)
|
||||
set(CPACK_BUNDLE_PLIST $<TARGET_BUNDLE_CONTENT_DIR:qtk_gui>/Info.plist)
|
||||
set(CPACK_BUNDLE_ICON ${QTK_OSX_ICONS})
|
||||
|
||||
# Platform defaults for source bundles.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,17 +29,30 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
|
|||
for(auto & qtkWidget : qtkWidgets) {
|
||||
qtkWidget->setScene(new Qtk::SceneEmpty);
|
||||
views_.emplace(qtkWidget->getScene()->getSceneName(), qtkWidget);
|
||||
|
||||
// Add GUI 'view' toolbar option to show debug console.
|
||||
ui_->menuView->addAction(qtkWidget->getActionToggleConsole());
|
||||
// Refresh GUI widgets when scene or objects are updated.
|
||||
connect(
|
||||
qtkWidget->getScene(), &Qtk::Scene::sceneUpdated, this,
|
||||
&MainWindow::refreshScene);
|
||||
connect(
|
||||
qtkWidget, &Qtk::QtkWidget::objectFocusChanged, ui_->qtk__ToolBox,
|
||||
&Qtk::ToolBox::updateFocus);
|
||||
}
|
||||
|
||||
auto docks = findChildren<QDockWidget *>();
|
||||
for(auto & dock : docks) {
|
||||
addDockWidget(Qt::RightDockWidgetArea, dock);
|
||||
ui_->menuView->addAction(dock->toggleViewAction());
|
||||
}
|
||||
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets.
|
||||
// For now we will add them manually, but we should be able to do this in the
|
||||
// designer. At the moment if you edit the UI in designer the dock widget
|
||||
// areas below will override the designer settings.
|
||||
|
||||
// Dock the toolbox widget to the main window.
|
||||
addDockWidget(Qt::LeftDockWidgetArea, ui_->qtk__ToolBox);
|
||||
// Add an option to toggle active widgets in the GUI's toolbar 'view' menu.
|
||||
ui_->menuView->addAction(ui_->qtk__ToolBox->toggleViewAction());
|
||||
|
||||
addDockWidget(Qt::RightDockWidgetArea, ui_->qtk__TreeView);
|
||||
ui_->menuView->addAction(ui_->qtk__TreeView->toggleViewAction());
|
||||
|
||||
// Set the window icon used for Qtk.
|
||||
setWindowIcon(Qtk::getIcon());
|
||||
|
@ -74,7 +87,7 @@ Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name) {
|
|||
return views_[name];
|
||||
}
|
||||
|
||||
void MainWindow::refreshScene(QString sceneName) {
|
||||
// TODO: Select TreeView using sceneName>
|
||||
void MainWindow::refreshScene(const QString & sceneName) {
|
||||
// TODO: Select TreeView using sceneName
|
||||
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class MainWindow : public QMainWindow {
|
|||
* Trigger a refresh for widgets related to a scene that has been updated.
|
||||
* @param sceneName The name of the scene that has been modified.
|
||||
*/
|
||||
void refreshScene(QString sceneName);
|
||||
void refreshScene(const QString & sceneName);
|
||||
|
||||
private:
|
||||
/***************************************************************************
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>824</width>
|
||||
<width>1034</width>
|
||||
<height>601</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -28,11 +28,27 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="Qtk::ToolBox" name="qtk::ToolBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Object details and configuration panel.</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>When an object is double-clicked in the TreeView for a scene, this panel will display relevant details and options.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
|
@ -50,10 +66,10 @@
|
|||
<item>
|
||||
<widget class="Qtk::QtkWidget" name="qtk::QtkWidget">
|
||||
<property name="toolTip">
|
||||
<string>A custom widget tool tip.</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Custom widget what's this?</string>
|
||||
<string>Qtk scene view rendered using OpenGL.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -66,30 +82,22 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="Qtk::TreeView" name="qtk::TreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>A custom widget tool tip.</string>
|
||||
<string>TreeView of objects within the current scene.</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Custom widget what's this?</string>
|
||||
<string>TreeView of objects within the current scene. Double-click to select an object and snap to it's position.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Qtk::ToolBox" name="qtk::ToolBox">
|
||||
<property name="toolTip">
|
||||
<string>A custom widget tool tip.</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>Custom widget what's this?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
|
@ -97,7 +105,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>824</width>
|
||||
<width>1034</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -179,7 +187,7 @@
|
|||
</widget>
|
||||
<action name="actionOpen">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resources/resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/folder-open.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/folder-open.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -188,7 +196,7 @@
|
|||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resources/resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/floppy-disk.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/floppy-disk.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -215,7 +223,7 @@
|
|||
</action>
|
||||
<action name="actionLoad_Model">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resources/resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/solid/cube.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/solid/cube.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -227,7 +235,7 @@
|
|||
</action>
|
||||
<action name="actionDelete_Object">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resources/resources.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/trash-can.svg</normaloff>:/icons/fontawesome-free-6.2.1-desktop/svgs/regular/trash-can.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -318,9 +326,7 @@
|
|||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionExit</sender>
|
||||
|
|
|
@ -38,11 +38,12 @@ void QtkScene::init() {
|
|||
/* Create a red cube with a mini master chief on top. */
|
||||
auto myCube = new MeshRenderer("My cube", Cube(Qtk::QTK_DRAW_ELEMENTS));
|
||||
myCube->setColor(RED);
|
||||
myCube->getTransform().setTranslation(5.0f, 0.0f, 0.0f);
|
||||
addObject(myCube);
|
||||
|
||||
auto mySpartan =
|
||||
new Model("My spartan", ":/models/models/spartan/spartan.obj");
|
||||
mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
|
||||
mySpartan->getTransform().setTranslation(5.0f, 0.5f, 0.0f);
|
||||
mySpartan->getTransform().setScale(0.5f);
|
||||
addObject(mySpartan);
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
##############################################################################*/
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QMimeData>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <qtk/input.h>
|
||||
#include <qtk/scene.h>
|
||||
#include <qtk/shape.h>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <qtk/input.h>
|
||||
|
@ -31,6 +37,7 @@ QtkWidget::QtkWidget(QWidget * parent, const QString & name) :
|
|||
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;
|
||||
|
@ -70,6 +77,7 @@ void QtkWidget::initializeGL() {
|
|||
// Connect the frameSwapped signal to call the update() function
|
||||
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
|
||||
|
||||
toggleConsole();
|
||||
// Initialize OpenGL debug context
|
||||
mDebugLogger = new QOpenGLDebugLogger(this);
|
||||
if(mDebugLogger->initialize()) {
|
||||
|
@ -107,11 +115,11 @@ void QtkWidget::paintGL() {
|
|||
}
|
||||
}
|
||||
|
||||
void QtkWidget::setScene(Qtk::Scene * scene) {
|
||||
void QtkWidget::setScene(Scene * scene) {
|
||||
if(mScene != Q_NULLPTR) {
|
||||
delete mScene;
|
||||
connect(
|
||||
scene, &Qtk::Scene::sceneUpdated, MainWindow::getMainWindow(),
|
||||
scene, &Scene::sceneUpdated, MainWindow::getMainWindow(),
|
||||
&MainWindow::refreshScene);
|
||||
}
|
||||
|
||||
|
@ -129,8 +137,7 @@ void QtkWidget::toggleConsole() {
|
|||
mConsoleActive = false;
|
||||
} else {
|
||||
MainWindow::getMainWindow()->addDockWidget(
|
||||
Qt::DockWidgetArea::BottomDockWidgetArea,
|
||||
dynamic_cast<QDockWidget *>(mConsole));
|
||||
Qt::DockWidgetArea::BottomDockWidgetArea, mConsole);
|
||||
mConsole->setHidden(false);
|
||||
mConsoleActive = true;
|
||||
}
|
||||
|
@ -140,6 +147,34 @@ void QtkWidget::toggleConsole() {
|
|||
* Protected Methods
|
||||
******************************************************************************/
|
||||
|
||||
void QtkWidget::dragEnterEvent(QDragEnterEvent * event) {
|
||||
if(event->mimeData()->hasFormat("text/plain")) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void QtkWidget::dropEvent(QDropEvent * event) {
|
||||
mConsole->sendLog(event->mimeData()->text());
|
||||
auto urls = event->mimeData()->urls();
|
||||
if(!urls.isEmpty()) {
|
||||
if(urls.size() > 1) {
|
||||
qDebug() << "Cannot accept drop of multiple files.";
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Support other object types.
|
||||
auto url = urls.front();
|
||||
if(url.fileName().endsWith(".obj")) {
|
||||
mScene->loadModel(url);
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
qDebug() << "Unsupported file type: " + url.fileName() + "\n";
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtkWidget::keyPressEvent(QKeyEvent * event) {
|
||||
if(event->isAutoRepeat()) {
|
||||
// Do not repeat input while a key is held down
|
||||
|
@ -253,7 +288,8 @@ void QtkWidget::teardownGL() { /* Nothing to teardown yet... */
|
|||
void QtkWidget::updateCameraInput() {
|
||||
Input::update();
|
||||
// Camera Transformation
|
||||
if(Input::buttonPressed(Qt::RightButton)) {
|
||||
if(Input::buttonPressed(Qt::LeftButton)
|
||||
|| Input::buttonPressed(Qt::RightButton)) {
|
||||
static const float transSpeed = 0.1f;
|
||||
static const float rotSpeed = 0.5f;
|
||||
|
||||
|
|
|
@ -131,11 +131,19 @@ namespace Qtk {
|
|||
*/
|
||||
void sendLog(const QString & message, DebugContext context = Status);
|
||||
|
||||
// TODO: Use this signal in treeview and toolbox to update object
|
||||
// properties
|
||||
void objectFocusChanged(const QString objectName);
|
||||
|
||||
protected:
|
||||
/*************************************************************************
|
||||
* Protected Methods
|
||||
************************************************************************/
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent * event) override;
|
||||
|
||||
void dropEvent(QDropEvent * event) override;
|
||||
|
||||
/**
|
||||
* @param event Key press event to update camera input manager.
|
||||
*/
|
||||
|
@ -166,6 +174,7 @@ namespace Qtk {
|
|||
/**
|
||||
* Called when the `messageLogged` signal is caught.
|
||||
* See definition of initializeGL()
|
||||
* https://doc.qt.io/qt-6/qopengldebuglogger.html#signals
|
||||
*
|
||||
* @param msg The message logged.
|
||||
*/
|
||||
|
|
|
@ -8,13 +8,142 @@
|
|||
*/
|
||||
|
||||
#include "toolbox.h"
|
||||
#include "qtkmainwindow.h"
|
||||
#include "ui_toolbox.h"
|
||||
|
||||
Qtk::ToolBox::ToolBox(QWidget * parent) :
|
||||
QDockWidget(parent), ui(new Ui::ToolBox) {
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace Qtk;
|
||||
|
||||
ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox) {
|
||||
ui->setupUi(this);
|
||||
setMinimumWidth(350);
|
||||
}
|
||||
|
||||
Qtk::ToolBox::~ToolBox() {
|
||||
void ToolBox::updateFocus(const QString & name) {
|
||||
auto object =
|
||||
MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name);
|
||||
if(object != Q_NULLPTR) {
|
||||
removePages();
|
||||
createPageProperties(object);
|
||||
createPageShader(object);
|
||||
}
|
||||
}
|
||||
|
||||
ToolBox::~ToolBox() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ToolBox::removePages() {
|
||||
// Remove all existing pages.
|
||||
for(size_t i = 0; i < ui->toolBox->count(); i++) {
|
||||
delete ui->toolBox->widget(i);
|
||||
ui->toolBox->removeItem(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolBox::createPageProperties(const Object * object) {
|
||||
auto transform = object->getTransform();
|
||||
auto type = object->getType();
|
||||
auto * widget = new QWidget;
|
||||
ui->toolBox->addItem(widget, "Properties");
|
||||
ui->toolBox->setCurrentWidget(widget);
|
||||
|
||||
auto * layout = new QFormLayout;
|
||||
layout->addRow(
|
||||
new QLabel(tr("Name:")), new QLabel(object->getName().c_str()));
|
||||
|
||||
layout->addRow(
|
||||
new QLabel(tr("Type:")),
|
||||
new QLabel(type == Object::Type::QTK_MESH ? "Mesh" : "Model"));
|
||||
|
||||
auto rowLayout = new QHBoxLayout;
|
||||
rowLayout->addWidget(new QLabel(tr("Translation:")));
|
||||
int minWidth = 75;
|
||||
for(size_t i = 0; i < 3; i++) {
|
||||
auto spinBox = new QDoubleSpinBox;
|
||||
spinBox->setMinimum(std::numeric_limits<double>::lowest());
|
||||
spinBox->setSingleStep(0.1);
|
||||
spinBox->setValue(transform.getTranslation()[i]);
|
||||
spinBox->setFixedWidth(minWidth);
|
||||
rowLayout->addWidget(spinBox);
|
||||
|
||||
if(i == 0) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object,
|
||||
&Object::setTranslationX);
|
||||
} else if(i == 1) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object,
|
||||
&Object::setTranslationY);
|
||||
} else if(i == 2) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object,
|
||||
&Object::setTranslationZ);
|
||||
}
|
||||
}
|
||||
layout->addRow(rowLayout);
|
||||
|
||||
rowLayout = new QHBoxLayout;
|
||||
rowLayout->addWidget(new QLabel(tr("Scale:")));
|
||||
for(size_t i = 0; i < 3; i++) {
|
||||
auto spinBox = new QDoubleSpinBox;
|
||||
spinBox->setMinimum(std::numeric_limits<double>::lowest());
|
||||
spinBox->setSingleStep(0.1);
|
||||
spinBox->setValue(transform.getScale()[i]);
|
||||
spinBox->setFixedWidth(minWidth);
|
||||
rowLayout->addWidget(spinBox);
|
||||
|
||||
if(i == 0) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleX);
|
||||
} else if(i == 1) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleY);
|
||||
} else if(i == 2) {
|
||||
connect(
|
||||
spinBox, &QDoubleSpinBox::valueChanged, object, &Object::setScaleZ);
|
||||
}
|
||||
}
|
||||
layout->addRow(rowLayout);
|
||||
widget->setLayout(layout);
|
||||
}
|
||||
|
||||
void ToolBox::createPageShader(const Object * object) {
|
||||
// Shaders page.
|
||||
auto widget = new QWidget;
|
||||
ui->toolBox->addItem(widget, "Shaders");
|
||||
auto mainLayout = new QFormLayout;
|
||||
auto rowLayout = new QHBoxLayout;
|
||||
rowLayout->addWidget(new QLabel("Vertex Shader:"));
|
||||
rowLayout->addWidget(new QLabel(object->getVertexShader().c_str()));
|
||||
mainLayout->addRow(rowLayout);
|
||||
|
||||
auto shaderView = new QTextEdit;
|
||||
shaderView->setReadOnly(true);
|
||||
auto vertexFile = QFile(object->getVertexShader().c_str());
|
||||
if(vertexFile.exists()) {
|
||||
vertexFile.open(QIODeviceBase::ReadOnly);
|
||||
shaderView->setText(vertexFile.readAll());
|
||||
vertexFile.close();
|
||||
mainLayout->addRow(shaderView);
|
||||
}
|
||||
|
||||
rowLayout = new QHBoxLayout;
|
||||
rowLayout->addWidget(new QLabel("Fragment Shader:"));
|
||||
rowLayout->addWidget(new QLabel(object->getFragmentShader().c_str()));
|
||||
mainLayout->addRow(rowLayout);
|
||||
|
||||
shaderView = new QTextEdit;
|
||||
shaderView->setReadOnly(true);
|
||||
auto fragmentfile = QFile(object->getFragmentShader().c_str());
|
||||
if(fragmentfile.exists()) {
|
||||
fragmentfile.open(QIODeviceBase::ReadOnly);
|
||||
shaderView->setText(fragmentfile.readAll());
|
||||
fragmentfile.close();
|
||||
mainLayout->addRow(shaderView);
|
||||
}
|
||||
|
||||
widget->setLayout(mainLayout);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
#include <QDesignerExportWidget>
|
||||
#include <QDockWidget>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QGroupBox>
|
||||
|
||||
|
||||
#include "qtk/scene.h"
|
||||
|
||||
namespace Ui {
|
||||
class ToolBox;
|
||||
|
@ -30,6 +35,15 @@ namespace Qtk {
|
|||
|
||||
~ToolBox();
|
||||
|
||||
void removePages();
|
||||
|
||||
void createPageProperties(const Object * object);
|
||||
|
||||
void createPageShader(const Object * object);
|
||||
|
||||
void updateFocus(const QString & name);
|
||||
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
|
|
|
@ -10,17 +10,57 @@
|
|||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>86</width>
|
||||
<height>167</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Object Details</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<widget class="QWidget" name="page_properties">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>382</width>
|
||||
<height>201</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Properties</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_shaders">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -33,19 +73,6 @@
|
|||
<string>Shaders</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>382</width>
|
||||
<height>201</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Properties</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -48,16 +48,25 @@ void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
|
|||
auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
|
||||
auto & transform = scene->getCamera().getTransform();
|
||||
auto object = scene->getObject(name);
|
||||
Transform3D * objectTransform;
|
||||
// If the object is a mesh or model, focus the camera on it.
|
||||
if(object == Q_NULLPTR) {
|
||||
qDebug() << "Attempt to get non-existing object with name '" << name
|
||||
<< "'\n";
|
||||
}
|
||||
Transform3D * objectTransform;
|
||||
if(object->getType() == Object::QTK_MESH) {
|
||||
} else if(object->getType() == Object::QTK_MESH) {
|
||||
objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform();
|
||||
} else if(object->getType() == Object::QTK_MODEL) {
|
||||
objectTransform = &dynamic_cast<Model *>(object)->getTransform();
|
||||
}
|
||||
transform.setTranslation(objectTransform->getTranslation());
|
||||
auto focusScale = objectTransform->getScale();
|
||||
float width = focusScale.x() / 2.0f;
|
||||
float height = focusScale.y() / 2.0f;
|
||||
QVector3D pos = objectTransform->getTranslation();
|
||||
// pos.setX(pos.x() + width);
|
||||
pos.setY(pos.y() + height);
|
||||
transform.setTranslation(pos);
|
||||
transform.translate(0.0f, 0.0f, 3.0f);
|
||||
|
||||
// Emit signal from qtk widget for new object focus. Triggers GUI updates.
|
||||
emit MainWindow::getMainWindow()->getQtkWidget()->objectFocusChanged(name);
|
||||
}
|
||||
|
|
|
@ -68,9 +68,9 @@ target_link_libraries(
|
|||
Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets
|
||||
)
|
||||
|
||||
if(QTK_UPDATE_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE)
|
||||
if(QTK_SUBMODULES OR NOT QTK_ASSIMP_NEW_INTERFACE)
|
||||
target_link_libraries(qtk_library PUBLIC assimp)
|
||||
elseif(ASSIMP_NEW_INTERFACE)
|
||||
elseif(QTK_ASSIMP_NEW_INTERFACE)
|
||||
target_link_libraries(qtk_library PUBLIC assimp::assimp)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -211,6 +211,14 @@ namespace Qtk {
|
|||
*/
|
||||
inline Transform3D & getTransform() { return mTransform; }
|
||||
|
||||
inline std::string getVertexShader() const override {
|
||||
return mVertexShader;
|
||||
}
|
||||
|
||||
inline std::string getFragmentShader() const override {
|
||||
return mFragmentShader;
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
|
|
|
@ -43,7 +43,7 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
|
|||
texture.mTexture->destroy();
|
||||
texture.mTexture->create();
|
||||
texture.mTexture->setData(
|
||||
*OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY));
|
||||
OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY));
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
|
|||
// Add the texture to the textures container
|
||||
textures.push_back(texture);
|
||||
// Add the texture to the loaded textures to avoid loading it twice
|
||||
mTexturesLoaded.push_back(texture);
|
||||
mTexturesLoaded.push_back(textures.back());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include <assimp/Importer.hpp>
|
||||
|
||||
// Qtk
|
||||
#include <QFileInfo>
|
||||
|
||||
|
||||
#include "modelmesh.h"
|
||||
#include "qtkapi.h"
|
||||
|
||||
|
@ -124,6 +127,14 @@ namespace Qtk {
|
|||
*/
|
||||
inline Transform3D & getTransform() { return mTransform; }
|
||||
|
||||
inline std::string getVertexShader() const override {
|
||||
return mVertexShader;
|
||||
}
|
||||
|
||||
inline std::string getFragmentShader() const override {
|
||||
return mFragmentShader;
|
||||
}
|
||||
|
||||
private:
|
||||
/*************************************************************************
|
||||
* Private Methods
|
||||
|
|
|
@ -52,6 +52,10 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
|
|||
shader.setUniformValue((name + number).c_str(), i);
|
||||
}
|
||||
|
||||
// Always reset active texture to GL_TEXTURE0 before we draw.
|
||||
// This is important for models with no textures.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Draw the mesh
|
||||
glDrawElements(
|
||||
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
|
||||
|
@ -62,7 +66,6 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
|
|||
}
|
||||
shader.release();
|
||||
mVAO->release();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -30,6 +30,21 @@ namespace Qtk {
|
|||
* Struct to store model textures. 3D Models may have multiple.
|
||||
*/
|
||||
struct QTKAPI ModelTexture {
|
||||
ModelTexture() = default;
|
||||
|
||||
/**
|
||||
* Construct a ModelTexture.
|
||||
*
|
||||
* @param id Texture ID for this texture.
|
||||
* @param type Type of texture in string format.
|
||||
* @param path Path to the texture on disk.
|
||||
*/
|
||||
ModelTexture(const std::string & type, const std::string & path) :
|
||||
mType(type), mPath(path) {
|
||||
mTexture = OpenGLTextureFactory::initTexture(path.c_str());
|
||||
mID = mTexture->textureId();
|
||||
}
|
||||
|
||||
/** Texture ID for for this texture. */
|
||||
GLuint mID {};
|
||||
QOpenGLTexture * mTexture {};
|
||||
|
|
|
@ -96,10 +96,24 @@ namespace Qtk {
|
|||
|
||||
[[nodiscard]] inline const Type & getType() const { return mType; }
|
||||
|
||||
[[nodiscard]] inline virtual const Transform3D & getTransform() const {
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline virtual std::string getVertexShader() const {
|
||||
return "Base Object has no vertex shader.";
|
||||
}
|
||||
|
||||
virtual inline std::string getFragmentShader() const {
|
||||
return "Base Object has no fragment shader.";
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Setters
|
||||
************************************************************************/
|
||||
|
||||
virtual inline void setName(const std::string & name) { mName = name; }
|
||||
|
||||
virtual inline void setColors(const Colors & value) {
|
||||
mShape.mColors = value;
|
||||
}
|
||||
|
@ -135,6 +149,39 @@ namespace Qtk {
|
|||
mShape.mVertices = value;
|
||||
}
|
||||
|
||||
inline void setScaleX(double x) {
|
||||
mTransform.setScale(
|
||||
x, mTransform.getScale().y(), mTransform.getScale().z());
|
||||
}
|
||||
|
||||
inline void setScaleY(double y) {
|
||||
mTransform.setScale(
|
||||
mTransform.getScale().x(), y, mTransform.getScale().z());
|
||||
}
|
||||
|
||||
inline void setScaleZ(double z) {
|
||||
mTransform.setScale(
|
||||
mTransform.getScale().x(), mTransform.getScale().y(), z);
|
||||
}
|
||||
|
||||
inline void setTranslationX(double x) {
|
||||
mTransform.setTranslation(
|
||||
x, mTransform.getTranslation().y(),
|
||||
mTransform.getTranslation().z());
|
||||
}
|
||||
|
||||
inline void setTranslationY(double y) {
|
||||
mTransform.setTranslation(
|
||||
mTransform.getTranslation().x(), y,
|
||||
mTransform.getTranslation().z());
|
||||
}
|
||||
|
||||
inline void setTranslationZ(double z) {
|
||||
mTransform.setTranslation(
|
||||
mTransform.getTranslation().x(), mTransform.getTranslation().y(),
|
||||
z);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Public Methods
|
||||
************************************************************************/
|
||||
|
|
|
@ -17,17 +17,23 @@ using namespace Qtk;
|
|||
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
|
||||
mFile(pFile) {
|
||||
QString mode(pMode);
|
||||
bool read = mode.contains('r');
|
||||
bool write = mode.contains('w');
|
||||
if(read && write) {
|
||||
mFile.open(QIODevice::ReadWrite);
|
||||
} else if(read) {
|
||||
mFile.open(QIODevice::ReadOnly);
|
||||
} else if(write) {
|
||||
mFile.open(QIODevice::WriteOnly);
|
||||
bool open = false;
|
||||
if(mode == "w" || mode == "wb") {
|
||||
open = mFile.open(QIODeviceBase::WriteOnly);
|
||||
} else if(mode == "r" || mode == "rb") {
|
||||
open = mFile.open(QIODeviceBase::ReadOnly);
|
||||
} else if(mode == "wt") {
|
||||
open = mFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text);
|
||||
} else if(mode == "rt") {
|
||||
open = mFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text);
|
||||
} else {
|
||||
open = false;
|
||||
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
|
||||
}
|
||||
if(!open) {
|
||||
qDebug() << "[Qtk::QtkIOStream] Could not open file: " << QString(pFile)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -35,34 +41,24 @@ QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
|
|||
******************************************************************************/
|
||||
|
||||
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
|
||||
size_t read = 0;
|
||||
do {
|
||||
auto readSize = mFile.read((char *)pvBuffer + read, pSize);
|
||||
qint64 readSize = mFile.read((char *)pvBuffer, pSize * pCount);
|
||||
if(readSize < 0) {
|
||||
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
|
||||
<< ") bytes from file at: " << mFile.filesystemFileName().c_str()
|
||||
<< "\n";
|
||||
return -1;
|
||||
}
|
||||
read += readSize;
|
||||
} while(pCount--);
|
||||
return read;
|
||||
return readSize;
|
||||
}
|
||||
|
||||
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
|
||||
size_t wrote = 0;
|
||||
do {
|
||||
auto writeSize = mFile.write((char *)pvBuffer + wrote, pSize);
|
||||
qint64 writeSize = mFile.write((char *)pvBuffer, pSize * pCount);
|
||||
if(writeSize < 0) {
|
||||
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size ("
|
||||
<< pSize
|
||||
<< ") to file at: " << mFile.filesystemFileName().c_str()
|
||||
<< "\n";
|
||||
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size (" << pSize
|
||||
<< ") to file at: " << mFile.filesystemFileName().c_str() << "\n";
|
||||
return -1;
|
||||
}
|
||||
wrote += writeSize;
|
||||
} while(pCount--);
|
||||
return wrote;
|
||||
return writeSize;
|
||||
}
|
||||
|
||||
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
##############################################################################*/
|
||||
|
||||
#include "qtkiosystem.h"
|
||||
#include <QDir>
|
||||
|
||||
using namespace Qtk;
|
||||
|
||||
|
@ -19,15 +20,11 @@ bool QtkIOSystem::Exists(const char * pFile) const {
|
|||
}
|
||||
|
||||
char QtkIOSystem::getOsSeparator() const {
|
||||
#ifndef _WIN32
|
||||
return '/';
|
||||
#else
|
||||
return '\\';
|
||||
#endif
|
||||
return QDir::separator().toLatin1();
|
||||
}
|
||||
|
||||
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) {
|
||||
if(!QFileInfo::exists(pFile)) {
|
||||
if(!Exists(pFile)) {
|
||||
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -37,16 +37,42 @@ Scene::~Scene() {
|
|||
* Public Methods
|
||||
******************************************************************************/
|
||||
|
||||
template <> MeshRenderer * Scene::addObject(MeshRenderer * object) {
|
||||
initSceneObjectName(object);
|
||||
mMeshes.push_back(object);
|
||||
sceneUpdated(mSceneName);
|
||||
return object;
|
||||
}
|
||||
|
||||
template <> Model * Scene::addObject(Model * object) {
|
||||
initSceneObjectName(object);
|
||||
mModels.push_back(object);
|
||||
sceneUpdated(mSceneName);
|
||||
return object;
|
||||
}
|
||||
|
||||
void Scene::draw() {
|
||||
if(!mInit) {
|
||||
initializeOpenGLFunctions();
|
||||
init();
|
||||
mInit = true;
|
||||
}
|
||||
|
||||
while(!mModelLoadQueue.empty()) {
|
||||
auto modelSpec = mModelLoadQueue.front();
|
||||
// Load the model and add it to the scene.
|
||||
addObject(new Model(modelSpec.first.c_str(), modelSpec.second.c_str()));
|
||||
mModelLoadQueue.pop();
|
||||
}
|
||||
|
||||
if(mPause) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(mSkybox != Q_NULLPTR) {
|
||||
mSkybox->draw();
|
||||
}
|
||||
for(auto & model : mModels) {
|
||||
for(const auto & model : mModels) {
|
||||
model->draw();
|
||||
}
|
||||
for(const auto & mesh : mMeshes) {
|
||||
|
@ -57,8 +83,8 @@ void Scene::draw() {
|
|||
std::vector<Object *> Scene::getObjects() const {
|
||||
// All scene objects must inherit from Qtk::Object.
|
||||
std::vector<Object *> objects(mMeshes.begin(), mMeshes.end());
|
||||
for(auto model : mModels) {
|
||||
objects.push_back(dynamic_cast<Object *>(model));
|
||||
for(const auto & model : mModels) {
|
||||
objects.push_back(model);
|
||||
if(objects.back() == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
@ -66,8 +92,8 @@ std::vector<Object *> Scene::getObjects() const {
|
|||
return objects;
|
||||
}
|
||||
|
||||
Object * Scene::getObject(const QString & name) {
|
||||
for(auto object : getObjects()) {
|
||||
Object * Scene::getObject(const QString & name) const {
|
||||
for(const auto & object : getObjects()) {
|
||||
if(object->getName() == name.toStdString()) {
|
||||
return object;
|
||||
}
|
||||
|
@ -80,14 +106,14 @@ void Scene::setSkybox(Skybox * skybox) {
|
|||
mSkybox = skybox;
|
||||
}
|
||||
|
||||
template <> MeshRenderer * Scene::addObject(MeshRenderer * object) {
|
||||
mMeshes.push_back(object);
|
||||
sceneUpdated(mSceneName);
|
||||
return object;
|
||||
}
|
||||
|
||||
template <> Model * Scene::addObject(Model * object) {
|
||||
mModels.push_back(object);
|
||||
sceneUpdated(mSceneName);
|
||||
return object;
|
||||
void Scene::initSceneObjectName(Object * object) {
|
||||
if(!mObjectCount.count(object->getName())) {
|
||||
mObjectCount[object->getName()] = 1;
|
||||
} else {
|
||||
mObjectCount[object->getName()]++;
|
||||
}
|
||||
auto count = mObjectCount[object->getName()];
|
||||
if(count > 1) {
|
||||
object->setName(object->getName() + " (" + std::to_string(count) + ")");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
#define QTK_SCENE_H
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QUrl>
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "camera3d.h"
|
||||
|
@ -75,6 +78,18 @@ namespace Qtk {
|
|||
*/
|
||||
virtual void update() {}
|
||||
|
||||
void loadModel(const QUrl & url) {
|
||||
auto fileName = url.fileName().replace(".obj", "").toStdString();
|
||||
auto filePath = url.toLocalFile().toStdString();
|
||||
loadModel(fileName, filePath);
|
||||
}
|
||||
|
||||
void loadModel(const std::string & name, const std::string & path) {
|
||||
// Add the dropped model to the load queue.
|
||||
// This is consumed during rendering of the scene if not empty.
|
||||
mModelLoadQueue.emplace(name, path);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Accessors
|
||||
************************************************************************/
|
||||
|
@ -91,7 +106,16 @@ namespace Qtk {
|
|||
* @param name The objectName to look for within this scene.
|
||||
* @return The found object or Q_NULLPTR if none found.
|
||||
*/
|
||||
[[nodiscard]] Object * getObject(const QString & name);
|
||||
[[nodiscard]] Object * getObject(const QString & name) const;
|
||||
|
||||
/**
|
||||
* @return The number of objects within the scene with the given name.
|
||||
*/
|
||||
[[nodiscard]] uint64_t getObjectCount(const QString & name) {
|
||||
return mObjectCount.count(name.toStdString())
|
||||
? mObjectCount[name.toStdString()]
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Camera attached to this scene.
|
||||
|
@ -166,6 +190,8 @@ namespace Qtk {
|
|||
*/
|
||||
inline void setSceneName(QString name) { mSceneName = std::move(name); }
|
||||
|
||||
inline void setPause(bool pause) { mPause = pause; }
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Signal thrown when the scene is modified by adding or removing objects.
|
||||
|
@ -175,7 +201,26 @@ namespace Qtk {
|
|||
*/
|
||||
void sceneUpdated(QString sceneName);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Public Members
|
||||
************************************************************************/
|
||||
public:
|
||||
/* Models used for storing 3D models in the scene. */
|
||||
std::vector<Model *> mModels {};
|
||||
|
||||
/* Queue of models requested to load at runtime. */
|
||||
std::queue<std::pair<std::string, std::string>> mModelLoadQueue;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize an object name relative to other objects already loaded.
|
||||
* Protects against having two objects with the same name.
|
||||
*
|
||||
* @param object Qtk Object to name within this scene.
|
||||
*/
|
||||
void initSceneObjectName(Qtk::Object * object);
|
||||
|
||||
/*************************************************************************
|
||||
* Private Members
|
||||
************************************************************************/
|
||||
|
@ -183,14 +228,16 @@ namespace Qtk {
|
|||
static Camera3D mCamera;
|
||||
static QMatrix4x4 mProjection;
|
||||
bool mInit = false;
|
||||
/* Pause rendering of the scene. */
|
||||
bool mPause = false;
|
||||
|
||||
QString mSceneName;
|
||||
/* The skybox for this scene. */
|
||||
Skybox * mSkybox {};
|
||||
/* MeshRenderers used simple geometry. */
|
||||
std::vector<MeshRenderer *> mMeshes {};
|
||||
/* Models used for storing 3D models in the scene. */
|
||||
std::vector<Model *> mModels {};
|
||||
/* Track count of objects with same initial name. */
|
||||
std::unordered_map<std::string, uint64_t> mObjectCount;
|
||||
};
|
||||
|
||||
class SceneEmpty : public Scene {
|
||||
|
|
|
@ -9,19 +9,18 @@
|
|||
#include <QDebug>
|
||||
#include <QImageReader>
|
||||
|
||||
#include "app/qtkmainwindow.h"
|
||||
#include "texture.h"
|
||||
|
||||
using namespace Qtk;
|
||||
|
||||
QImage * OpenGLTextureFactory::initImage(
|
||||
QImage OpenGLTextureFactory::initImage(
|
||||
const char * image, bool flipX, bool flipY) {
|
||||
// Qt6 limits loaded images to 256MB by default
|
||||
QImageReader::setAllocationLimit(512);
|
||||
auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY));
|
||||
if(loadedImage->isNull()) {
|
||||
qDebug() << "[Qtk::OpenGLTextureFactory] Error loading image: " << image
|
||||
<< "\nSupported types: " << QImageReader::supportedImageFormats();
|
||||
return Q_NULLPTR;
|
||||
QImageReader::setAllocationLimit(1024);
|
||||
auto loadedImage = QImage(image).mirrored(flipX, flipY);
|
||||
if(loadedImage.isNull()) {
|
||||
return defaultTexture();
|
||||
}
|
||||
|
||||
return loadedImage;
|
||||
|
@ -29,13 +28,12 @@ QImage * OpenGLTextureFactory::initImage(
|
|||
|
||||
QOpenGLTexture * OpenGLTextureFactory::initTexture(
|
||||
const char * texture, bool flipX, bool flipY) {
|
||||
QImage * image = initImage(texture, flipX, flipY);
|
||||
QImage image = initImage(texture, flipX, flipY);
|
||||
auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
newTexture->setData(*image);
|
||||
newTexture->setData(image);
|
||||
newTexture->setWrapMode(QOpenGLTexture::Repeat);
|
||||
newTexture->setMinMagFilters(
|
||||
QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
|
||||
delete image;
|
||||
return newTexture;
|
||||
}
|
||||
|
||||
|
@ -71,6 +69,7 @@ QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
|
|||
QImage faceImage(faceTextures[i]);
|
||||
if(faceImage.isNull()) {
|
||||
qDebug() << "Error loading cube map image\n";
|
||||
faceImage = defaultTexture();
|
||||
}
|
||||
faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888);
|
||||
|
||||
|
|
|
@ -74,9 +74,9 @@ namespace Qtk {
|
|||
* Can be absolute or Qt resource path.
|
||||
* @param flipX If true the image will be flipped on X axis.
|
||||
* @param flipY If true the image will be flipped on Y axis.
|
||||
* @return Pointer to an initialized QImage object.
|
||||
* @return QImage object.
|
||||
*/
|
||||
static QImage * initImage(
|
||||
static QImage initImage(
|
||||
const char * image, bool flipX = false, bool flipY = false);
|
||||
|
||||
/**
|
||||
|
@ -132,6 +132,14 @@ namespace Qtk {
|
|||
const char * right, const char * top, const char * front,
|
||||
const char * left, const char * bottom, const char * back);
|
||||
|
||||
/// The texture used in place of a missing texture.
|
||||
static QImage defaultTexture() {
|
||||
// Use plaster for default texture if image fails to load.
|
||||
// This prevents segfaults when loading a texture that doesn't exist.
|
||||
// TODO: Replace with a '?' texture to indicate missing texture.
|
||||
return QImage(":/textures/plaster.png");
|
||||
}
|
||||
|
||||
private:
|
||||
// Private ctor to prevent creating instances of this class
|
||||
OpenGLTextureFactory() = default;
|
||||
|
|
Loading…
Reference in New Issue