diff options
Diffstat (limited to 'src/core/frontend')
-rw-r--r-- | src/core/frontend/camera/blank_camera.cpp | 31 | ||||
-rw-r--r-- | src/core/frontend/camera/blank_camera.h | 28 | ||||
-rw-r--r-- | src/core/frontend/camera/factory.cpp | 32 | ||||
-rw-r--r-- | src/core/frontend/camera/factory.h | 41 | ||||
-rw-r--r-- | src/core/frontend/camera/interface.cpp | 11 | ||||
-rw-r--r-- | src/core/frontend/camera/interface.h | 61 | ||||
-rw-r--r-- | src/core/frontend/emu_window.cpp | 45 | ||||
-rw-r--r-- | src/core/frontend/emu_window.h | 54 | ||||
-rw-r--r-- | src/core/frontend/input.h | 110 | ||||
-rw-r--r-- | src/core/frontend/key_map.cpp | 152 | ||||
-rw-r--r-- | src/core/frontend/key_map.h | 93 |
11 files changed, 323 insertions, 335 deletions
diff --git a/src/core/frontend/camera/blank_camera.cpp b/src/core/frontend/camera/blank_camera.cpp new file mode 100644 index 000000000..7995abcbd --- /dev/null +++ b/src/core/frontend/camera/blank_camera.cpp @@ -0,0 +1,31 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/frontend/camera/blank_camera.h" + +namespace Camera { + +void BlankCamera::StartCapture() {} + +void BlankCamera::StopCapture() {} + +void BlankCamera::SetFormat(Service::CAM::OutputFormat output_format) { + output_rgb = output_format == Service::CAM::OutputFormat::RGB565; +} + +void BlankCamera::SetResolution(const Service::CAM::Resolution& resolution) { + width = resolution.width; + height = resolution.height; +}; + +void BlankCamera::SetFlip(Service::CAM::Flip) {} + +void BlankCamera::SetEffect(Service::CAM::Effect) {} + +std::vector<u16> BlankCamera::ReceiveFrame() const { + // Note: 0x80008000 stands for two black pixels in YUV422 + return std::vector<u16>(width * height, output_rgb ? 0 : 0x8000); +} + +} // namespace Camera diff --git a/src/core/frontend/camera/blank_camera.h b/src/core/frontend/camera/blank_camera.h new file mode 100644 index 000000000..c6619bd88 --- /dev/null +++ b/src/core/frontend/camera/blank_camera.h @@ -0,0 +1,28 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/frontend/camera/factory.h" +#include "core/frontend/camera/interface.h" + +namespace Camera { + +class BlankCamera final : public CameraInterface { +public: + void StartCapture() override; + void StopCapture() override; + void SetResolution(const Service::CAM::Resolution&) override; + void SetFlip(Service::CAM::Flip) override; + void SetEffect(Service::CAM::Effect) override; + void SetFormat(Service::CAM::OutputFormat) override; + std::vector<u16> ReceiveFrame() const override; + +private: + int width = 0; + int height = 0; + bool output_rgb = false; +}; + +} // namespace Camera diff --git a/src/core/frontend/camera/factory.cpp b/src/core/frontend/camera/factory.cpp new file mode 100644 index 000000000..4b4da50dd --- /dev/null +++ b/src/core/frontend/camera/factory.cpp @@ -0,0 +1,32 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <unordered_map> +#include "common/logging/log.h" +#include "core/frontend/camera/blank_camera.h" +#include "core/frontend/camera/factory.h" + +namespace Camera { + +static std::unordered_map<std::string, std::unique_ptr<CameraFactory>> factories; + +CameraFactory::~CameraFactory() = default; + +void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory) { + factories[name] = std::move(factory); +} + +std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config) { + auto pair = factories.find(name); + if (pair != factories.end()) { + return pair->second->Create(config); + } + + if (name != "blank") { + LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str()); + } + return std::make_unique<BlankCamera>(); +} + +} // namespace Camera diff --git a/src/core/frontend/camera/factory.h b/src/core/frontend/camera/factory.h new file mode 100644 index 000000000..f46413fa7 --- /dev/null +++ b/src/core/frontend/camera/factory.h @@ -0,0 +1,41 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include "core/frontend/camera/interface.h" + +namespace Camera { + +class CameraFactory { +public: + virtual ~CameraFactory(); + + /** + * Creates a camera object based on the configuration string. + * @param config Configuration string to create the camera. The implementation can decide the + * meaning of this string. + * @returns a unique_ptr to the created camera object. + */ + virtual std::unique_ptr<CameraInterface> Create(const std::string& config) const = 0; +}; + +/** + * Registers an external camera factory. + * @param name Identifier of the camera factory. + * @param factory Camera factory to register. + */ +void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory); + +/** + * Creates a camera from the factory. + * @param name Identifier of the camera factory. + * @param config Configuration string to create the camera. The meaning of this string is + * defined by the factory. + */ +std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config); + +} // namespace Camera diff --git a/src/core/frontend/camera/interface.cpp b/src/core/frontend/camera/interface.cpp new file mode 100644 index 000000000..9aec9e7f1 --- /dev/null +++ b/src/core/frontend/camera/interface.cpp @@ -0,0 +1,11 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/frontend/camera/interface.h" + +namespace Camera { + +CameraInterface::~CameraInterface() = default; + +} // namespace Camera diff --git a/src/core/frontend/camera/interface.h b/src/core/frontend/camera/interface.h new file mode 100644 index 000000000..a55a495c9 --- /dev/null +++ b/src/core/frontend/camera/interface.h @@ -0,0 +1,61 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <vector> +#include "common/common_types.h" +#include "core/hle/service/cam/cam.h" + +namespace Camera { + +/// An abstract class standing for a camera. All camera implementations should inherit from this. +class CameraInterface { +public: + virtual ~CameraInterface(); + + /// Starts the camera for video capturing. + virtual void StartCapture() = 0; + + /// Stops the camera for video capturing. + virtual void StopCapture() = 0; + + /** + * Sets the video resolution from raw CAM service parameters. + * For the meaning of the parameters, please refer to Service::CAM::Resolution. Note that the + * actual camera implementation doesn't need to respect all the parameters. However, the width + * and the height parameters must be respected and be used to determine the size of output + * frames. + * @param resolution The resolution parameters to set + */ + virtual void SetResolution(const Service::CAM::Resolution& resolution) = 0; + + /** + * Configures how received frames should be flipped by the camera. + * @param flip Flip applying to the frame + */ + virtual void SetFlip(Service::CAM::Flip flip) = 0; + + /** + * Configures what effect should be applied to received frames by the camera. + * @param effect Effect applying to the frame + */ + virtual void SetEffect(Service::CAM::Effect effect) = 0; + + /** + * Sets the output format of the all frames received after this function is called. + * @param format Output format of the frame + */ + virtual void SetFormat(Service::CAM::OutputFormat format) = 0; + + /** + * Receives a frame from the camera. + * This function should be only called between a StartCapture call and a StopCapture call. + * @returns A std::vector<u16> containing pixels. The total size of the vector is width * height + * where width and height are set by a call to SetResolution. + */ + virtual std::vector<u16> ReceiveFrame() const = 0; +}; + +} // namespace Camera diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index e5b1147a5..5fdb3a7e8 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -5,35 +5,11 @@ #include <algorithm> #include <cmath> #include "common/assert.h" -#include "common/profiler_reporting.h" +#include "core/core.h" #include "core/frontend/emu_window.h" -#include "core/frontend/key_map.h" +#include "core/settings.h" #include "video_core/video_core.h" -void EmuWindow::ButtonPressed(Service::HID::PadState pad) { - pad_state.hex |= pad.hex; -} - -void EmuWindow::ButtonReleased(Service::HID::PadState pad) { - pad_state.hex &= ~pad.hex; -} - -void EmuWindow::CirclePadUpdated(float x, float y) { - constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position - - // Make sure the coordinates are in the unit circle, - // otherwise normalize it. - float r = x * x + y * y; - if (r > 1) { - r = std::sqrt(r); - x /= r; - y /= r; - } - - circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS); - circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS); -} - /** * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout * @param layout FramebufferLayout object describing the framebuffer size and screen positions @@ -70,14 +46,12 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top); touch_pressed = true; - pad_state.touch.Assign(1); } void EmuWindow::TouchReleased() { touch_pressed = false; touch_x = 0; touch_y = 0; - pad_state.touch.Assign(0); } void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { @@ -98,20 +72,19 @@ void EmuWindow::AccelerometerChanged(float x, float y, float z) { // TODO(wwylele): do a time stretch as it in GyroscopeChanged // The time stretch formula should be like // stretched_vector = (raw_vector - gravity) * stretch_ratio + gravity - accel_x = x * coef; - accel_y = y * coef; - accel_z = z * coef; + accel_x = static_cast<s16>(x * coef); + accel_y = static_cast<s16>(y * coef); + accel_z = static_cast<s16>(z * coef); } void EmuWindow::GyroscopeChanged(float x, float y, float z) { constexpr float FULL_FPS = 60; float coef = GetGyroscopeRawToDpsCoefficient(); - float stretch = - FULL_FPS / Common::Profiling::GetTimingResultsAggregator()->GetAggregatedResults().fps; + float stretch = Core::System::GetInstance().perf_stats.GetLastFrameTimeScale(); std::lock_guard<std::mutex> lock(gyro_mutex); - gyro_x = x * coef * stretch; - gyro_y = y * coef * stretch; - gyro_z = z * coef * stretch; + gyro_x = static_cast<s16>(x * coef * stretch); + gyro_y = static_cast<s16>(y * coef * stretch); + gyro_z = static_cast<s16>(z * coef * stretch); } void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 1ba64c92b..36f2667fa 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -10,7 +10,6 @@ #include "common/common_types.h" #include "common/framebuffer_layout.h" #include "common/math_util.h" -#include "core/hle/service/hid/hid.h" /** * Abstraction class used to provide an interface between emulation code and the frontend @@ -52,30 +51,6 @@ public: /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread virtual void DoneCurrent() = 0; - virtual void ReloadSetKeymaps() = 0; - - /** - * Signals a button press action to the HID module. - * @param pad_state indicates which button to press - * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. - */ - void ButtonPressed(Service::HID::PadState pad_state); - - /** - * Signals a button release action to the HID module. - * @param pad_state indicates which button to press - * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. - */ - void ButtonReleased(Service::HID::PadState pad_state); - - /** - * Signals a circle pad change action to the HID module. - * @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0] - * @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0] - * @note the coordinates will be normalized if the radius is larger than 1 - */ - void CirclePadUpdated(float x, float y); - /** * Signal that a touch pressed event has occurred (e.g. mouse click pressed) * @param framebuffer_x Framebuffer x-coordinate that was pressed @@ -115,27 +90,6 @@ public: void GyroscopeChanged(float x, float y, float z); /** - * Gets the current pad state (which buttons are pressed). - * @note This should be called by the core emu thread to get a state set by the window thread. - * @note This doesn't include analog input like circle pad direction - * @todo Fix this function to be thread-safe. - * @return PadState object indicating the current pad state - */ - Service::HID::PadState GetPadState() const { - return pad_state; - } - - /** - * Gets the current circle pad state. - * @note This should be called by the core emu thread to get a state set by the window thread. - * @todo Fix this function to be thread-safe. - * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates - */ - std::tuple<s16, s16> GetCirclePadState() const { - return std::make_tuple(circle_pad_x, circle_pad_y); - } - - /** * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). * @note This should be called by the core emu thread to get a state set by the window thread. * @todo Fix this function to be thread-safe. @@ -230,11 +184,8 @@ protected: // TODO: Find a better place to set this. config.min_client_area_size = std::make_pair(400u, 480u); active_config = config; - pad_state.hex = 0; touch_x = 0; touch_y = 0; - circle_pad_x = 0; - circle_pad_y = 0; touch_pressed = false; accel_x = 0; accel_y = -512; @@ -304,9 +255,6 @@ private: u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) - s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156) - s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156) - std::mutex accel_mutex; s16 accel_x; ///< Accelerometer X-axis value in native 3DS units s16 accel_y; ///< Accelerometer Y-axis value in native 3DS units @@ -321,6 +269,4 @@ private: * Clip the provided coordinates to be inside the touchscreen area. */ std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y); - - Service::HID::PadState pad_state; }; diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h new file mode 100644 index 000000000..0a5713dc0 --- /dev/null +++ b/src/core/frontend/input.h @@ -0,0 +1,110 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include <tuple> +#include <unordered_map> +#include <utility> +#include "common/logging/log.h" +#include "common/param_package.h" + +namespace Input { + +/// An abstract class template for an input device (a button, an analog input, etc.). +template <typename StatusType> +class InputDevice { +public: + virtual ~InputDevice() = default; + virtual StatusType GetStatus() const { + return {}; + } +}; + +/// An abstract class template for a factory that can create input devices. +template <typename InputDeviceType> +class Factory { +public: + virtual ~Factory() = default; + virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0; +}; + +namespace Impl { + +template <typename InputDeviceType> +using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>; + +template <typename InputDeviceType> +struct FactoryList { + static FactoryListType<InputDeviceType> list; +}; + +template <typename InputDeviceType> +FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list; + +} // namespace Impl + +/** + * Registers an input device factory. + * @tparam InputDeviceType the type of input devices the factory can create + * @param name the name of the factory. Will be used to match the "engine" parameter when creating + * a device + * @param factory the factory object to register + */ +template <typename InputDeviceType> +void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) { + auto pair = std::make_pair(name, std::move(factory)); + if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) { + LOG_ERROR(Input, "Factory %s already registered", name.c_str()); + } +} + +/** + * Unregisters an input device factory. + * @tparam InputDeviceType the type of input devices the factory can create + * @param name the name of the factory to unregister + */ +template <typename InputDeviceType> +void UnregisterFactory(const std::string& name) { + if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) { + LOG_ERROR(Input, "Factory %s not registered", name.c_str()); + } +} + +/** + * Create an input device from given paramters. + * @tparam InputDeviceType the type of input devices to create + * @param params a serialized ParamPackage string contains all parameters for creating the device + */ +template <typename InputDeviceType> +std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) { + const Common::ParamPackage package(params); + const std::string engine = package.Get("engine", "null"); + const auto& factory_list = Impl::FactoryList<InputDeviceType>::list; + const auto pair = factory_list.find(engine); + if (pair == factory_list.end()) { + if (engine != "null") { + LOG_ERROR(Input, "Unknown engine name: %s", engine.c_str()); + } + return std::make_unique<InputDeviceType>(); + } + return pair->second->Create(package); +} + +/** + * A button device is an input device that returns bool as status. + * true for pressed; false for released. + */ +using ButtonDevice = InputDevice<bool>; + +/** + * An analog device is an input device that returns a tuple of x and y coordinates as status. The + * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up + * direction + */ +using AnalogDevice = InputDevice<std::tuple<float, float>>; + +} // namespace Input diff --git a/src/core/frontend/key_map.cpp b/src/core/frontend/key_map.cpp deleted file mode 100644 index 15f0e079c..000000000 --- a/src/core/frontend/key_map.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <map> -#include "core/frontend/emu_window.h" -#include "core/frontend/key_map.h" - -namespace KeyMap { - -// TODO (wwylele): currently we treat c-stick as four direction buttons -// and map it directly to EmuWindow::ButtonPressed. -// It should go the analog input way like circle pad does. -const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets = {{ - Service::HID::PAD_A, - Service::HID::PAD_B, - Service::HID::PAD_X, - Service::HID::PAD_Y, - Service::HID::PAD_L, - Service::HID::PAD_R, - Service::HID::PAD_ZL, - Service::HID::PAD_ZR, - Service::HID::PAD_START, - Service::HID::PAD_SELECT, - Service::HID::PAD_NONE, - Service::HID::PAD_UP, - Service::HID::PAD_DOWN, - Service::HID::PAD_LEFT, - Service::HID::PAD_RIGHT, - Service::HID::PAD_C_UP, - Service::HID::PAD_C_DOWN, - Service::HID::PAD_C_LEFT, - Service::HID::PAD_C_RIGHT, - - IndirectTarget::CirclePadUp, - IndirectTarget::CirclePadDown, - IndirectTarget::CirclePadLeft, - IndirectTarget::CirclePadRight, - IndirectTarget::CirclePadModifier, -}}; - -static std::map<HostDeviceKey, KeyTarget> key_map; -static int next_device_id = 0; - -static bool circle_pad_up = false; -static bool circle_pad_down = false; -static bool circle_pad_left = false; -static bool circle_pad_right = false; -static bool circle_pad_modifier = false; - -static void UpdateCirclePad(EmuWindow& emu_window) { - constexpr float SQRT_HALF = 0.707106781f; - int x = 0, y = 0; - - if (circle_pad_right) - ++x; - if (circle_pad_left) - --x; - if (circle_pad_up) - ++y; - if (circle_pad_down) - --y; - - float modifier = circle_pad_modifier ? Settings::values.pad_circle_modifier_scale : 1.0f; - emu_window.CirclePadUpdated(x * modifier * (y == 0 ? 1.0f : SQRT_HALF), - y * modifier * (x == 0 ? 1.0f : SQRT_HALF)); -} - -int NewDeviceId() { - return next_device_id++; -} - -void SetKeyMapping(HostDeviceKey key, KeyTarget target) { - key_map[key] = target; -} - -void ClearKeyMapping(int device_id) { - auto iter = key_map.begin(); - while (iter != key_map.end()) { - if (iter->first.device_id == device_id) - key_map.erase(iter++); - else - ++iter; - } -} - -void PressKey(EmuWindow& emu_window, HostDeviceKey key) { - auto target = key_map.find(key); - if (target == key_map.end()) - return; - - if (target->second.direct) { - emu_window.ButtonPressed({{target->second.target.direct_target_hex}}); - } else { - switch (target->second.target.indirect_target) { - case IndirectTarget::CirclePadUp: - circle_pad_up = true; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadDown: - circle_pad_down = true; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadLeft: - circle_pad_left = true; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadRight: - circle_pad_right = true; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadModifier: - circle_pad_modifier = true; - UpdateCirclePad(emu_window); - break; - } - } -} - -void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key) { - auto target = key_map.find(key); - if (target == key_map.end()) - return; - - if (target->second.direct) { - emu_window.ButtonReleased({{target->second.target.direct_target_hex}}); - } else { - switch (target->second.target.indirect_target) { - case IndirectTarget::CirclePadUp: - circle_pad_up = false; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadDown: - circle_pad_down = false; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadLeft: - circle_pad_left = false; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadRight: - circle_pad_right = false; - UpdateCirclePad(emu_window); - break; - case IndirectTarget::CirclePadModifier: - circle_pad_modifier = false; - UpdateCirclePad(emu_window); - break; - } - } -} -} diff --git a/src/core/frontend/key_map.h b/src/core/frontend/key_map.h deleted file mode 100644 index 040794578..000000000 --- a/src/core/frontend/key_map.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <tuple> -#include "core/hle/service/hid/hid.h" - -class EmuWindow; - -namespace KeyMap { - -/** - * Represents key mapping targets that are not real 3DS buttons. - * They will be handled by KeyMap and translated to 3DS input. - */ -enum class IndirectTarget { - CirclePadUp, - CirclePadDown, - CirclePadLeft, - CirclePadRight, - CirclePadModifier, -}; - -/** - * Represents a key mapping target. It can be a PadState that represents real 3DS buttons, - * or an IndirectTarget. - */ -struct KeyTarget { - bool direct; - union { - u32 direct_target_hex; - IndirectTarget indirect_target; - } target; - - KeyTarget() : direct(true) { - target.direct_target_hex = 0; - } - - KeyTarget(Service::HID::PadState pad) : direct(true) { - target.direct_target_hex = pad.hex; - } - - KeyTarget(IndirectTarget i) : direct(false) { - target.indirect_target = i; - } -}; - -/** - * Represents a key for a specific host device. - */ -struct HostDeviceKey { - int key_code; - int device_id; ///< Uniquely identifies a host device - - bool operator<(const HostDeviceKey& other) const { - return std::tie(key_code, device_id) < std::tie(other.key_code, other.device_id); - } - - bool operator==(const HostDeviceKey& other) const { - return std::tie(key_code, device_id) == std::tie(other.key_code, other.device_id); - } -}; - -extern const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets; - -/** - * Generates a new device id, which uniquely identifies a host device within KeyMap. - */ -int NewDeviceId(); - -/** - * Maps a device-specific key to a target (a PadState or an IndirectTarget). - */ -void SetKeyMapping(HostDeviceKey key, KeyTarget target); - -/** - * Clears all key mappings belonging to one device. - */ -void ClearKeyMapping(int device_id); - -/** - * Maps a key press action and call the corresponding function in EmuWindow - */ -void PressKey(EmuWindow& emu_window, HostDeviceKey key); - -/** - * Maps a key release action and call the corresponding function in EmuWindow - */ -void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key); -} |