├── examples
├── CMakeLists.txt
├── vsgqtmdi
│ ├── CMakeLists.txt
│ └── main.cpp
├── vsgqtviewer
│ ├── CMakeLists.txt
│ └── main.cpp
└── vsgqtwindows
│ ├── CMakeLists.txt
│ └── main.cpp
├── src
└── vsgQt
│ ├── vsgQtConfig.cmake.in
│ ├── CMakeLists.txt
│ ├── Viewer.cpp
│ ├── KeyboardMap.cpp
│ └── Window.cpp
├── LICENSE.md
├── .gitignore
├── README.md
├── CMakeLists.txt
├── include
└── vsgQt
│ ├── KeyboardMap.h
│ ├── Viewer.h
│ └── Window.h
└── .clang-format
/examples/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(vsgXchange CONFIG)
2 |
3 | add_subdirectory(vsgqtviewer)
4 | add_subdirectory(vsgqtmdi)
5 | add_subdirectory(vsgqtwindows)
6 |
--------------------------------------------------------------------------------
/src/vsgQt/vsgQtConfig.cmake.in:
--------------------------------------------------------------------------------
1 | # generated by cmake, do not change
2 |
3 | include(CMakeFindDependencyMacro)
4 |
5 | find_dependency(@QT_PACKAGE_NAME@ COMPONENTS Widgets)
6 |
7 | include("${CMAKE_CURRENT_LIST_DIR}/vsgQtTargets.cmake")
8 |
--------------------------------------------------------------------------------
/examples/vsgqtmdi/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SOURCES
2 | main.cpp
3 | )
4 |
5 | set(HEADERS
6 | )
7 |
8 | add_executable(vsgqtmdi ${MODE} ${SOURCES} ${HEADERS} ${FORMS})
9 |
10 | target_link_libraries(vsgqtmdi vsgQt)
11 |
12 | if (vsgXchange_FOUND)
13 | target_compile_definitions(vsgqtmdi PRIVATE vsgXchange_FOUND)
14 | target_link_libraries(vsgqtmdi vsgXchange::vsgXchange)
15 | endif()
16 |
17 |
18 | install(TARGETS vsgqtmdi DESTINATION bin)
19 |
20 |
--------------------------------------------------------------------------------
/examples/vsgqtviewer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SOURCES
2 | main.cpp
3 | )
4 |
5 | set(HEADERS
6 | )
7 |
8 | add_executable(vsgqtviewer ${MODE} ${SOURCES} ${HEADERS} ${FORMS})
9 |
10 | target_link_libraries(vsgqtviewer vsgQt)
11 |
12 | if (vsgXchange_FOUND)
13 | target_compile_definitions(vsgqtviewer PRIVATE vsgXchange_FOUND)
14 | target_link_libraries(vsgqtviewer vsgXchange::vsgXchange)
15 | endif()
16 |
17 |
18 | install(TARGETS vsgqtviewer DESTINATION bin)
19 |
20 |
--------------------------------------------------------------------------------
/examples/vsgqtwindows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SOURCES
2 | main.cpp
3 | )
4 |
5 | set(HEADERS
6 | )
7 |
8 | add_executable(vsgqtwindows ${MODE} ${SOURCES} ${HEADERS} ${FORMS})
9 |
10 | target_link_libraries(vsgqtwindows vsgQt)
11 |
12 | if (vsgXchange_FOUND)
13 | target_compile_definitions(vsgqtwindows PRIVATE vsgXchange_FOUND)
14 | target_link_libraries(vsgqtwindows vsgXchange::vsgXchange)
15 | endif()
16 |
17 |
18 | install(TARGETS vsgqtwindows DESTINATION bin)
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Robert Osfield
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | cmake_uninstall.cmake
3 |
4 | lib/
5 | bin/
6 | install/
7 |
8 | # Autogenerated files
9 | *.pc
10 | *.conf
11 | *.backup
12 | CMakeCache.txt
13 | CMakeFiles
14 | CMakeScripts
15 | Makefile
16 | cmake_install.cmake
17 | install_manifest.txt
18 | CMakeDoxyfile.in
19 | CMakeDoxygenDefaults.cmake
20 | Doxyfile.docs
21 | vsgQtConfig.cmake
22 | vsgQtConfigVersion.cmake
23 | *_autogen/
24 | include/vsgQt/Export.h
25 | Doxyfile.docs-vsgQt
26 |
27 | # Compiled Object files
28 | *.slo
29 | *.lo
30 | *.o
31 | *.obj
32 |
33 | # Precompiled Headers
34 | *.gch
35 | *.pch
36 |
37 | # Compiled Dynamic libraries
38 | *.so
39 | *.dylib
40 | *.dll
41 |
42 | # Fortran module files
43 | *.mod
44 |
45 | # Compiled Static libraries
46 | *.lai
47 | *.la
48 | *.a
49 | *.lib
50 |
51 | # Executables
52 | *.exe
53 | *.out
54 | *.app
55 |
56 | # Visual Studio files
57 | *.sln
58 | *.vcxproj
59 | *.vcxproj.filters
60 | *.vcxproj.user
61 | .vs/
62 | x64/
63 | src/vsgGIS/vsgGIS.dir/
64 | *.pdb
65 | *.tlog
66 | *.log
67 |
68 | # Xcode
69 | DerivedData/
70 | *.build
71 | *.xcodeproj
72 |
73 | # Gradle
74 | .gradle/
75 | .idea/
76 | .externalNativeBuild/
77 | *.iml
78 | build/
79 | local.properties
80 |
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vsgQt
2 | Open Source ([MIT Licensed](LICENSE.md)), cross platform C++ library providing integration of VulkanSceneGraph with Qt windowing. Supports Windows, Linux and macOS.
3 |
4 | vsgQt provides full Vulkan support through the VulkanSceneGraph's built in Window/VkSurface support rather than the limited Vulkan support that Qt-5.10 or later provide. Using the VulkanSceneGraph for providing Vulkan support avoids the restriction that Qt's VulkanWindow has with not being able to share VkDevice between windows, and provides compatibility with Qt versions prior to it adding Vulkan support. Sharing vsg::Device/VkDevice between Windows is crucial for providing multiple windows without blowing up GPU memory usage.
5 |
6 | ## Checking out vsgQt
7 |
8 | ~~~ sh
9 | git clone https://github.com/vsg-dev/vsgQt.git
10 | ~~~
11 |
12 | ## Dependencies:
13 |
14 | * [VulkanSDK](https://www.lunarg.com/vulkan-sdk/) version 1.1.70 or later
15 | * [VulkanSceneGraph](https://github.com/vsg-dev/VulkanSceneGraph) master, 1.0.8 or later.
16 | * [CMake](https://cmake.org/) version 3.7 or later
17 | * [Qt](https://www.qt.io/) version 5 or later
18 | * C++17 capable compiler
19 |
20 | ## Building vsgQt
21 |
22 | ~~~ sh
23 | cd vsgQt
24 | cmake .
25 | make -j 8
26 | ~~~
27 |
28 | ## Examples
29 |
30 | * [vsgqtviewer](examples/vsgqtviewer/main.cpp) - example of QApplication/QMainWindow usage with single vsgQt::Window.
31 | * [vsgqtmdi](examples/vsgqtmdi/main.cpp) - example of QMdiArea usage with multiple vsgQt::Window.
32 | * [vsgqtwindows](examples/vsgqtwindows/main.cpp) - example of multiple vsgQt::Window.
33 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10)
2 |
3 | project(vsgQt
4 | VERSION 0.5.0
5 | DESCRIPTION "Qt integration with VulkanSceneGraph"
6 | LANGUAGES CXX
7 | )
8 |
9 | option(VSGQT_BUILD_EXAMPLES "Build examples" ON)
10 |
11 | set(VSGQT_SOVERSION 3)
12 | set(VSGQT_RELEASE_CANDIDATE 0)
13 |
14 | set(VSGQT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "Root source directory of vsgQt")
15 | set(VSGQT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "Root binary directory of vsgQt")
16 |
17 | set(QT_PACKAGE_NAME Qt5 CACHE STRING "Set Qt package name, i.e. Qt5 or Qt6.")
18 |
19 | find_package(vsg 1.1.13)
20 |
21 | vsg_setup_dir_vars()
22 | vsg_setup_build_vars()
23 |
24 | # if Qt5 then we need 5.10 or later
25 | find_package(${QT_PACKAGE_NAME} COMPONENTS Widgets REQUIRED)
26 |
27 | vsg_add_target_clang_format(
28 | FILES
29 | include/*/*.h
30 | src/*/*.cpp
31 | )
32 | vsg_add_target_clobber()
33 | vsg_add_target_cppcheck(
34 | FILES
35 | include/*/*.h
36 | src/*/*.cpp
37 | )
38 | vsg_add_target_docs(
39 | FILES
40 | src
41 | include/*/*.h
42 | src/*/*.cpp
43 | )
44 | vsg_add_target_uninstall()
45 |
46 | # only provide custom targets if not building as a submodule/FetchContent
47 | if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
48 |
49 | vsg_add_option_maintainer(
50 | PREFIX v
51 | RCLEVEL ${VSGQT_RELEASE_CANDIDATE}
52 | )
53 |
54 | endif()
55 |
56 | set(CMAKE_AUTOMOC ON)
57 | set(CMAKE_AUTORCC ON)
58 | set(CMAKE_AUTOUIC ON)
59 |
60 | if(WIN32)
61 | add_definitions(-DNOMINMAX)
62 | set(MODE WIN32)
63 | endif()
64 |
65 | add_subdirectory(src/vsgQt)
66 | if (VSGQT_BUILD_EXAMPLES)
67 | add_subdirectory(examples)
68 | endif()
69 |
70 | vsg_add_feature_summary()
71 |
--------------------------------------------------------------------------------
/include/vsgQt/KeyboardMap.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 |
5 | Copyright(c) 2021 Robert Osfield
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | */
14 |
15 | #include
16 |
17 | #include
18 | #include
19 |
20 | namespace vsgQt
21 | {
22 |
23 | class VSGQT_DECLSPEC KeyboardMap : public vsg::Inherit
24 | {
25 | public:
26 | KeyboardMap();
27 |
28 | bool getKeySymbol(const QKeyEvent* e, vsg::KeySymbol& keySymbol, vsg::KeySymbol& modifiedKeySymbol, vsg::KeyModifier& keyModifier);
29 |
30 | protected:
31 | using VirtualKeyToKeySymbolMap = std::map;
32 | VirtualKeyToKeySymbolMap _keycodeMap;
33 | };
34 |
35 | } // namespace vsgQt
36 |
37 | EVSG_type_name(vsgQt::KeyboardMap);
38 |
--------------------------------------------------------------------------------
/src/vsgQt/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | # create and install export header which contains export macros for libraries
3 | #
4 | # available arguments:
5 | #
6 | # pattern for generating macro names (_DECLSPEC)
7 | # and install paths (include//Export.h)
8 | #
9 | # In public c++ headers the generated file must be included with
10 | #
11 | # #include </Export.h>
12 | #
13 | # and public classes be decorated with
14 | #
15 | # class _DECLSPEC ...
16 | #
17 | # @TODO: move to vsg
18 | macro(add_library_export_header _TARGET)
19 |
20 | string(TOUPPER ${_TARGET} TARGET_UPPER)
21 |
22 | include(GenerateExportHeader)
23 | generate_export_header(${_TARGET}
24 | EXPORT_MACRO_NAME ${TARGET_UPPER}_DECLSPEC
25 | EXPORT_FILE_NAME ${VSGQT_BINARY_DIR}/include/${_TARGET}/Export.h
26 | )
27 | install(FILES ${VSGQT_BINARY_DIR}/include/${_TARGET}/Export.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_TARGET})
28 |
29 | # pass the creation mode to the corresponding target in the cmake
30 | if(NOT BUILD_SHARED_LIBS)
31 | target_compile_definitions(${_TARGET} INTERFACE ${TARGET_UPPER}_STATIC_DEFINE)
32 | endif()
33 | endmacro()
34 |
35 | set(SOURCES
36 | KeyboardMap.cpp
37 | Window.cpp
38 | Viewer.cpp
39 | )
40 |
41 | set(HEADERS
42 | ../../include/vsgQt/KeyboardMap.h
43 | ../../include/vsgQt/Window.h
44 | ../../include/vsgQt/Viewer.h
45 | )
46 |
47 | # shared mode is automatically chosen by setting BUILD_SHARED_LIBS=ON
48 | # POSITION_INDEPENDENT_CODE ON is set by default in shared mode
49 | add_library(vsgQt ${SOURCES} ${HEADERS})
50 |
51 | # add definitions to enable building vsgQt as part of submodule
52 | add_library(vsgQt::vsgQt ALIAS vsgQt)
53 | set(vsgQt_FOUND TRUE CACHE INTERNAL "vsgQt found.")
54 | set(CMAKE_DISABLE_FIND_PACKAGE_vsgQt TRUE CACHE INTERNAL "Disable find_package(vsgQt) as it's not necessary.")
55 |
56 | set_target_properties(vsgQt
57 | PROPERTIES
58 | VERSION ${VSGQT_VERSION}
59 | SOVERSION ${VSGQT_SOVERSION}
60 | )
61 |
62 | target_include_directories(vsgQt
63 | PUBLIC
64 | $
65 | $
66 | $
67 | )
68 | target_link_libraries(vsgQt
69 | PUBLIC
70 | ${QT_PACKAGE_NAME}::Widgets
71 | vsg::vsg
72 | )
73 |
74 | add_library_export_header(vsgQt)
75 |
76 | install(TARGETS vsgQt ${INSTALL_TARGETS_DEFAULT_FLAGS})
77 | install(DIRECTORY ${VSGQT_SOURCE_DIR}/include/vsgQt DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
78 |
79 | vsg_add_cmake_support_files(
80 | CONFIG_TEMPLATE vsgQtConfig.cmake.in
81 | )
82 |
--------------------------------------------------------------------------------
/include/vsgQt/Viewer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 |
5 | Copyright(c) 2021 Robert Osfield
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | */
14 |
15 | #include
16 |
17 | #include
18 |
19 | #include
20 |
21 | namespace vsgQt
22 | {
23 |
24 | // forward declare
25 | class Window;
26 |
27 | class VSGQT_DECLSPEC Viewer : public vsg::Inherit
28 | {
29 | public:
30 | /// Create Viewer.
31 | /// If msecTimerInterval is > 0 then call setInterval(msecTimerInterval) to set up QTime to call Viewer::render() at this interval,
32 | /// otherwise the redraw is left application to call Viewer::render() when required, call Viewer::setInverval() to set up the timer,
33 | /// or to call the underlying vsg::Viewer methods for rendering a framne within the application when the viewer needs to redraw a frame.
34 | Viewer(int msecTimerInterval = 0);
35 |
36 | QTimer timer;
37 | std::atomic_uint requests;
38 | bool continuousUpdate = true;
39 |
40 | /// override pollEvents to prevent the window->pollEvents() from being called by vsg::Viewer
41 | bool pollEvents(bool discardPreviousEvents = true) override;
42 |
43 | /// increment the requests count to signal that a new frame should be rendered on the next timer call.
44 | virtual void request();
45 |
46 | /// called by the QTimer and will do the viewer frame calls to render all windows associated with the viewer.
47 | /// if continuousUpdate is false then the viewer frame calls are only done if the requests count is > 0
48 | virtual void render(double simulationTime = vsg::Viewer::UseTimeSinceStartPoint);
49 |
50 | /// set the QTimer interval in milliseconds, this controls how often the Viewer::render() is called
51 | void setInterval(int msecTimerInterval);
52 | };
53 |
54 | } // namespace vsgQt
55 |
56 | EVSG_type_name(vsgQt::Viewer);
57 |
--------------------------------------------------------------------------------
/src/vsgQt/Viewer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright(c) 2021 Robert Osfield, Andre Normann
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 | */
12 |
13 | #if defined(WIN32)
14 | # define VK_USE_PLATFORM_WIN32_KHR
15 | #elif defined(__APPLE__)
16 | # define VK_USE_PLATFORM_MACOS_MVK
17 | #else
18 | # define VK_USE_PLATFORM_XCB_KHR
19 | // #define VK_USE_PLATFORM_XLIB_KHR
20 | #endif
21 |
22 | #include
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #include
35 |
36 | using namespace vsgQt;
37 |
38 | Viewer::Viewer(int msecTimerInterval)
39 | {
40 | // set the default timer as 8ms.
41 | if (msecTimerInterval > 0) setInterval(msecTimerInterval);
42 | }
43 |
44 | bool Viewer::pollEvents(bool discardPreviousEvents)
45 | {
46 | if (discardPreviousEvents) _events.clear();
47 | for (auto& window : _windows)
48 | {
49 | _events.splice(_events.end(), window->bufferedEvents);
50 | window->bufferedEvents.clear();
51 | }
52 |
53 | return !_events.empty();
54 | }
55 |
56 | void Viewer::request()
57 | {
58 | ++requests;
59 | }
60 |
61 | void Viewer::render(double simulationTime)
62 | {
63 | if (!continuousUpdate && requests.load() == 0)
64 | {
65 | //vsg::info("render() no render : requests = ", requests.load());
66 | return;
67 | }
68 |
69 | if (advanceToNextFrame(simulationTime))
70 | {
71 | handleEvents();
72 | update();
73 | recordAndSubmit();
74 | present();
75 | }
76 | else
77 | {
78 | if (status->cancel())
79 | {
80 | QCoreApplication::quit();
81 | }
82 | }
83 |
84 | requests = 0;
85 | }
86 |
87 | void Viewer::setInterval(int msecTimerInterval)
88 | {
89 | timer.setInterval(msecTimerInterval);
90 | timer.connect(&timer, &QTimer::timeout, [&]() { render(); });
91 | timer.start();
92 | }
93 |
--------------------------------------------------------------------------------
/include/vsgQt/Window.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 |
5 | Copyright(c) 2021 Robert Osfield
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | */
14 |
15 | //#include
16 | #include
17 |
18 | #include
19 |
20 | #include
21 | #include
22 |
23 | namespace vsgQt
24 | {
25 |
26 | class VSGQT_DECLSPEC Window : public QWindow
27 | {
28 | public:
29 | Window(QScreen* targetScreen = nullptr);
30 | Window(QWindow* parent);
31 | Window(vsg::ref_ptr in_traits, QScreen* targetScreen = nullptr);
32 | Window(vsg::ref_ptr in_traits, QWindow* parent);
33 | Window(vsg::ref_ptr in_viewer, vsg::ref_ptr in_traits, QScreen* targetScreen = nullptr);
34 | Window(vsg::ref_ptr in_viewer, vsg::ref_ptr in_traits, QWindow* parent);
35 |
36 | virtual ~Window();
37 |
38 | vsg::ref_ptr traits;
39 | vsg::ref_ptr viewer;
40 |
41 | vsg::ref_ptr windowAdapter;
42 | vsg::ref_ptr keyboardMap;
43 |
44 | operator vsg::ref_ptr() { return windowAdapter; }
45 |
46 | /// Initialize the Vulkan integration using VulkanSceneGraph VkInstance/VkSurface support
47 | virtual void initializeWindow();
48 |
49 | protected:
50 | void cleanup();
51 |
52 | bool event(QEvent* e) override;
53 |
54 | void exposeEvent(QExposeEvent*) override;
55 | void hideEvent(QHideEvent* ev) override;
56 |
57 | void keyPressEvent(QKeyEvent*) override;
58 | void keyReleaseEvent(QKeyEvent*) override;
59 | void mouseMoveEvent(QMouseEvent*) override;
60 | void mousePressEvent(QMouseEvent*) override;
61 | void mouseReleaseEvent(QMouseEvent*) override;
62 | void resizeEvent(QResizeEvent*) override;
63 | void wheelEvent(QWheelEvent*) override;
64 |
65 | /// convert Qt's window coordinate into Vulkan/VSG ones by scaling by the devicePixelRatio()
66 | template
67 | int32_t convert_coord(T c) const { return static_cast(std::round(static_cast(c) * devicePixelRatio())); }
68 |
69 | std::pair convertMouseButtons(QMouseEvent* e) const;
70 | std::pair convertMousePosition(QMouseEvent* e) const;
71 |
72 | private:
73 | bool _initialized = false;
74 | };
75 |
76 | } // namespace vsgQt
77 |
78 | EVSG_type_name(vsgQt::Window);
79 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | # BasedOnStyle: LLVM
4 | AccessModifierOffset: -4
5 | AlignAfterOpenBracket: Align
6 | AlignConsecutiveAssignments: false
7 | AlignConsecutiveDeclarations: false
8 | AlignEscapedNewlines: Right
9 | AlignOperands: true
10 | AlignTrailingComments: true
11 | AllowAllParametersOfDeclarationOnNextLine: true
12 | AllowShortBlocksOnASingleLine: true
13 | AllowShortCaseLabelsOnASingleLine: true
14 | AllowShortFunctionsOnASingleLine: InlineOnly
15 | AllowShortIfStatementsOnASingleLine: true
16 | AllowShortLoopsOnASingleLine: true
17 | AlwaysBreakAfterDefinitionReturnType: None
18 | AlwaysBreakAfterReturnType: None
19 | AlwaysBreakBeforeMultilineStrings: false
20 | AlwaysBreakTemplateDeclarations: false
21 | BinPackArguments: true
22 | BinPackParameters: true
23 | BraceWrapping:
24 | AfterClass: true
25 | AfterControlStatement: true
26 | AfterEnum: true
27 | AfterFunction: true
28 | AfterNamespace: true
29 | AfterObjCDeclaration: true
30 | AfterStruct: true
31 | AfterUnion: true
32 | AfterExternBlock: true
33 | BeforeCatch: true
34 | BeforeElse: true
35 | IndentBraces: false
36 | SplitEmptyFunction: true
37 | SplitEmptyRecord: true
38 | SplitEmptyNamespace: true
39 | BreakBeforeBinaryOperators: None
40 | BreakBeforeBraces: Custom
41 | BreakBeforeInheritanceComma: false
42 | BreakBeforeTernaryOperators: true
43 | BreakConstructorInitializersBeforeComma: true
44 | BreakConstructorInitializers: AfterColon
45 | BreakAfterJavaFieldAnnotations: false
46 | BreakStringLiterals: true
47 | ColumnLimit: 0
48 | CommentPragmas: '^ IWYU pragma:'
49 | CompactNamespaces: false
50 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
51 | ConstructorInitializerIndentWidth: 4
52 | ContinuationIndentWidth: 4
53 | Cpp11BracedListStyle: true
54 | DerivePointerAlignment: false
55 | DisableFormat: false
56 | ExperimentalAutoDetectBinPacking: false
57 | FixNamespaceComments: true
58 | ForEachMacros:
59 | - foreach
60 | - Q_FOREACH
61 | - BOOST_FOREACH
62 | IncludeBlocks: Preserve
63 | IncludeCategories:
64 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
65 | Priority: 2
66 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
67 | Priority: 3
68 | - Regex: '.*'
69 | Priority: 1
70 | IncludeIsMainRegex: '(Test)?$'
71 | IndentCaseLabels: false
72 | IndentPPDirectives: AfterHash
73 | IndentWidth: 4
74 | IndentWrappedFunctionNames: false
75 | JavaScriptQuotes: Leave
76 | JavaScriptWrapImports: true
77 | KeepEmptyLinesAtTheStartOfBlocks: true
78 | MacroBlockBegin: ''
79 | MacroBlockEnd: ''
80 | MaxEmptyLinesToKeep: 1
81 | NamespaceIndentation: All
82 | ObjCBlockIndentWidth: 4
83 | ObjCSpaceAfterProperty: false
84 | ObjCSpaceBeforeProtocolList: true
85 | PenaltyBreakAssignment: 2
86 | PenaltyBreakBeforeFirstCallParameter: 19
87 | PenaltyBreakComment: 300
88 | PenaltyBreakFirstLessLess: 120
89 | PenaltyBreakString: 1000
90 | PenaltyExcessCharacter: 1000000
91 | PenaltyReturnTypeOnItsOwnLine: 60
92 | PointerAlignment: Left
93 | ReflowComments: false
94 | SortIncludes: true
95 | SortUsingDeclarations: true
96 | SpaceAfterCStyleCast: false
97 | SpaceAfterTemplateKeyword: false
98 | SpaceBeforeAssignmentOperators: true
99 | SpaceBeforeParens: ControlStatements
100 | SpaceInEmptyParentheses: false
101 | SpacesBeforeTrailingComments: 1
102 | SpacesInAngles: false
103 | SpacesInContainerLiterals: true
104 | SpacesInCStyleCastParentheses: false
105 | SpacesInParentheses: false
106 | SpacesInSquareBrackets: false
107 | Standard: Cpp11
108 | TabWidth: 8
109 | UseTab: Never
110 | ...
111 |
112 |
--------------------------------------------------------------------------------
/examples/vsgqtviewer/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #ifdef vsgXchange_FOUND
4 | # include
5 | #endif
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | #include
13 |
14 | vsgQt::Window* createWindow(vsg::ref_ptr viewer, vsg::ref_ptr traits, vsg::ref_ptr vsg_scene, QWindow* parent, const QString& title = {})
15 | {
16 | auto window = new vsgQt::Window(viewer, traits, parent);
17 |
18 | window->setTitle(title);
19 |
20 | window->initializeWindow();
21 |
22 | // if this is the first window to be created, use its device for future window creation.
23 | if (!traits->device) traits->device = window->windowAdapter->getOrCreateDevice();
24 |
25 | // compute the bounds of the scene graph to help position camera
26 | vsg::ComputeBounds computeBounds;
27 | vsg_scene->accept(computeBounds);
28 | vsg::dvec3 centre = (computeBounds.bounds.min + computeBounds.bounds.max) * 0.5;
29 | double radius = vsg::length(computeBounds.bounds.max - computeBounds.bounds.min) * 0.6;
30 | double nearFarRatio = 0.001;
31 |
32 | uint32_t width = window->traits->width;
33 | uint32_t height = window->traits->height;
34 |
35 | vsg::ref_ptr ellipsoidModel(vsg_scene->getObject("EllipsoidModel"));
36 | vsg::ref_ptr camera;
37 | {
38 | // set up the camera
39 | auto lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -radius * 3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0));
40 |
41 | vsg::ref_ptr perspective;
42 | if (ellipsoidModel)
43 | {
44 | perspective = vsg::EllipsoidPerspective::create(
45 | lookAt, ellipsoidModel, 30.0,
46 | static_cast(width) /
47 | static_cast(height),
48 | nearFarRatio, false);
49 | }
50 | else
51 | {
52 | perspective = vsg::Perspective::create(
53 | 30.0,
54 | static_cast(width) /
55 | static_cast(height),
56 | nearFarRatio * radius, radius * 4.5);
57 | }
58 |
59 | camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(VkExtent2D{width, height}));
60 | }
61 |
62 | auto trackball = vsg::Trackball::create(camera, ellipsoidModel);
63 | trackball->addWindow(*window);
64 |
65 | viewer->addEventHandler(trackball);
66 |
67 | auto commandGraph = vsg::createCommandGraphForView(*window, camera, vsg_scene);
68 |
69 | viewer->addRecordAndSubmitTaskAndPresentation({commandGraph});
70 |
71 | return window;
72 | }
73 |
74 | int main(int argc, char* argv[])
75 | {
76 | QApplication application(argc, argv);
77 |
78 | vsg::CommandLine arguments(&argc, argv);
79 |
80 | // set up vsg::Options to pass in filepaths, ReaderWriters and other IO
81 | // related options to use when reading and writing files.
82 | auto options = vsg::Options::create();
83 | options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
84 | options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
85 | #ifdef vsgXchange_FOUND
86 | options->add(vsgXchange::all::create());
87 | #endif
88 |
89 | options->readOptions(arguments);
90 |
91 | auto windowTraits = vsg::WindowTraits::create();
92 | windowTraits->windowTitle = "vsgQt viewer";
93 | windowTraits->debugLayer = arguments.read({"--debug", "-d"});
94 | windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
95 | arguments.read("--samples", windowTraits->samples);
96 | arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height);
97 | if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;
98 |
99 | bool continuousUpdate = !arguments.read({"--event-driven", "--ed"});
100 | auto interval = arguments.value(8, "--interval");
101 |
102 | if (arguments.errors())
103 | return arguments.writeErrorMessages(std::cerr);
104 |
105 | if (argc <= 1)
106 | {
107 | std::cout << "Please specify a 3d model or image file on the command line."
108 | << std::endl;
109 | return 1;
110 | }
111 |
112 | vsg::Path filename = arguments[1];
113 |
114 | auto vsg_scene = vsg::read_cast(filename, options);
115 | if (!vsg_scene)
116 | {
117 | std::cout << "Failed to load a valid scene graph. Please specify a valid 3d "
118 | "model or image file on the command line."
119 | << std::endl;
120 | return 1;
121 | }
122 |
123 |
124 | QMainWindow* mainWindow = new QMainWindow();
125 |
126 | // create the viewer that will manage all the rendering of the views
127 | auto viewer = vsgQt::Viewer::create();
128 |
129 | auto window = createWindow(viewer, windowTraits, vsg_scene, nullptr, "First Window");
130 |
131 | auto widget = QWidget::createWindowContainer(window, mainWindow);
132 |
133 | mainWindow->setCentralWidget(widget);
134 |
135 | mainWindow->setGeometry(windowTraits->x, windowTraits->y, windowTraits->width, windowTraits->height);
136 |
137 | mainWindow->show();
138 |
139 | if (interval >= 0) viewer->setInterval(interval);
140 | viewer->continuousUpdate = continuousUpdate;
141 |
142 | viewer->addEventHandler(vsg::CloseHandler::create(viewer));
143 | viewer->compile();
144 |
145 | return application.exec();
146 | }
147 |
--------------------------------------------------------------------------------
/examples/vsgqtwindows/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #ifdef vsgXchange_FOUND
4 | # include
5 | #endif
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | vsgQt::Window* createWindow(vsg::ref_ptr viewer, vsg::ref_ptr traits, vsg::ref_ptr vsg_scene, QWindow* parent, const QString& title = {})
16 | {
17 | auto window = new vsgQt::Window(viewer, traits, parent);
18 |
19 | window->setTitle(title);
20 |
21 | window->initializeWindow();
22 |
23 | // if this is the first window to be created, use its device for future window creation.
24 | if (!traits->device) traits->device = window->windowAdapter->getOrCreateDevice();
25 |
26 | // compute the bounds of the scene graph to help position camera
27 | vsg::ComputeBounds computeBounds;
28 | vsg_scene->accept(computeBounds);
29 | vsg::dvec3 centre = (computeBounds.bounds.min + computeBounds.bounds.max) * 0.5;
30 | double radius = vsg::length(computeBounds.bounds.max - computeBounds.bounds.min) * 0.6;
31 | double nearFarRatio = 0.001;
32 |
33 | uint32_t width = window->traits->width;
34 | uint32_t height = window->traits->height;
35 |
36 | vsg::ref_ptr ellipsoidModel(vsg_scene->getObject("EllipsoidModel"));
37 | vsg::ref_ptr camera;
38 | {
39 | // set up the camera
40 | auto lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -radius * 3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0));
41 |
42 | vsg::ref_ptr perspective;
43 | if (ellipsoidModel)
44 | {
45 | perspective = vsg::EllipsoidPerspective::create(
46 | lookAt, ellipsoidModel, 30.0,
47 | static_cast(width) /
48 | static_cast(height),
49 | nearFarRatio, false);
50 | }
51 | else
52 | {
53 | perspective = vsg::Perspective::create(
54 | 30.0,
55 | static_cast(width) /
56 | static_cast(height),
57 | nearFarRatio * radius, radius * 4.5);
58 | }
59 |
60 | camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(VkExtent2D{width, height}));
61 | }
62 |
63 | auto trackball = vsg::Trackball::create(camera, ellipsoidModel);
64 | trackball->addWindow(*window);
65 |
66 | viewer->addEventHandler(trackball);
67 |
68 | auto commandGraph = vsg::createCommandGraphForView(*window, camera, vsg_scene);
69 |
70 | viewer->addRecordAndSubmitTaskAndPresentation({commandGraph});
71 |
72 | return window;
73 | }
74 |
75 | int main(int argc, char* argv[])
76 | {
77 | QApplication application(argc, argv);
78 |
79 | vsg::CommandLine arguments(&argc, argv);
80 |
81 | // set up vsg::Options to pass in filepaths, ReaderWriters and other IO
82 | // related options to use when reading and writing files.
83 | auto options = vsg::Options::create();
84 | options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
85 | options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
86 | #ifdef vsgXchange_FOUND
87 | options->add(vsgXchange::all::create());
88 | #endif
89 |
90 | options->readOptions(arguments);
91 |
92 | auto windowTraits = vsg::WindowTraits::create();
93 | windowTraits->windowTitle = "vsgQt viewer";
94 | windowTraits->debugLayer = arguments.read({"--debug", "-d"});
95 | windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
96 | arguments.read("--samples", windowTraits->samples);
97 | arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height);
98 | if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;
99 |
100 | bool continuousUpdate = !arguments.read({"--event-driven", "--ed"});
101 | auto interval = arguments.value(8, "--interval");
102 |
103 | if (arguments.errors())
104 | return arguments.writeErrorMessages(std::cerr);
105 |
106 | if (argc <= 1)
107 | {
108 | std::cout << "Please specify a 3d model or image file on the command line."
109 | << std::endl;
110 | return 1;
111 | }
112 |
113 | vsg::Path filename = arguments[1];
114 |
115 | auto vsg_scene = vsg::read_cast(filename, options);
116 | if (!vsg_scene)
117 | {
118 | std::cout << "Failed to load a valid scene graph. Please specify a valid 3d "
119 | "model or image file on the command line."
120 | << std::endl;
121 | return 1;
122 | }
123 |
124 |
125 |
126 | // create the viewer that will manage all the rendering of the views
127 | auto viewer = vsgQt::Viewer::create();
128 |
129 | // add close handler to respond to the close window button and pressing escape
130 | viewer->addEventHandler(vsg::CloseHandler::create(viewer));
131 |
132 | // create the windows
133 | auto firstWindow = createWindow(viewer, windowTraits, vsg_scene, nullptr, "First Window");
134 | auto secondWindow = createWindow(viewer, windowTraits, vsg_scene, nullptr, "Second Window");
135 | auto thirdWindow = createWindow(viewer, windowTraits, vsg_scene, nullptr, "Third Window");
136 |
137 | firstWindow->setGeometry(0, 0, 640, 480);
138 | firstWindow->show();
139 |
140 | secondWindow->setGeometry(680, 0, 640, 480);
141 | secondWindow->show();
142 |
143 | thirdWindow->setGeometry(1360, 0, 640, 480);
144 | thirdWindow->show();
145 |
146 | if (interval >= 0) viewer->setInterval(interval);
147 | viewer->continuousUpdate = continuousUpdate;
148 |
149 | viewer->compile();
150 |
151 | return application.exec();
152 | }
153 |
--------------------------------------------------------------------------------
/examples/vsgqtmdi/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #ifdef vsgXchange_FOUND
4 | # include
5 | #endif
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | class MultiViewArea : public QMdiArea
16 | {
17 | public:
18 |
19 | vsg::ref_ptr traits;
20 | vsg::ref_ptr viewer;
21 |
22 | MultiViewArea(QWidget *parent = nullptr) :
23 | QMdiArea(parent),
24 | viewer(vsgQt::Viewer::create())
25 | {
26 | viewer->addEventHandler(vsg::CloseHandler::create(viewer));
27 | }
28 |
29 | struct ViewWindow
30 | {
31 | vsgQt::Window* window = nullptr;
32 | };
33 |
34 | using Views = std::vector;
35 | Views views;
36 |
37 | size_t addView(vsg::ref_ptr vsg_scene, const QString& title = {})
38 | {
39 | auto window = new vsgQt::Window(viewer, traits);
40 |
41 | auto widget = QWidget::createWindowContainer(window, this);
42 | widget->setWindowTitle(title);
43 |
44 | addSubWindow(widget);
45 |
46 | if (views.empty()) widget->showMaximized();
47 | else tileSubWindows();
48 |
49 | window->initializeWindow();
50 |
51 | // if this is the first window to be created, use its device for future window creation.
52 | if (!traits->device) traits->device = window->windowAdapter->getOrCreateDevice();
53 |
54 | // compute the bounds of the scene graph to help position camera
55 | vsg::ComputeBounds computeBounds;
56 | vsg_scene->accept(computeBounds);
57 | vsg::dvec3 centre = (computeBounds.bounds.min + computeBounds.bounds.max) * 0.5;
58 | double radius = vsg::length(computeBounds.bounds.max - computeBounds.bounds.min) * 0.6;
59 | double nearFarRatio = 0.001;
60 |
61 | uint32_t width = window->traits->width;
62 | uint32_t height = window->traits->height;
63 |
64 | vsg::ref_ptr ellipsoidModel(vsg_scene->getObject("EllipsoidModel"));
65 | vsg::ref_ptr camera;
66 | {
67 | // set up the camera
68 | auto lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -radius * 3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0));
69 |
70 | vsg::ref_ptr perspective;
71 | if (ellipsoidModel)
72 | {
73 | perspective = vsg::EllipsoidPerspective::create(
74 | lookAt, ellipsoidModel, 30.0,
75 | static_cast(width) /
76 | static_cast(height),
77 | nearFarRatio, false);
78 | }
79 | else
80 | {
81 | perspective = vsg::Perspective::create(
82 | 30.0,
83 | static_cast(width) /
84 | static_cast(height),
85 | nearFarRatio * radius, radius * 4.5);
86 | }
87 |
88 | camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(VkExtent2D{width, height}));
89 | }
90 |
91 | auto trackball = vsg::Trackball::create(camera, ellipsoidModel);
92 | trackball->addWindow(*window);
93 |
94 | viewer->addEventHandler(trackball);
95 |
96 | auto commandGraph = vsg::createCommandGraphForView(*window, camera, vsg_scene);
97 |
98 | viewer->addRecordAndSubmitTaskAndPresentation({commandGraph});
99 |
100 | views.push_back(ViewWindow{window});
101 |
102 | return views.size()-1;
103 | }
104 | };
105 |
106 |
107 | int main(int argc, char* argv[])
108 | {
109 | QApplication application(argc, argv);
110 |
111 | vsg::CommandLine arguments(&argc, argv);
112 |
113 | // set up vsg::Options to pass in filepaths, ReaderWriters and other IO
114 | // related options to use when reading and writing files.
115 | auto options = vsg::Options::create();
116 | options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
117 | options->paths = vsg::getEnvPaths("VSG_FILE_PATH");
118 | #ifdef vsgXchange_FOUND
119 | options->add(vsgXchange::all::create());
120 | #endif
121 |
122 | options->readOptions(arguments);
123 |
124 | auto windowTraits = vsg::WindowTraits::create();
125 | windowTraits->windowTitle = "vsgQt viewer";
126 | windowTraits->debugLayer = arguments.read({"--debug", "-d"});
127 | windowTraits->apiDumpLayer = arguments.read({"--api", "-a"});
128 | arguments.read("--samples", windowTraits->samples);
129 | arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height);
130 | if (arguments.read({"--fullscreen", "--fs"})) windowTraits->fullscreen = true;
131 |
132 | bool continuousUpdate = !arguments.read({"--event-driven", "--ed"});
133 | auto interval = arguments.value(8, "--interval");
134 |
135 | if (arguments.errors())
136 | return arguments.writeErrorMessages(std::cerr);
137 |
138 | if (argc <= 1)
139 | {
140 | std::cout << "Please specify a 3d model or image file on the command line."
141 | << std::endl;
142 | return 1;
143 | }
144 |
145 | vsg::Path filename = arguments[1];
146 |
147 | auto vsg_scene = vsg::read_cast(filename, options);
148 | if (!vsg_scene)
149 | {
150 | std::cout << "Failed to load a valid scene graph. Please specify a valid 3d "
151 | "model or image file on the command line."
152 | << std::endl;
153 | return 1;
154 | }
155 |
156 | QMainWindow* mainWindow = new QMainWindow();
157 |
158 | auto mdiArea = new MultiViewArea(mainWindow);
159 |
160 | mainWindow->setCentralWidget(mdiArea);
161 |
162 | mdiArea->traits = windowTraits;
163 |
164 | mdiArea->setContextMenuPolicy(Qt::PreventContextMenu);
165 | mdiArea->setViewMode(QMdiArea::ViewMode::SubWindowView);
166 | mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
167 | mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
168 | mdiArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
169 |
170 | mdiArea->addView(vsg_scene, "First Window");
171 | mdiArea->addView(vsg_scene, "Second Window");
172 | mdiArea->addView(vsg_scene, "Third Window");
173 |
174 | mdiArea->viewer->compile();
175 |
176 | if (interval >= 0) mdiArea->viewer->setInterval(interval);
177 | mdiArea->viewer->continuousUpdate = continuousUpdate;
178 |
179 | mainWindow->show();
180 |
181 | return application.exec();
182 | }
183 |
--------------------------------------------------------------------------------
/src/vsgQt/KeyboardMap.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright(c) 2021 Robert Osfield
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 | */
12 |
13 | #include
14 |
15 | using namespace vsgQt;
16 |
17 | KeyboardMap::KeyboardMap() :
18 | _keycodeMap{
19 | {0x0, vsg::KEY_Undefined},
20 | {Qt::Key_Space, vsg::KEY_Space},
21 |
22 | /* Cursor control & motion */
23 |
24 | {Qt::Key_Home, vsg::KEY_Home},
25 | {Qt::Key_Left, vsg::KEY_Left}, /* Move left, left arrow */
26 | {Qt::Key_Up, vsg::KEY_Up}, /* Move up, up arrow */
27 | {Qt::Key_Right, vsg::KEY_Right}, /* Move right, right arrow */
28 | {Qt::Key_Down, vsg::KEY_Down}, /* Move down, down arrow */
29 | //{Qt::Key_Home, vsg::KEY_Prior}, /* Prior, previous */
30 | {Qt::Key_PageUp, vsg::KEY_Page_Up},
31 | {Qt::Key_Home, vsg::KEY_Next}, /* Next */
32 | {Qt::Key_PageDown, vsg::KEY_Page_Down},
33 | {Qt::Key_End, vsg::KEY_End}, /* EOL */
34 | //{ KEY_Begin = 0xFF58, /* BOL */
35 |
36 | {'!', vsg::KEY_Exclaim},
37 | {'"', vsg::KEY_Quotedbl},
38 | {'#', vsg::KEY_Hash},
39 | {'$', vsg::KEY_Dollar},
40 | {'&', vsg::KEY_Ampersand},
41 | {Qt::Key_QuoteLeft, vsg::KEY_Quote},
42 | {'(', vsg::KEY_Leftparen},
43 | {')', vsg::KEY_Rightparen},
44 | {'*', vsg::KEY_Asterisk},
45 | {'+', vsg::KEY_Plus},
46 | {Qt::Key_Comma, vsg::KEY_Comma},
47 | {Qt::Key_Minus, vsg::KEY_Minus},
48 | {Qt::Key_Period, vsg::KEY_Period},
49 | {Qt::Key_Slash, vsg::KEY_Slash},
50 | {':', vsg::KEY_Colon},
51 | {Qt::Key_Semicolon, vsg::KEY_Semicolon},
52 | {'<', vsg::KEY_Less},
53 | {Qt::Key_Equal, vsg::KEY_Equals}, // + isn't an unmodded key, why does windows map is as a virtual??
54 | {'>', vsg::KEY_Greater},
55 | {'?', vsg::KEY_Question},
56 | {'@', vsg::KEY_At},
57 | {Qt::Key_BracketLeft, vsg::KEY_Leftbracket},
58 | {Qt::Key_Backslash, vsg::KEY_Backslash},
59 | {Qt::Key_BracketRight, vsg::KEY_Rightbracket},
60 | {'|', vsg::KEY_Caret},
61 | {'_', vsg::KEY_Underscore},
62 | {0xc0, vsg::KEY_Backquote},
63 |
64 | {Qt::Key_Back, vsg::KEY_BackSpace}, /* back space, back char */
65 | {Qt::Key_Tab, vsg::KEY_Tab},
66 | {Qt::Key_Backtab, vsg::KEY_Tab},
67 | // KEY_Linefeed = 0xFF0A, /* Linefeed, LF */
68 | {Qt::Key_Clear, vsg::KEY_Clear},
69 | {Qt::Key_Return, vsg::KEY_Return}, /* Return, enter */
70 | {Qt::Key_Pause, vsg::KEY_Pause}, /* Pause, hold */
71 | {Qt::Key_ScrollLock, vsg::KEY_Scroll_Lock},
72 | // KEY_Sys_Req = 0xFF15,
73 | {Qt::Key_Escape, vsg::KEY_Escape},
74 | {Qt::Key_Delete, vsg::KEY_Delete}, /* Delete, rubout */
75 |
76 | /* Misc Functions */
77 |
78 | {Qt::Key_Select, vsg::KEY_Select}, /* Select, mark */
79 | {Qt::Key_Print, vsg::KEY_Print},
80 | {Qt::Key_Execute, vsg::KEY_Execute}, /* Execute, run, do */
81 | {Qt::Key_Insert, vsg::KEY_Insert}, /* Insert, insert here */
82 | //{ KEY_Undo = 0xFF65, /* Undo, oops */
83 | //KEY_Redo = 0xFF66, /* redo, again */
84 | {Qt::Key_Menu, vsg::KEY_Menu}, /* On Windows, this is VK_APPS, the context-menu key */
85 | // KEY_Find = 0xFF68, /* Find, search */
86 | {Qt::Key_Cancel, vsg::KEY_Cancel}, /* Cancel, stop, abort, exit */
87 | {Qt::Key_Help, vsg::KEY_Help}, /* Help */
88 | //{ KEY_Break = 0xFF6B,
89 | //KEY_Mode_switch = 0xFF7E, /* Character set switch */
90 | //KEY_Script_switch = 0xFF7E, /* Alias for mode_switch */
91 | {Qt::Key_NumLock, vsg::KEY_Num_Lock},
92 |
93 | #if 0
94 | {Qt::Key_0, vsg::KEY_KP_0},
95 | {Qt::Key_1, vsg::KEY_KP_1},
96 | {Qt::Key_2, vsg::KEY_KP_2},
97 | {Qt::Key_3, vsg::KEY_KP_3},
98 | {Qt::Key_4, vsg::KEY_KP_4},
99 | {Qt::Key_5, vsg::KEY_KP_5},
100 | {Qt::Key_6, vsg::KEY_KP_6},
101 | {Qt::Key_7, vsg::KEY_KP_7},
102 | {Qt::Key_8, vsg::KEY_KP_8},
103 | {Qt::Key_9, vsg::KEY_KP_9},
104 |
105 | #endif
106 | /*
107 | * Auxiliary Functions; note the duplicate definitions for left and right
108 | * function keys; Sun keyboards and a few other manufacturers have such
109 | * function key groups on the left and/or right sides of the keyboard.
110 | * We've not found a keyboard with more than 35 function keys total.
111 | */
112 |
113 | {Qt::Key_F1, vsg::KEY_F1},
114 | {Qt::Key_F2, vsg::KEY_F2},
115 | {Qt::Key_F3, vsg::KEY_F3},
116 | {Qt::Key_F4, vsg::KEY_F4},
117 | {Qt::Key_F5, vsg::KEY_F5},
118 | {Qt::Key_F6, vsg::KEY_F6},
119 | {Qt::Key_F7, vsg::KEY_F7},
120 | {Qt::Key_F8, vsg::KEY_F8},
121 | {Qt::Key_F9, vsg::KEY_F9},
122 | {Qt::Key_F10, vsg::KEY_F10},
123 | {Qt::Key_F11, vsg::KEY_F11},
124 | {Qt::Key_F12, vsg::KEY_F12},
125 | {Qt::Key_F13, vsg::KEY_F13},
126 | {Qt::Key_F14, vsg::KEY_F14},
127 | {Qt::Key_F15, vsg::KEY_F15},
128 | {Qt::Key_F16, vsg::KEY_F16},
129 | {Qt::Key_F17, vsg::KEY_F17},
130 | {Qt::Key_F18, vsg::KEY_F18},
131 | {Qt::Key_F19, vsg::KEY_F19},
132 | {Qt::Key_F20, vsg::KEY_F20},
133 | {Qt::Key_F21, vsg::KEY_F21},
134 | {Qt::Key_F22, vsg::KEY_F22},
135 | {Qt::Key_F23, vsg::KEY_F23},
136 | {Qt::Key_F24, vsg::KEY_F24},
137 |
138 | //KEY_F25 = 0xFFD6,
139 | //KEY_F26 = 0xFFD7,
140 | //KEY_F27 = 0xFFD8,
141 | //KEY_F28 = 0xFFD9,
142 | //KEY_F29 = 0xFFDA,
143 | //KEY_F30 = 0xFFDB,
144 | //KEY_F31 = 0xFFDC,
145 | //KEY_F32 = 0xFFDD,
146 | //KEY_F33 = 0xFFDE,
147 | //KEY_F34 = 0xFFDF,
148 | //KEY_F35 = 0xFFE0,
149 |
150 | /* Modifiers */
151 |
152 | {Qt::Key_Shift, vsg::KEY_Shift_L}, /* Left shift */
153 | // {VK_RSHIFT, KEY_Shift_R}, /* Right shift */
154 | // {VK_LCONTROL, KEY_Control_L}, /* Left control */
155 | {Qt::Key_Control, vsg::KEY_Control_R}, /* Right control */
156 | {Qt::Key_CapsLock, vsg::KEY_Caps_Lock} /* Caps lock */
157 | //KEY_Shift_Lock = 0xFFE6, /* Shift lock */
158 |
159 | //KEY_Meta_L = 0xFFE7, /* Left meta */
160 | //KEY_Meta_R = 0xFFE8, /* Right meta */
161 | // {VK_LMENU, KEY_Alt_L}, /* Left alt */
162 | // {VK_RMENU, KEY_Alt_R}, /* Right alt */
163 | // {VK_LWIN, KEY_Super_L}, /* Left super */
164 | // {VK_RWIN, KEY_Super_R} /* Right super */
165 | //KEY_Hyper_L = 0xFFED, /* Left hyper */
166 | //KEY_Hyper_R = 0xFFEE /* Right hyper */
167 | }
168 | {
169 | }
170 |
171 | bool KeyboardMap::getKeySymbol(const QKeyEvent* e, vsg::KeySymbol& keySymbol, vsg::KeySymbol& modifiedKeySymbol, vsg::KeyModifier& keyModifier)
172 | {
173 | uint16_t modifierMask = 0;
174 | if (e->modifiers() & Qt::ShiftModifier)
175 | {
176 | modifierMask |= vsg::KeyModifier::MODKEY_Shift;
177 | }
178 | if (e->modifiers() & Qt::ControlModifier)
179 | {
180 | modifierMask |= vsg::KeyModifier::MODKEY_Control;
181 | }
182 | if (e->modifiers() & Qt::AltModifier)
183 | {
184 | modifierMask |= vsg::KeyModifier::MODKEY_Alt;
185 | }
186 | if (e->modifiers() & Qt::MetaModifier)
187 | {
188 | modifierMask |= vsg::KeyModifier::MODKEY_Meta;
189 | }
190 |
191 | keyModifier = (vsg::KeyModifier)modifierMask;
192 |
193 | auto itr = _keycodeMap.find((uint32_t)e->key());
194 | if (itr != _keycodeMap.end())
195 | {
196 | keySymbol = itr->second;
197 | modifiedKeySymbol = keySymbol;
198 |
199 | // std::cout<<"KeyboardMap::getKeySymbol() found in map, keySymbol = "<key());
204 | if (keySymbol >= 'A' && keySymbol <= 'Z') keySymbol = vsg::KeySymbol(int(keySymbol) + int('a' - 'A'));
205 |
206 | modifiedKeySymbol = vsg::KeySymbol(*(e->text().toLatin1().data()));
207 |
208 | // std::cout<<"KeyboardMap::getKeySymbol() NOT found in map, keySymbol = "<
2 |
3 | Copyright(c) 2021 Robert Osfield, Andre Normann
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 | */
12 |
13 | #if defined(WIN32)
14 | # define VK_USE_PLATFORM_WIN32_KHR
15 | #elif defined(__APPLE__)
16 | # define VK_USE_PLATFORM_MACOS_MVK
17 | #else
18 | # define VK_USE_PLATFORM_XCB_KHR
19 | // #define VK_USE_PLATFORM_XLIB_KHR
20 | #endif
21 |
22 | #include
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | #include
32 |
33 | #include
34 |
35 | using namespace vsgQt;
36 |
37 | Window::Window(QScreen* targetScreen) :
38 | QWindow(targetScreen),
39 | traits(vsg::WindowTraits::create()),
40 | keyboardMap(KeyboardMap::create())
41 | {
42 | traits->x = x();
43 | traits->y = y();
44 | traits->width = width();
45 | traits->height = height();
46 | }
47 |
48 | Window::Window(QWindow* parent) :
49 | QWindow(parent),
50 | traits(vsg::WindowTraits::create()),
51 | keyboardMap(KeyboardMap::create())
52 | {
53 | traits->x = x();
54 | traits->y = y();
55 | traits->width = width();
56 | traits->height = height();
57 | }
58 |
59 | Window::Window(vsg::ref_ptr in_traits, QScreen* targetScreen) :
60 | QWindow(targetScreen),
61 | keyboardMap(KeyboardMap::create())
62 | {
63 | if (in_traits)
64 | {
65 | traits = vsg::WindowTraits::create(*in_traits);
66 | setGeometry(traits->x, traits->y, traits->width, traits->height);
67 | }
68 | else
69 | {
70 | traits = vsg::WindowTraits::create();
71 | traits->x = x();
72 | traits->y = y();
73 | traits->width = width();
74 | traits->height = height();
75 | }
76 | }
77 |
78 | Window::Window(vsg::ref_ptr in_traits, QWindow* parent) :
79 | QWindow(parent),
80 | keyboardMap(KeyboardMap::create())
81 | {
82 | if (in_traits)
83 | {
84 | traits = vsg::WindowTraits::create(*in_traits);
85 | setGeometry(traits->x, traits->y, traits->width, traits->height);
86 | }
87 | else
88 | {
89 | traits = vsg::WindowTraits::create();
90 | traits->x = x();
91 | traits->y = y();
92 | traits->width = width();
93 | traits->height = height();
94 | }
95 | }
96 |
97 | Window::Window(vsg::ref_ptr in_viewer, vsg::ref_ptr in_traits, QScreen* targetScreen) :
98 | QWindow(targetScreen),
99 | viewer(in_viewer),
100 | keyboardMap(KeyboardMap::create())
101 | {
102 | if (in_traits)
103 | {
104 | traits = vsg::WindowTraits::create(*in_traits);
105 | setGeometry(traits->x, traits->y, traits->width, traits->height);
106 | }
107 | else
108 | {
109 | traits = vsg::WindowTraits::create();
110 | traits->x = x();
111 | traits->y = y();
112 | traits->width = width();
113 | traits->height = height();
114 | }
115 | }
116 |
117 | Window::Window(vsg::ref_ptr in_viewer, vsg::ref_ptr in_traits, QWindow* parent) :
118 | QWindow(parent),
119 | viewer(in_viewer),
120 | keyboardMap(KeyboardMap::create())
121 | {
122 | if (in_traits)
123 | {
124 | traits = vsg::WindowTraits::create(*in_traits);
125 | setGeometry(traits->x, traits->y, traits->width, traits->height);
126 | }
127 | else
128 | {
129 | traits = vsg::WindowTraits::create();
130 | traits->x = x();
131 | traits->y = y();
132 | traits->width = width();
133 | traits->height = height();
134 | }
135 | }
136 |
137 | Window::~Window()
138 | {
139 | cleanup();
140 | }
141 |
142 | void Window::initializeWindow()
143 | {
144 | if (windowAdapter) return;
145 |
146 | if (!traits) traits = vsg::WindowTraits::create();
147 |
148 | #if defined(VK_USE_PLATFORM_WIN32_KHR)
149 | traits->nativeWindow = reinterpret_cast(winId());
150 | #elif defined(VK_USE_PLATFORM_XLIB_KHR)
151 | traits->nativeWindow = static_cast<::Window>(winId());
152 | #elif defined(VK_USE_PLATFORM_XCB_KHR)
153 | traits->nativeWindow = static_cast(winId());
154 | #elif defined(VK_USE_PLATFORM_MACOS_MVK)
155 | traits->nativeWindow = winId();
156 | #endif
157 |
158 | traits->x = convert_coord(x());
159 | traits->y = convert_coord(y());
160 | traits->width = convert_coord(width());
161 | traits->height = convert_coord(height());
162 |
163 | windowAdapter = vsg::Window::create(traits);
164 | _initialized = true;
165 | }
166 |
167 | void Window::cleanup()
168 | {
169 | // remove links to all the VSG related classes.
170 | if (windowAdapter)
171 | {
172 | // wait for all rendering to be completed before we start cleaning up resources.
173 | if (viewer)
174 | {
175 | viewer->deviceWaitIdle();
176 | viewer->removeWindow(windowAdapter);
177 | }
178 |
179 | windowAdapter->releaseWindow();
180 | }
181 |
182 | windowAdapter = {};
183 | viewer = {};
184 | }
185 |
186 | bool Window::event(QEvent* e)
187 | {
188 | switch (e->type())
189 | {
190 | case QEvent::PlatformSurface: {
191 | auto surfaceEvent = dynamic_cast(e);
192 | if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
193 | {
194 | vsg::clock::time_point event_time = vsg::clock::now();
195 | windowAdapter->bufferedEvents.push_back(vsg::CloseWindowEvent::create(windowAdapter, event_time));
196 |
197 | cleanup();
198 | }
199 | break;
200 | }
201 |
202 | default:
203 | break;
204 | }
205 |
206 | return QWindow::event(e);
207 | }
208 |
209 | void Window::exposeEvent(QExposeEvent* /*e*/)
210 | {
211 | if (!_initialized && isExposed())
212 | {
213 | initializeWindow();
214 | }
215 |
216 | if (viewer) viewer->request();
217 | }
218 |
219 | void Window::hideEvent(QHideEvent* /*e*/)
220 | {
221 | }
222 |
223 | void Window::resizeEvent(QResizeEvent* /*e*/)
224 | {
225 | if (!windowAdapter) return;
226 |
227 | vsg::clock::time_point event_time = vsg::clock::now();
228 | windowAdapter->bufferedEvents.push_back(vsg::ConfigureWindowEvent::create(windowAdapter, event_time, convert_coord(x()), convert_coord(y()), convert_coord(width()), convert_coord(height())));
229 |
230 | windowAdapter->resize();
231 |
232 | if (viewer) viewer->request();
233 | }
234 |
235 | void Window::keyPressEvent(QKeyEvent* e)
236 | {
237 | if (!windowAdapter) return;
238 |
239 | vsg::KeySymbol keySymbol, modifiedKeySymbol;
240 | vsg::KeyModifier keyModifier;
241 |
242 | if (keyboardMap->getKeySymbol(e, keySymbol, modifiedKeySymbol, keyModifier))
243 | {
244 | vsg::clock::time_point event_time = vsg::clock::now();
245 | windowAdapter->bufferedEvents.push_back(vsg::KeyPressEvent::create(windowAdapter, event_time, keySymbol, modifiedKeySymbol, keyModifier));
246 | }
247 |
248 | if (viewer) viewer->request();
249 | }
250 |
251 | void Window::keyReleaseEvent(QKeyEvent* e)
252 | {
253 | if (!windowAdapter) return;
254 |
255 | vsg::KeySymbol keySymbol, modifiedKeySymbol;
256 | vsg::KeyModifier keyModifier;
257 |
258 | if (keyboardMap->getKeySymbol(e, keySymbol, modifiedKeySymbol, keyModifier))
259 | {
260 | vsg::clock::time_point event_time = vsg::clock::now();
261 | windowAdapter->bufferedEvents.push_back(vsg::KeyReleaseEvent::create(windowAdapter, event_time, keySymbol, modifiedKeySymbol, keyModifier));
262 | }
263 |
264 | if (viewer) viewer->request();
265 | }
266 |
267 | void Window::mouseMoveEvent(QMouseEvent* e)
268 | {
269 | if (!windowAdapter) return;
270 |
271 | vsg::clock::time_point event_time = vsg::clock::now();
272 |
273 | auto [mask, button] = convertMouseButtons(e);
274 | auto [x, y] = convertMousePosition(e);
275 |
276 | windowAdapter->bufferedEvents.push_back(vsg::MoveEvent::create(windowAdapter, event_time, x, y, mask));
277 |
278 | if (viewer) viewer->request();
279 | }
280 |
281 | void Window::mousePressEvent(QMouseEvent* e)
282 | {
283 | if (!windowAdapter) return;
284 |
285 | vsg::clock::time_point event_time = vsg::clock::now();
286 |
287 | auto [mask, button] = convertMouseButtons(e);
288 | auto [x, y] = convertMousePosition(e);
289 |
290 | windowAdapter->bufferedEvents.push_back(vsg::ButtonPressEvent::create(windowAdapter, event_time, x, y, mask, button));
291 |
292 | if (viewer) viewer->request();
293 | }
294 |
295 | void Window::mouseReleaseEvent(QMouseEvent* e)
296 | {
297 | if (!windowAdapter) return;
298 |
299 | vsg::clock::time_point event_time = vsg::clock::now();
300 |
301 | auto [mask, button] = convertMouseButtons(e);
302 | auto [x, y] = convertMousePosition(e);
303 |
304 | windowAdapter->bufferedEvents.push_back(vsg::ButtonReleaseEvent::create(windowAdapter, event_time, x, y, mask, button));
305 |
306 | if (viewer) viewer->request();
307 | }
308 |
309 | void Window::wheelEvent(QWheelEvent* e)
310 | {
311 | if (!windowAdapter) return;
312 |
313 | vsg::clock::time_point event_time = vsg::clock::now();
314 | windowAdapter->bufferedEvents.push_back(vsg::ScrollWheelEvent::create(windowAdapter, event_time, e->angleDelta().y() < 0 ? vsg::vec3(0.0f, -1.0f, 0.0f) : vsg::vec3(0.0f, 1.0f, 0.0f)));
315 |
316 | if (viewer) viewer->request();
317 | }
318 |
319 | std::pair Window::convertMouseButtons(QMouseEvent* e) const
320 | {
321 | uint16_t mask{0};
322 | uint32_t button = 0;
323 |
324 | if (e->buttons() & Qt::LeftButton) mask = mask | vsg::BUTTON_MASK_1;
325 | if (e->buttons() & Qt::MiddleButton) mask = mask | vsg::BUTTON_MASK_2;
326 | if (e->buttons() & Qt::RightButton) mask = mask | vsg::BUTTON_MASK_3;
327 |
328 | switch (e->button())
329 | {
330 | case Qt::LeftButton: button = 1; break;
331 | case Qt::MiddleButton: button = 2; break;
332 | case Qt::RightButton: button = 3; break;
333 | default: break;
334 | }
335 |
336 | return {static_cast(mask), button};
337 | }
338 |
339 | std::pair Window::convertMousePosition(QMouseEvent* e) const
340 | {
341 | #if QT_VERSION_MAJOR == 6
342 | return {convert_coord(e->position().x()), convert_coord(e->position().y())};
343 | #else
344 | return {convert_coord(e->x()), convert_coord(e->y())};
345 | #endif
346 | }
347 |
--------------------------------------------------------------------------------