Compare commits

..

28 Commits
master ... ui

Author SHA1 Message Date
Shaun Reed 2087f10681 README 2023-03-11 20:23:25 -05:00
Shaun Reed e6b197d6fa Fix CI 2023-03-11 19:59:53 -05:00
Shaun Reed 6a52eee501 Debian packaging CI 2023-03-11 18:46:11 -05:00
Shaun Reed 6d51aef9cf Cleanup 2023-03-11 18:26:58 -05:00
Shaun Reed 5bde82d956 Format 2023-03-11 12:31:09 -05:00
Shaun Reed ae5abb9939 Windows CI 2023-03-11 12:18:16 -05:00
Shaun Reed d9c59a04ec Update CI for new targets 2023-03-11 11:30:17 -05:00
Shaun Reed e6bcd131b7 Connect TreeWidget when scene is updated. 2023-03-11 11:21:26 -05:00
Shaun Reed 0659df94bd Add SceneInterface
+ Renames binaries qtk_main->qtk_app and example->example_app
2023-03-11 10:59:33 -05:00
Shaun Reed 0dcb6d337b CI 2023-02-11 10:01:52 -05:00
Shaun Reed 002bedd7ef Mac packaging 2023-02-05 10:21:38 -05:00
Shaun Reed 6ce71dda86 Update CI for new targets 2023-01-29 20:08:02 -05:00
Shaun Reed b3484ced03 CI 2023-01-29 13:46:52 -05:00
Shaun Reed 5e886672da Packaging / install updates 2023-01-29 13:26:25 -05:00
Shaun Reed 126cd438e1 Cmake install components 2023-01-28 22:27:01 -05:00
Shaun Reed 39fa8e8cdc Fix windows packaging 2023-01-28 15:12:45 -05:00
Shaun Reed 48719412f2 CMake updates 2023-01-16 19:34:50 -05:00
Shaun Reed aa32cbcc17 OSX packaging 2023-01-16 10:53:15 -05:00
Shaun Reed cfefc49c53 CMake target renaming to avoid C++ errors with `-` 2023-01-15 17:04:06 -05:00
Shaun Reed 195a4ef30d Assimp IOSystem for Qt Resource paths 2023-01-15 16:06:15 -05:00
Shaun Reed 55dd8e5c3c Test packaging
+ Update assimp to latest
2023-01-15 10:14:24 -05:00
Shaun Reed cf433ad7fc CMake packaging updates 2023-01-14 16:33:06 -05:00
Shaun Reed 4bc0ae22c6 Format 2023-01-02 22:19:38 -05:00
Shaun Reed faa9fe28f7 CMake packaging 2023-01-02 22:18:53 -05:00
Shaun Reed f83f68207d Add fontawesome icons
+ Clean up resource prefixes
2023-01-01 23:44:43 -05:00
Shaun Reed 85c9e2eac1 Clean and comment code 2023-01-01 22:51:46 -05:00
Shaun Reed 194888ed19 Refactor build system and UI
+ Install configs for Qt Designer plugins and Qtk application
+ Add Qtk plugin collection for Qt Designer
+ QtkWidget plugin
+ TreeView widget plugin
+ DebugConsole widget plugin
+ All widgets are fully integrated with Qt Designer
+ All widgets can be popped out or docked within the window
+ All widgets can be stacked to use tab view for side panels
+ All widgets can be toggled on/off through the view context menu
+ QtkWidget debug console
+ QtkWidget active scene TreeVew
+ QtkWidget dockable tool bar
+ Double-click an object name in the TreeView to focus camera
+ Separate libaray from widgets

There is still a lot to do here, but the major refactoring should be
done after this commit. Some of the new features were put together as
POC for working with the new UI. A few placeholder buttons were added
that have no functionality.
2023-01-01 22:49:04 -05:00
Shaun Reed c948d9e1a6 Fix loading of QtkWidget in mainwindow 2022-12-11 12:36:07 -05:00
39 changed files with 393 additions and 806 deletions

View File

@ -5,27 +5,21 @@ on:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
env:
QT_VERSION: 6.6.0
jobs: jobs:
Qtk: Build-Qtk:
env: env:
CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=ON -DQTK_PLUGINS=OFF -DQTK_EXAMPLE=ON CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=ON -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=OFF
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -34,7 +28,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
# Windows # Windows
@ -50,24 +44,33 @@ jobs:
sudo apt update -y sudo apt update -y
sudo apt install libxcb-cursor0 -y sudo apt install libxcb-cursor0 -y
- name: Configure Qtk Application - name: Configure Qtk Application (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake -B build/ ${{ matrix.cmake }} run: cmake -B build/ ${{ matrix.cmake }}
- name: Build Qtk Application - name: Build Qtk Application (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake --build build/ --config Release --target qtk_gui ${{ matrix.flags }} run: cmake --build build/ --config Release
- name: Build Qtk Example # OSX / Linux
- name: Configure Qtk Application (OSX / Linux)
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
shell: bash shell: bash
run: cmake --build build/ --config Release --target qtk_example ${{ matrix.flags }} 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)
# Packaging # Packaging
- name: Install Qtk Application - name: Install Qtk Application
shell: bash shell: bash
run: cmake --install build/ --config Release --component qtk_gui run: cmake --install build/ --config Release --prefix=$(pwd)/install --component qtk
- name: Package Qtk Application - name: Package Qtk Application
shell: bash shell: bash
@ -84,7 +87,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: qtk-gui-${{ matrix.os }} name: qtk-app-${{ matrix.os }}
path: | path: |
build/packages/*.deb build/packages/*.deb
@ -99,7 +102,7 @@ jobs:
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: qtk-gui-${{ matrix.os }} name: qtk-app-${{ matrix.os }}
path: | path: |
build/packages/*.exe build/packages/*.exe
@ -114,14 +117,14 @@ jobs:
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: qtk-gui-${{ matrix.os }} name: qtk-app-${{ matrix.os }}
path: | path: |
build/packages/*.tar.gz build/packages/*.tar.gz
- name: Upload Qtk install directory - name: Upload Qtk install directory
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: qtk-gui-${{ matrix.os }}-install name: qtk-app-${{ matrix.os }}-install
path: install/* path: install/*
# TODO: Enable after trimming resources. # TODO: Enable after trimming resources.
@ -139,23 +142,20 @@ jobs:
# build/packages/* # build/packages/*
# !build/packages/_CPack_Packages/* # !build/packages/_CPack_Packages/*
Qtk-Library: Build-Qtk-Library:
env: env:
CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=OFF -DQTK_PLUGINS=OFF -DQTK_EXAMPLE=OFF CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=OFF
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -164,7 +164,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
# Windows # Windows
@ -174,19 +174,33 @@ jobs:
with: with:
args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1 args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1
- name: Configure Qtk Library - name: Configure Qtk Library (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake -B build/ ${{ matrix.cmake }} run: cmake -B build/ ${{ matrix.cmake }}
- name: Build Qtk Library - name: Build Qtk Library (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake --build build/ --config Release --target qtk_library -- ${{ matrix.flags }} 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)
# Packaging # Packaging
- name: Install Qtk Library - name: Install Qtk Library
shell: bash shell: bash
run: cmake --install build/ --config Release --prefix=$(pwd)/install --component qtk_library run: cmake --install build/ --config Release --prefix=$(pwd)/install --component libqtk
- name: Package Qtk Library - name: Package Qtk Library
shell: bash shell: bash
@ -244,23 +258,20 @@ jobs:
name: libqtk-${{ matrix.os }}-install name: libqtk-${{ matrix.os }}-install
path: install/* path: install/*
Qtk-Plugins: Build-Qtk-Plugins:
env: env:
CONFIG: -DQTK_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_CCACHE=OFF -DQTK_GUI=OFF -DQTK_PLUGINS=ON -DQTK_EXAMPLE=OFF CONFIG: -DQTK_UPDATE_SUBMODULES=ON -DQTK_DEBUG=OFF -DQTK_ENABLE_CCACHE=OFF -DQTK_BUILD_GUI=OFF -DQTK_INSTALL_LIBRARY=OFF -DQTK_INSTALL_PLUGINS=ON
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
- os: windows-latest - os: windows-latest
cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/$QT_VERSION/mingw81_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=D:/a/qtk/qtk/Qt/6.5.0/mingw81_64/ $CONFIG
flags: ''
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ $CONFIG cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ $CONFIG
flags: -j $(nproc)
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -269,7 +280,9 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
# Windows
- name: Chocolatey Action - name: Chocolatey Action
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
@ -277,30 +290,44 @@ jobs:
with: with:
args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1 args: install pkgconfiglite --checksum e87b5ea3c9142256af60f2d5b917aa63b571e6a0 --checksum-type sha1
- name: Configure Qtk Plugins - name: Configure Qtk Plugins (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake -B build/ ${{ matrix.cmake }} run: cmake -B build/ ${{ matrix.cmake }}
- name: Build Qtk Plugins - name: Build Qtk Plugins (Windows)
if: matrix.os == 'windows-latest'
shell: bash shell: bash
run: cmake --build build/ --config Release --target qtk_plugins -- ${{ matrix.flags }} 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)
# Packaging # Packaging
- name: Install Qtk Plugins - name: Install Qtk Plugins
shell: bash shell: bash
run: cmake --install build/ --config Release --component qtk_plugins run: cmake --install build/ --config Release --prefix=$(pwd)/install --component collection
Qtk-Assimp-Targets: Build-Qtk-Assimp-Targets:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/
- os: macos-latest - os: macos-latest
cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/$QT_VERSION/gcc_64/ cmake: -DCMAKE_PREFIX_PATH=/home/runner/work/qtk/Qt/6.5.0/gcc_64/ -DASSIMP_NEW_INTERFACE=ON
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -309,7 +336,7 @@ jobs:
- name: Install Qt - name: Install Qt
uses: jurplel/install-qt-action@v2 uses: jurplel/install-qt-action@v2
with: with:
version: ${{ env.QT_VERSION }} version: '6.5.0'
- name: Install Assimp MacOS - name: Install Assimp MacOS
if: matrix.os == 'macos-latest' if: matrix.os == 'macos-latest'
@ -325,7 +352,7 @@ jobs:
- name: Configure Qtk - name: Configure Qtk
shell: bash shell: bash
run: cmake -B build/ ${{ matrix.cmake }} -DQTK_CCACHE=OFF -DQTK_ASSIMP_NEW_INTERFACE=ON run: cmake -B build/ ${{ matrix.cmake }} -DQTK_ENABLE_CCACHE=OFF
- name: Build Qtk - name: Build Qtk
shell: bash shell: bash

View File

@ -21,8 +21,8 @@ jobs:
- name: Build Qtk - name: Build Qtk
run: | run: |
cmake -B build -DQTK_SUBMODULES=OFF -DQTK_CCACHE=OFF -DQTK_PLUGINS=OFF -DQTK_GUI=ON cmake -B build -DQTK_UPDATE_SUBMODULES=OFF -DQTK_ENABLE_CCACHE=OFF
cmake --build build --target qtk_gui -- -j $(nproc) cmake --build build
- uses: cpp-linter/cpp-linter-action@v2 - uses: cpp-linter/cpp-linter-action@v2
id: linter id: linter

3
.gitignore vendored
View File

@ -1,9 +1,6 @@
# CLion # CLion
**/.idea/** **/.idea/**
# VS Code
**/.vscode/**
# CMake build files # CMake build files
**/cmake-build-debug/** **/cmake-build-debug/**
**/build/** **/build/**

View File

@ -46,13 +46,14 @@ include(GNUInstallDirs)
# Options # Options
################################################################################ ################################################################################
option(QTK_DEBUG "Enable debugger" OFF) option(QTK_DEBUG "Enable debugger" OFF)
option(QTK_SUBMODULES "Update external project (assimp) submodule" OFF) option(QTK_UPDATE_SUBMODULES "Update external project (assimp) submodule" OFF)
option(QTK_GUI "Build the Qtk desktop application" ON) option(QTK_BUILD_GUI "Build the Qtk desktop application" ON)
option(QTK_PLUGINS "Install Qtk plugins to Qt Creator path." OFF) option(QTK_INSTALL_LIBRARY "Install libqtk to CMAKE_INSTALL_PREFIX path." ON)
option(QTK_EXAMPLE "Build the Qtk example desktop application" ON) option(QTK_INSTALL_PLUGINS "Install Qtk plugin collection to Qt Creator." OFF)
option(QTK_CCACHE "Enable ccache" ON) option(QTK_BUILD_EXAMPLE "Build the Qtk example desktop application" ON)
option(QTK_ENABLE_CCACHE "Enable ccache" ON)
if (QTK_CCACHE) if (QTK_ENABLE_CCACHE)
set(CMAKE_CXX_COMPILER_LAUNCHER ccache) set(CMAKE_CXX_COMPILER_LAUNCHER ccache)
endif() endif()
@ -60,30 +61,21 @@ endif()
option(QTK_PREFIX_QTCREATOR "Install Qtk to Qt Creator. Untested." OFF) option(QTK_PREFIX_QTCREATOR "Install Qtk to Qt Creator. Untested." OFF)
# Option for bringing your own assimp installation; Otherwise not needed # Option for bringing your own assimp installation; Otherwise not needed
# + If assimp is available system-wide we can just set QTK_SUBMODULES OFF # + If assimp is available system-wide we can just set QTK_UPDATE_SUBMODULES OFF
option( option(
QTK_ASSIMP_NEW_INTERFACE QTK_ASSIMP_NEW_INTERFACE
"Use the assimp::assimp interface (WIN / OSX)" "Use the assimp::assimp interface (WIN / OSX)"
OFF OFF
) )
if(QTK_DEBUG OR CMAKE_BUILD_TYPE MATCHES "^[Dd][Ee][Bb][Uu][Gg]$") if(NOT QTK_DEBUG)
set(QTK_DEBUG ON)
set(CMAKE_BUILD_TYPE Debug)
else()
set(QTK_DEBUG OFF)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
else()
set(CMAKE_BUILD_TYPE Debug)
endif() endif()
# This should be set to your Qt6 installation directory. # This should be set to your Qt6 installation directory.
set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/lib/cmake" CACHE PATH "Path to Qt6 install.") set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64" 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 # Point CMAKE_PREFIX_PATH to Qt6 install directory
# If Qtk is built within Qt Creator this is not required. # If Qtk is built within Qt Creator this is not required.
list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}")
@ -97,13 +89,31 @@ set(
"${QT_INSTALL_DIR}/../../Tools/QtCreator" "${QT_INSTALL_DIR}/../../Tools/QtCreator"
CACHE PATH "Qt Creator path used to install Qtk plugins for Qt Designer." 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}")
# Print all QTK options and their values at the end of configuration. message(STATUS "[Qtk] CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
# We initialize this list here so that we can append to it as needed. set(QTK_RESOURCES "${CMAKE_SOURCE_DIR}/resources")
# All variables in this list will be printed at the end of configuration. set(QTK_OSX_ICONS ${CMAKE_SOURCE_DIR}/resources/icons/osx/kilroy.icns)
# Print all QTK options and their values.
get_cmake_property(VAR_NAMES VARIABLES) get_cmake_property(VAR_NAMES VARIABLES)
list(FILTER VAR_NAMES INCLUDE REGEX "^[qQ][tT][kK]_.*$") list(FILTER VAR_NAMES INCLUDE REGEX "^Q[tT][kK]_.*$")
list(SORT VAR_NAMES) list(SORT VAR_NAMES)
foreach(VAR_NAME ${VAR_NAMES})
message(STATUS "[Qtk] ${VAR_NAME}=${${VAR_NAME}}")
endforeach()
################################################################################ ################################################################################
# External Dependencies # External Dependencies
@ -123,33 +133,8 @@ if(NOT Qt6_FOUND)
) )
endif() 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. # Find Assimp.
if(QTK_SUBMODULES) if(QTK_UPDATE_SUBMODULES)
# Required to statically link. # Required to statically link.
add_compile_options(-fPIC) add_compile_options(-fPIC)
set(BUILD_SHARED_LIBS OFF CACHE STRING "Build static assimp libs" FORCE) set(BUILD_SHARED_LIBS OFF CACHE STRING "Build static assimp libs" FORCE)
@ -181,20 +166,8 @@ endif()
################################################################################ ################################################################################
add_subdirectory(src) add_subdirectory(src)
if(QTK_EXAMPLE) if(QTK_BUILD_EXAMPLE)
# Create a namespaced alias for linking with qtk_library in the example. # Create a namespaced alias for linking with qtk_library in the example.
add_library(${PROJECT_NAME}::qtk_library ALIAS qtk_library) add_library(${PROJECT_NAME}::qtk_library ALIAS qtk_library)
add_subdirectory(example-app EXCLUDE_FROM_ALL) add_subdirectory(example-app)
endif() 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
View File

@ -40,59 +40,88 @@ and [Qt Creator](https://github.com/qt-creator/qt-creator).
Simply open the root `CMakeLists.txt` with either of these editors and Simply open the root `CMakeLists.txt` with either of these editors and
configurations will be loaded. configurations will be loaded.
This project has been ported to **Qt 6.6.0**, which is not yet available in This project has been ported to **Qt 6.5.0**, which is not yet available in
Ubuntu apt repositories. Ubuntu apt repositories.
To run this project, you will *need* to To run this project, you will *need* to
install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for install [Qt6 Open Source Binaries](https://www.qt.io/download-qt-installer) for
your system, **version 6.6.0** or later. your system, **version 6.5.0** or later.
Be sure to take note of the Qt6 installation directory, as we will need it to 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. 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 If the build is configured with all options enabled, we can subsequently install
individual components as needed with cmake. individual components as needed with cmake.
```bash ```bash
sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache libgl1-mesa-dev libglvnd-dev zlib1g-dev -y cmake -B build-all/ -DQTK_BUILD_GUI=ON -DQTK_INSTALL_LIBRARY=ON -DQTK_INSTALL_PLUGINS=ON
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 ```bash
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 # 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
``` ```
#### Qtk GUI #### Qtk GUI
Once Qt6 is installed, to build and run `qtk` on Ubuntu -
```bash ```bash
cmake --build build-all/ --target qtk_gui -- -j $(nproc) sudo apt update -y && sudo apt install libassimp-dev cmake build-essential git ccache -y
# Install Qtk desktop application (output removed) git clone https://github.com/shaunrd0/qtk
# Installation prefix path must be absolute, since Qtk uses Qt deploy tools. cmake -S qtk/ -B qtk/build/ -DCMAKE_PREFIX_PATH=$HOME/Qt/6.5.0/gcc_64
cmake --install build-all/ --component qtk_gui --prefix=$(pwd)/install cmake --build qtk/build/ -j $(nproc --ignore=2)
./install/bin/qtk_gui ./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
``` ```
If any errors are encountered loading plugins, we can debug plugin loading by If any errors are encountered loading plugins, we can debug plugin loading by
setting the following environment variable - setting the following environment variable -
```bash ```bash
QT_DEBUG_PLUGINS=1 ./install/bin/qtk_gui QT_DEBUG_PLUGINS=1 ./qtk-main
``` ```
#### Qtk Library #### Qtk Library
@ -102,10 +131,12 @@ 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 set `CMAKE_PREFIX_PATH` to point to this location when building an application
using libqtk. using libqtk.
Below is an example of installing on a system path.
```bash ```bash
# Install libqtk only 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 build-all/ --target qtk_library -- -j $(nproc) cmake --build qtk/build/ -j $(nproc --ignore=2)
cmake --install build-all/ --component qtk_library --prefix=/usr/local sudo cmake --install . --prefix=/usr/local
-- Install configuration: "Release" -- Install configuration: "Release"
-- Installing: /usr/local/lib/cmake/Qtk/QtkConfig.cmake -- Installing: /usr/local/lib/cmake/Qtk/QtkConfig.cmake
-- Installing: /usr/local/lib/cmake/Qtk/QtkConfigVersion.cmake -- Installing: /usr/local/lib/cmake/Qtk/QtkConfigVersion.cmake
@ -144,14 +175,9 @@ interfaces.
To build and install the Qtk plugin collection - To build and install the Qtk plugin collection -
```bash ```bash
cmake --build build-all/ --target qtk_plugins -- -j $(nproc) 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
# Install Qtk widget collection to use Qt Designer cmake --build /path/to/qtk/build
# The path here should be initialized during build configuration, so no need for --prefix cmake --install /path/to/qtk/build
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 To uninstall after a previous installation, we can run the following command
@ -161,22 +187,16 @@ from the root of the repository.
xargs rm < build/install_manifest.txt xargs rm < build/install_manifest.txt
``` ```
#### Qtk Example #### Windows / MacOS
There is a simple example of using libqtk in the [example-app/](example-app) If you are building on **Windows / Mac**, consider setting
directory. The example can be built standalone using `find_package` or as a the `-DASSIMP_NEW_INTERFACE` build flag.
target within any qtk build.
```bash ```bash
# Build the example from a configured qtk build tree 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 build-all/ --target qtk_example -- -j $(nproc) cmake --build qtk/build/ -j $(nproc --ignore=2)
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 ### Controls
You can fly around the scene if you hold the right mouse button and use WASD. You can fly around the scene if you hold the right mouse button and use WASD.
@ -233,7 +253,7 @@ CLion automatically.
# Move to the root of the repo # Move to the root of the repo
cd qtk cd qtk
# Build # Build
cmake -B build && cmake --build build -- -j $(nproc) cmake -B build && cmake --build build
clang-tidy -p build/ --fix --config-file=.clang-tidy src/*.cpp src/*.h app/*.cpp app/*.h clang-tidy -p build/ --fix --config-file=.clang-tidy src/*.cpp src/*.h app/*.cpp app/*.h
``` ```
@ -241,7 +261,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. This will reformat all the code in the repository.
```bash ```bash
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 -i --style=file:.clang-format src/*.cpp src/*.h app/*.cpp app/*.h
``` ```
`clang-format` can be run with git integration (or CLion if you prefer). `clang-format` can be run with git integration (or CLion if you prefer).
@ -300,8 +320,12 @@ Any of the above options can be appended with `--trace-expand` to debug package
generation issues. generation issues.
The contents of all packages will depend on how the build was configured. 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 To generate packages for Qtk desktop application, we should
set `-DQTK_GUI=ON`. If this option is not set we will only package libqtk. set `-DQTK_BUILD_GUI=ON`, and optionally `-DQTK_INSTALL_LIBRARY=ON` if we would
like to bundle libqtk with the desktop application.
The NSIS installer will allow component-specific path modification for all of The NSIS installer will allow component-specific path modification for all of
these installation components through a GUI install application. these installation components through a GUI install application.

View File

@ -10,7 +10,7 @@ find_package(Git)
# _PATH: Path to git submodule location that we want to update # _PATH: Path to git submodule location that we want to update
# + submodule_update(extern/assimp) # + submodule_update(extern/assimp)
function(submodule_update _PATH) function(submodule_update _PATH)
if (NOT QTK_SUBMODULES) if (NOT QTK_UPDATE_SUBMODULES)
return() return()
endif() endif()

View File

@ -2,12 +2,8 @@
include("${CMAKE_CURRENT_LIST_DIR}/QtkTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtkTargets.cmake")
set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_gui") set_and_check(QTK_EXECUTABLE "${PACKAGE_PREFIX_DIR}/bin/qtk_app")
set_and_check(QTK_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include") set_and_check(QTK_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")
set_and_check(QTK_LIBRARIES "${PACKAGE_PREFIX_DIR}/lib") 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) check_required_components(Qtk)

View File

@ -22,11 +22,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
endif() endif()
# If you did not install Qtk on a system path, point cmake to installation. # If you did not install Qtk on a system path, point cmake to installation.
set( set(QTK_PATH /usr/local CACHE PATH "Path to installation of Qtk")
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. # 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") set(QT_INSTALL_DIR "$ENV{HOME}/Qt/6.5.0/gcc_64/" CACHE PATH "Path to Qt6")
@ -44,6 +40,12 @@ project(
list(APPEND CMAKE_PREFIX_PATH "${QTK_PATH}") list(APPEND CMAKE_PREFIX_PATH "${QTK_PATH}")
list(APPEND CMAKE_PREFIX_PATH "${QT_INSTALL_DIR}") 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 # Print all QTK variables
if (NOT Qtk_IS_TOP_LEVEL) if (NOT Qtk_IS_TOP_LEVEL)
get_cmake_property(VAR_NAMES VARIABLES) get_cmake_property(VAR_NAMES VARIABLES)
@ -54,12 +56,6 @@ if (NOT Qtk_IS_TOP_LEVEL)
endforeach() endforeach()
endif() 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) find_package(Qt6 COMPONENTS Core Widgets OpenGLWidgets REQUIRED)
set( set(
@ -69,28 +65,6 @@ set(
examplewidget.cpp examplewidget.h examplewidget.cpp examplewidget.h
) )
configure_file( add_executable(example_app ${EXAMPLE_SOURCES})
#[[INPUT]] "${CMAKE_CURRENT_SOURCE_DIR}/resources.h.in" target_link_libraries(example_app PUBLIC Qt6::Widgets Qt6::OpenGLWidgets Qt6::Core)
#[[OUTPUT]] "${CMAKE_CURRENT_BINARY_DIR}/resources.h" target_link_libraries(example_app PUBLIC Qtk::qtk_library)
@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)

View File

@ -62,12 +62,11 @@ custom installation directory.
```bash ```bash
cmake -S /path/to/qtk/example-app/ -B /path/to/qtk/example-app/build -DQTK_PATH=/path/to/qtk/install/ 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 --target qtk_example -- -j $(nproc) cmake --build /path/to/qtk/example-app/build
cmake --install build/ --component qtk_example
``` ```
After this, we can run the example application - After this, we can run the example application -
```bash ```bash
./path/to/qtk/example-app/build/install/bin/example ./path/to/qtk/example-app/build/bin/example
``` ```

View File

@ -7,7 +7,6 @@
##############################################################################*/ ##############################################################################*/
#include "examplescene.h" #include "examplescene.h"
#include <resources.h>
using namespace Qtk; using namespace Qtk;
@ -23,11 +22,9 @@ void ExampleScene::init() {
auto skybox = new Qtk::Skybox("Skybox"); auto skybox = new Qtk::Skybox("Skybox");
setSkybox(skybox); setSkybox(skybox);
std::string spartanPath = QTK_EXAMPLE_SOURCE_DIR; auto spartan = new Model(
spartanPath += "/resources/models/spartan/spartan.obj"; "spartan", "/home/kapper/Code/qtk/resources/models/spartan/spartan.obj");
auto spartan = new Model("spartan", spartanPath.c_str());
addObject(spartan); addObject(spartan);
spartan->getTransform().setTranslation(-4.0f, 0.0f, 0.0f);
auto mesh = addObject( auto mesh = addObject(
new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rightTriangle", Triangle(QTK_DRAW_ARRAYS)));

View File

@ -1,6 +0,0 @@
#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 5d5496f1ad895297cede723b3c96b513263f82ed Subproject commit eb328ce69dd7b06977aed125e967a41e835b8431

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

View File

@ -1,6 +1,5 @@
<RCC> <RCC>
<qresource prefix="/textures"> <qresource prefix="/textures">
<file alias="plaster.png">images/plaster.png</file>
<file alias="crate.png">images/crate.png</file> <file alias="crate.png">images/crate.png</file>
<file alias="stone.png">images/stone.png</file> <file alias="stone.png">images/stone.png</file>
<file alias="wood.png">images/wood.png</file> <file alias="wood.png">images/wood.png</file>

View File

@ -13,14 +13,14 @@ install(
FILES FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPONENT qtk_library COMPONENT libqtk
DESTINATION lib/cmake/${PROJECT_NAME} DESTINATION lib/cmake/${PROJECT_NAME}
) )
install( install(
EXPORT qtk_export EXPORT qtk_export
FILE ${PROJECT_NAME}Targets.cmake FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}:: NAMESPACE ${PROJECT_NAME}::
COMPONENT qtk_library COMPONENT libqtk
DESTINATION lib/cmake/${PROJECT_NAME} DESTINATION lib/cmake/${PROJECT_NAME}
) )
# System install for qtk_library # System install for qtk_library
@ -28,45 +28,53 @@ install(
TARGETS qtk_library TARGETS qtk_library
# Associate qtk_library target with qtk-export # Associate qtk_library target with qtk-export
EXPORT qtk_export EXPORT qtk_export
COMPONENT qtk_library COMPONENT libqtk
FILE_SET HEADERS DESTINATION include FILE_SET HEADERS DESTINATION include
INCLUDES DESTINATION include INCLUDES DESTINATION include
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
) )
# Qtk Application # Qtk Application
if(QTK_GUI OR QTK_PLUGINS) if(QTK_BUILD_GUI OR QTK_INSTALL_PLUGINS)
add_subdirectory(app) add_subdirectory(app)
endif() endif()
if(QTK_PLUGINS) if(QTK_INSTALL_PLUGINS)
# Optionally install custom Qtk plugins for Qt Designer.
install( install(
TARGETS qtk_plugins qtk_library qtk_plugin_library TARGETS qtk_library qtk_plugin_library
COMPONENT qtk_plugins 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
LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" LIBRARY DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
ARCHIVE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" ARCHIVE DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}" RUNTIME DESTINATION "${QTK_PLUGIN_INSTALL_DIR}"
) )
endif() endif()
if(QTK_GUI) if(QTK_BUILD_GUI)
install( install(
TARGETS qtk_gui TARGETS qtk_app
COMPONENT qtk_gui COMPONENT qtk
BUNDLE DESTINATION . BUNDLE DESTINATION .
LIBRARY DESTINATION lib LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib/static
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
) )
qt_generate_deploy_app_script( qt_generate_deploy_app_script(
TARGET qtk_gui TARGET qtk_app
OUTPUT_SCRIPT QTK_DEPLOY_SCRIPT OUTPUT_SCRIPT QTK_DEPLOY_SCRIPT
NO_UNSUPPORTED_PLATFORM_ERROR NO_UNSUPPORTED_PLATFORM_ERROR
) )
install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk_gui) install(SCRIPT ${QTK_DEPLOY_SCRIPT} COMPONENT qtk)
if(WIN32) if(WIN32)
if(MSVC AND TARGET Qt6::qmake) if(MSVC AND TARGET Qt6::qmake)
@ -79,7 +87,7 @@ if(QTK_GUI)
) )
file(TO_NATIVE_PATH "${QT6_INSTALL_PREFIX}/bin" QT6_INSTALL_PREFIX) file(TO_NATIVE_PATH "${QT6_INSTALL_PREFIX}/bin" QT6_INSTALL_PREFIX)
set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_gui.vcxproj.user") set(VSUSER_FILE "${CMAKE_CURRENT_BINARY_DIR}/qtk_app.vcxproj.user")
file(WRITE ${VSUSER_FILE} "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n") 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} "<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n")
file(APPEND ${VSUSER_FILE} " <PropertyGroup>\n") file(APPEND ${VSUSER_FILE} " <PropertyGroup>\n")
@ -116,7 +124,7 @@ set(CPACK_THREADS 0)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Qtk") set(CPACK_PACKAGE_INSTALL_DIRECTORY "Qtk")
# Remove any assimp components if defined by submodule. # Remove any assimp components if defined by submodule.
if (QTK_SUBMODULES) if (QTK_UPDATE_SUBMODULES)
get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS) get_cmake_property(CPACK_COMPONENTS_ALL COMPONENTS)
list(FILTER CPACK_COMPONENTS_ALL EXCLUDE REGEX .*assimp.*) list(FILTER CPACK_COMPONENTS_ALL EXCLUDE REGEX .*assimp.*)
list(REMOVE_ITEM CPACK_COMPONENTS_ALL Unspecified) list(REMOVE_ITEM CPACK_COMPONENTS_ALL Unspecified)
@ -128,7 +136,7 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
# https://nsis.sourceforge.io/Reference/CreateShortCut # https://nsis.sourceforge.io/Reference/CreateShortCut
set( set(
CPACK_NSIS_CREATE_ICONS_EXTRA CPACK_NSIS_CREATE_ICONS_EXTRA
"CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_gui.exe'" "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Qtk.lnk' '$INSTDIR\\\\bin\\\\qtk_app.exe'"
) )
set( set(
CPACK_NSIS_DELETE_ICONS_EXTRA CPACK_NSIS_DELETE_ICONS_EXTRA
@ -144,7 +152,7 @@ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
# OSX # OSX
set(CPACK_BUNDLE_NAME ${PROJECT_NAME}) set(CPACK_BUNDLE_NAME ${PROJECT_NAME})
set(CPACK_BUNDLE_PLIST $<TARGET_BUNDLE_CONTENT_DIR:qtk_gui>/Info.plist) set(CPACK_BUNDLE_PLIST $<TARGET_BUNDLE_CONTENT_DIR:qtk_app>/Info.plist)
set(CPACK_BUNDLE_ICON ${QTK_OSX_ICONS}) set(CPACK_BUNDLE_ICON ${QTK_OSX_ICONS})
# Platform defaults for source bundles. # Platform defaults for source bundles.

View File

@ -33,32 +33,32 @@ target_sources(
target_link_libraries(qtk_plugin_library PUBLIC Qt6::UiPlugin qtk_library) target_link_libraries(qtk_plugin_library PUBLIC Qt6::UiPlugin qtk_library)
################################################################################ ################################################################################
# Qtk Widget Plugins # Qtk Widget Collection Plugin
################################################################################ ################################################################################
# Create a Qt Designer plugin for a collection of widgets from our library. # Create a Qt Designer plugin for a collection of widgets from our library.
qt_add_plugin(qtk_plugins SHARED) qt_add_plugin(qtk_collection SHARED)
target_sources( target_sources(
qtk_plugins PRIVATE qtk_collection PRIVATE
widgetplugincollection.cpp widgetplugincollection.h widgetplugincollection.cpp widgetplugincollection.h
widgetplugin.cpp widgetplugin.h widgetplugin.cpp widgetplugin.h
) )
target_link_libraries(qtk_plugins PUBLIC qtk_plugin_library) target_link_libraries(qtk_collection PUBLIC qtk_plugin_library)
################################################################################ ################################################################################
# Final Qtk Application # Final Qtk Application
################################################################################ ################################################################################
set( set(
QTK_GUI_SOURCES QTK_APP_SOURCES
qtkscene.cpp qtkscene.h qtkscene.cpp qtkscene.h
main.cpp main.cpp
) )
qt_add_executable(qtk_gui ${QTK_GUI_SOURCES}) qt_add_executable(qtk_app ${QTK_APP_SOURCES})
target_link_libraries(qtk_gui PRIVATE qtk_plugin_library) target_link_libraries(qtk_app PRIVATE qtk_plugin_library)
set_target_properties( set_target_properties(
qtk_gui PROPERTIES qtk_app PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_BUNDLE_NAME Qtk MACOSX_BUNDLE_BUNDLE_NAME Qtk

View File

@ -29,30 +29,17 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent) {
for(auto & qtkWidget : qtkWidgets) { for(auto & qtkWidget : qtkWidgets) {
qtkWidget->setScene(new Qtk::SceneEmpty); qtkWidget->setScene(new Qtk::SceneEmpty);
views_.emplace(qtkWidget->getScene()->getSceneName(), qtkWidget); views_.emplace(qtkWidget->getScene()->getSceneName(), qtkWidget);
// Add GUI 'view' toolbar option to show debug console.
ui_->menuView->addAction(qtkWidget->getActionToggleConsole()); ui_->menuView->addAction(qtkWidget->getActionToggleConsole());
// Refresh GUI widgets when scene or objects are updated.
connect( connect(
qtkWidget->getScene(), &Qtk::Scene::sceneUpdated, this, qtkWidget->getScene(), &Qtk::Scene::sceneUpdated, this,
&MainWindow::refreshScene); &MainWindow::refreshScene);
connect(
qtkWidget, &Qtk::QtkWidget::objectFocusChanged, ui_->qtk__ToolBox,
&Qtk::ToolBox::updateFocus);
} }
// TODO: Fix / use MainWindow in Qt Designer to add these dock widgets. auto docks = findChildren<QDockWidget *>();
// For now we will add them manually, but we should be able to do this in the for(auto & dock : docks) {
// designer. At the moment if you edit the UI in designer the dock widget addDockWidget(Qt::RightDockWidgetArea, dock);
// areas below will override the designer settings. ui_->menuView->addAction(dock->toggleViewAction());
}
// 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. // Set the window icon used for Qtk.
setWindowIcon(Qtk::getIcon()); setWindowIcon(Qtk::getIcon());
@ -87,7 +74,7 @@ Qtk::QtkWidget * MainWindow::getQtkWidget(const QString & name) {
return views_[name]; return views_[name];
} }
void MainWindow::refreshScene(const QString & sceneName) { void MainWindow::refreshScene(QString sceneName) {
// TODO: Select TreeView using sceneName // TODO: Select TreeView using sceneName>
ui_->qtk__TreeView->updateView(getQtkWidget()->getScene()); ui_->qtk__TreeView->updateView(getQtkWidget()->getScene());
} }

View File

@ -69,7 +69,7 @@ class MainWindow : public QMainWindow {
* Trigger a refresh for widgets related to a scene that has been updated. * Trigger a refresh for widgets related to a scene that has been updated.
* @param sceneName The name of the scene that has been modified. * @param sceneName The name of the scene that has been modified.
*/ */
void refreshScene(const QString & sceneName); void refreshScene(QString sceneName);
private: private:
/*************************************************************************** /***************************************************************************

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1034</width> <width>824</width>
<height>601</height> <height>601</height>
</rect> </rect>
</property> </property>
@ -28,27 +28,11 @@
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout"> <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> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>3</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
@ -66,10 +50,10 @@
<item> <item>
<widget class="Qtk::QtkWidget" name="qtk::QtkWidget"> <widget class="Qtk::QtkWidget" name="qtk::QtkWidget">
<property name="toolTip"> <property name="toolTip">
<string/> <string>A custom widget tool tip.</string>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string>Qtk scene view rendered using OpenGL.</string> <string>Custom widget what's this?</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -82,22 +66,30 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="Qtk::TreeView" name="qtk::TreeView"> <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"> <property name="toolTip">
<string>TreeView of objects within the current scene.</string> <string>A custom widget tool tip.</string>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string>TreeView of objects within the current scene. Double-click to select an object and snap to it's position.</string> <string>Custom widget what's this?</string>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
@ -105,7 +97,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1034</width> <width>824</width>
<height>22</height> <height>22</height>
</rect> </rect>
</property> </property>
@ -187,7 +179,7 @@
</widget> </widget>
<action name="actionOpen"> <action name="actionOpen">
<property name="icon"> <property name="icon">
<iconset> <iconset resource="../../resources/resources.qrc">
<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> <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>
<property name="text"> <property name="text">
@ -196,7 +188,7 @@
</action> </action>
<action name="actionSave"> <action name="actionSave">
<property name="icon"> <property name="icon">
<iconset> <iconset resource="../../resources/resources.qrc">
<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> <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>
<property name="text"> <property name="text">
@ -223,7 +215,7 @@
</action> </action>
<action name="actionLoad_Model"> <action name="actionLoad_Model">
<property name="icon"> <property name="icon">
<iconset> <iconset resource="../../resources/resources.qrc">
<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> <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>
<property name="text"> <property name="text">
@ -235,7 +227,7 @@
</action> </action>
<action name="actionDelete_Object"> <action name="actionDelete_Object">
<property name="icon"> <property name="icon">
<iconset> <iconset resource="../../resources/resources.qrc">
<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> <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>
<property name="text"> <property name="text">
@ -326,7 +318,9 @@
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources>
<include location="../../resources/resources.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>actionExit</sender> <sender>actionExit</sender>

View File

@ -38,12 +38,11 @@ void QtkScene::init() {
/* Create a red cube with a mini master chief on top. */ /* Create a red cube with a mini master chief on top. */
auto myCube = new MeshRenderer("My cube", Cube(Qtk::QTK_DRAW_ELEMENTS)); auto myCube = new MeshRenderer("My cube", Cube(Qtk::QTK_DRAW_ELEMENTS));
myCube->setColor(RED); myCube->setColor(RED);
myCube->getTransform().setTranslation(5.0f, 0.0f, 0.0f);
addObject(myCube); addObject(myCube);
auto mySpartan = auto mySpartan =
new Model("My spartan", ":/models/models/spartan/spartan.obj"); new Model("My spartan", ":/models/models/spartan/spartan.obj");
mySpartan->getTransform().setTranslation(5.0f, 0.5f, 0.0f); mySpartan->getTransform().setTranslation(0.0f, 0.5f, 0.0f);
mySpartan->getTransform().setScale(0.5f); mySpartan->getTransform().setScale(0.5f);
addObject(mySpartan); addObject(mySpartan);

View File

@ -7,12 +7,6 @@
##############################################################################*/ ##############################################################################*/
#include <QKeyEvent> #include <QKeyEvent>
#include <QMimeData>
#include <QVBoxLayout>
#include <qtk/input.h>
#include <qtk/scene.h>
#include <qtk/shape.h>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <qtk/input.h> #include <qtk/input.h>
@ -37,7 +31,6 @@ QtkWidget::QtkWidget(QWidget * parent, const QString & name) :
QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) : QtkWidget::QtkWidget(QWidget * parent, const QString & name, Scene * scene) :
QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR), QOpenGLWidget(parent), mDebugLogger(Q_NULLPTR),
mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) { mConsole(new DebugConsole(this, name)), mScene(Q_NULLPTR) {
setAcceptDrops(true);
setScene(scene); setScene(scene);
setObjectName(name); setObjectName(name);
QSurfaceFormat format; QSurfaceFormat format;
@ -77,7 +70,6 @@ void QtkWidget::initializeGL() {
// Connect the frameSwapped signal to call the update() function // Connect the frameSwapped signal to call the update() function
connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
toggleConsole();
// Initialize OpenGL debug context // Initialize OpenGL debug context
mDebugLogger = new QOpenGLDebugLogger(this); mDebugLogger = new QOpenGLDebugLogger(this);
if(mDebugLogger->initialize()) { if(mDebugLogger->initialize()) {
@ -115,11 +107,11 @@ void QtkWidget::paintGL() {
} }
} }
void QtkWidget::setScene(Scene * scene) { void QtkWidget::setScene(Qtk::Scene * scene) {
if(mScene != Q_NULLPTR) { if(mScene != Q_NULLPTR) {
delete mScene; delete mScene;
connect( connect(
scene, &Scene::sceneUpdated, MainWindow::getMainWindow(), scene, &Qtk::Scene::sceneUpdated, MainWindow::getMainWindow(),
&MainWindow::refreshScene); &MainWindow::refreshScene);
} }
@ -137,7 +129,8 @@ void QtkWidget::toggleConsole() {
mConsoleActive = false; mConsoleActive = false;
} else { } else {
MainWindow::getMainWindow()->addDockWidget( MainWindow::getMainWindow()->addDockWidget(
Qt::DockWidgetArea::BottomDockWidgetArea, mConsole); Qt::DockWidgetArea::BottomDockWidgetArea,
dynamic_cast<QDockWidget *>(mConsole));
mConsole->setHidden(false); mConsole->setHidden(false);
mConsoleActive = true; mConsoleActive = true;
} }
@ -147,34 +140,6 @@ void QtkWidget::toggleConsole() {
* Protected Methods * 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) { void QtkWidget::keyPressEvent(QKeyEvent * event) {
if(event->isAutoRepeat()) { if(event->isAutoRepeat()) {
// Do not repeat input while a key is held down // Do not repeat input while a key is held down
@ -288,8 +253,7 @@ void QtkWidget::teardownGL() { /* Nothing to teardown yet... */
void QtkWidget::updateCameraInput() { void QtkWidget::updateCameraInput() {
Input::update(); Input::update();
// Camera Transformation // Camera Transformation
if(Input::buttonPressed(Qt::LeftButton) if(Input::buttonPressed(Qt::RightButton)) {
|| Input::buttonPressed(Qt::RightButton)) {
static const float transSpeed = 0.1f; static const float transSpeed = 0.1f;
static const float rotSpeed = 0.5f; static const float rotSpeed = 0.5f;

View File

@ -131,19 +131,11 @@ namespace Qtk {
*/ */
void sendLog(const QString & message, DebugContext context = Status); 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:
/************************************************************************* /*************************************************************************
* Protected Methods * Protected Methods
************************************************************************/ ************************************************************************/
void dragEnterEvent(QDragEnterEvent * event) override;
void dropEvent(QDropEvent * event) override;
/** /**
* @param event Key press event to update camera input manager. * @param event Key press event to update camera input manager.
*/ */
@ -174,7 +166,6 @@ namespace Qtk {
/** /**
* Called when the `messageLogged` signal is caught. * Called when the `messageLogged` signal is caught.
* See definition of initializeGL() * See definition of initializeGL()
* https://doc.qt.io/qt-6/qopengldebuglogger.html#signals
* *
* @param msg The message logged. * @param msg The message logged.
*/ */

View File

@ -8,142 +8,13 @@
*/ */
#include "toolbox.h" #include "toolbox.h"
#include "qtkmainwindow.h"
#include "ui_toolbox.h" #include "ui_toolbox.h"
#include <QFormLayout> Qtk::ToolBox::ToolBox(QWidget * parent) :
#include <QLabel> QDockWidget(parent), ui(new Ui::ToolBox) {
using namespace Qtk;
ToolBox::ToolBox(QWidget * parent) : QDockWidget(parent), ui(new Ui::ToolBox) {
ui->setupUi(this); ui->setupUi(this);
setMinimumWidth(350);
} }
void ToolBox::updateFocus(const QString & name) { Qtk::ToolBox::~ToolBox() {
auto object =
MainWindow::getMainWindow()->getQtkWidget()->getScene()->getObject(name);
if(object != Q_NULLPTR) {
removePages();
createPageProperties(object);
createPageShader(object);
}
}
ToolBox::~ToolBox() {
delete ui; 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);
}

View File

@ -12,11 +12,6 @@
#include <QDesignerExportWidget> #include <QDesignerExportWidget>
#include <QDockWidget> #include <QDockWidget>
#include <QDoubleSpinBox>
#include <QGroupBox>
#include "qtk/scene.h"
namespace Ui { namespace Ui {
class ToolBox; class ToolBox;
@ -35,15 +30,6 @@ namespace Qtk {
~ToolBox(); ~ToolBox();
void removePages();
void createPageProperties(const Object * object);
void createPageShader(const Object * object);
void updateFocus(const QString & name);
private: private:
/************************************************************************* /*************************************************************************
* Private Members * Private Members

View File

@ -10,57 +10,17 @@
<height>300</height> <height>300</height>
</rect> </rect>
</property> </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"> <property name="windowTitle">
<string>Object Details</string> <string>Object Details</string>
</property> </property>
<widget class="QWidget" name="dockWidgetContents"> <widget class="QWidget" name="dockWidgetContents">
<property name="sizePolicy"> <layout class="QHBoxLayout" name="horizontalLayout">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QToolBox" name="toolBox"> <widget class="QToolBox" name="toolBox">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page_properties"> <widget class="QWidget" name="page">
<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"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -73,6 +33,19 @@
<string>Shaders</string> <string>Shaders</string>
</attribute> </attribute>
</widget> </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> </widget>
</item> </item>
</layout> </layout>

View File

@ -48,25 +48,16 @@ void Qtk::TreeView::itemFocus(QTreeWidgetItem * item, int column) {
auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene(); auto scene = MainWindow::getMainWindow()->getQtkWidget()->getScene();
auto & transform = scene->getCamera().getTransform(); auto & transform = scene->getCamera().getTransform();
auto object = scene->getObject(name); auto object = scene->getObject(name);
Transform3D * objectTransform;
// If the object is a mesh or model, focus the camera on it.
if(object == Q_NULLPTR) { if(object == Q_NULLPTR) {
qDebug() << "Attempt to get non-existing object with name '" << name qDebug() << "Attempt to get non-existing object with name '" << name
<< "'\n"; << "'\n";
} else if(object->getType() == Object::QTK_MESH) { }
Transform3D * objectTransform;
if(object->getType() == Object::QTK_MESH) {
objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform(); objectTransform = &dynamic_cast<MeshRenderer *>(object)->getTransform();
} else if(object->getType() == Object::QTK_MODEL) { } else if(object->getType() == Object::QTK_MODEL) {
objectTransform = &dynamic_cast<Model *>(object)->getTransform(); objectTransform = &dynamic_cast<Model *>(object)->getTransform();
} }
auto focusScale = objectTransform->getScale(); transform.setTranslation(objectTransform->getTranslation());
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); 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);
} }

View File

@ -68,9 +68,9 @@ target_link_libraries(
Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets Qt6::Core Qt6::OpenGLWidgets Qt6::Widgets
) )
if(QTK_SUBMODULES OR NOT QTK_ASSIMP_NEW_INTERFACE) if(QTK_UPDATE_SUBMODULES OR NOT ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk_library PUBLIC assimp) target_link_libraries(qtk_library PUBLIC assimp)
elseif(QTK_ASSIMP_NEW_INTERFACE) elseif(ASSIMP_NEW_INTERFACE)
target_link_libraries(qtk_library PUBLIC assimp::assimp) target_link_libraries(qtk_library PUBLIC assimp::assimp)
endif() endif()

View File

@ -211,14 +211,6 @@ namespace Qtk {
*/ */
inline Transform3D & getTransform() { return mTransform; } inline Transform3D & getTransform() { return mTransform; }
inline std::string getVertexShader() const override {
return mVertexShader;
}
inline std::string getFragmentShader() const override {
return mFragmentShader;
}
private: private:
/************************************************************************* /*************************************************************************
* Private Members * Private Members

View File

@ -43,7 +43,7 @@ void Model::flipTexture(const std::string & fileName, bool flipX, bool flipY) {
texture.mTexture->destroy(); texture.mTexture->destroy();
texture.mTexture->create(); texture.mTexture->create();
texture.mTexture->setData( texture.mTexture->setData(
OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY)); *OpenGLTextureFactory::initImage(fullPath.c_str(), flipX, flipY));
modified = true; modified = true;
} }
} }
@ -238,7 +238,7 @@ ModelMesh::Textures Model::loadMaterialTextures(
// Add the texture to the textures container // Add the texture to the textures container
textures.push_back(texture); textures.push_back(texture);
// Add the texture to the loaded textures to avoid loading it twice // Add the texture to the loaded textures to avoid loading it twice
mTexturesLoaded.push_back(textures.back()); mTexturesLoaded.push_back(texture);
} }
} }

View File

@ -18,9 +18,6 @@
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
// Qtk // Qtk
#include <QFileInfo>
#include "modelmesh.h" #include "modelmesh.h"
#include "qtkapi.h" #include "qtkapi.h"
@ -127,14 +124,6 @@ namespace Qtk {
*/ */
inline Transform3D & getTransform() { return mTransform; } inline Transform3D & getTransform() { return mTransform; }
inline std::string getVertexShader() const override {
return mVertexShader;
}
inline std::string getFragmentShader() const override {
return mFragmentShader;
}
private: private:
/************************************************************************* /*************************************************************************
* Private Methods * Private Methods

View File

@ -52,10 +52,6 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
shader.setUniformValue((name + number).c_str(), i); 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 // Draw the mesh
glDrawElements( glDrawElements(
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
@ -66,6 +62,7 @@ void ModelMesh::draw(QOpenGLShaderProgram & shader) {
} }
shader.release(); shader.release();
mVAO->release(); mVAO->release();
glActiveTexture(GL_TEXTURE0);
} }
/******************************************************************************* /*******************************************************************************

View File

@ -30,21 +30,6 @@ namespace Qtk {
* Struct to store model textures. 3D Models may have multiple. * Struct to store model textures. 3D Models may have multiple.
*/ */
struct QTKAPI ModelTexture { 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. */ /** Texture ID for for this texture. */
GLuint mID {}; GLuint mID {};
QOpenGLTexture * mTexture {}; QOpenGLTexture * mTexture {};

View File

@ -96,24 +96,10 @@ namespace Qtk {
[[nodiscard]] inline const Type & getType() const { return mType; } [[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 * Setters
************************************************************************/ ************************************************************************/
virtual inline void setName(const std::string & name) { mName = name; }
virtual inline void setColors(const Colors & value) { virtual inline void setColors(const Colors & value) {
mShape.mColors = value; mShape.mColors = value;
} }
@ -149,39 +135,6 @@ namespace Qtk {
mShape.mVertices = value; 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 * Public Methods
************************************************************************/ ************************************************************************/

View File

@ -17,23 +17,17 @@ using namespace Qtk;
QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) : QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
mFile(pFile) { mFile(pFile) {
QString mode(pMode); QString mode(pMode);
bool open = false; bool read = mode.contains('r');
if(mode == "w" || mode == "wb") { bool write = mode.contains('w');
open = mFile.open(QIODeviceBase::WriteOnly); if(read && write) {
} else if(mode == "r" || mode == "rb") { mFile.open(QIODevice::ReadWrite);
open = mFile.open(QIODeviceBase::ReadOnly); } else if(read) {
} else if(mode == "wt") { mFile.open(QIODevice::ReadOnly);
open = mFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text); } else if(write) {
} else if(mode == "rt") { mFile.open(QIODevice::WriteOnly);
open = mFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text);
} else { } else {
open = false;
qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n"; qDebug() << "[Qtk::QtkIOStream] Invalid file open mode: " << mode << "\n";
} }
if(!open) {
qDebug() << "[Qtk::QtkIOStream] Could not open file: " << QString(pFile)
<< "\n";
}
} }
/******************************************************************************* /*******************************************************************************
@ -41,24 +35,34 @@ QtkIOStream::QtkIOStream(const char * pFile, const char * pMode) :
******************************************************************************/ ******************************************************************************/
size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Read(void * pvBuffer, size_t pSize, size_t pCount) {
qint64 readSize = mFile.read((char *)pvBuffer, pSize * pCount); size_t read = 0;
do {
auto readSize = mFile.read((char *)pvBuffer + read, pSize);
if(readSize < 0) { if(readSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to read (" << pSize
<< ") bytes from file at: " << mFile.filesystemFileName().c_str() << ") bytes from file at: " << mFile.filesystemFileName().c_str()
<< "\n"; << "\n";
return -1; return -1;
} }
return readSize; read += readSize;
} while(pCount--);
return read;
} }
size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) { size_t QtkIOStream::Write(const void * pvBuffer, size_t pSize, size_t pCount) {
qint64 writeSize = mFile.write((char *)pvBuffer, pSize * pCount); size_t wrote = 0;
do {
auto writeSize = mFile.write((char *)pvBuffer + wrote, pSize);
if(writeSize < 0) { if(writeSize < 0) {
qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size (" << pSize qDebug() << "[Qtk::QtkIOStream] Failed to write buffer with size ("
<< ") to file at: " << mFile.filesystemFileName().c_str() << "\n"; << pSize
<< ") to file at: " << mFile.filesystemFileName().c_str()
<< "\n";
return -1; return -1;
} }
return writeSize; wrote += writeSize;
} while(pCount--);
return wrote;
} }
aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) { aiReturn QtkIOStream::Seek(size_t pOffset, aiOrigin pOrigin) {

View File

@ -7,7 +7,6 @@
##############################################################################*/ ##############################################################################*/
#include "qtkiosystem.h" #include "qtkiosystem.h"
#include <QDir>
using namespace Qtk; using namespace Qtk;
@ -20,11 +19,15 @@ bool QtkIOSystem::Exists(const char * pFile) const {
} }
char QtkIOSystem::getOsSeparator() const { char QtkIOSystem::getOsSeparator() const {
return QDir::separator().toLatin1(); #ifndef _WIN32
return '/';
#else
return '\\';
#endif
} }
Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) { Assimp::IOStream * QtkIOSystem::Open(const char * pFile, const char * pMode) {
if(!Exists(pFile)) { if(!QFileInfo::exists(pFile)) {
qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n"; qDebug() << "[Qtk::QtkIOSystem] failed to open file: " << pFile << "\n";
return nullptr; return nullptr;
} }

View File

@ -37,42 +37,16 @@ Scene::~Scene() {
* Public Methods * 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() { void Scene::draw() {
if(!mInit) { if(!mInit) {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
init(); init();
mInit = true; 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) { if(mSkybox != Q_NULLPTR) {
mSkybox->draw(); mSkybox->draw();
} }
for(const auto & model : mModels) { for(auto & model : mModels) {
model->draw(); model->draw();
} }
for(const auto & mesh : mMeshes) { for(const auto & mesh : mMeshes) {
@ -83,8 +57,8 @@ void Scene::draw() {
std::vector<Object *> Scene::getObjects() const { std::vector<Object *> Scene::getObjects() const {
// All scene objects must inherit from Qtk::Object. // All scene objects must inherit from Qtk::Object.
std::vector<Object *> objects(mMeshes.begin(), mMeshes.end()); std::vector<Object *> objects(mMeshes.begin(), mMeshes.end());
for(const auto & model : mModels) { for(auto model : mModels) {
objects.push_back(model); objects.push_back(dynamic_cast<Object *>(model));
if(objects.back() == nullptr) { if(objects.back() == nullptr) {
return {}; return {};
} }
@ -92,8 +66,8 @@ std::vector<Object *> Scene::getObjects() const {
return objects; return objects;
} }
Object * Scene::getObject(const QString & name) const { Object * Scene::getObject(const QString & name) {
for(const auto & object : getObjects()) { for(auto object : getObjects()) {
if(object->getName() == name.toStdString()) { if(object->getName() == name.toStdString()) {
return object; return object;
} }
@ -106,14 +80,14 @@ void Scene::setSkybox(Skybox * skybox) {
mSkybox = skybox; mSkybox = skybox;
} }
void Scene::initSceneObjectName(Object * object) { template <> MeshRenderer * Scene::addObject(MeshRenderer * object) {
if(!mObjectCount.count(object->getName())) { mMeshes.push_back(object);
mObjectCount[object->getName()] = 1; sceneUpdated(mSceneName);
} else { return object;
mObjectCount[object->getName()]++; }
}
auto count = mObjectCount[object->getName()]; template <> Model * Scene::addObject(Model * object) {
if(count > 1) { mModels.push_back(object);
object->setName(object->getName() + " (" + std::to_string(count) + ")"); sceneUpdated(mSceneName);
} return object;
} }

View File

@ -10,10 +10,7 @@
#define QTK_SCENE_H #define QTK_SCENE_H
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QUrl>
#include <queue>
#include <unordered_map>
#include <utility> #include <utility>
#include "camera3d.h" #include "camera3d.h"
@ -78,18 +75,6 @@ namespace Qtk {
*/ */
virtual void update() {} 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 * Accessors
************************************************************************/ ************************************************************************/
@ -106,16 +91,7 @@ namespace Qtk {
* @param name The objectName to look for within this scene. * @param name The objectName to look for within this scene.
* @return The found object or Q_NULLPTR if none found. * @return The found object or Q_NULLPTR if none found.
*/ */
[[nodiscard]] Object * getObject(const QString & name) const; [[nodiscard]] Object * getObject(const QString & name);
/**
* @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. * @return Camera attached to this scene.
@ -190,8 +166,6 @@ namespace Qtk {
*/ */
inline void setSceneName(QString name) { mSceneName = std::move(name); } inline void setSceneName(QString name) { mSceneName = std::move(name); }
inline void setPause(bool pause) { mPause = pause; }
signals: signals:
/** /**
* Signal thrown when the scene is modified by adding or removing objects. * Signal thrown when the scene is modified by adding or removing objects.
@ -201,26 +175,7 @@ namespace Qtk {
*/ */
void sceneUpdated(QString sceneName); 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: 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 * Private Members
************************************************************************/ ************************************************************************/
@ -228,16 +183,14 @@ namespace Qtk {
static Camera3D mCamera; static Camera3D mCamera;
static QMatrix4x4 mProjection; static QMatrix4x4 mProjection;
bool mInit = false; bool mInit = false;
/* Pause rendering of the scene. */
bool mPause = false;
QString mSceneName; QString mSceneName;
/* The skybox for this scene. */ /* The skybox for this scene. */
Skybox * mSkybox {}; Skybox * mSkybox {};
/* MeshRenderers used simple geometry. */ /* MeshRenderers used simple geometry. */
std::vector<MeshRenderer *> mMeshes {}; std::vector<MeshRenderer *> mMeshes {};
/* Track count of objects with same initial name. */ /* Models used for storing 3D models in the scene. */
std::unordered_map<std::string, uint64_t> mObjectCount; std::vector<Model *> mModels {};
}; };
class SceneEmpty : public Scene { class SceneEmpty : public Scene {

View File

@ -9,18 +9,19 @@
#include <QDebug> #include <QDebug>
#include <QImageReader> #include <QImageReader>
#include "app/qtkmainwindow.h"
#include "texture.h" #include "texture.h"
using namespace Qtk; using namespace Qtk;
QImage OpenGLTextureFactory::initImage( QImage * OpenGLTextureFactory::initImage(
const char * image, bool flipX, bool flipY) { const char * image, bool flipX, bool flipY) {
// Qt6 limits loaded images to 256MB by default // Qt6 limits loaded images to 256MB by default
QImageReader::setAllocationLimit(1024); QImageReader::setAllocationLimit(512);
auto loadedImage = QImage(image).mirrored(flipX, flipY); auto loadedImage = new QImage(QImage(image).mirrored(flipX, flipY));
if(loadedImage.isNull()) { if(loadedImage->isNull()) {
return defaultTexture(); qDebug() << "[Qtk::OpenGLTextureFactory] Error loading image: " << image
<< "\nSupported types: " << QImageReader::supportedImageFormats();
return Q_NULLPTR;
} }
return loadedImage; return loadedImage;
@ -28,12 +29,13 @@ QImage OpenGLTextureFactory::initImage(
QOpenGLTexture * OpenGLTextureFactory::initTexture( QOpenGLTexture * OpenGLTextureFactory::initTexture(
const char * texture, bool flipX, bool flipY) { 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); auto newTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
newTexture->setData(image); newTexture->setData(*image);
newTexture->setWrapMode(QOpenGLTexture::Repeat); newTexture->setWrapMode(QOpenGLTexture::Repeat);
newTexture->setMinMagFilters( newTexture->setMinMagFilters(
QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
delete image;
return newTexture; return newTexture;
} }
@ -69,7 +71,6 @@ QOpenGLTexture * OpenGLTextureFactory::initCubeMap(
QImage faceImage(faceTextures[i]); QImage faceImage(faceTextures[i]);
if(faceImage.isNull()) { if(faceImage.isNull()) {
qDebug() << "Error loading cube map image\n"; qDebug() << "Error loading cube map image\n";
faceImage = defaultTexture();
} }
faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888); faceImage = faceImage.convertToFormat(QImage::Format_RGBA8888);

View File

@ -74,9 +74,9 @@ namespace Qtk {
* Can be absolute or Qt resource path. * Can be absolute or Qt resource path.
* @param flipX If true the image will be flipped on X axis. * @param flipX If true the image will be flipped on X axis.
* @param flipY If true the image will be flipped on Y axis. * @param flipY If true the image will be flipped on Y axis.
* @return QImage object. * @return Pointer to an initialized QImage object.
*/ */
static QImage initImage( static QImage * initImage(
const char * image, bool flipX = false, bool flipY = false); const char * image, bool flipX = false, bool flipY = false);
/** /**
@ -132,14 +132,6 @@ namespace Qtk {
const char * right, const char * top, const char * front, const char * right, const char * top, const char * front,
const char * left, const char * bottom, const char * back); 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:
// Private ctor to prevent creating instances of this class // Private ctor to prevent creating instances of this class
OpenGLTextureFactory() = default; OpenGLTextureFactory() = default;