mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
feat: LD 截图 (#10581)
* feat: EmulatorExtras 子模块更新 * feat: 写了一坨 * feat: 大概是能用了 * feat: ui 支持 ld 截图增强 * chore: 修改 LdSpecialScreenshot 颜色,调整版本要求描述 * chore: 使用 steady_clock * chore: 移除未使用变量
This commit is contained in:
2
3rdparty/EmulatorExtras
vendored
2
3rdparty/EmulatorExtras
vendored
Submodule 3rdparty/EmulatorExtras updated: 42442b1183...54d3a3ad44
@@ -69,6 +69,8 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inited/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=iter/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ldconsole/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=LD_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=leidian/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lolicon/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=lpwndpl/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=ls_005B_0022sub/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@@ -216,6 +216,23 @@ void asst::AdbController::init_mumu_extras(const AdbCfg& adb_cfg [[maybe_unused]
|
||||
#endif
|
||||
}
|
||||
|
||||
void asst::AdbController::init_ld_extras(const AdbCfg& adb_cfg [[maybe_unused]])
|
||||
{
|
||||
#if !ASST_WITH_EMULATOR_EXTRAS
|
||||
Log.error("MaaCore is not compiled with ASST_WITH_EMULATOR_EXTRAS");
|
||||
#else
|
||||
if (adb_cfg.extras.empty()) {
|
||||
LogWarn << "adb_cfg.extras is empty";
|
||||
return;
|
||||
}
|
||||
|
||||
std::filesystem::path ld_path = utils::path(adb_cfg.extras.get("path", ""));
|
||||
int ld_index = adb_cfg.extras.get("index", 0);
|
||||
int ld_pid = adb_cfg.extras.get("pid", 0);
|
||||
m_ld_extras.init(ld_path, ld_index, ld_pid, m_width, m_height);
|
||||
#endif
|
||||
}
|
||||
|
||||
void asst::AdbController::close_socket() noexcept
|
||||
{
|
||||
m_platform_io->close_socket();
|
||||
@@ -458,10 +475,10 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
auto min_cost = milliseconds(LLONG_MAX);
|
||||
clear_lf_info();
|
||||
|
||||
auto start_time = high_resolution_clock::now();
|
||||
auto start_time = steady_clock::now();
|
||||
if (m_support_socket && m_server_started
|
||||
&& screencap(m_adb.screencap_raw_by_nc, decode_raw, allow_reconnect, true, 5000)) {
|
||||
auto duration = duration_cast<milliseconds>(high_resolution_clock::now() - start_time);
|
||||
auto duration = duration_cast<milliseconds>(steady_clock::now() - start_time);
|
||||
if (duration < min_cost) {
|
||||
m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc;
|
||||
m_inited = true;
|
||||
@@ -474,9 +491,9 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
}
|
||||
clear_lf_info();
|
||||
|
||||
start_time = high_resolution_clock::now();
|
||||
start_time = steady_clock::now();
|
||||
if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip, allow_reconnect)) {
|
||||
auto duration = duration_cast<milliseconds>(high_resolution_clock::now() - start_time);
|
||||
auto duration = duration_cast<milliseconds>(steady_clock::now() - start_time);
|
||||
if (duration < min_cost) {
|
||||
m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip;
|
||||
m_inited = true;
|
||||
@@ -489,9 +506,9 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
}
|
||||
clear_lf_info();
|
||||
|
||||
start_time = high_resolution_clock::now();
|
||||
start_time = steady_clock::now();
|
||||
if (screencap(m_adb.screencap_encode, decode_encode, allow_reconnect)) {
|
||||
auto duration = duration_cast<milliseconds>(high_resolution_clock::now() - start_time);
|
||||
auto duration = duration_cast<milliseconds>(steady_clock::now() - start_time);
|
||||
if (duration < min_cost) {
|
||||
m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode;
|
||||
m_inited = true;
|
||||
@@ -505,10 +522,10 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
if (m_mumu_extras.inited()) {
|
||||
start_time = high_resolution_clock::now();
|
||||
start_time = steady_clock::now();
|
||||
if (m_mumu_extras.screencap()) {
|
||||
auto duration =
|
||||
duration_cast<milliseconds>(high_resolution_clock::now() - start_time);
|
||||
duration_cast<milliseconds>(steady_clock::now() - start_time);
|
||||
if (duration < min_cost) {
|
||||
m_adb.screencap_method = AdbProperty::ScreencapMethod::MumuExtras;
|
||||
m_inited = true;
|
||||
@@ -520,6 +537,22 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
Log.info("MumuExtras is not supported");
|
||||
}
|
||||
}
|
||||
if (m_ld_extras.inited()) {
|
||||
start_time = steady_clock::now();
|
||||
if (m_ld_extras.screencap()) {
|
||||
auto duration = duration_cast<milliseconds>(steady_clock::now() - start_time);
|
||||
if (duration < min_cost) {
|
||||
m_adb.screencap_method = AdbProperty::ScreencapMethod::LDExtras;
|
||||
m_inited = true;
|
||||
min_cost = duration;
|
||||
}
|
||||
Log.info("LDExtras cost", duration.count(), "ms");
|
||||
}
|
||||
else {
|
||||
Log.info("LDExtras is not supported");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static const std::unordered_map<AdbProperty::ScreencapMethod, std::string> MethodName = {
|
||||
@@ -529,6 +562,7 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
{ AdbProperty::ScreencapMethod::Encode, "Encode" },
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
{ AdbProperty::ScreencapMethod::MumuExtras, "MumuExtras" },
|
||||
{ AdbProperty::ScreencapMethod::LDExtras, "LDExtras" },
|
||||
#endif
|
||||
};
|
||||
Log.info(
|
||||
@@ -577,6 +611,20 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect
|
||||
screencap_ret = img_opt.has_value();
|
||||
}
|
||||
|
||||
if (screencap_ret) {
|
||||
image_payload = img_opt.value();
|
||||
}
|
||||
} break;
|
||||
case AdbProperty::ScreencapMethod::LDExtras: {
|
||||
auto img_opt = m_ld_extras.screencap();
|
||||
screencap_ret = img_opt.has_value();
|
||||
|
||||
if (!screencap_ret && allow_reconnect) {
|
||||
m_ld_extras.reload();
|
||||
img_opt = m_ld_extras.screencap();
|
||||
screencap_ret = img_opt.has_value();
|
||||
}
|
||||
|
||||
if (screencap_ret) {
|
||||
image_payload = img_opt.value();
|
||||
}
|
||||
@@ -986,6 +1034,9 @@ bool asst::AdbController::connect(
|
||||
if (config == "MuMuEmulator12") {
|
||||
init_mumu_extras(adb_cfg);
|
||||
}
|
||||
else if (config == "LDPlayer") {
|
||||
init_ld_extras(adb_cfg);
|
||||
}
|
||||
|
||||
if (need_exit()) {
|
||||
return false;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Config/GeneralConfig.h"
|
||||
#include "InstHelper.h"
|
||||
#include "MumuExtras.h"
|
||||
#include "LDExtras.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
@@ -103,6 +104,7 @@ protected:
|
||||
virtual void clear_info() noexcept;
|
||||
void callback(AsstMsg msg, const json::value& details);
|
||||
void init_mumu_extras(const AdbCfg& adb_cfg);
|
||||
void init_ld_extras(const AdbCfg& adb_cfg);
|
||||
|
||||
// 转换 data 中的 CRLF 为 LF:有些模拟器自带的 adb,exec-out 输出的 \n 会被替换成 \r\n,
|
||||
// 导致解码错误,所以这里转一下回来(点名批评 mumu 和雷电)
|
||||
@@ -158,6 +160,7 @@ protected:
|
||||
Encode,
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
MumuExtras,
|
||||
LDExtras,
|
||||
#endif
|
||||
} screencap_method = ScreencapMethod::UnknownYet;
|
||||
} m_adb;
|
||||
@@ -178,6 +181,7 @@ protected:
|
||||
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
MumuExtras m_mumu_extras;
|
||||
LDExtras m_ld_extras;
|
||||
#endif
|
||||
};
|
||||
} // namespace asst
|
||||
|
||||
124
src/MaaCore/LDExtras.cpp
Normal file
124
src/MaaCore/LDExtras.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "LDExtras.h"
|
||||
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
|
||||
#include "Utils/Logger.hpp"
|
||||
#include "Utils/NoWarningCV.h"
|
||||
#include "Utils/Platform/SafeWindows.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <Controller/AdbController.h>
|
||||
|
||||
namespace asst
|
||||
{
|
||||
LDExtras::~LDExtras()
|
||||
{
|
||||
uninit();
|
||||
}
|
||||
|
||||
bool LDExtras::init(const std::filesystem::path& ld_path, unsigned int ld_inst_index, unsigned int ld_pid, int width, int height)
|
||||
{
|
||||
const bool same = ld_inst_index == ld_inst_index_ && ld_pid == ld_pid_;
|
||||
|
||||
if (same && inited_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ld_inst_index_ = ld_inst_index;
|
||||
ld_path_ = ld_path;
|
||||
ld_pid_ = ld_pid;
|
||||
display_width_ = width;
|
||||
display_height_ = height;
|
||||
|
||||
inited_ = load_ld_library() && connect_ld() && init_screencap();
|
||||
|
||||
return inited_;
|
||||
}
|
||||
|
||||
bool LDExtras::reload()
|
||||
{
|
||||
inited_ = load_ld_library() && connect_ld() && init_screencap();
|
||||
LogInfo << "Reload LDExtras: " << VAR(inited_);
|
||||
return inited_;
|
||||
}
|
||||
|
||||
void LDExtras::uninit()
|
||||
{
|
||||
inited_ = false;
|
||||
disconnect_ld();
|
||||
}
|
||||
|
||||
std::optional<cv::Mat> LDExtras::screencap() const
|
||||
{
|
||||
if (!screenshot_instance_) {
|
||||
LogError << "screenshot_instance_ is null";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void* pixels = screenshot_instance_->cap();
|
||||
if (!pixels) {
|
||||
LogError << "Failed to capture screen";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const cv::Mat raw(display_height_, display_width_, CV_8UC3, pixels);
|
||||
cv::Mat dst;
|
||||
cv::flip(raw, dst, 0);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
bool LDExtras::load_ld_library()
|
||||
{
|
||||
auto lib_path = ld_path_ / "ldopengl64.dll";
|
||||
|
||||
if (!load_library(lib_path)) {
|
||||
LogError << "Failed to load library" << VAR(lib_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
create_screenshot_instance_func_ = get_function<decltype(CreateScreenShotInstance)>(kCreateScreenShotInstanceFuncName);
|
||||
if (!create_screenshot_instance_func_) {
|
||||
LogError << "Failed to get function" << VAR(kCreateScreenShotInstanceFuncName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LDExtras::connect_ld()
|
||||
{
|
||||
LogInfo << VAR(ld_inst_index_) << VAR(ld_pid_);
|
||||
|
||||
screenshot_instance_ = create_screenshot_instance_func_(ld_inst_index_, ld_pid_);
|
||||
if (!screenshot_instance_) {
|
||||
LogError << "Failed to create screenshot instance" << VAR(ld_inst_index_);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LDExtras::init_screencap()
|
||||
{
|
||||
if (!screenshot_instance_) {
|
||||
LogError << "screenshot_instance_ is null";
|
||||
return false;
|
||||
}
|
||||
|
||||
LogDebug << VAR(display_width_) << VAR(display_height_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LDExtras::disconnect_ld()
|
||||
{
|
||||
LogInfo << "Disconnecting LD";
|
||||
|
||||
if (screenshot_instance_) {
|
||||
screenshot_instance_->release();
|
||||
screenshot_instance_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
58
src/MaaCore/LDExtras.h
Normal file
58
src/MaaCore/LDExtras.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/AsstConf.h"
|
||||
|
||||
#if ASST_WITH_EMULATOR_EXTRAS
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include "Utils/Platform/SafeWindows.h"
|
||||
|
||||
#include "LD/dnopengl/dnopengl.h"
|
||||
|
||||
#include "Utils/LibraryHolder.hpp"
|
||||
#include "Utils/NoWarningCVMat.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
class LDExtras : public LibraryHolder<LDExtras>
|
||||
{
|
||||
public:
|
||||
LDExtras() = default;
|
||||
|
||||
virtual ~LDExtras();
|
||||
|
||||
bool inited() const { return inited_; }
|
||||
|
||||
bool init(const std::filesystem::path& ld_path, unsigned int ld_inst_index, unsigned int ld_pid, int width, int height);
|
||||
bool reload();
|
||||
void uninit();
|
||||
|
||||
std::optional<cv::Mat> screencap() const;
|
||||
|
||||
private:
|
||||
bool load_ld_library();
|
||||
bool connect_ld();
|
||||
bool init_screencap();
|
||||
void disconnect_ld();
|
||||
|
||||
private:
|
||||
unsigned int ld_inst_index_ = 0;
|
||||
unsigned int ld_pid_ = 0;
|
||||
|
||||
IScreenShotClass* screenshot_instance_ = nullptr;
|
||||
int display_width_ = 0;
|
||||
int display_height_ = 0;
|
||||
|
||||
bool inited_ = false;
|
||||
|
||||
private:
|
||||
std::filesystem::path ld_path_;
|
||||
inline static const std::string kCreateScreenShotInstanceFuncName = "CreateScreenShotInstance";
|
||||
|
||||
private:
|
||||
std::function<decltype(CreateScreenShotInstance)> create_screenshot_instance_func_;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -69,6 +69,7 @@
|
||||
<ClInclude Include="Controller\Platform\PlatformIO.h" />
|
||||
<ClInclude Include="Controller\Platform\PlatformFactory.h" />
|
||||
<ClInclude Include="InstHelper.h" />
|
||||
<ClInclude Include="LDExtras.h" />
|
||||
<ClInclude Include="Task\Experiment\CombatRecordRecognitionTask.h" />
|
||||
<ClInclude Include="Task\Experiment\SingleStepBattleProcessTask.h" />
|
||||
<ClInclude Include="Task\Fight\FightTimesTaskPlugin.h" />
|
||||
@@ -260,6 +261,7 @@
|
||||
<ClCompile Include="Controller\Platform\PosixIO.cpp" />
|
||||
<ClCompile Include="Controller\Platform\Win32IO.cpp" />
|
||||
<ClCompile Include="InstHelper.cpp" />
|
||||
<ClCompile Include="LDExtras.cpp" />
|
||||
<ClCompile Include="Task\Experiment\CombatRecordRecognitionTask.cpp" />
|
||||
<ClCompile Include="Task\Experiment\SingleStepBattleProcessTask.cpp" />
|
||||
<ClCompile Include="Task\Fight\FightTimesTaskPlugin.cpp" />
|
||||
|
||||
@@ -728,6 +728,9 @@
|
||||
<ClInclude Include="Task\Roguelike\Map\RoguelikeRoutingTaskPlugin.h">
|
||||
<Filter>Source\Task\Roguelike</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LDExtras.h">
|
||||
<Filter>Source\Controller</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vision\VisionHelper.cpp">
|
||||
@@ -1221,5 +1224,8 @@
|
||||
<ClCompile Include="Config\Roguelike\Sami\RoguelikeFoldartalConfig.cpp">
|
||||
<Filter>Source\Resource\Roguelike</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LDExtras.cpp">
|
||||
<Filter>Source\Controller</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -64,6 +64,9 @@ namespace MaaWpfGui.Constants
|
||||
public const string MuMu12EmulatorPath = "Connect.MuMu12EmulatorPath";
|
||||
public const string MuMu12Index = "Connect.MuMu12Index";
|
||||
public const string MuMu12Display = "Connect.MuMu12Display";
|
||||
public const string LdPlayerExtrasEnabled = "Connect.LdPlayerExtras.Enabled";
|
||||
public const string LdPlayerEmulatorPath = "Connect.LdPlayerEmulatorPath";
|
||||
public const string LdPlayerIndex = "Connect.LdPlayerIndex";
|
||||
public const string RetryOnAdbDisconnected = "Connect.RetryOnDisconnected";
|
||||
public const string AllowAdbRestart = "Connect.AllowADBRestart";
|
||||
public const string AllowAdbHardRestart = "Connect.AllowADBHardRestart";
|
||||
|
||||
@@ -64,6 +64,11 @@ namespace MaaWpfGui.Constants
|
||||
/// </summary>
|
||||
public const string MuMuSpecialScreenshot = "MuMuSpecialScreenshot";
|
||||
|
||||
/// <summary>
|
||||
/// The recommended color for LD special screenshot.
|
||||
/// </summary>
|
||||
public const string LdSpecialScreenshot = "LdSpecialScreenshot";
|
||||
|
||||
// 颜色在MaaWpfGui\Res\Themes中定义
|
||||
// Brush are defined in MaaWpfGui\Res\Themes
|
||||
}
|
||||
|
||||
@@ -119,6 +119,11 @@ namespace MaaWpfGui.Main
|
||||
AsstSetConnectionExtras("MuMuEmulator12", extras);
|
||||
}
|
||||
|
||||
private static void AsstSetConnectionExtrasLdPlayer(string extras)
|
||||
{
|
||||
AsstSetConnectionExtras("LDPlayer", extras);
|
||||
}
|
||||
|
||||
private static unsafe AsstTaskId AsstAppendTask(AsstHandle handle, string type, string taskParams)
|
||||
{
|
||||
fixed (byte* ptr1 = EncodeNullTerminatedUtf8(type),
|
||||
@@ -534,6 +539,20 @@ namespace MaaWpfGui.Main
|
||||
method = "MuMuExtras";
|
||||
}
|
||||
|
||||
break;
|
||||
case "LDPlayer":
|
||||
if (Instances.SettingsViewModel.LdPlayerExtras.Enable && method != "LDExtras")
|
||||
{
|
||||
Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("LdExtrasNotEnabledMessage"), UiLogColor.Error);
|
||||
Instances.CopilotViewModel.AddLog(LocalizationHelper.GetString("LdExtrasNotEnabledMessage"), UiLogColor.Error, showTime: false);
|
||||
needToStop = true;
|
||||
}
|
||||
else if (timeCost < 100)
|
||||
{
|
||||
color = UiLogColor.LdSpecialScreenshot;
|
||||
method = "LDExtras";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1766,6 +1785,9 @@ namespace MaaWpfGui.Main
|
||||
case "MuMuEmulator12":
|
||||
AsstSetConnectionExtrasMuMu12(Instances.SettingsViewModel.MuMuEmulator12Extras.Config);
|
||||
break;
|
||||
case "LDPlayer":
|
||||
AsstSetConnectionExtrasLdPlayer(Instances.SettingsViewModel.LdPlayerExtras.Config);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Instances.SettingsViewModel.AutoDetectConnection)
|
||||
|
||||
@@ -395,6 +395,22 @@ Only supports Official(CN) and Bilibili server. Login account is not supported.<
|
||||
<system:String x:Key="MuMu12Index">Instance Number</system:String>
|
||||
<system:String x:Key="MuMu12Display">Display Number</system:String>
|
||||
<system:String x:Key="MuMuExtrasNotEnabledMessage">Mumu screenshot enhancement not enabled, please check related settings</system:String>
|
||||
<system:String x:Key="LdExtrasEnabled">Enable LD's screenshot enhancement mode</system:String>
|
||||
<system:String x:Key="LdExtrasEnabledTip">
|
||||
Requires LDPlayer 9 V9.0.78 or later.\n
|
||||
It is strongly recommended to perform a screenshot test before using this feature for the first time.\n\n
|
||||
Please provide the following information:\n\n
|
||||
1. Emulator path: (e.g., C:\\leidian\\LDPlayer9)\n
|
||||
The emulator path should be the folder where the emulator application is located, for example, if the application path is\n
|
||||
"C:\\leidian\\LDPlayer9\\ldconsole.exe"\n
|
||||
You should fill in\n
|
||||
"C:\\leidian\\LDPlayer9".\n\n
|
||||
2. Instance number: (e.g., 0)\n
|
||||
The instance number can be found in the LDPlayer multi-instance manager, default is 0. If there are multiple instances, the number can be found in the ID column under Version/ID.\n
|
||||
</system:String>
|
||||
<system:String x:Key="LdEmulatorPath">LD Emulator exec path</system:String>
|
||||
<system:String x:Key="LdIndex">Instance Number</system:String>
|
||||
<system:String x:Key="LdExtrasNotEnabledMessage">LD screenshot enhancement not enabled, please check related settings</system:String>
|
||||
<system:String x:Key="RetryOnDisconnected">Retry launching the emulator when ADB connection fails</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedTip">Try restarting the emulator after 20 failed reconnect attempts, must be checked when using a background timed task and setting the task to close the emulator when finished</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedEmulatorPathEmptyError">Emulator path is empty! Please fill in "Launch Settings - Emulator Path" and reselect.</system:String>
|
||||
|
||||
@@ -395,6 +395,21 @@
|
||||
<system:String x:Key="MuMu12Index">インスタンス番号</system:String>
|
||||
<system:String x:Key="MuMu12Display">表示番号</system:String>
|
||||
<system:String x:Key="MuMuExtrasNotEnabledMessage">MuMu スクリーンショットの強化 が有効になっていません。関連する設定を確認してください</system:String>
|
||||
<system:String x:Key="LdExtrasEnabled">LD のスクリーンショット拡張モードを有効にする</system:String>
|
||||
<system:String x:Key="LdExtrasEnabledTip">
|
||||
LDPlayer 9 V9.0.78 以降のバージョンが必要です。\n
|
||||
この機能を初めて使用する前に、スクリーンショットテストを行うことを強くお勧めします。\n\n
|
||||
以下の情報を入力してください:\n\n
|
||||
1. エミュレーターのパス:(例:C:\\leidian\\LDPlayer9)\n
|
||||
エミュレーターのパスは、エミュレーターアプリケーションが存在するフォルダのパスを入力してください。例えば、アプリケーションパスが\n
|
||||
「C:\\leidian\\LDPlayer9\\ldconsole.exe」の場合、\n
|
||||
「C:\\leidian\\LDPlayer9」と入力してください。\n\n
|
||||
2. インスタンス番号:(例:0)\n
|
||||
インスタンス番号は、LDPlayerのマルチインスタンスマネージャーで確認できます。デフォルトは0です。複数のインスタンスがある場合、バージョン/番号のID列に番号が表示されます。\n
|
||||
</system:String>
|
||||
<system:String x:Key="LdEmulatorPath">LD エミュレータパス</system:String>
|
||||
<system:String x:Key="LdIndex">インスタンス番号</system:String>
|
||||
<system:String x:Key="LdExtrasNotEnabledMessage">LD スクリーンショットの強化 が有効になっていません。関連する設定を確認してください</system:String>
|
||||
<system:String x:Key="RetryOnDisconnected">ADB接続が失敗した場合、エミュレータの起動を試みる</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedTip">再接続に20回失敗した後、エミュレータを再起動してみてください,バックグラウンドのタイムドタスクを使用し、終了時にエミュレータを終了させるタスクを設定する場合は、必ずチェックを入れること</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedEmulatorPathEmptyError">エミュレータのパスが空です!「起動設定-エミュレータのパス」を入力してから再度選択してください。</system:String>
|
||||
|
||||
@@ -396,6 +396,21 @@ OF-1을 해금하지 않았다면 선택하지 말아 주세요.</system:String>
|
||||
<system:String x:Key="MuMu12Index">인스턴스 번호</system:String>
|
||||
<system:String x:Key="MuMu12Display">표시 번호</system:String>
|
||||
<system:String x:Key="MuMuExtrasNotEnabledMessage">MuMu의 스크린샷 향상가 활성화되지 않았습니다. 관련 설정을 확인하세요</system:String>
|
||||
<system:String x:Key="LdExtrasEnabled">LD 스크린샷 향상 모드 활성화</system:String>
|
||||
<system:String x:Key="LdExtrasEnabledTip">
|
||||
LDPlayer 9 V9.0.78 이상 버전이 필요합니다.\n
|
||||
이 기능을 처음 사용하기 전에 스크린샷 테스트를 수행하는 것이 좋습니다.\n\n
|
||||
다음 정보를 입력하십시오:\n\n
|
||||
1. 에뮬레이터 경로: (예: C:\\leidian\\LDPlayer9)\n
|
||||
에뮬레이터 경로는 에뮬레이터 응용 프로그램이 있는 폴더 경로여야 합니다. 예를 들어, 응용 프로그램 경로가\n
|
||||
"C:\\leidian\\LDPlayer9\\ldconsole.exe"인 경우,\n
|
||||
"C:\\leidian\\LDPlayer9"를 입력해야 합니다。\n\n
|
||||
2. 인스턴스 번호: (예: 0)\n
|
||||
인스턴스 번호는 LDPlayer 다중 인스턴스 관리자에서 확인할 수 있습니다. 기본값은 0입니다. 여러 인스턴스가 있는 경우, 버전/번호의 ID 열에서 번호를 찾을 수 있습니다。\n
|
||||
</system:String>
|
||||
<system:String x:Key="LdEmulatorPath">LD 에뮬레이터 경로</system:String>
|
||||
<system:String x:Key="LdIndex">인스턴스 번호</system:String>
|
||||
<system:String x:Key="LdExtrasNotEnabledMessage">LD 의 스크린샷 향상가 활성화되지 않았습니다. 관련 설정을 확인하세요</system:String>
|
||||
<system:String x:Key="RetryOnDisconnected">ADB 연결이 실패하면 에뮬레이터를 다시 시도합니다</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedTip">재연결을 20회 시도해도 실패하면 에뮬레이터를 다시 시작합니다. 백그라운드 예약을 사용하고 작업이 완료되면 에뮬레이터가 종료되도록 설정하려면 반드시 선택해야 합니다</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedEmulatorPathEmptyError">에뮬레이터 경로가 비어 있습니다!「연결 설정/에뮬레이터 경로」를 입력한 후 다시 선택하세요.</system:String>
|
||||
|
||||
@@ -395,6 +395,22 @@
|
||||
<system:String x:Key="MuMu12Index">实例编号</system:String>
|
||||
<system:String x:Key="MuMu12Display">屏幕编号</system:String>
|
||||
<system:String x:Key="MuMuExtrasNotEnabledMessage">Mumu 截图增强未生效,请检查相关设置</system:String>
|
||||
<system:String x:Key="LdExtrasEnabled">启用 LD 截图增强模式</system:String>
|
||||
<system:String x:Key="LdExtrasEnabledTip">
|
||||
需使用 LDPlayer 9 V9.0.78 及更新版本。\n
|
||||
强烈建议在开启本功能后的首次使用之前进行截图测试。\n\n
|
||||
请填写以下信息:\n\n
|
||||
1. 模拟器路径:(例如:C:\\leidian\\LDPlayer9)\n
|
||||
模拟器路径应填写模拟器应用所在文件夹路径,例如应用路径为\n
|
||||
「C:\\leidian\\LDPlayer9\\ldconsole.exe」\n
|
||||
应填写\n
|
||||
「C:\\leidian\\LDPlayer9」。\n\n
|
||||
2. 实例编号:(例如:0)\n
|
||||
实例编号可在 LDPlayer 多开器中查看,默认为 0,若有多开实例,编号见 版本/编号 中的 ID。\n
|
||||
</system:String>
|
||||
<system:String x:Key="LdEmulatorPath">LD 安装路径</system:String>
|
||||
<system:String x:Key="LdIndex">实例编号</system:String>
|
||||
<system:String x:Key="LdExtrasNotEnabledMessage">LD 截图增强未生效,请检查相关设置</system:String>
|
||||
<system:String x:Key="RetryOnDisconnected">ADB 连接失败时尝试启动模拟器</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedTip">重连失败 20 次后尝试重启模拟器,使用后台定时任务且设置任务完成关闭模拟器时请勾选</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedEmulatorPathEmptyError">模拟器路径为空!请填写「启动设置-模拟器路径」后重新勾选。</system:String>
|
||||
|
||||
@@ -395,6 +395,22 @@
|
||||
<system:String x:Key="MuMu12Index">實例號碼</system:String>
|
||||
<system:String x:Key="MuMu12Display">螢幕號碼</system:String>
|
||||
<system:String x:Key="MuMuExtrasNotEnabledMessage">Mumu 截圖增強未生效,请檢查相關設定</system:String>
|
||||
<system:String x:Key="LdExtrasEnabled">啟用 LD 截圖增強模式</system:String>
|
||||
<system:String x:Key="LdExtrasEnabledTip">
|
||||
需使用 LDPlayer 9 V9.0.78 及更新版本。\n
|
||||
強烈建議在開啟本功能後的首次使用之前進行截圖測試。\n\n
|
||||
請填寫以下信息:\n\n
|
||||
1. 模擬器路徑:(例如:C:\\leidian\\LDPlayer9)\n
|
||||
模擬器路徑應填寫模擬器應用所在文件夾路徑,例如應用路徑為\n
|
||||
「C:\\leidian\\LDPlayer9\\ldconsole.exe」\n
|
||||
應填寫\n
|
||||
「C:\\leidian\\LDPlayer9」。\n\n
|
||||
2. 實例編號:(例如:0)\n
|
||||
實例編號可在 LDPlayer 多開器中查看,默認為 0,若有多開實例,編號見 版本/編號 中的 ID。\n
|
||||
</system:String>
|
||||
<system:String x:Key="LdEmulatorPath">LD 模擬器路徑</system:String>
|
||||
<system:String x:Key="LdIndex">實例號碼</system:String>
|
||||
<system:String x:Key="LdExtrasNotEnabledMessage">LD 截圖增強未生效,请檢查相關設定</system:String>
|
||||
<system:String x:Key="RetryOnDisconnected">ADB 連線失敗時嘗試啟動模擬器</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedTip">重連失敗 20 次後嘗試重開模擬器,使用後台定時任務且設定任務完成關閉模擬器時必須勾選</system:String>
|
||||
<system:String x:Key="RetryOnDisconnectedEmulatorPathEmptyError">模擬器路徑為空!請填寫「啟動設定-模擬器路徑」後重新勾選。</system:String>
|
||||
|
||||
@@ -44,4 +44,5 @@
|
||||
<SolidColorBrush x:Key="RobotOperatorLogBrush" Color="Gray" />
|
||||
<SolidColorBrush x:Key="DownloadLogBrush" Color="Violet" />
|
||||
<SolidColorBrush x:Key="MuMuSpecialScreenshot" Color="#02BFFF" />
|
||||
<SolidColorBrush x:Key="LdSpecialScreenshot" Color="#6666FF" />
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -26,4 +26,5 @@
|
||||
<SolidColorBrush x:Key="RobotOperatorLogBrush" Color="DarkGray" />
|
||||
<SolidColorBrush x:Key="DownloadLogBrush" Color="BlueViolet" />
|
||||
<SolidColorBrush x:Key="MuMuSpecialScreenshot" Color="#02BFFF" />
|
||||
<SolidColorBrush x:Key="LdSpecialScreenshot" Color="#6666FF" />
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -4305,6 +4305,144 @@ namespace MaaWpfGui.ViewModels.UI
|
||||
|
||||
public MuMuEmulator12ConnectionExtras MuMuEmulator12Extras { get; set; } = new();
|
||||
|
||||
public class LdPlayerConnectionExtras : PropertyChangedBase
|
||||
{
|
||||
private bool _enable = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerExtrasEnabled, bool.FalseString));
|
||||
|
||||
public bool Enable
|
||||
{
|
||||
get => _enable;
|
||||
set
|
||||
{
|
||||
if (!SetAndNotify(ref _enable, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
MessageBoxHelper.Show(LocalizationHelper.GetString("LdExtrasEnabledTip"));
|
||||
}
|
||||
|
||||
Instances.AsstProxy.Connected = false;
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerExtrasEnabled, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerEmulatorPath, @"C:\leidian\LDPlayer9");
|
||||
private string _emulatorPath = Directory.Exists(_configuredPath) ? _configuredPath : string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the path of the emulator.
|
||||
/// </summary>
|
||||
public string EmulatorPath
|
||||
{
|
||||
get => _emulatorPath;
|
||||
set
|
||||
{
|
||||
if (_enable && !string.IsNullOrEmpty(value) && !Directory.Exists(value))
|
||||
{
|
||||
MessageBoxHelper.Show("LD Emulator Path Not Found");
|
||||
value = string.Empty;
|
||||
}
|
||||
|
||||
Instances.AsstProxy.Connected = false;
|
||||
SetAndNotify(ref _emulatorPath, value);
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerEmulatorPath, value);
|
||||
}
|
||||
}
|
||||
|
||||
private string _index = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerIndex, "0");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index of the emulator.
|
||||
/// </summary>
|
||||
public string Index
|
||||
{
|
||||
get => _index;
|
||||
set
|
||||
{
|
||||
Instances.AsstProxy.Connected = false;
|
||||
SetAndNotify(ref _index, value);
|
||||
ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetEmulatorPid(int index)
|
||||
{
|
||||
string emulatorPath = $@"{EmulatorPath}\ldconsole.exe";
|
||||
if (!File.Exists(emulatorPath))
|
||||
{
|
||||
MessageBoxHelper.Show("LD Emulator Path Not Found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = emulatorPath,
|
||||
Arguments = "list2",
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
using Process? process = Process.Start(startInfo);
|
||||
if (process == null)
|
||||
{
|
||||
_logger.Warning("Failed to start ldconsole list2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
using StreamReader reader = process.StandardOutput;
|
||||
string result = reader.ReadToEnd();
|
||||
string[] lines = result.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (lines.Length <= 0)
|
||||
{
|
||||
_logger.Warning("Failed to get emulator PID.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string[] parts = line.Split(',');
|
||||
if (parts.Length < 6 || !int.TryParse(parts[0], out int currentIndex) || currentIndex != index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (int.TryParse(parts[5], out int pid))
|
||||
{
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Warning("Failed to get emulator PID.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string Config
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Enable)
|
||||
{
|
||||
return JsonConvert.SerializeObject(new JObject());
|
||||
}
|
||||
|
||||
var configObject = new JObject
|
||||
{
|
||||
["path"] = EmulatorPath,
|
||||
["index"] = int.TryParse(Index, out var indexParse) ? indexParse : 0,
|
||||
["pid"] = GetEmulatorPid(indexParse),
|
||||
};
|
||||
return JsonConvert.SerializeObject(configObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LdPlayerConnectionExtras LdPlayerExtras { get; set; } = new();
|
||||
|
||||
private bool _retryOnDisconnected = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.RetryOnAdbDisconnected, bool.FalseString));
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center">
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<hc:TextBox
|
||||
Width="420"
|
||||
Height="30"
|
||||
@@ -120,43 +120,69 @@
|
||||
ItemsSource="{Binding ConnectConfigList}"
|
||||
SelectedValue="{Binding ConnectConfig}"
|
||||
SelectedValuePath="Value" />
|
||||
<CheckBox
|
||||
Margin="10"
|
||||
HorizontalAlignment="Center"
|
||||
Content="{DynamicResource MuMu12ExtrasEnabled}"
|
||||
IsChecked="{Binding MuMuEmulator12Extras.Enable}"
|
||||
Visibility="{c:Binding 'ConnectConfig=="MuMuEmulator12"'}" />
|
||||
<hc:TextBox
|
||||
Width="420"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="Example: C:\Program Files\Netease\MuMuPlayer-12.0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12EmulatorPath}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.EmulatorPath}"
|
||||
Visibility="{c:Binding 'MuMuEmulator12Extras.Enable and ConnectConfig=="MuMuEmulator12"'}" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Visibility="{c:Binding MuMuEmulator12Extras.Enable}">
|
||||
<hc:TextBox
|
||||
Width="130"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12Index}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.Index}"
|
||||
Visibility="{c:Binding 'ConnectConfig=="MuMuEmulator12"'}" />
|
||||
<hc:TextBox
|
||||
Width="130"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12Display}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.Display}"
|
||||
Visibility="{c:Binding 'ConnectConfig=="MuMuEmulator12"'}" />
|
||||
<StackPanel>
|
||||
<StackPanel Visibility="{c:Binding 'ConnectConfig=="MuMuEmulator12"'}">
|
||||
<CheckBox
|
||||
Margin="10"
|
||||
HorizontalAlignment="Center"
|
||||
Content="{DynamicResource MuMu12ExtrasEnabled}"
|
||||
IsChecked="{Binding MuMuEmulator12Extras.Enable}" />
|
||||
<hc:TextBox
|
||||
Width="420"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="Example: C:\Program Files\Netease\MuMuPlayer-12.0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12EmulatorPath}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.EmulatorPath}"
|
||||
Visibility="{c:Binding MuMuEmulator12Extras.Enable}" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Visibility="{c:Binding MuMuEmulator12Extras.Enable}">
|
||||
<hc:TextBox
|
||||
Width="130"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12Index}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.Index}" />
|
||||
<hc:TextBox
|
||||
Width="130"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="0"
|
||||
hc:TitleElement.Title="{DynamicResource MuMu12Display}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding MuMuEmulator12Extras.Display}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Visibility="{c:Binding 'ConnectConfig=="LDPlayer"'}">
|
||||
<CheckBox
|
||||
Margin="10"
|
||||
HorizontalAlignment="Center"
|
||||
Content="{DynamicResource LdExtrasEnabled}"
|
||||
IsChecked="{Binding LdPlayerExtras.Enable}" />
|
||||
<hc:TextBox
|
||||
Width="420"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="Example: C:\leidian\LDPlayer9"
|
||||
hc:TitleElement.Title="{DynamicResource LdEmulatorPath}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding LdPlayerExtras.EmulatorPath}"
|
||||
Visibility="{c:Binding LdPlayerExtras.Enable}" />
|
||||
<hc:TextBox
|
||||
Width="130"
|
||||
Height="30"
|
||||
Margin="10"
|
||||
hc:InfoElement.Placeholder="0"
|
||||
hc:TitleElement.Title="{DynamicResource LdIndex}"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Text="{Binding LdPlayerExtras.Index}"
|
||||
Visibility="{c:Binding LdPlayerExtras.Enable}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical">
|
||||
<Button
|
||||
@@ -172,9 +198,7 @@
|
||||
Visibility="{c:Binding 'TestLinkInfo!=""'}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Row="4"
|
||||
HorizontalAlignment="Center">
|
||||
<StackPanel Grid.Row="4" HorizontalAlignment="Center">
|
||||
<CheckBox
|
||||
Margin="20,10"
|
||||
Content="{DynamicResource RetryOnDisconnected}"
|
||||
@@ -216,8 +240,7 @@
|
||||
Content="{DynamicResource ForcedReplaceAdb}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="6">
|
||||
<StackPanel Grid.Row="6">
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<CheckBox
|
||||
Margin="20,10"
|
||||
|
||||
Reference in New Issue
Block a user