Input: add device and factory template
This commit is contained in:
parent
8a8c0f348b
commit
3974895e08
|
@ -71,6 +71,7 @@ namespace Log {
|
||||||
CLS(Audio) \
|
CLS(Audio) \
|
||||||
SUB(Audio, DSP) \
|
SUB(Audio, DSP) \
|
||||||
SUB(Audio, Sink) \
|
SUB(Audio, Sink) \
|
||||||
|
CLS(Input) \
|
||||||
CLS(Loader)
|
CLS(Loader)
|
||||||
|
|
||||||
// GetClassName is a macro defined by Windows.h, grrr...
|
// GetClassName is a macro defined by Windows.h, grrr...
|
||||||
|
|
|
@ -89,6 +89,7 @@ enum class Class : ClassType {
|
||||||
Audio_DSP, ///< The HLE implementation of the DSP
|
Audio_DSP, ///< The HLE implementation of the DSP
|
||||||
Audio_Sink, ///< Emulator audio output backend
|
Audio_Sink, ///< Emulator audio output backend
|
||||||
Loader, ///< ROM loader
|
Loader, ///< ROM loader
|
||||||
|
Input, ///< Input emulation
|
||||||
Count ///< Total number of logging classes
|
Count ///< Total number of logging classes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,7 @@ set(HEADERS
|
||||||
frontend/camera/factory.h
|
frontend/camera/factory.h
|
||||||
frontend/camera/interface.h
|
frontend/camera/interface.h
|
||||||
frontend/emu_window.h
|
frontend/emu_window.h
|
||||||
|
frontend/input.h
|
||||||
frontend/key_map.h
|
frontend/key_map.h
|
||||||
frontend/motion_emu.h
|
frontend/motion_emu.h
|
||||||
gdbstub/gdbstub.h
|
gdbstub/gdbstub.h
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Input
|
Reference in New Issue