Skip to content

Commit

Permalink
refactor: 重新整理Command运行期参数替换
Browse files Browse the repository at this point in the history
  • Loading branch information
MistEO committed Dec 18, 2024
1 parent 2e6e93c commit 0eab5ba
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 43 deletions.
25 changes: 18 additions & 7 deletions docs/en_us/3.1-PipelineProtocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,12 +564,14 @@ This action attribute requires additional fields:

- `args`: *list<string,>*
The arguments to be executed. Optional.
Some runtime parameters can be passed in:
supports runtime parameters replacement:

- `{ENTRY}`: Task entry name
- `{NODE}`: Current task name
- `{IMAGE}`: Current screenshot file path
- `{BOX}`: Identify the hit target
- `{ENTRY}`: Entry name.
- `{NODE}`: Node name.
- `{IMAGE}`: The path to the file where the screenshot is saved. The file is deleted before the process exits. Please copy it by yourself if you want to save it permanently.
- `{BOX}`: Identify the hit target, the format is `[x, y, w, h]`.
- `{RESOURCE_DIR}`: The path of the resource folder loaded last time.
- `{LIBRARY_DIR}`: The path of the folder where the MaaFW library is located.

- `detach`: *bool*
Detach the child process, that is, do not wait for the child process to complete, and directly continue with the subsequent tasks. Optional, default false.
Expand All @@ -580,21 +582,30 @@ Example:
{
"TaskA": {
"action": "Command",
"exec": "my_exec.exe",
"exec": "Python",
"args": [
"{RESOURCE_DIR}/my_script/test.py"
"Haha",
"{IMAGE}",
"{NODE}",
"{BOX}"
]
},
"TaskB": {
"action": "Command",
"exec": "{RESOURCE_DIR}/my_exec/my_exec.exe"
}
}
```

The actual command is:

```bash
my_exec.exe Haha C:/temp/123.png TaskA [0,0,0,0]
# TaskA
Python C:/MaaXXX/resource/my_script/test.py Haha C:/temp/123.png TaskA [0,0,0,0]
# TaskB
C:/MaaXXX/resource/my_exec/my_exec.exe
```

### `Custom`
Expand Down
21 changes: 16 additions & 5 deletions docs/zh_cn/3.1-任务流水线协议.md
Original file line number Diff line number Diff line change
Expand Up @@ -574,12 +574,14 @@ Orange 的 next 中,
- `args`: *list<string,>*
执行的参数。可选。
可传入部分运行期参数
支持部分运行期参数替换
- `{ENTRY}`: 任务入口名
- `{NODE}`: 当前任务名
- `{IMAGE}`: 当前截图文件路径
- `{BOX}`: 识别命中的目标
- `{IMAGE}`: 截图保存到文件的路径。该文件在进程退出前删除,若要持久保存请自行复制
- `{BOX}`: 识别命中的目标,格式为 `[x, y, w, h]`
- `{RESOURCE_DIR}`: 最后一次加载的资源文件夹路径
- `{LIBRARY_DIR}`: MaaFW 库所在的文件夹路径
- `detach`: *bool*
分离子进程,即不等待子进程执行完成,直接继续之后后面的任务。可选,默认 false。
Expand All @@ -590,21 +592,30 @@ Orange 的 next 中,
{
"TaskA": {
"action": "Command",
"exec": "my_exec.exe",
"exec": "Python",
"args": [
"{RESOURCE_DIR}/my_script/test.py"
"Haha",
"{IMAGE}",
"{NODE}",
"{BOX}"
]
},
"TaskB": {
"action": "Command",
"exec": "{RESOURCE_DIR}/my_exec/my_exec.exe"
}
}
```
实际将会执行命令
```bash
my_exec.exe Haha C:/temp/123.png TaskA [0,0,0,0]
# TaskA
Python C:/MaaXXX/resource/my_script/test.py Haha C:/temp/123.png TaskA [0,0,0,0]
# TaskB
C:/MaaXXX/resource/my_exec/my_exec.exe
```
### `Custom`
Expand Down
2 changes: 2 additions & 0 deletions source/MaaFramework/Resource/ResourceMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class ResourceMgr : public MaaResource

const auto& default_pipeline() const { return default_pipeline_; }

const std::vector<std::filesystem::path>& paths() const { return paths_; }

CustomRecognitionSession custom_recognition(const std::string& name) const;
CustomActionSession custom_action(const std::string& name) const;

Expand Down
13 changes: 12 additions & 1 deletion source/MaaFramework/Task/Component/Actuator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,24 @@ bool Actuator::stop_app(const MAA_RES_NS::Action::AppParam& param)
return controller()->stop_app(param.package);
}

bool Actuator::command(const MAA_RES_NS::Action::CommandParam& param, const cv::Rect& box, const std::string& name, const std::string& entry)
bool Actuator::command(
const MAA_RES_NS::Action::CommandParam& param,
const cv::Rect& box,
const std::string& name,
const std::string& entry)
{
if (!controller()) {
LogError << "Controller is null";
return false;
}
auto* resource = tasker_ ? tasker_->resource() : nullptr;
if (!resource) {
LogError << "Resource is null";
return false;
}

CommandAction::Runtime rt {
.resource_paths = resource->paths(),
.entry = entry,
.node = name,
.image = controller()->cached_image(),
Expand Down
70 changes: 47 additions & 23 deletions source/MaaFramework/Task/Component/CommandAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,37 @@ bool CommandAction::run(const MAA_RES_NS::Action::CommandParam& command, const R
{
LogFunc << VAR(command.exec) << VAR(command.args) << VAR(command.detach);

static std::unordered_map<std::string, std::string> kExecReplacement = {
{ "{LIBRARY_DIR}", path_to_utf8_string(library_dir()) },
auto gen_runtime = [&](const std::string& src) -> std::string {
static std::unordered_map<std::string, std::function<std::string(const Runtime&)>> kArgvReplacement = {
{ "{ENTRY}", std::bind(&CommandAction::get_entry_name, this, std::placeholders::_1) },
{ "{NODE}", std::bind(&CommandAction::get_node_name, this, std::placeholders::_1) },
{ "{IMAGE}", std::bind(&CommandAction::get_image_path, this, std::placeholders::_1) },
{ "{BOX}", std::bind(&CommandAction::get_box, this, std::placeholders::_1) },
{ "{LIBRARY_DIR}", std::bind(&CommandAction::get_library_dir, this, std::placeholders::_1) },
{ "{RESOURCE_DIR}", std::bind(&CommandAction::get_resource_dir, this, std::placeholders::_1) },
};

std::string dst = src;
for (const auto& [key, func] : kArgvReplacement) {
if (src.find(key) == std::string::npos) {
continue;
}
string_replace_all(dst, key, func(runtime));
}
return dst;
};
std::string conv_exec = string_replace_all(command.exec, kExecReplacement);

std::string conv_exec = gen_runtime(command.exec);
std::filesystem::path exec = boost::process::search_path(path(conv_exec));
if (!std::filesystem::exists(exec)) {
LogError << "exec not exists" << VAR(command.exec) << VAR(conv_exec) << VAR(exec);
return false;
}

static std::unordered_map<std::string, std::function<std::string(const Runtime&)>> kArgvReplacement = {
{ "{ENTRY}", std::bind(&CommandAction::gen_entry_name, this, std::placeholders::_1) },
{ "{NODE}", std::bind(&CommandAction::gen_node_name, this, std::placeholders::_1) },
{ "{IMAGE}", std::bind(&CommandAction::gen_image_path, this, std::placeholders::_1) },
{ "{BOX}", std::bind(&CommandAction::gen_box, this, std::placeholders::_1) },
};

std::vector<os_string> args;
for (const std::string& arg : command.args) {
auto iter = kArgvReplacement.find(arg);
std::string dst = gen_runtime(arg);

std::string dst;
if (iter == kArgvReplacement.end()) {
dst = arg;
}
else {
dst = iter->second(runtime);
}
#ifdef _WIN32
args.emplace_back(to_u16(dst));
#else
Expand All @@ -82,27 +84,49 @@ bool CommandAction::run(const MAA_RES_NS::Action::CommandParam& command, const R
return true;
}

std::string CommandAction::gen_entry_name(const Runtime& runtime)
std::string CommandAction::get_entry_name(const Runtime& runtime)
{
return runtime.entry;
}

std::string CommandAction::gen_node_name(const Runtime& runtime)
std::string CommandAction::get_node_name(const Runtime& runtime)
{
return runtime.node;
}

std::string CommandAction::gen_image_path(const Runtime& runtime)
std::string CommandAction::get_image_path(const Runtime& runtime)
{
if (!image_path_.empty()) {
return image_path_;
}

auto dst_path = std::filesystem::temp_directory_path() / (format_now_for_filename() + ".png");
cached_images_.emplace_back(dst_path);
imwrite(dst_path, runtime.image);
return path_to_utf8_string(dst_path);
image_path_ = path_to_utf8_string(dst_path);
return image_path_;
}

std::string CommandAction::gen_box(const Runtime& runtime)
std::string CommandAction::get_box(const Runtime& runtime)
{
return std::format("[{},{},{},{}]", runtime.box.x, runtime.box.y, runtime.box.width, runtime.box.height);
}

std::string CommandAction::get_library_dir(const Runtime& runtime)
{
std::ignore = runtime;

return path_to_utf8_string(library_dir());
}

std::string CommandAction::get_resource_dir(const Runtime& runtime)
{
if (runtime.resource_paths.empty()) {
LogWarn << "no resource";
return {};
}

return path_to_utf8_string(runtime.resource_paths.back());
}

MAA_TASK_NS_END
20 changes: 13 additions & 7 deletions source/MaaFramework/Task/Component/CommandAction.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
#pragma once

#include <filesystem>
#include <string>
#include <vector>

#include "Conf/Conf.h"
#include "Resource/PipelineTypes.h"
#include "Utils/SingletonHolder.hpp"
#include "Utils/Platform.h"

MAA_TASK_NS_BEGIN

class CommandAction : public SingletonHolder<CommandAction>
class CommandAction
{
public:
struct Runtime
{
std::vector<std::filesystem::path> resource_paths;

std::string entry;
std::string node;
cv::Mat image;
Expand All @@ -27,13 +29,17 @@ class CommandAction : public SingletonHolder<CommandAction>
bool run(const MAA_RES_NS::Action::CommandParam& command, const Runtime& runtime);

private:
std::string gen_entry_name(const Runtime& runtime);
std::string gen_node_name(const Runtime& runtime);
std::string gen_image_path(const Runtime& runtime);
std::string gen_box(const Runtime& runtime);
std::string get_entry_name(const Runtime& runtime);
std::string get_node_name(const Runtime& runtime);
std::string get_image_path(const Runtime& runtime);
std::string get_box(const Runtime& runtime);
std::string get_library_dir(const Runtime& runtime);
std::string get_resource_dir(const Runtime& runtime);

private:
std::vector<std::filesystem::path> cached_images_;
static std::vector<std::filesystem::path> cached_images_;

std::string image_path_;
};

MAA_TASK_NS_END

0 comments on commit 0eab5ba

Please sign in to comment.