diff --git "a/docs/zh_cn/3.3-\344\273\273\345\212\241\346\265\201\346\260\264\347\272\277\345\215\217\350\256\256.md" "b/docs/zh_cn/3.3-\344\273\273\345\212\241\346\265\201\346\260\264\347\272\277\345\215\217\350\256\256.md" index 95fc50dd6..b599cd661 100644 --- "a/docs/zh_cn/3.3-\344\273\273\345\212\241\346\265\201\346\260\264\347\272\277\345\215\217\350\256\256.md" +++ "b/docs/zh_cn/3.3-\344\273\273\345\212\241\346\265\201\346\260\264\347\272\277\345\215\217\350\256\256.md" @@ -64,7 +64,7 @@ - `action`: *string* 执行的动作。可选,默认 `DoNothing`。 - 可选的值:`DoNothing` | `Click` | `Swipe` | `StartApp` | `StopApp` | `CustomTask` + 可选的值:`DoNothing` | `Click` | `Swipe` | `Key` | `StartApp` | `StopApp` | `CustomTask` 详见 [动作类型](#动作类型)。 - `next` : *string* | *list* @@ -185,6 +185,13 @@ - `duration`: *uint* 滑动持续时间,单位毫秒。可选,默认 200 +### `Key` + +按键。 + +- `key`: *string* | *int* | *list* + 要按的键,仅支持 ascii。 + ### `StartApp` 启动 App。 diff --git a/include/interfaces/ThriftController.thrift b/include/interfaces/ThriftController.thrift index 4c3d76fa7..67e86a746 100644 --- a/include/interfaces/ThriftController.thrift +++ b/include/interfaces/ThriftController.thrift @@ -17,6 +17,9 @@ struct SwipeStep { struct SwipeParams { 1: list steps, } +struct PressKeyParams { + 1: i32 keycode, +} struct CustomImage { 1: Size size, @@ -31,7 +34,7 @@ service ThriftController { bool connect(), bool click(1: ClickParams param), bool swipe(1: SwipeParams param), - bool press_key(1: i32 keycode), + bool press_key(1: PressKeyParams param), bool start_game(1: string activity), bool stop_game(1: string activity), diff --git a/source/Controller/AdbController.cpp b/source/Controller/AdbController.cpp index 02846520b..e4a0b448e 100644 --- a/source/Controller/AdbController.cpp +++ b/source/Controller/AdbController.cpp @@ -140,6 +140,20 @@ void AdbController::_swipe(SwipeParams param) } } +void AdbController::_press_key(PressKeyParams param) +{ + if (!unit_mgr_ || !unit_mgr_->key_input_obj()) { + LogError << "unit is nullptr" << VAR(unit_mgr_) << VAR(unit_mgr_->key_input_obj()); + return; + } + + bool ret = unit_mgr_->key_input_obj()->press_key(param.keycode); + + if (!ret) { + LogError << "failed to press_key"; + } +} + cv::Mat AdbController::_screencap() { if (!unit_mgr_ || !unit_mgr_->screencap_obj()) { diff --git a/source/Controller/AdbController.h b/source/Controller/AdbController.h index 65b6b9292..de601327c 100644 --- a/source/Controller/AdbController.h +++ b/source/Controller/AdbController.h @@ -21,6 +21,7 @@ class AdbController : public ControllerMgr virtual std::pair _get_resolution() const override; virtual void _click(ClickParams param) override; virtual void _swipe(SwipeParams param) override; + virtual void _press_key(PressKeyParams param) override; virtual cv::Mat _screencap() override; virtual bool _start_app(AppParams param) override; virtual bool _stop_app(AppParams param) override; diff --git a/source/Controller/ControllerMgr.cpp b/source/Controller/ControllerMgr.cpp index 137fd1054..48e9232c7 100644 --- a/source/Controller/ControllerMgr.cpp +++ b/source/Controller/ControllerMgr.cpp @@ -147,6 +147,11 @@ void ControllerMgr::swipe(const cv::Point& p1, const cv::Point& p2, int duration action_runner_->post({ .type = Action::Type::swipe, .params = std::move(params) }, true); } +void ControllerMgr::press_key(int keycode) +{ + action_runner_->post({ .type = Action::Type::press_key, .params = PressKeyParams { .keycode = keycode } }, true); +} + cv::Mat ControllerMgr::screencap() { std::unique_lock lock(image_mutex_); @@ -221,6 +226,9 @@ bool ControllerMgr::run_action(typename AsyncRunner::Id id, Action actio case Action::Type::swipe: _swipe(std::get(action.params)); return true; + case Action::Type::press_key: + _press_key(std::get(action.params)); + return true; case Action::Type::screencap: return postproc_screenshot(_screencap()); diff --git a/source/Controller/ControllerMgr.h b/source/Controller/ControllerMgr.h index 4b378932e..25d4fcacc 100644 --- a/source/Controller/ControllerMgr.h +++ b/source/Controller/ControllerMgr.h @@ -32,6 +32,10 @@ struct SwipeParams }; std::vector steps; }; +struct PressKeyParams +{ + int keycode = 0; +}; struct AppParams { std::string package; @@ -39,7 +43,7 @@ struct AppParams std::ostream& operator<<(std::ostream& os, const SwipeParams::Step& step); -using Params = std::variant; +using Params = std::variant; struct Action { @@ -48,6 +52,7 @@ struct Action connect, click, swipe, + press_key, screencap, start_app, stop_app, @@ -85,6 +90,7 @@ class ControllerMgr : public MaaControllerAPI void click(const cv::Point& p); void swipe(const cv::Rect& r1, const cv::Rect& r2, int duration); void swipe(const cv::Point& p1, const cv::Point& p2, int duration); + void press_key(int keycode); cv::Mat screencap(); void start_app(); @@ -97,6 +103,7 @@ class ControllerMgr : public MaaControllerAPI virtual std::pair _get_resolution() const = 0; virtual void _click(ClickParams param) = 0; virtual void _swipe(SwipeParams param) = 0; + virtual void _press_key(PressKeyParams param) = 0; virtual cv::Mat _screencap() = 0; virtual bool _start_app(AppParams param) = 0; virtual bool _stop_app(AppParams param) = 0; diff --git a/source/Controller/CustomController.cpp b/source/Controller/CustomController.cpp index a34ee3d5d..858b9dc07 100644 --- a/source/Controller/CustomController.cpp +++ b/source/Controller/CustomController.cpp @@ -95,6 +95,18 @@ void CustomController::_swipe(SwipeParams param) handle_->swipe(x_buf.data(), y_buf.data(), delay_buf.data(), size); } +void CustomController::_press_key(PressKeyParams param) +{ + LogFunc << VAR_VOIDP(handle_) << VAR_VOIDP(handle_->press_key) << VAR(param.keycode); + + if (!handle_ || !handle_->press_key) { + LogError << "handle_ or handle_->press_key is nullptr"; + return; + } + + handle_->press_key(param.keycode); +} + cv::Mat CustomController::_screencap() { LogFunc << VAR_VOIDP(handle_) << VAR_VOIDP(handle_->get_image); diff --git a/source/Controller/CustomController.h b/source/Controller/CustomController.h index 719fd551e..3a998a6b2 100644 --- a/source/Controller/CustomController.h +++ b/source/Controller/CustomController.h @@ -18,6 +18,7 @@ class CustomController : public ControllerMgr virtual std::pair _get_resolution() const override; virtual void _click(ClickParams param) override; virtual void _swipe(SwipeParams param) override; + virtual void _press_key(PressKeyParams param) override; virtual cv::Mat _screencap() override; virtual bool _start_app(AppParams param) override; virtual bool _stop_app(AppParams param) override; diff --git a/source/Controller/CustomThriftController.cpp b/source/Controller/CustomThriftController.cpp index 31a1d8a78..e65d5b155 100644 --- a/source/Controller/CustomThriftController.cpp +++ b/source/Controller/CustomThriftController.cpp @@ -157,6 +157,21 @@ void CustomThriftController::_swipe(SwipeParams param) client_->swipe(swipe_param); } +void CustomThriftController::_press_key(PressKeyParams param) +{ + LogFunc; + + if (!client_ || !transport_->isOpen()) { + LogError << "client_ is nullptr or transport_ is not open"; + return; + } + + ThriftController::PressKeyParams thrift_param; + thrift_param.keycode = param.keycode; + + client_->press_key(thrift_param); +} + cv::Mat CustomThriftController::_screencap() { LogFunc; diff --git a/source/Controller/CustomThriftController.h b/source/Controller/CustomThriftController.h index 075c4344b..faa083393 100644 --- a/source/Controller/CustomThriftController.h +++ b/source/Controller/CustomThriftController.h @@ -18,6 +18,7 @@ class CustomThriftController : public ControllerMgr virtual std::pair _get_resolution() const override; virtual void _click(ClickParams param) override; virtual void _swipe(SwipeParams param) override; + virtual void _press_key(PressKeyParams param) override; virtual cv::Mat _screencap() override; virtual bool _start_app(AppParams param) override; virtual bool _stop_app(AppParams param) override; diff --git a/source/Resource/PipelineConfig.cpp b/source/Resource/PipelineConfig.cpp index 90584da7c..e7ab35556 100644 --- a/source/Resource/PipelineConfig.cpp +++ b/source/Resource/PipelineConfig.cpp @@ -466,12 +466,10 @@ bool PipelineConfig::parse_action(const json::value& input, MAA_PIPELINE_RES_NS: } static const std::unordered_map kActTypeMap = { - { "DoNothing", Type::DoNothing }, // - { "Click", Type::Click }, // - { "Swipe", Type::Swipe }, // - { "Key", Type::Key }, // - { "StopApp", Type::StopApp }, // - { "CustomTask", Type::CustomTask }, // + { "DoNothing", Type::DoNothing }, { "Click", Type::Click }, + { "Swipe", Type::Swipe }, { "Key", Type::Key }, + { "StartApp", Type::StartApp }, { "StopApp", Type::StopApp }, + { "CustomTask", Type::CustomTask }, }; auto act_type_iter = kActTypeMap.find(act_type_name); if (act_type_iter == kActTypeMap.cend()) { @@ -550,10 +548,18 @@ bool PipelineConfig::parse_swipe(const json::value& input, MAA_PIPELINE_RES_NS:: bool PipelineConfig::parse_key_press(const json::value& input, MAA_PIPELINE_RES_NS::Action::KeyParams& output) { - if (!get_and_check_value_or_array(input, "key", output.keys)) { - LogError << "failed to get_and_check_value_or_array key" << VAR(input); - return false; + std::string str_keys; + if (!get_and_check_value(input, "key", str_keys, std::string())) { + if (!get_and_check_value_or_array(input, "key", output.keys)) { + LogError << "failed to get_and_check_value_or_array key" << VAR(input); + return false; + } } + else { + ranges::transform(str_keys, std::back_inserter(output.keys), [](char c) { return static_cast(c); }); + LogTrace << "key press" << VAR(str_keys) << VAR(output.keys); + } + return true; } diff --git a/source/Task/PipelineTask.cpp b/source/Task/PipelineTask.cpp index 1a4ee58e9..5c3ae0bad 100644 --- a/source/Task/PipelineTask.cpp +++ b/source/Task/PipelineTask.cpp @@ -262,6 +262,7 @@ void PipelineTask::start_to_act(const FoundResult& act) case Type::Swipe: swipe(std::get(act.task_data.action_params), act.rec.box); break; + case Type::Key: break; case Type::StartApp: start_app(std::get(act.task_data.action_params)); @@ -306,6 +307,17 @@ void PipelineTask::swipe(const MAA_PIPELINE_RES_NS::Action::SwipeParams& param, controller()->swipe(begin, end, param.duration); } +void PipelineTask::press_key(const MAA_PIPELINE_RES_NS::Action::KeyParams& param) +{ + if (!controller()) { + LogError << "Controller is null"; + return; + } + for (const auto& key : param.keys) { + controller()->press_key(key); + } +} + void PipelineTask::wait_freezes(const MAA_PIPELINE_RES_NS::WaitFreezesParams& param, const cv::Rect& cur_box) { if (param.time <= std::chrono::milliseconds(0)) { diff --git a/source/Task/PipelineTask.h b/source/Task/PipelineTask.h index dfb9d8275..d6d6335e1 100644 --- a/source/Task/PipelineTask.h +++ b/source/Task/PipelineTask.h @@ -54,6 +54,8 @@ class PipelineTask : public TaskBase private: void click(const MAA_PIPELINE_RES_NS::Action::ClickParams& param, const cv::Rect& cur_box); void swipe(const MAA_PIPELINE_RES_NS::Action::SwipeParams& param, const cv::Rect& cur_box); + void press_key(const MAA_PIPELINE_RES_NS::Action::KeyParams& param); + void start_app(const MAA_PIPELINE_RES_NS::Action::AppInfo& param); void stop_app(const MAA_PIPELINE_RES_NS::Action::AppInfo& param); void run_custom_task(const MAA_PIPELINE_RES_NS::Action::CustomTaskParams& param);