mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-26 14:09:05 -06:00
216 lines
8.5 KiB
C++
216 lines
8.5 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014-2021 *
|
|
* *
|
|
* 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 <openspace/interaction/websocketcamerastates.h>
|
|
|
|
#include <openspace/engine/openspaceengine.h>
|
|
#include <openspace/interaction/inputstate.h>
|
|
#include <openspace/scripting/scriptengine.h>
|
|
#include <ghoul/misc/exception.h>
|
|
#include <ghoul/misc/stringconversion.h>
|
|
#include <utility>
|
|
#include <cmath>
|
|
|
|
namespace openspace::interaction {
|
|
|
|
WebsocketCameraStates::WebsocketCameraStates(double sensitivity,
|
|
double velocityScaleFactor)
|
|
: CameraInteractionStates(sensitivity, velocityScaleFactor)
|
|
{}
|
|
|
|
void WebsocketCameraStates::updateStateFromInput(const InputState& inputState,
|
|
double deltaTime)
|
|
{
|
|
std::pair<bool, glm::dvec2> globalRotation = { false, glm::dvec2(0.0) };
|
|
std::pair<bool, double> zoom = { false, 0.0 };
|
|
std::pair<bool, glm::dvec2> localRoll = { false, glm::dvec2(0.0) };
|
|
std::pair<bool, glm::dvec2> globalRoll = { false, glm::dvec2(0.0) };
|
|
std::pair<bool, glm::dvec2> localRotation = { false, glm::dvec2(0.0) };
|
|
|
|
if (inputState.hasWebsocketStates()) {
|
|
for (int i = 0; i < WebsocketInputState::MaxAxes; ++i) {
|
|
AxisInformation t = _axisMapping[i];
|
|
if (t.type == AxisType::None) {
|
|
continue;
|
|
}
|
|
|
|
float value = inputState.websocketAxis(i);
|
|
bool hasValue = std::fabs(value) > t.deadzone;
|
|
|
|
if (!hasValue) {
|
|
value = 0.f;
|
|
}
|
|
|
|
if (t.normalize) {
|
|
value = (value + 1.f) / 2.f;
|
|
}
|
|
|
|
if (t.invert) {
|
|
value *= -1.f;
|
|
}
|
|
|
|
value = static_cast<float>(value * _sensitivity);
|
|
|
|
switch (t.type) {
|
|
case AxisType::None:
|
|
break;
|
|
case AxisType::OrbitX:
|
|
globalRotation.first = hasValue || globalRotation.first;
|
|
globalRotation.second.x = value;
|
|
break;
|
|
case AxisType::OrbitY:
|
|
globalRotation.first = hasValue || globalRotation.first;
|
|
globalRotation.second.y = value;
|
|
break;
|
|
case AxisType::ZoomIn:
|
|
zoom.first = hasValue || zoom.first;
|
|
zoom.second += value;
|
|
break;
|
|
case AxisType::ZoomOut:
|
|
zoom.first = hasValue || zoom.first;
|
|
zoom.second -= value;
|
|
break;
|
|
case AxisType::LocalRollX:
|
|
localRoll.first = hasValue || localRoll.first;
|
|
localRoll.second.x = value;
|
|
break;
|
|
case AxisType::LocalRollY:
|
|
localRoll.first = hasValue || localRoll.first;
|
|
localRoll.second.y = value;
|
|
break;
|
|
case AxisType::GlobalRollX:
|
|
globalRoll.first = hasValue || globalRoll.first;
|
|
globalRoll.second.x = value;
|
|
break;
|
|
case AxisType::GlobalRollY:
|
|
globalRoll.first = hasValue || globalRoll.first;
|
|
globalRoll.second.y = value;
|
|
break;
|
|
case AxisType::PanX:
|
|
localRotation.first = hasValue || localRotation.first;
|
|
localRotation.second.x = value;
|
|
break;
|
|
case AxisType::PanY:
|
|
localRotation.first = hasValue || localRotation.first;
|
|
localRotation.second.y = value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (globalRotation.first) {
|
|
_globalRotationState.velocity.set(globalRotation.second, deltaTime);
|
|
}
|
|
else {
|
|
_globalRotationState.velocity.decelerate(deltaTime);
|
|
}
|
|
|
|
if (zoom.first) {
|
|
_truckMovementState.velocity.set(glm::dvec2(zoom.second), deltaTime);
|
|
}
|
|
else {
|
|
_truckMovementState.velocity.decelerate(deltaTime);
|
|
}
|
|
|
|
if (localRoll.first) {
|
|
_localRollState.velocity.set(localRoll.second, deltaTime);
|
|
}
|
|
else {
|
|
_localRollState.velocity.decelerate(deltaTime);
|
|
}
|
|
|
|
if (globalRoll.first) {
|
|
_globalRollState.velocity.set(globalRoll.second, deltaTime);
|
|
}
|
|
else {
|
|
_globalRollState.velocity.decelerate(deltaTime);
|
|
}
|
|
|
|
if (localRotation.first) {
|
|
_localRotationState.velocity.set(localRotation.second, deltaTime);
|
|
}
|
|
else {
|
|
_localRotationState.velocity.decelerate(deltaTime);
|
|
}
|
|
}
|
|
|
|
void WebsocketCameraStates::setAxisMapping(int axis, AxisType mapping,
|
|
AxisInvert shouldInvert,
|
|
AxisNormalize shouldNormalize)
|
|
{
|
|
ghoul_assert(axis < WebsocketInputState::MaxAxes, "axis must be < MaxAxes");
|
|
|
|
_axisMapping[axis].type = mapping;
|
|
_axisMapping[axis].invert = shouldInvert;
|
|
_axisMapping[axis].normalize = shouldNormalize;
|
|
}
|
|
|
|
WebsocketCameraStates::AxisInformation WebsocketCameraStates::axisMapping(int axis) const
|
|
{
|
|
return _axisMapping[axis];
|
|
}
|
|
|
|
void WebsocketCameraStates::setDeadzone(int axis, float deadzone) {
|
|
_axisMapping[axis].deadzone = deadzone;
|
|
}
|
|
|
|
float WebsocketCameraStates::deadzone(int axis) const {
|
|
return _axisMapping[axis].deadzone;
|
|
}
|
|
|
|
void WebsocketCameraStates::bindButtonCommand(int button, std::string command,
|
|
WebsocketAction action,
|
|
ButtonCommandRemote remote,
|
|
std::string documentation)
|
|
{
|
|
_buttonMapping.insert({
|
|
button,
|
|
{ std::move(command), action, remote, std::move(documentation) }
|
|
});
|
|
}
|
|
|
|
void WebsocketCameraStates::clearButtonCommand(int button) {
|
|
for (auto it = _buttonMapping.begin(); it != _buttonMapping.end();) {
|
|
// If the current iterator is the button that we are looking for, delete it
|
|
// (std::multimap::erase will return the iterator to the next element for us)
|
|
if (it->first == button) {
|
|
it = _buttonMapping.erase(it);
|
|
}
|
|
else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> WebsocketCameraStates::buttonCommand(int button) const {
|
|
std::vector<std::string> result;
|
|
auto itRange = _buttonMapping.equal_range(button);
|
|
for (auto it = itRange.first; it != itRange.second; ++it) {
|
|
result.push_back(it->second.command);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace openspace::interaction
|