From 2f2b04e36139f8f1089f604c3d9b05f571a3154f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 5 May 2023 11:37:22 +0100 Subject: [PATCH 01/21] Initial support for movement controlled by keys --- src/vsg/app/Trackball.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 5b185b4f1..07b153e97 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -137,6 +137,42 @@ void Trackball::apply(KeyPressEvent& keyPress) keyPress.handled = true; } + else + { + vsg::dvec2 delta(0.0, 0.0); + if (keyPress.keyBase == KEY_Left) delta.x = -1.0; + else if (keyPress.keyBase == KEY_Right) delta.x = 1.0; + else if (keyPress.keyBase == KEY_Up) delta.y = 1.0; + else if (keyPress.keyBase == KEY_Down) delta.y = -1.0; + + if (delta.x != 0.0 || delta.y != 0.0) + { + double scale = 0.05; + if ((keyPress.keyModifier & MODKEY_Shift) != 0) scale *= 0.2; + + if ((keyPress.keyModifier & MODKEY_Alt) != 0) + { + dvec3 lookVector = _lookAt->center - _lookAt->eye; + dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.1)); + + info("need to implement left/right and move forward/right = ", matrix); + + _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); + _lookAt->center = matrix * _lookAt->center; + _lookAt->eye = matrix * _lookAt->eye; + + clampToGlobe(); + } + else if ((keyPress.keyModifier & MODKEY_Control) != 0) + { + info("need to implement rotate"); + } + else + { + pan( dvec2(-delta.x, delta.y) * scale); + } + } + } } void Trackball::apply(ButtonPressEvent& buttonPress) From 6be18aa5abae62195f7d8522d743b3264a3c65c8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 12 May 2023 16:26:10 +0100 Subject: [PATCH 02/21] Implemented turn left/right. --- src/vsg/app/Trackball.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 07b153e97..4452a8785 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -153,9 +153,10 @@ void Trackball::apply(KeyPressEvent& keyPress) if ((keyPress.keyModifier & MODKEY_Alt) != 0) { dvec3 lookVector = _lookAt->center - _lookAt->eye; - dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.1)); - - info("need to implement left/right and move forward/right = ", matrix); + dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.1)) * + vsg::translate(_lookAt->eye) * + vsg::rotate(-delta.x * scale, _lookAt->up) * + vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); _lookAt->center = matrix * _lookAt->center; From a043ecc4fb43f11031e92de0d7c811c29308fc50 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 13 May 2023 13:03:30 +0100 Subject: [PATCH 03/21] Experiment with tracking holding keyboard keys --- include/vsg/app/Trackball.h | 9 +++++ src/vsg/app/Trackball.cpp | 55 +++++++++++++++++++++++++++++ src/vsg/platform/xcb/Xcb_Window.cpp | 4 +-- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index d17842f97..dc49a5809 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -37,6 +37,7 @@ namespace vsg dvec3 tbc(PointerEvent& event); void apply(KeyPressEvent& keyPress) override; + void apply(KeyReleaseEvent& keyRelease) override; void apply(ButtonPressEvent& buttonPress) override; void apply(ButtonReleaseEvent& buttonRelease) override; void apply(MoveEvent& moveEvent) override; @@ -99,6 +100,14 @@ namespace vsg /// Toggle on/off whether the view should continue moving when the mouse buttons are released while the mouse is in motion. bool supportsThrow = true; + struct KeyHistory + { + vsg::time_point timeOfKeyPress = {}; + vsg::time_point timeOfKeyRelease = {}; + }; + + std::map keyState; + protected: ref_ptr _camera; ref_ptr _lookAt; diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 4452a8785..8ba2280e9 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -125,10 +125,36 @@ dvec3 Trackball::tbc(PointerEvent& event) } } +#include + void Trackball::apply(KeyPressEvent& keyPress) { if (keyPress.handled || !eventRelevant(keyPress) || !_lastPointerEventWithinRenderArea) return; + auto keyState_itr = keyState.find(keyPress.keyBase); + if (keyState_itr != keyState.end()) + { + auto& keyHistory = keyState_itr->second; + if (keyHistory.timeOfKeyRelease == keyPress.time) + { + keyHistory.timeOfKeyRelease = keyHistory.timeOfKeyPress; + std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<second; + keyHistory.timeOfKeyRelease = keyRelease.time; + std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfKeyPress).count()<<"ms"<second; + if (keyHistory.timeOfKeyRelease != keyHistory.timeOfKeyPress) + { + std::cout<<"Trackball::apply(FrameEvent&) key = "<first<<" released "<(frame.time - _startTime).count(); diff --git a/src/vsg/platform/xcb/Xcb_Window.cpp b/src/vsg/platform/xcb/Xcb_Window.cpp index 494240c69..48e2568d4 100644 --- a/src/vsg/platform/xcb/Xcb_Window.cpp +++ b/src/vsg/platform/xcb/Xcb_Window.cpp @@ -611,11 +611,11 @@ bool Xcb_Window::pollEvents(UIEvents& events) break; } case (XCB_FOCUS_IN): { - //debug("xcb_focus_in_event_t"); + info("xcb_focus_in_event_t"); break; } case (XCB_FOCUS_OUT): { - //debug("xcb_focus_out_event_t"); + info("xcb_focus_out_event_t"); break; } case (XCB_ENTER_NOTIFY): { From 06d78b5ebfb88d85b55ca2a015ca916434f80604 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 14 May 2023 19:27:11 +0100 Subject: [PATCH 04/21] Added experimental update of camera position using key controls. --- include/vsg/app/Trackball.h | 3 +- src/vsg/app/Trackball.cpp | 80 ++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index dc49a5809..ca21d8c91 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -102,7 +102,8 @@ namespace vsg struct KeyHistory { - vsg::time_point timeOfKeyPress = {}; + vsg::time_point timeOfFirstKeyPress = {}; + vsg::time_point timeOfLastKeyPress = {}; vsg::time_point timeOfKeyRelease = {}; }; diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 8ba2280e9..d51df9817 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -137,22 +137,25 @@ void Trackball::apply(KeyPressEvent& keyPress) auto& keyHistory = keyState_itr->second; if (keyHistory.timeOfKeyRelease == keyPress.time) { - keyHistory.timeOfKeyRelease = keyHistory.timeOfKeyPress; - std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; keyHistory.timeOfKeyRelease = keyRelease.time; - std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfKeyPress).count()<<"ms"<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(frame.time - keyHistory.timeOfLastKeyPress).count(); + if (timeSinceLastRepeat > 1.0) + { + //std::cout<<" Trackball::apply(FrameEvent&) key = "<first<<" time out!!!!! timeSinceLastRepeat = "<(frame.time - keyHistory.timeOfFirstKeyPress).count(); + // std::cout<<" Trackball::apply(FrameEvent&) key = "<first<<" held down "<first; + + vsg::dvec2 delta(0.0, 0.0); + if (key == KEY_Left) delta.x = -1.0; + else if (key == KEY_Right) delta.x = 1.0; + else if (key == KEY_Up) delta.y = 1.0; + else if (key == KEY_Down) delta.y = -1.0; + + double scale = std::chrono::duration(frame.time - _previousTime).count(); + if (delta.x != 0.0 || delta.y != 0.0) + { + pan( dvec2(-delta.x, delta.y) * scale); + } + + delta.set(0.0, 0.0); + if (key == 'w') delta.y = 1.0; + else if (key == 's') delta.y = -1.0; + else if (key == 'a') delta.x = -1.0; + else if (key == 'd') delta.x = 1.0; + + if (delta.x != 0.0 || delta.y != 0.0) + { + dvec3 lookVector = _lookAt->center - _lookAt->eye; + dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.2)) * + vsg::translate(_lookAt->eye) * + vsg::rotate(-delta.x * scale * 0.25, _lookAt->up) * + vsg::translate(-_lookAt->eye); + + _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); + _lookAt->center = matrix * _lookAt->center; + _lookAt->eye = matrix * _lookAt->eye; + + clampToGlobe(); + } + ++itr; } } From eecadeed8650a9b4519b15c0ef850597c76a37c9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 May 2023 10:48:54 +0100 Subject: [PATCH 05/21] Moved keyboard state tracking into decidated Keyboard class --- include/vsg/app/Trackball.h | 35 ++++-- src/vsg/app/Trackball.cpp | 244 ++++++++++++++++-------------------- 2 files changed, 133 insertions(+), 146 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index ca21d8c91..08c6bd2cd 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -24,6 +24,30 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI namespace vsg { + /// Keyboard tracks keyboard events to maintain the key pressed state and how long the key has been hel for + class VSG_DECLSPEC Keyboard : public Inherit + { + public: + + void apply(KeyPressEvent& keyPress) override; + void apply(KeyReleaseEvent& keyRelease) override; + + struct KeyHistory + { + vsg::time_point timeOfFirstKeyPress = {}; + vsg::time_point timeOfLastKeyPress = {}; + vsg::time_point timeOfKeyRelease = {}; + }; + + std::map keyState; + + /// return true if key is currently pressed + bool pressed(KeySymbol key); + + /// return the length of time key has been pressed, return -1.0 for key is not currently pressed + double time_pressed(KeySymbol key); + }; + /// Trackball is an event handler that provides mouse and touch controlled 3d trackball camera view manipulation. class VSG_DECLSPEC Trackball : public Inherit { @@ -100,15 +124,6 @@ namespace vsg /// Toggle on/off whether the view should continue moving when the mouse buttons are released while the mouse is in motion. bool supportsThrow = true; - struct KeyHistory - { - vsg::time_point timeOfFirstKeyPress = {}; - vsg::time_point timeOfLastKeyPress = {}; - vsg::time_point timeOfKeyRelease = {}; - }; - - std::map keyState; - protected: ref_ptr _camera; ref_ptr _lookAt; @@ -141,6 +156,8 @@ namespace vsg ref_ptr _endLookAt; std::map> _previousTouches; + ref_ptr _keyboard; + double _animationDuration = 0.0; }; VSG_type_name(vsg::Trackball); diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index d51df9817..841e40583 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -15,13 +15,90 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include +#include using namespace vsg; +void Keyboard::apply(KeyPressEvent& keyPress) +{ + //std::cout<<"Keyboard::apply(KeyReleaseEvent& keyRelease)"<second; + if (keyHistory.timeOfKeyRelease == keyPress.time) + { + keyHistory.timeOfKeyRelease = keyHistory.timeOfFirstKeyPress; + keyHistory.timeOfLastKeyPress = keyPress.time; + //std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; + keyHistory.timeOfKeyRelease = keyRelease.time; + //std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; + if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) + { + keyState.erase(itr); + return false; + } + + return true; +} + +double Keyboard::time_pressed(KeySymbol key) +{ + auto itr = keyState.find(key); + if (itr == keyState.end()) return -1.0; + + auto& keyHistory = itr->second; + if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) + { + keyState.erase(itr); + return -1.0; + } + + return std::chrono::duration(clock::now() - keyHistory.timeOfFirstKeyPress).count(); +} + Trackball::Trackball(ref_ptr camera, ref_ptr ellipsoidModel) : _camera(camera), _lookAt(camera->viewMatrix.cast()), - _ellipsoidModel(ellipsoidModel) + _ellipsoidModel(ellipsoidModel), + _keyboard(Keyboard::create()) { if (!_lookAt) { @@ -125,38 +202,11 @@ dvec3 Trackball::tbc(PointerEvent& event) } } -#include - void Trackball::apply(KeyPressEvent& keyPress) { - if (keyPress.handled || !eventRelevant(keyPress) || !_lastPointerEventWithinRenderArea) return; + if (_keyboard) keyPress.accept(*_keyboard); - auto keyState_itr = keyState.find(keyPress.keyBase); - if (keyState_itr != keyState.end()) - { - auto& keyHistory = keyState_itr->second; - if (keyHistory.timeOfKeyRelease == keyPress.time) - { - keyHistory.timeOfKeyRelease = keyHistory.timeOfFirstKeyPress; - keyHistory.timeOfLastKeyPress = keyPress.time; - //std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<center - _lookAt->eye; - dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.1)) * - vsg::translate(_lookAt->eye) * - vsg::rotate(-delta.x * scale, _lookAt->up) * - vsg::translate(-_lookAt->eye); - - _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); - _lookAt->center = matrix * _lookAt->center; - _lookAt->eye = matrix * _lookAt->eye; - - clampToGlobe(); - } - else if ((keyPress.keyModifier & MODKEY_Control) != 0) - { - info("need to implement rotate"); - } - else - { - pan( dvec2(-delta.x, delta.y) * scale); - } - } - } -#endif } void Trackball::apply(KeyReleaseEvent& keyRelease) { - if (keyRelease.handled || !eventRelevant(keyRelease) || !_lastPointerEventWithinRenderArea) return; - - auto keyState_itr = keyState.find(keyRelease.keyBase); - if (keyState_itr != keyState.end()) - { - auto& keyHistory = keyState_itr->second; - keyHistory.timeOfKeyRelease = keyRelease.time; - // std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(frame.time - keyHistory.timeOfFirstKeyPress).count(); - // std::cout<<" Trackball::apply(FrameEvent&) key = "<first<<" held down "<first; - vsg::dvec2 delta(0.0, 0.0); - if (key == KEY_Left) delta.x = -1.0; - else if (key == KEY_Right) delta.x = 1.0; - else if (key == KEY_Up) delta.y = 1.0; - else if (key == KEY_Down) delta.y = -1.0; - - double scale = std::chrono::duration(frame.time - _previousTime).count(); - if (delta.x != 0.0 || delta.y != 0.0) - { - pan( dvec2(-delta.x, delta.y) * scale); - } - - delta.set(0.0, 0.0); - if (key == 'w') delta.y = 1.0; - else if (key == 's') delta.y = -1.0; - else if (key == 'a') delta.x = -1.0; - else if (key == 'd') delta.x = 1.0; - - if (delta.x != 0.0 || delta.y != 0.0) - { - dvec3 lookVector = _lookAt->center - _lookAt->eye; - dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.2)) * - vsg::translate(_lookAt->eye) * - vsg::rotate(-delta.x * scale * 0.25, _lookAt->up) * - vsg::translate(-_lookAt->eye); + delta.set(0.0, 0.0); + if (_keyboard->pressed(KEY_w)) delta.y = 1.0; + if (_keyboard->pressed(KEY_s)) delta.y = -1.0; + if (_keyboard->pressed(KEY_a)) delta.x = -1.0; + if (_keyboard->pressed(KEY_d)) delta.x = 1.0; - _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); - _lookAt->center = matrix * _lookAt->center; - _lookAt->eye = matrix * _lookAt->eye; + if (delta.x != 0.0 || delta.y != 0.0) + { + dvec3 lookVector = _lookAt->center - _lookAt->eye; + dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.2)) * + vsg::translate(_lookAt->eye) * + vsg::rotate(-delta.x * scale * 0.25, _lookAt->up) * + vsg::translate(-_lookAt->eye); - clampToGlobe(); - } + _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); + _lookAt->center = matrix * _lookAt->center; + _lookAt->eye = matrix * _lookAt->eye; - ++itr; + clampToGlobe(); } + } if (_endLookAt) From e5dfd876a7e1cad039ce95c40aa3651f34aa46e0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 May 2023 12:48:39 +0100 Subject: [PATCH 06/21] Improved support for handling keyboard focus --- include/vsg/app/Trackball.h | 8 +++++--- src/vsg/app/Trackball.cpp | 36 ++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index 08c6bd2cd..38e3bf1cf 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -37,15 +37,16 @@ namespace vsg vsg::time_point timeOfFirstKeyPress = {}; vsg::time_point timeOfLastKeyPress = {}; vsg::time_point timeOfKeyRelease = {}; + bool handled = false; }; std::map keyState; /// return true if key is currently pressed - bool pressed(KeySymbol key); + bool pressed(KeySymbol key, bool ignore_handled_keys = true); /// return the length of time key has been pressed, return -1.0 for key is not currently pressed - double time_pressed(KeySymbol key); + double time_pressed(KeySymbol key, bool ignore_handled_keys = true); }; /// Trackball is an event handler that provides mouse and touch controlled 3d trackball camera view manipulation. @@ -129,7 +130,8 @@ namespace vsg ref_ptr _lookAt; ref_ptr _ellipsoidModel; - bool _hasFocus = false; + bool _hasKeyboardFocus = false; + bool _hasPointerFocus = false; bool _lastPointerEventWithinRenderArea = false; enum UpdateMode diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 841e40583..71198fced 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -27,6 +27,7 @@ void Keyboard::apply(KeyPressEvent& keyPress) if (keyState_itr != keyState.end()) { auto& keyHistory = keyState_itr->second; + keyHistory.handled = keyPress.handled; if (keyHistory.timeOfKeyRelease == keyPress.time) { keyHistory.timeOfKeyRelease = keyHistory.timeOfFirstKeyPress; @@ -44,6 +45,7 @@ void Keyboard::apply(KeyPressEvent& keyPress) else { auto& keyHistory = keyState[keyPress.keyBase]; + keyHistory.handled = keyPress.handled; keyHistory.timeOfFirstKeyPress = keyPress.time; keyHistory.timeOfLastKeyPress = keyPress.time; keyHistory.timeOfKeyRelease = keyPress.time; @@ -59,12 +61,13 @@ void Keyboard::apply(KeyReleaseEvent& keyRelease) if (keyState_itr != keyState.end()) { auto& keyHistory = keyState_itr->second; + keyHistory.handled = keyRelease.handled; keyHistory.timeOfKeyRelease = keyRelease.time; //std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(clock::now() - keyHistory.timeOfFirstKeyPress).count(); } @@ -206,7 +213,7 @@ void Trackball::apply(KeyPressEvent& keyPress) { if (_keyboard) keyPress.accept(*_keyboard); - if (keyPress.handled || !eventRelevant(keyPress) || !_lastPointerEventWithinRenderArea) return; + if (!_hasKeyboardFocus || keyPress.handled || !eventRelevant(keyPress)) return; if (auto itr = keyViewpointMap.find(keyPress.keyBase); itr != keyViewpointMap.end()) { @@ -225,10 +232,14 @@ void Trackball::apply(KeyReleaseEvent& keyRelease) void Trackball::apply(ButtonPressEvent& buttonPress) { - if (buttonPress.handled || !eventRelevant(buttonPress)) return; + if (buttonPress.handled || !eventRelevant(buttonPress)) + { + _hasKeyboardFocus = false; + return; + } - _hasFocus = withinRenderArea(buttonPress); - _lastPointerEventWithinRenderArea = _hasFocus; + _hasPointerFocus = _hasKeyboardFocus = withinRenderArea(buttonPress); + _lastPointerEventWithinRenderArea = _hasPointerFocus; if (buttonPress.mask & rotateButtonMask) _updateMode = ROTATE; @@ -239,7 +250,7 @@ void Trackball::apply(ButtonPressEvent& buttonPress) else _updateMode = INACTIVE; - if (_hasFocus) buttonPress.handled = true; + if (_hasPointerFocus) buttonPress.handled = true; _zoomPreviousRatio = 0.0; _pan.set(0.0, 0.0); @@ -257,7 +268,7 @@ void Trackball::apply(ButtonReleaseEvent& buttonRelease) if (supportsThrow) _thrown = _previousPointerEvent && (buttonRelease.time == _previousPointerEvent->time); _lastPointerEventWithinRenderArea = withinRenderArea(buttonRelease); - _hasFocus = false; + _hasPointerFocus = false; _previousPointerEvent = &buttonRelease; } @@ -268,7 +279,7 @@ void Trackball::apply(MoveEvent& moveEvent) _lastPointerEventWithinRenderArea = withinRenderArea(moveEvent); - if (moveEvent.handled || !_hasFocus) return; + if (moveEvent.handled || !_hasPointerFocus) return; dvec2 new_ndc = ndc(moveEvent); dvec3 new_tbc = tbc(moveEvent); @@ -460,7 +471,7 @@ void Trackball::apply(TouchMoveEvent& touchMove) void Trackball::apply(FrameEvent& frame) { // std::cout<<"Trackball::apply(FrameEvent&) frameCount = "<frameCount<pressed(KEY_Left)) delta.x = -1.0; @@ -472,6 +483,7 @@ void Trackball::apply(FrameEvent& frame) if (delta.x != 0.0 || delta.y != 0.0) { pan( dvec2(-delta.x, delta.y) * scale); + _thrown = false; } delta.set(0.0, 0.0); @@ -485,7 +497,7 @@ void Trackball::apply(FrameEvent& frame) dvec3 lookVector = _lookAt->center - _lookAt->eye; dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.2)) * vsg::translate(_lookAt->eye) * - vsg::rotate(-delta.x * scale * 0.25, _lookAt->up) * + vsg::rotate(-delta.x * scale * 0.5, _lookAt->up) * vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); @@ -493,8 +505,8 @@ void Trackball::apply(FrameEvent& frame) _lookAt->eye = matrix * _lookAt->eye; clampToGlobe(); + _thrown = false; } - } if (_endLookAt) From 30b5535cfd39ed4b302dcf7c2cf016b75c341c2e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 May 2023 14:01:01 +0100 Subject: [PATCH 07/21] Added look up/down and forwrd/back support with 'w', 's', 'i' and 'o' keys respectively. --- src/vsg/app/Trackball.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 71198fced..84cc78713 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -473,7 +473,7 @@ void Trackball::apply(FrameEvent& frame) // std::cout<<"Trackball::apply(FrameEvent&) frameCount = "<frameCount<pressed(KEY_Left)) delta.x = -1.0; if (_keyboard->pressed(KEY_Right)) delta.x = 1.0; if (_keyboard->pressed(KEY_Up)) delta.y = 1.0; @@ -486,18 +486,22 @@ void Trackball::apply(FrameEvent& frame) _thrown = false; } - delta.set(0.0, 0.0); + delta.set(0.0, 0.0, 0.0); if (_keyboard->pressed(KEY_w)) delta.y = 1.0; if (_keyboard->pressed(KEY_s)) delta.y = -1.0; if (_keyboard->pressed(KEY_a)) delta.x = -1.0; if (_keyboard->pressed(KEY_d)) delta.x = 1.0; + if (_keyboard->pressed(KEY_o)) delta.z = 1.0; + if (_keyboard->pressed(KEY_i)) delta.z = -1.0; - if (delta.x != 0.0 || delta.y != 0.0) + if (delta.x != 0.0 || delta.y != 0.0 || delta.z != 0.0) { dvec3 lookVector = _lookAt->center - _lookAt->eye; - dmat4 matrix = vsg::translate(lookVector * (scale * delta.y * 0.2)) * + dvec3 sideVector = vsg::normalize(vsg::cross(_lookAt->up, lookVector)); + dmat4 matrix = vsg::translate(lookVector * (scale * delta.z * 0.2)) * vsg::translate(_lookAt->eye) * vsg::rotate(-delta.x * scale * 0.5, _lookAt->up) * + vsg::rotate(-delta.y * scale * 0.5, sideVector) * vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); From 364a7980db4ba050e537b728da30d2c76322fb6e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 12:24:05 +0100 Subject: [PATCH 08/21] Test build of WM_SETFOCUS & WM_KILLFOCUS --- src/vsg/platform/win32/Win32_Window.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vsg/platform/win32/Win32_Window.cpp b/src/vsg/platform/win32/Win32_Window.cpp index 45ec47fe8..2d6322e92 100644 --- a/src/vsg/platform/win32/Win32_Window.cpp +++ b/src/vsg/platform/win32/Win32_Window.cpp @@ -631,6 +631,12 @@ LRESULT Win32_Window::handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam break; } + case WM_SETFOCUS : + info("win32_focus_in_event"); + break; + case WM_KILLFOCUS : + info("win32_focus_out_event"); + break; default: break; } From 907e247d152728fb76bc679ed5170cc3d34a1105 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:01:41 +0100 Subject: [PATCH 09/21] Added FocusInEvent and FocusOutEvent for tracking when a window gain/looses keyboard focus --- include/vsg/core/ConstVisitor.h | 4 ++++ include/vsg/core/Visitor.h | 4 ++++ include/vsg/ui/WindowEvent.h | 22 ++++++++++++++++++++++ src/vsg/core/ConstVisitor.cpp | 8 ++++++++ src/vsg/core/Visitor.cpp | 8 ++++++++ 5 files changed, 46 insertions(+) diff --git a/include/vsg/core/ConstVisitor.h b/include/vsg/core/ConstVisitor.h index 3ceb633b2..13568b8fd 100644 --- a/include/vsg/core/ConstVisitor.h +++ b/include/vsg/core/ConstVisitor.h @@ -109,6 +109,8 @@ namespace vsg class ExposeWindowEvent; class ConfigureWindowEvent; class CloseWindowEvent; + class FocusInEvent; + class FocusOutEvent; class KeyEvent; class KeyPressEvent; class KeyReleaseEvent; @@ -356,6 +358,8 @@ namespace vsg virtual void apply(const ExposeWindowEvent&); virtual void apply(const ConfigureWindowEvent&); virtual void apply(const CloseWindowEvent&); + virtual void apply(const FocusInEvent&); + virtual void apply(const FocusOutEvent&); virtual void apply(const KeyEvent&); virtual void apply(const KeyPressEvent&); virtual void apply(const KeyReleaseEvent&); diff --git a/include/vsg/core/Visitor.h b/include/vsg/core/Visitor.h index b06e1d129..d30addf03 100644 --- a/include/vsg/core/Visitor.h +++ b/include/vsg/core/Visitor.h @@ -109,6 +109,8 @@ namespace vsg class ExposeWindowEvent; class ConfigureWindowEvent; class CloseWindowEvent; + class FocusInEvent; + class FocusOutEvent; class KeyEvent; class KeyPressEvent; class KeyReleaseEvent; @@ -356,6 +358,8 @@ namespace vsg virtual void apply(ExposeWindowEvent&); virtual void apply(ConfigureWindowEvent&); virtual void apply(CloseWindowEvent&); + virtual void apply(FocusInEvent&); + virtual void apply(FocusOutEvent&); virtual void apply(KeyEvent&); virtual void apply(KeyPressEvent&); virtual void apply(KeyReleaseEvent&); diff --git a/include/vsg/ui/WindowEvent.h b/include/vsg/ui/WindowEvent.h index 32c908020..62f3a46f5 100644 --- a/include/vsg/ui/WindowEvent.h +++ b/include/vsg/ui/WindowEvent.h @@ -93,4 +93,26 @@ namespace vsg }; VSG_type_name(vsg::CloseWindowEvent); + /// FocusInEvent represents a window aquiring focus event. + class FocusInEvent : public Inherit + { + public: + FocusInEvent() {} + + FocusInEvent(Window* in_window, time_point in_time) : + Inherit(in_window, in_time) {} + }; + VSG_type_name(vsg::FocusInEvent); + + /// FocusOutEvent represents a window loosing focus event. + class FocusOutEvent : public Inherit + { + public: + FocusOutEvent() {} + + FocusOutEvent(Window* in_window, time_point in_time) : + Inherit(in_window, in_time) {} + }; + VSG_type_name(vsg::FocusOutEvent); + } // namespace vsg diff --git a/src/vsg/core/ConstVisitor.cpp b/src/vsg/core/ConstVisitor.cpp index ac19df6e2..e94a2e477 100644 --- a/src/vsg/core/ConstVisitor.cpp +++ b/src/vsg/core/ConstVisitor.cpp @@ -837,6 +837,14 @@ void ConstVisitor::apply(const CloseWindowEvent& event) { apply(static_cast(event)); } +void ConstVisitor::apply(const FocusInEvent& event) +{ + apply(static_cast(event)); +} +void ConstVisitor::apply(const FocusOutEvent& event) +{ + apply(static_cast(event)); +} void ConstVisitor::apply(const KeyEvent& event) { apply(static_cast(event)); diff --git a/src/vsg/core/Visitor.cpp b/src/vsg/core/Visitor.cpp index ebd926ba1..e11f27343 100644 --- a/src/vsg/core/Visitor.cpp +++ b/src/vsg/core/Visitor.cpp @@ -837,6 +837,14 @@ void Visitor::apply(CloseWindowEvent& event) { apply(static_cast(event)); } +void Visitor::apply(FocusInEvent& event) +{ + apply(static_cast(event)); +} +void Visitor::apply(FocusOutEvent& event) +{ + apply(static_cast(event)); +} void Visitor::apply(KeyEvent& event) { apply(static_cast(event)); From 5f7b64f42e50575430e74a6f2e3711f756d9052e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:02:55 +0100 Subject: [PATCH 10/21] Added FocusInEvent/FocusOutEvent suppprt to Xcb_Window and Win32_Window. --- src/vsg/platform/win32/Win32_Window.cpp | 6 ++++-- src/vsg/platform/xcb/Xcb_Window.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/vsg/platform/win32/Win32_Window.cpp b/src/vsg/platform/win32/Win32_Window.cpp index 2d6322e92..9078b48ec 100644 --- a/src/vsg/platform/win32/Win32_Window.cpp +++ b/src/vsg/platform/win32/Win32_Window.cpp @@ -632,10 +632,12 @@ LRESULT Win32_Window::handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam break; } case WM_SETFOCUS : - info("win32_focus_in_event"); + vsg::clock::time_point event_time = vsg::clock::now(); + bufferedEvents.emplace_back(vsg::FocusInEvent::create(this, event_time)); break; case WM_KILLFOCUS : - info("win32_focus_out_event"); + vsg::clock::time_point event_time = vsg::clock::now(); + bufferedEvents.emplace_back(vsg::FocusOutEvent::create(this, event_time)); break; default: break; diff --git a/src/vsg/platform/xcb/Xcb_Window.cpp b/src/vsg/platform/xcb/Xcb_Window.cpp index 48e2568d4..879474389 100644 --- a/src/vsg/platform/xcb/Xcb_Window.cpp +++ b/src/vsg/platform/xcb/Xcb_Window.cpp @@ -611,11 +611,13 @@ bool Xcb_Window::pollEvents(UIEvents& events) break; } case (XCB_FOCUS_IN): { - info("xcb_focus_in_event_t"); + vsg::clock::time_point event_time = vsg::clock::now(); + bufferedEvents.emplace_back(vsg::FocusInEvent::create(this, event_time)); break; } case (XCB_FOCUS_OUT): { - info("xcb_focus_out_event_t"); + vsg::clock::time_point event_time = vsg::clock::now(); + bufferedEvents.emplace_back(vsg::FocusOutEvent::create(this, event_time)); break; } case (XCB_ENTER_NOTIFY): { From d7755f1733a067a16ba680c0276135958f6600f1 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:03:38 +0100 Subject: [PATCH 11/21] Added use of FocusInEvent/FocusOutEvent to Trackball --- include/vsg/app/Trackball.h | 4 ++++ src/vsg/app/Trackball.cpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index 38e3bf1cf..b71375c46 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -31,6 +31,8 @@ namespace vsg void apply(KeyPressEvent& keyPress) override; void apply(KeyReleaseEvent& keyRelease) override; + void apply(FocusInEvent& focusIn) override; + void apply(FocusOutEvent& focusOut) override; struct KeyHistory { @@ -63,6 +65,8 @@ namespace vsg void apply(KeyPressEvent& keyPress) override; void apply(KeyReleaseEvent& keyRelease) override; + void apply(FocusInEvent& focusIn) override; + void apply(FocusOutEvent& focusOut) override; void apply(ButtonPressEvent& buttonPress) override; void apply(ButtonReleaseEvent& buttonRelease) override; void apply(MoveEvent& moveEvent) override; diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 84cc78713..eaa15f0e7 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -67,6 +67,16 @@ void Keyboard::apply(KeyReleaseEvent& keyRelease) } } +void Keyboard::apply(FocusInEvent&) +{ +} + +void Keyboard::apply(FocusOutEvent& focusOut) +{ + focusOut.handled = true; + keyState.clear(); +} + bool Keyboard::pressed(KeySymbol key, bool ignore_handled_keys) { auto itr = keyState.find(key); @@ -230,6 +240,16 @@ void Trackball::apply(KeyReleaseEvent& keyRelease) if (_keyboard) keyRelease.accept(*_keyboard); } +void Trackball::apply(FocusInEvent& focusIn) +{ + if (_keyboard) focusIn.accept(*_keyboard); +} + +void Trackball::apply(FocusOutEvent& focusOut) +{ + if (_keyboard) focusOut.accept(*_keyboard); +} + void Trackball::apply(ButtonPressEvent& buttonPress) { if (buttonPress.handled || !eventRelevant(buttonPress)) From e21f72604f17eadec7f068034f943b5188ec3625 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:16:48 +0100 Subject: [PATCH 12/21] Moved Keyboard class into into own header --- include/vsg/all.h | 1 + include/vsg/app/Trackball.h | 30 +--------- include/vsg/ui/Keyboard.h | 49 ++++++++++++++++ src/vsg/CMakeLists.txt | 1 + src/vsg/app/Trackball.cpp | 92 ------------------------------ src/vsg/ui/Keyboard.cpp | 109 ++++++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 121 deletions(-) create mode 100644 include/vsg/ui/Keyboard.h create mode 100644 src/vsg/ui/Keyboard.cpp diff --git a/include/vsg/all.h b/include/vsg/all.h index 522be1a4e..989cf6a31 100644 --- a/include/vsg/all.h +++ b/include/vsg/all.h @@ -163,6 +163,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include #include #include diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index b71375c46..195785595 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -15,8 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include -#include -#include +#include #include #include #include @@ -24,33 +23,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI namespace vsg { - /// Keyboard tracks keyboard events to maintain the key pressed state and how long the key has been hel for - class VSG_DECLSPEC Keyboard : public Inherit - { - public: - - void apply(KeyPressEvent& keyPress) override; - void apply(KeyReleaseEvent& keyRelease) override; - void apply(FocusInEvent& focusIn) override; - void apply(FocusOutEvent& focusOut) override; - - struct KeyHistory - { - vsg::time_point timeOfFirstKeyPress = {}; - vsg::time_point timeOfLastKeyPress = {}; - vsg::time_point timeOfKeyRelease = {}; - bool handled = false; - }; - - std::map keyState; - - /// return true if key is currently pressed - bool pressed(KeySymbol key, bool ignore_handled_keys = true); - - /// return the length of time key has been pressed, return -1.0 for key is not currently pressed - double time_pressed(KeySymbol key, bool ignore_handled_keys = true); - }; - /// Trackball is an event handler that provides mouse and touch controlled 3d trackball camera view manipulation. class VSG_DECLSPEC Trackball : public Inherit { diff --git a/include/vsg/ui/Keyboard.h b/include/vsg/ui/Keyboard.h new file mode 100644 index 000000000..34ac954ee --- /dev/null +++ b/include/vsg/ui/Keyboard.h @@ -0,0 +1,49 @@ +#pragma once + +/* + +Copyright(c) 2023 Robert Osfield + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. + + */ + +#include +#include + +namespace vsg +{ + + /// Keyboard tracks keyboard events to maintain the key pressed state and how long the key has been hel for + class VSG_DECLSPEC Keyboard : public Inherit + { + public: + + void apply(KeyPressEvent& keyPress) override; + void apply(KeyReleaseEvent& keyRelease) override; + void apply(FocusInEvent& focusIn) override; + void apply(FocusOutEvent& focusOut) override; + + struct KeyHistory + { + vsg::time_point timeOfFirstKeyPress = {}; + vsg::time_point timeOfLastKeyPress = {}; + vsg::time_point timeOfKeyRelease = {}; + bool handled = false; + }; + + std::map keyState; + + /// return true if key is currently pressed + bool pressed(KeySymbol key, bool ignore_handled_keys = true); + + /// return the length of time key has been pressed, return -1.0 for key is not currently pressed + double time_pressed(KeySymbol key, bool ignore_handled_keys = true); + }; + VSG_type_name(vsg::Keyboard); + +} // namespace vsg diff --git a/src/vsg/CMakeLists.txt b/src/vsg/CMakeLists.txt index 4154312f1..3d9625e4d 100644 --- a/src/vsg/CMakeLists.txt +++ b/src/vsg/CMakeLists.txt @@ -192,6 +192,7 @@ set(SOURCES ui/ShiftEventTime.cpp ui/PlayEvents.cpp ui/PrintEvents.cpp + ui/Keyboard.cpp vk/CommandBuffer.cpp vk/CommandPool.cpp diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index eaa15f0e7..5549cd0a3 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -19,98 +19,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI using namespace vsg; -void Keyboard::apply(KeyPressEvent& keyPress) -{ - //std::cout<<"Keyboard::apply(KeyReleaseEvent& keyRelease)"<second; - keyHistory.handled = keyPress.handled; - if (keyHistory.timeOfKeyRelease == keyPress.time) - { - keyHistory.timeOfKeyRelease = keyHistory.timeOfFirstKeyPress; - keyHistory.timeOfLastKeyPress = keyPress.time; - //std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; - keyHistory.handled = keyRelease.handled; - keyHistory.timeOfKeyRelease = keyRelease.time; - //std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; - if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) - { - keyState.erase(itr); - return false; - } - - if (ignore_handled_keys && keyHistory.handled) return false; - - return true; -} - -double Keyboard::time_pressed(KeySymbol key, bool ignore_handled_keys) -{ - auto itr = keyState.find(key); - if (itr == keyState.end()) return -1.0; - - auto& keyHistory = itr->second; - if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) - { - keyState.erase(itr); - return -1.0; - } - - if (ignore_handled_keys && keyHistory.handled) return -1.0; - - return std::chrono::duration(clock::now() - keyHistory.timeOfFirstKeyPress).count(); -} - Trackball::Trackball(ref_ptr camera, ref_ptr ellipsoidModel) : _camera(camera), _lookAt(camera->viewMatrix.cast()), diff --git a/src/vsg/ui/Keyboard.cpp b/src/vsg/ui/Keyboard.cpp new file mode 100644 index 000000000..4cf0dfcee --- /dev/null +++ b/src/vsg/ui/Keyboard.cpp @@ -0,0 +1,109 @@ +/* + +Copyright(c) 2023 Robert Osfield + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. + + */ + +#include +#include +#include + +using namespace vsg; + +void Keyboard::apply(KeyPressEvent& keyPress) +{ + //std::cout<<"Keyboard::apply(KeyReleaseEvent& keyRelease)"<second; + keyHistory.handled = keyPress.handled; + if (keyHistory.timeOfKeyRelease == keyPress.time) + { + keyHistory.timeOfKeyRelease = keyHistory.timeOfFirstKeyPress; + keyHistory.timeOfLastKeyPress = keyPress.time; + //std::cout<<"key repeated "<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<(keyPress.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; + keyHistory.handled = keyRelease.handled; + keyHistory.timeOfKeyRelease = keyRelease.time; + //std::cout<<"key provisionally released "<(keyRelease.time - keyHistory.timeOfFirstKeyPress).count()<<"ms"<second; + if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) + { + keyState.erase(itr); + return false; + } + + if (ignore_handled_keys && keyHistory.handled) return false; + + return true; +} + +double Keyboard::time_pressed(KeySymbol key, bool ignore_handled_keys) +{ + auto itr = keyState.find(key); + if (itr == keyState.end()) return -1.0; + + auto& keyHistory = itr->second; + if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) + { + keyState.erase(itr); + return -1.0; + } + + if (ignore_handled_keys && keyHistory.handled) return -1.0; + + return std::chrono::duration(clock::now() - keyHistory.timeOfFirstKeyPress).count(); +} From cdf26b81e8d5f8c7dc1ce602c2f80bb99470aa1c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:17:23 +0100 Subject: [PATCH 13/21] Ran clang-format --- include/vsg/app/WindowResizeHandler.h | 1 - include/vsg/ui/Keyboard.h | 1 - src/vsg/app/CompileTraversal.cpp | 2 +- src/vsg/app/Trackball.cpp | 10 +++++----- src/vsg/platform/win32/Win32_Window.cpp | 4 ++-- src/vsg/ui/Keyboard.cpp | 2 +- src/vsg/vk/RenderPass.cpp | 2 +- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/vsg/app/WindowResizeHandler.h b/include/vsg/app/WindowResizeHandler.h index cee73928c..8e4aa6147 100644 --- a/include/vsg/app/WindowResizeHandler.h +++ b/include/vsg/app/WindowResizeHandler.h @@ -26,7 +26,6 @@ namespace vsg class VSG_DECLSPEC UpdateGraphicsPipelines : public vsg::Inherit { public: - UpdateGraphicsPipelines(); vsg::ref_ptr context; diff --git a/include/vsg/ui/Keyboard.h b/include/vsg/ui/Keyboard.h index 34ac954ee..2c30df1e8 100644 --- a/include/vsg/ui/Keyboard.h +++ b/include/vsg/ui/Keyboard.h @@ -22,7 +22,6 @@ namespace vsg class VSG_DECLSPEC Keyboard : public Inherit { public: - void apply(KeyPressEvent& keyPress) override; void apply(KeyReleaseEvent& keyRelease) override; void apply(FocusInEvent& focusIn) override; diff --git a/src/vsg/app/CompileTraversal.cpp b/src/vsg/app/CompileTraversal.cpp index 717255aec..698c0bcee 100644 --- a/src/vsg/app/CompileTraversal.cpp +++ b/src/vsg/app/CompileTraversal.cpp @@ -310,7 +310,7 @@ void CompileTraversal::apply(View& view) { // if context is associated with a view make sure we only apply it if it matches with view, oherwsie we skip this context auto context_view = context->view.ref_ptr(); - if (context_view && context_view.get()!=&view) continue; + if (context_view && context_view.get() != &view) continue; context->viewID = view.viewID; context->viewDependentState = view.viewDependentState.get(); diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 5549cd0a3..de25518db 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -410,7 +410,7 @@ void Trackball::apply(FrameEvent& frame) double scale = std::chrono::duration(frame.time - _previousTime).count(); if (delta.x != 0.0 || delta.y != 0.0) { - pan( dvec2(-delta.x, delta.y) * scale); + pan(dvec2(-delta.x, delta.y) * scale); _thrown = false; } @@ -427,10 +427,10 @@ void Trackball::apply(FrameEvent& frame) dvec3 lookVector = _lookAt->center - _lookAt->eye; dvec3 sideVector = vsg::normalize(vsg::cross(_lookAt->up, lookVector)); dmat4 matrix = vsg::translate(lookVector * (scale * delta.z * 0.2)) * - vsg::translate(_lookAt->eye) * - vsg::rotate(-delta.x * scale * 0.5, _lookAt->up) * - vsg::rotate(-delta.y * scale * 0.5, sideVector) * - vsg::translate(-_lookAt->eye); + vsg::translate(_lookAt->eye) * + vsg::rotate(-delta.x * scale * 0.5, _lookAt->up) * + vsg::rotate(-delta.y * scale * 0.5, sideVector) * + vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); _lookAt->center = matrix * _lookAt->center; diff --git a/src/vsg/platform/win32/Win32_Window.cpp b/src/vsg/platform/win32/Win32_Window.cpp index 9078b48ec..d571dce37 100644 --- a/src/vsg/platform/win32/Win32_Window.cpp +++ b/src/vsg/platform/win32/Win32_Window.cpp @@ -631,11 +631,11 @@ LRESULT Win32_Window::handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam break; } - case WM_SETFOCUS : + case WM_SETFOCUS: vsg::clock::time_point event_time = vsg::clock::now(); bufferedEvents.emplace_back(vsg::FocusInEvent::create(this, event_time)); break; - case WM_KILLFOCUS : + case WM_KILLFOCUS: vsg::clock::time_point event_time = vsg::clock::now(); bufferedEvents.emplace_back(vsg::FocusOutEvent::create(this, event_time)); break; diff --git a/src/vsg/ui/Keyboard.cpp b/src/vsg/ui/Keyboard.cpp index 4cf0dfcee..bcddfc483 100644 --- a/src/vsg/ui/Keyboard.cpp +++ b/src/vsg/ui/Keyboard.cpp @@ -10,9 +10,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ -#include #include #include +#include using namespace vsg; diff --git a/src/vsg/vk/RenderPass.cpp b/src/vsg/vk/RenderPass.cpp index b6a2b81a8..8d233d566 100644 --- a/src/vsg/vk/RenderPass.cpp +++ b/src/vsg/vk/RenderPass.cpp @@ -12,8 +12,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include -#include #include +#include #include #include From 788225a7665801221d7fefb5952be7c8760b45e8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 13:22:09 +0100 Subject: [PATCH 14/21] Added { } to fix build --- src/vsg/platform/win32/Win32_Window.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vsg/platform/win32/Win32_Window.cpp b/src/vsg/platform/win32/Win32_Window.cpp index d571dce37..271c57dff 100644 --- a/src/vsg/platform/win32/Win32_Window.cpp +++ b/src/vsg/platform/win32/Win32_Window.cpp @@ -631,14 +631,16 @@ LRESULT Win32_Window::handleWin32Messages(UINT msg, WPARAM wParam, LPARAM lParam break; } - case WM_SETFOCUS: + case WM_SETFOCUS: { vsg::clock::time_point event_time = vsg::clock::now(); bufferedEvents.emplace_back(vsg::FocusInEvent::create(this, event_time)); break; - case WM_KILLFOCUS: + } + case WM_KILLFOCUS: { vsg::clock::time_point event_time = vsg::clock::now(); bufferedEvents.emplace_back(vsg::FocusOutEvent::create(this, event_time)); break; + } default: break; } From 20f7b545deed335bcfeeb53e410987432e67db1c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 15:14:11 +0100 Subject: [PATCH 15/21] Added user controllable keys for controlling motion --- include/vsg/app/Trackball.h | 30 ++++++++++++++++++++++++++++++ src/vsg/app/Trackball.cpp | 20 ++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index 195785595..09cac5c03 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -83,6 +83,36 @@ namespace vsg /// container that maps key symbol bindings with the Viewpoint that should move the LookAt to when pressed. std::map keyViewpointMap; + /// Key that turns the view left around the eye points + KeySymbol turnLeftKey = KEY_a; + + /// Key that turns the view right around the eye points + KeySymbol turnRightKey = KEY_d; + + /// Key that pitches up the view around the eye point + KeySymbol pitchUpKey = KEY_w; + + /// Key that pitches down the view around the eye point + KeySymbol pitchDownKey = KEY_s; + + /// Key that moves the view forward + KeySymbol moveForwardKey = KEY_o; + + /// Key that moves the view backwards + KeySymbol moveBackwardKey = KEY_i; + + /// Key that moves the view left + KeySymbol moveLeftKey = KEY_Left; + + /// Key that moves the view right + KeySymbol moveRightKey = KEY_Right; + + /// Key that moves the view upward + KeySymbol moveUpKey = KEY_Up; + + /// Key that moves the view downard + KeySymbol moveDownKey = KEY_Down; + /// Button mask value used to enable panning of the view, defaults to left mouse button ButtonMask rotateButtonMask = BUTTON_MASK_1; diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index de25518db..acaf6f079 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -402,10 +402,10 @@ void Trackball::apply(FrameEvent& frame) if (_hasKeyboardFocus && _keyboard) { vsg::dvec3 delta(0.0, 0.0, 0.0); - if (_keyboard->pressed(KEY_Left)) delta.x = -1.0; - if (_keyboard->pressed(KEY_Right)) delta.x = 1.0; - if (_keyboard->pressed(KEY_Up)) delta.y = 1.0; - if (_keyboard->pressed(KEY_Down)) delta.y = -1.0; + if (_keyboard->pressed(moveLeftKey)) delta.x = -1.0; + if (_keyboard->pressed(moveRightKey)) delta.x = 1.0; + if (_keyboard->pressed(moveUpKey)) delta.y = 1.0; + if (_keyboard->pressed(moveDownKey)) delta.y = -1.0; double scale = std::chrono::duration(frame.time - _previousTime).count(); if (delta.x != 0.0 || delta.y != 0.0) @@ -415,12 +415,12 @@ void Trackball::apply(FrameEvent& frame) } delta.set(0.0, 0.0, 0.0); - if (_keyboard->pressed(KEY_w)) delta.y = 1.0; - if (_keyboard->pressed(KEY_s)) delta.y = -1.0; - if (_keyboard->pressed(KEY_a)) delta.x = -1.0; - if (_keyboard->pressed(KEY_d)) delta.x = 1.0; - if (_keyboard->pressed(KEY_o)) delta.z = 1.0; - if (_keyboard->pressed(KEY_i)) delta.z = -1.0; + if (_keyboard->pressed(pitchUpKey)) delta.y = 1.0; + if (_keyboard->pressed(pitchDownKey)) delta.y = -1.0; + if (_keyboard->pressed(turnLeftKey)) delta.x = -1.0; + if (_keyboard->pressed(turnRightKey)) delta.x = 1.0; + if (_keyboard->pressed(moveForwardKey)) delta.z = 1.0; + if (_keyboard->pressed(moveBackwardKey)) delta.z = -1.0; if (delta.x != 0.0 || delta.y != 0.0 || delta.z != 0.0) { From 16a17510f17435e1a64c63ed31e7169fd6dbea3d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 16 May 2023 18:15:14 +0100 Subject: [PATCH 16/21] Resutrctured the keyboard movement implementation --- src/vsg/app/Trackball.cpp | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index acaf6f079..80eca76e5 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -401,35 +401,35 @@ void Trackball::apply(FrameEvent& frame) // std::cout<<"Trackball::apply(FrameEvent&) frameCount = "<frameCount<pressed(moveLeftKey)) delta.x = -1.0; - if (_keyboard->pressed(moveRightKey)) delta.x = 1.0; - if (_keyboard->pressed(moveUpKey)) delta.y = 1.0; - if (_keyboard->pressed(moveDownKey)) delta.y = -1.0; - - double scale = std::chrono::duration(frame.time - _previousTime).count(); - if (delta.x != 0.0 || delta.y != 0.0) + bool update = false; + vsg::dvec3 move(0.0, 0.0, 0.0); + if (_keyboard->pressed(moveLeftKey)) { move.x = -1.0; update = true; } + if (_keyboard->pressed(moveRightKey)) { move.x = 1.0; update = true; } + if (_keyboard->pressed(moveUpKey)) { move.y = 1.0; update = true; } + if (_keyboard->pressed(moveDownKey)) { move.y = -1.0; update = true; } + if (_keyboard->pressed(moveForwardKey)) { move.z = 1.0; update = true; } + if (_keyboard->pressed(moveBackwardKey)) { move.z = -1.0; update = true; } + + vsg::dvec2 rot(0.0, 0.0); + if (_keyboard->pressed(pitchUpKey)) { rot.y = 1.0; update = true; } + if (_keyboard->pressed(pitchDownKey)) { rot.y = -1.0; update = true; } + if (_keyboard->pressed(turnLeftKey)) { rot.x = -1.0; update = true; } + if (_keyboard->pressed(turnRightKey)) { rot.x = 1.0; update = true; } + + if (update) { - pan(dvec2(-delta.x, delta.y) * scale); - _thrown = false; - } - - delta.set(0.0, 0.0, 0.0); - if (_keyboard->pressed(pitchUpKey)) delta.y = 1.0; - if (_keyboard->pressed(pitchDownKey)) delta.y = -1.0; - if (_keyboard->pressed(turnLeftKey)) delta.x = -1.0; - if (_keyboard->pressed(turnRightKey)) delta.x = 1.0; - if (_keyboard->pressed(moveForwardKey)) delta.z = 1.0; - if (_keyboard->pressed(moveBackwardKey)) delta.z = -1.0; - - if (delta.x != 0.0 || delta.y != 0.0 || delta.z != 0.0) - { - dvec3 lookVector = _lookAt->center - _lookAt->eye; - dvec3 sideVector = vsg::normalize(vsg::cross(_lookAt->up, lookVector)); - dmat4 matrix = vsg::translate(lookVector * (scale * delta.z * 0.2)) * - vsg::translate(_lookAt->eye) * - vsg::rotate(-delta.x * scale * 0.5, _lookAt->up) * - vsg::rotate(-delta.y * scale * 0.5, sideVector) * + double scale = std::chrono::duration(frame.time - _previousTime).count(); + double scaleTranslation = scale * 0.2 * length(_lookAt->center - _lookAt->eye) ; + double scaleRotation = scale * 0.5; + + dvec3 upVector = _lookAt->up; + dvec3 lookVector = vsg::normalize(_lookAt->center - _lookAt->eye); + dvec3 sideVector = vsg::normalize(vsg::cross(lookVector, upVector)); + + dvec3 delta = sideVector * (scaleTranslation * move.x) + upVector * (scaleTranslation * move.y) + lookVector * (scaleTranslation * move.z); + dmat4 matrix = vsg::translate(_lookAt->eye + delta) * + vsg::rotate(-rot.x * scaleRotation, upVector) * + vsg::rotate(-rot.y * scaleRotation, sideVector) * vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); From ecd23ae63c0dae02aa4d35a9dbf0147bd5da6ae8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 May 2023 09:52:43 +0100 Subject: [PATCH 17/21] Ran clang-format --- src/vsg/app/Trackball.cpp | 62 ++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 80eca76e5..5c8506fe8 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -403,23 +403,63 @@ void Trackball::apply(FrameEvent& frame) { bool update = false; vsg::dvec3 move(0.0, 0.0, 0.0); - if (_keyboard->pressed(moveLeftKey)) { move.x = -1.0; update = true; } - if (_keyboard->pressed(moveRightKey)) { move.x = 1.0; update = true; } - if (_keyboard->pressed(moveUpKey)) { move.y = 1.0; update = true; } - if (_keyboard->pressed(moveDownKey)) { move.y = -1.0; update = true; } - if (_keyboard->pressed(moveForwardKey)) { move.z = 1.0; update = true; } - if (_keyboard->pressed(moveBackwardKey)) { move.z = -1.0; update = true; } + if (_keyboard->pressed(moveLeftKey)) + { + move.x = -1.0; + update = true; + } + if (_keyboard->pressed(moveRightKey)) + { + move.x = 1.0; + update = true; + } + if (_keyboard->pressed(moveUpKey)) + { + move.y = 1.0; + update = true; + } + if (_keyboard->pressed(moveDownKey)) + { + move.y = -1.0; + update = true; + } + if (_keyboard->pressed(moveForwardKey)) + { + move.z = 1.0; + update = true; + } + if (_keyboard->pressed(moveBackwardKey)) + { + move.z = -1.0; + update = true; + } vsg::dvec2 rot(0.0, 0.0); - if (_keyboard->pressed(pitchUpKey)) { rot.y = 1.0; update = true; } - if (_keyboard->pressed(pitchDownKey)) { rot.y = -1.0; update = true; } - if (_keyboard->pressed(turnLeftKey)) { rot.x = -1.0; update = true; } - if (_keyboard->pressed(turnRightKey)) { rot.x = 1.0; update = true; } + if (_keyboard->pressed(pitchUpKey)) + { + rot.y = 1.0; + update = true; + } + if (_keyboard->pressed(pitchDownKey)) + { + rot.y = -1.0; + update = true; + } + if (_keyboard->pressed(turnLeftKey)) + { + rot.x = -1.0; + update = true; + } + if (_keyboard->pressed(turnRightKey)) + { + rot.x = 1.0; + update = true; + } if (update) { double scale = std::chrono::duration(frame.time - _previousTime).count(); - double scaleTranslation = scale * 0.2 * length(_lookAt->center - _lookAt->eye) ; + double scaleTranslation = scale * 0.2 * length(_lookAt->center - _lookAt->eye); double scaleRotation = scale * 0.5; dvec3 upVector = _lookAt->up; From 68fe63662cfb0beb05851bce85aa5e9a51b53f86 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 May 2023 11:56:43 +0100 Subject: [PATCH 18/21] Added bool method to vec/plane/quat class to make it easier to test if they are non zero --- include/vsg/maths/plane.h | 2 ++ include/vsg/maths/quat.h | 2 ++ include/vsg/maths/vec2.h | 2 ++ include/vsg/maths/vec3.h | 2 ++ include/vsg/maths/vec4.h | 2 ++ 5 files changed, 10 insertions(+) diff --git a/include/vsg/maths/plane.h b/include/vsg/maths/plane.h index 3c1003d8c..85d1ebcfc 100644 --- a/include/vsg/maths/plane.h +++ b/include/vsg/maths/plane.h @@ -102,6 +102,8 @@ namespace vsg bool valid() const { return n.x != 0.0 && n.y != 0.0 && n.z != 0.0; } + explicit operator bool() const noexcept { return valid(); } + T* data() { return value; } const T* data() const { return value; } }; diff --git a/include/vsg/maths/quat.h b/include/vsg/maths/quat.h index a49374636..d03e90401 100644 --- a/include/vsg/maths/quat.h +++ b/include/vsg/maths/quat.h @@ -141,6 +141,8 @@ namespace vsg z = axis.z * sinhalfangle * inversenorm; w = coshalfangle; } + + explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0 || value[3] != 0.0; } }; using quat = t_quat; /// float quaternion diff --git a/include/vsg/maths/vec2.h b/include/vsg/maths/vec2.h index 1b62507dc..f57d71740 100644 --- a/include/vsg/maths/vec2.h +++ b/include/vsg/maths/vec2.h @@ -130,6 +130,8 @@ namespace vsg } return *this; } + + explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0; } }; using vec2 = t_vec2; // float 2D vector diff --git a/include/vsg/maths/vec3.h b/include/vsg/maths/vec3.h index 040910cfa..40cf7752b 100644 --- a/include/vsg/maths/vec3.h +++ b/include/vsg/maths/vec3.h @@ -140,6 +140,8 @@ namespace vsg } return *this; } + + explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0; } }; using vec3 = t_vec3; // float 3D vector diff --git a/include/vsg/maths/vec4.h b/include/vsg/maths/vec4.h index 28f69f3e0..72473012a 100644 --- a/include/vsg/maths/vec4.h +++ b/include/vsg/maths/vec4.h @@ -154,6 +154,8 @@ namespace vsg } return *this; } + + explicit operator bool() const noexcept { return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0 || value[3] != 0.0; } }; using vec4 = t_vec4; // float 4D vector From b30c90dc51de01c742a4ef894e3a7c49bddb173f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 May 2023 11:58:55 +0100 Subject: [PATCH 19/21] Added inertial effect to Trackball keyboard controls. --- include/vsg/ui/Keyboard.h | 5 ++- src/vsg/app/Trackball.cpp | 82 ++++++++++++++------------------------- src/vsg/ui/Keyboard.cpp | 16 ++++---- 3 files changed, 42 insertions(+), 61 deletions(-) diff --git a/include/vsg/ui/Keyboard.h b/include/vsg/ui/Keyboard.h index 2c30df1e8..18e7bfbf5 100644 --- a/include/vsg/ui/Keyboard.h +++ b/include/vsg/ui/Keyboard.h @@ -40,8 +40,9 @@ namespace vsg /// return true if key is currently pressed bool pressed(KeySymbol key, bool ignore_handled_keys = true); - /// return the length of time key has been pressed, return -1.0 for key is not currently pressed - double time_pressed(KeySymbol key, bool ignore_handled_keys = true); + /// return a pair of times, the first is the time, in seconds, since the key was first pressed and the second is the time, in secnds, since it was released. + /// if the key hasn't been pressed then then first value will be < 0.0, if the key is still pressed then the second value will be 0.0. + std::pair times(KeySymbol key, bool ignore_handled_keys = true); }; VSG_type_name(vsg::Keyboard); diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index 5c8506fe8..e75d33526 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -401,62 +401,40 @@ void Trackball::apply(FrameEvent& frame) // std::cout<<"Trackball::apply(FrameEvent&) frameCount = "<frameCount<pressed(moveLeftKey)) - { - move.x = -1.0; - update = true; - } - if (_keyboard->pressed(moveRightKey)) - { - move.x = 1.0; - update = true; - } - if (_keyboard->pressed(moveUpKey)) - { - move.y = 1.0; - update = true; - } - if (_keyboard->pressed(moveDownKey)) + auto times2speed = [](std::pair duration) -> double { - move.y = -1.0; - update = true; - } - if (_keyboard->pressed(moveForwardKey)) - { - move.z = 1.0; - update = true; - } - if (_keyboard->pressed(moveBackwardKey)) - { - move.z = -1.0; - update = true; - } + if (duration.first<=0.0) return 0.0; + double speed = duration.first >= 1.0 ? 1.0 : duration.first; + + if (duration.second > 0.0) + { + // key has been released so slow down + speed -= duration.second; + return speed > 0.0 ? speed : 0.0 ; + } + else + { + // key still pressed so return speed based on duration of press + return speed; + } + }; + + double speed = 0.0; + vsg::dvec3 move(0.0, 0.0, 0.0); + if ((speed = times2speed(_keyboard->times(moveLeftKey))) != 0.0) move.x += -speed; + if ((speed = times2speed(_keyboard->times(moveRightKey))) != 0.0) move.x += speed; + if ((speed = times2speed(_keyboard->times(moveUpKey))) != 0.0) move.y += speed; + if ((speed = times2speed(_keyboard->times(moveDownKey))) != 0.0) move.y += -speed; + if ((speed = times2speed(_keyboard->times(moveForwardKey))) != 0.0) move.z += speed; + if ((speed = times2speed(_keyboard->times(moveBackwardKey))) != 0.0) move.z += -speed; vsg::dvec2 rot(0.0, 0.0); - if (_keyboard->pressed(pitchUpKey)) - { - rot.y = 1.0; - update = true; - } - if (_keyboard->pressed(pitchDownKey)) - { - rot.y = -1.0; - update = true; - } - if (_keyboard->pressed(turnLeftKey)) - { - rot.x = -1.0; - update = true; - } - if (_keyboard->pressed(turnRightKey)) - { - rot.x = 1.0; - update = true; - } + if ((speed = times2speed(_keyboard->times(pitchUpKey))) != 0.0) rot.y += -speed; + if ((speed = times2speed(_keyboard->times(pitchDownKey))) != 0.0) rot.y += speed; + if ((speed = times2speed(_keyboard->times(turnLeftKey))) != 0.0) rot.x += -speed; + if ((speed = times2speed(_keyboard->times(turnRightKey))) != 0.0) rot.x += speed; - if (update) + if (rot || move) { double scale = std::chrono::duration(frame.time - _previousTime).count(); double scaleTranslation = scale * 0.2 * length(_lookAt->center - _lookAt->eye); diff --git a/src/vsg/ui/Keyboard.cpp b/src/vsg/ui/Keyboard.cpp index bcddfc483..474d37675 100644 --- a/src/vsg/ui/Keyboard.cpp +++ b/src/vsg/ui/Keyboard.cpp @@ -82,7 +82,6 @@ bool Keyboard::pressed(KeySymbol key, bool ignore_handled_keys) auto& keyHistory = itr->second; if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) { - keyState.erase(itr); return false; } @@ -91,19 +90,22 @@ bool Keyboard::pressed(KeySymbol key, bool ignore_handled_keys) return true; } -double Keyboard::time_pressed(KeySymbol key, bool ignore_handled_keys) + +std::pair Keyboard::times(KeySymbol key, bool ignore_handled_keys) { auto itr = keyState.find(key); - if (itr == keyState.end()) return -1.0; + if (itr == keyState.end()) return {-1.0, -1.0}; + + auto currentTime = clock::now(); auto& keyHistory = itr->second; if (keyHistory.timeOfKeyRelease != keyHistory.timeOfFirstKeyPress) { - keyState.erase(itr); - return -1.0; + return {std::chrono::duration(currentTime - keyHistory.timeOfFirstKeyPress).count(), + std::chrono::duration(currentTime - keyHistory.timeOfLastKeyPress).count()}; } - if (ignore_handled_keys && keyHistory.handled) return -1.0; + if (ignore_handled_keys && keyHistory.handled) return {-1.0, -1.0}; - return std::chrono::duration(clock::now() - keyHistory.timeOfFirstKeyPress).count(); + return {std::chrono::duration(currentTime - keyHistory.timeOfFirstKeyPress).count(), 0.0}; } From f08409d8e287eab976c5029bbde8e115486d1b8b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 May 2023 12:24:20 +0100 Subject: [PATCH 20/21] Added roll with q and e keys --- include/vsg/app/Trackball.h | 6 ++++++ src/vsg/app/Trackball.cpp | 17 ++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/vsg/app/Trackball.h b/include/vsg/app/Trackball.h index 09cac5c03..841ce8faf 100644 --- a/include/vsg/app/Trackball.h +++ b/include/vsg/app/Trackball.h @@ -95,6 +95,12 @@ namespace vsg /// Key that pitches down the view around the eye point KeySymbol pitchDownKey = KEY_s; + /// Key that rools the view anti-clockwise/left + KeySymbol rollLeftKey = KEY_q; + + /// Key that rolls the view clockwise/right + KeySymbol rollRightKey = KEY_e; + /// Key that moves the view forward KeySymbol moveForwardKey = KEY_o; diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index e75d33526..d0decb3ea 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -428,11 +428,13 @@ void Trackball::apply(FrameEvent& frame) if ((speed = times2speed(_keyboard->times(moveForwardKey))) != 0.0) move.z += speed; if ((speed = times2speed(_keyboard->times(moveBackwardKey))) != 0.0) move.z += -speed; - vsg::dvec2 rot(0.0, 0.0); - if ((speed = times2speed(_keyboard->times(pitchUpKey))) != 0.0) rot.y += -speed; - if ((speed = times2speed(_keyboard->times(pitchDownKey))) != 0.0) rot.y += speed; - if ((speed = times2speed(_keyboard->times(turnLeftKey))) != 0.0) rot.x += -speed; - if ((speed = times2speed(_keyboard->times(turnRightKey))) != 0.0) rot.x += speed; + vsg::dvec3 rot(0.0, 0.0, 0.0); + if ((speed = times2speed(_keyboard->times(turnLeftKey))) != 0.0) rot.x += speed; + if ((speed = times2speed(_keyboard->times(turnRightKey))) != 0.0) rot.x -= speed; + if ((speed = times2speed(_keyboard->times(pitchUpKey))) != 0.0) rot.y += speed; + if ((speed = times2speed(_keyboard->times(pitchDownKey))) != 0.0) rot.y -= speed; + if ((speed = times2speed(_keyboard->times(rollLeftKey))) != 0.0) rot.z -= speed; + if ((speed = times2speed(_keyboard->times(rollRightKey))) != 0.0) rot.z += speed; if (rot || move) { @@ -446,8 +448,9 @@ void Trackball::apply(FrameEvent& frame) dvec3 delta = sideVector * (scaleTranslation * move.x) + upVector * (scaleTranslation * move.y) + lookVector * (scaleTranslation * move.z); dmat4 matrix = vsg::translate(_lookAt->eye + delta) * - vsg::rotate(-rot.x * scaleRotation, upVector) * - vsg::rotate(-rot.y * scaleRotation, sideVector) * + vsg::rotate(rot.x * scaleRotation, upVector) * + vsg::rotate(rot.y * scaleRotation, sideVector) * + vsg::rotate(rot.z * scaleRotation, lookVector) * vsg::translate(-_lookAt->eye); _lookAt->up = normalize(matrix * (_lookAt->eye + _lookAt->up) - matrix * _lookAt->eye); From 8b4dee7bbc9852f293c202f08a9d93548aa98f98 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 17 May 2023 12:41:15 +0100 Subject: [PATCH 21/21] Ran clang-format --- src/vsg/app/Trackball.cpp | 7 +++---- src/vsg/ui/Keyboard.cpp | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/vsg/app/Trackball.cpp b/src/vsg/app/Trackball.cpp index d0decb3ea..4ca4cfbb2 100644 --- a/src/vsg/app/Trackball.cpp +++ b/src/vsg/app/Trackball.cpp @@ -401,16 +401,15 @@ void Trackball::apply(FrameEvent& frame) // std::cout<<"Trackball::apply(FrameEvent&) frameCount = "<frameCount< duration) -> double - { - if (duration.first<=0.0) return 0.0; + auto times2speed = [](std::pair duration) -> double { + if (duration.first <= 0.0) return 0.0; double speed = duration.first >= 1.0 ? 1.0 : duration.first; if (duration.second > 0.0) { // key has been released so slow down speed -= duration.second; - return speed > 0.0 ? speed : 0.0 ; + return speed > 0.0 ? speed : 0.0; } else { diff --git a/src/vsg/ui/Keyboard.cpp b/src/vsg/ui/Keyboard.cpp index 474d37675..19d8399c7 100644 --- a/src/vsg/ui/Keyboard.cpp +++ b/src/vsg/ui/Keyboard.cpp @@ -90,7 +90,6 @@ bool Keyboard::pressed(KeySymbol key, bool ignore_handled_keys) return true; } - std::pair Keyboard::times(KeySymbol key, bool ignore_handled_keys) { auto itr = keyState.find(key);