// // Created by Bradley Austin Davis 2015/10/09 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "ScriptingInterface.h" #include #include #include #include #include #include #include #include #include "impl/MappingBuilderProxy.h" #include "Logging.h" #include "InputDevice.h" static QRegularExpression SANITIZE_NAME_EXPRESSION{ "[\\(\\)\\.\\s]" }; static QVariantMap createDeviceMap(const controller::InputDevice::Pointer device) { auto userInputMapper = DependencyManager::get(); QVariantMap deviceMap; for (const auto& inputMapping : userInputMapper->getAvailableInputs(device->getDeviceID())) { const auto& input = inputMapping.first; const auto inputName = QString(inputMapping.second).remove(SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "\tInput " << input.getChannel() << (int)input.getType() << QString::number(input.getID(), 16) << ": " << inputName; deviceMap.insert(inputName, input.getID()); } return deviceMap; } // FIXME this throws a hissy fit on MSVC if I put it in the main controller namespace block controller::ScriptingInterface::ScriptingInterface() { auto userInputMapper = DependencyManager::get(); connect(userInputMapper.data(), &UserInputMapper::actionEvent, this, &controller::ScriptingInterface::actionEvent); connect(userInputMapper.data(), &UserInputMapper::inputEvent, this, &controller::ScriptingInterface::inputEvent); // FIXME make this thread safe connect(userInputMapper.data(), &UserInputMapper::hardwareChanged, this, [=] { updateMaps(); emit hardwareChanged(); }); qCDebug(controllers) << "Setting up standard controller abstraction"; _standard = createDeviceMap(userInputMapper->getStandardDevice()); // FIXME allow custom user actions? auto actionNames = userInputMapper->getActionNames(); qCDebug(controllers) << "Setting up standard actions"; for (const auto& namedInput : userInputMapper->getActionInputs()) { const QString& actionName = namedInput.second; const Input& actionInput = namedInput.first; qCDebug(controllers) << "\tAction: " << actionName << " " << actionInput.getChannel(); // Expose the IDs to JS QString cleanActionName = QString(actionName).remove(SANITIZE_NAME_EXPRESSION); _actions.insert(cleanActionName, actionInput.getID()); } updateMaps(); } namespace controller { QObject* ScriptingInterface::newMapping(const QString& mappingName) { auto userInputMapper = DependencyManager::get(); return new MappingBuilderProxy(*userInputMapper, userInputMapper->newMapping(mappingName)); } void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { auto userInputMapper = DependencyManager::get(); userInputMapper->enableMapping(mappingName, enable); } float ScriptingInterface::getValue(const int& source) const { auto userInputMapper = DependencyManager::get(); return userInputMapper->getValue(Input((uint32_t)source)); } float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { return getValue(Input(device, source, ChannelType::BUTTON).getID()); } float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { return getValue(Input(device, source, ChannelType::AXIS).getID()); } Pose ScriptingInterface::getPoseValue(const int& source) const { auto userInputMapper = DependencyManager::get(); return userInputMapper->getPose(Input((uint32_t)source)); } Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { return getPoseValue(Input(device, source, ChannelType::POSE).getID()); } //bool ScriptingInterface::isPrimaryButtonPressed() const { // return isButtonPressed(StandardButtonChannel::A); //} // //glm::vec2 ScriptingInterface::getPrimaryJoystickPosition() const { // return getJoystickPosition(0); //} //int ScriptingInterface::getNumberOfButtons() const { // return StandardButtonChannel::NUM_STANDARD_BUTTONS; //} //bool ScriptingInterface::isButtonPressed(int buttonIndex) const { // return getButtonValue((StandardButtonChannel)buttonIndex) == 0.0 ? false : true; //} //int ScriptingInterface::getNumberOfTriggers() const { // return StandardCounts::TRIGGERS; //} //float ScriptingInterface::getTriggerValue(int triggerIndex) const { // return getAxisValue(triggerIndex == 0 ? StandardAxisChannel::LT : StandardAxisChannel::RT); //} //int ScriptingInterface::getNumberOfJoysticks() const { // return StandardCounts::ANALOG_STICKS; //} //glm::vec2 ScriptingInterface::getJoystickPosition(int joystickIndex) const { // StandardAxisChannel xid = StandardAxisChannel::LX; // StandardAxisChannel yid = StandardAxisChannel::LY; // if (joystickIndex != 0) { // xid = StandardAxisChannel::RX; // yid = StandardAxisChannel::RY; // } // vec2 result; // result.x = getAxisValue(xid); // result.y = getAxisValue(yid); // return result; //} //int ScriptingInterface::getNumberOfSpatialControls() const { // return StandardCounts::POSES; //} //glm::vec3 ScriptingInterface::getSpatialControlPosition(int controlIndex) const { // // FIXME extract the position from the standard pose // return vec3(); //} //glm::vec3 ScriptingInterface::getSpatialControlVelocity(int controlIndex) const { // // FIXME extract the velocity from the standard pose // return vec3(); //} //glm::vec3 ScriptingInterface::getSpatialControlNormal(int controlIndex) const { // // FIXME extract the normal from the standard pose // return vec3(); //} // //glm::quat ScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { // // FIXME extract the rotation from the standard pose // return quat(); //} QVector ScriptingInterface::getAllActions() { return DependencyManager::get()->getAllActions(); } QString ScriptingInterface::getDeviceName(unsigned int device) { return DependencyManager::get()->getDeviceName((unsigned short)device); } QVector ScriptingInterface::getAvailableInputs(unsigned int device) { return DependencyManager::get()->getAvailableInputs((unsigned short)device); } int ScriptingInterface::findDevice(QString name) { return DependencyManager::get()->findDevice(name); } QVector ScriptingInterface::getDeviceNames() { return DependencyManager::get()->getDeviceNames(); } float ScriptingInterface::getActionValue(int action) { return DependencyManager::get()->getActionState(Action(action)); } int ScriptingInterface::findAction(QString actionName) { return DependencyManager::get()->findAction(actionName); } QVector ScriptingInterface::getActionNames() const { return DependencyManager::get()->getActionNames(); } void ScriptingInterface::updateMaps() { QVariantMap newHardware; auto userInputMapper = DependencyManager::get(); const auto& devices = userInputMapper->getDevices(); for (const auto& deviceMapping : devices) { auto deviceID = deviceMapping.first; if (deviceID != userInputMapper->getStandardDeviceID()) { auto device = deviceMapping.second; auto deviceName = QString(device->getName()).remove(SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "Device" << deviceMapping.first << ":" << deviceName; if (newHardware.contains(deviceName)) { continue; } // Expose the IDs to JS newHardware.insert(deviceName, createDeviceMap(device)); } } _hardware = newHardware; } QObject* ScriptingInterface::parseMapping(const QString& json) { auto userInputMapper = DependencyManager::get(); auto mapping = userInputMapper->parseMapping(json); return new MappingBuilderProxy(*userInputMapper, mapping); } QObject* ScriptingInterface::loadMapping(const QString& jsonUrl) { return nullptr; } } // namespace controllers