diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index b657d00..fb10c4d 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -7,8 +7,8 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run clang-format style check for C/C++/Protobuf programs. - uses: jidicula/clang-format-action@v4.14.0 + uses: jidicula/clang-format-action@v4.15.0 with: - clang-format-version: '19' + clang-format-version: '20' exclude-regex: '(qt-template|mkinstaller|grammar)' fallback-style: 'LLVM' # optional diff --git a/CMakeLists.txt b/CMakeLists.txt index 7704290..af83184 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,7 +298,11 @@ set(CLASS_SRC src/class/asconsolecompletion.h src/class/asconsolecompletion.cpp src/class/scriptsettings.h - src/class/scriptsettings.cpp) + src/class/scriptsettings.cpp + src/class/wingangel.h + src/class/wingangel.cpp + src/class/winggeneric.h + src/class/winggeneric.cpp) set(INTERNAL_PLG_SRC src/class/wingangelapi.h src/class/wingangelapi.cpp diff --git a/TestPlugin/lang/TestPlugin_zh_CN.ts b/TestPlugin/lang/TestPlugin_zh_CN.ts index 2999742..b35a3a5 100644 --- a/TestPlugin/lang/TestPlugin_zh_CN.ts +++ b/TestPlugin/lang/TestPlugin_zh_CN.ts @@ -269,60 +269,60 @@ TestPlugin - + Test 测试 - - - - + + + + TestPlugin 测试插件 - + Button - 按钮 - - + Click 点击 - + A Test Plugin for WingHexExplorer2. 一个用来测试羽云十六进制编辑器2的插件 - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + InvalidParamsCount 无效参数个数 - - + + InvalidParam 非法参数 - + AllocArrayFailed 分配数组失败 diff --git a/TestPlugin/testplugin.cpp b/TestPlugin/testplugin.cpp index adce988..378864b 100644 --- a/TestPlugin/testplugin.cpp +++ b/TestPlugin/testplugin.cpp @@ -19,6 +19,7 @@ */ #include "testplugin.h" +#include "WingPlugin/iwingangel.h" #include "testform.h" #include "testsettingpage.h" #include "testwingeditorviewwidget.h" @@ -26,6 +27,8 @@ #include #include +WING_DECLARE_STATIC_API; + // 注意:所有提供的脚本接口函数都不是线程安全的,只是测试 TestPlugin::TestPlugin() : WingHex::IWingPlugin() { @@ -36,145 +39,7 @@ TestPlugin::TestPlugin() : WingHex::IWingPlugin() { // 初始化会传递一个配置类,插件系统会统一管理放到统一的地方,使用 INI 保存 // 你可以自行管理,但不建议,统一管理方便使用者备份和转移插件配置 - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_a), - this, std::placeholders::_1); - info.ret = MetaType::Void; - _scriptInfo.insert(QStringLiteral("test_a"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_b), - this, std::placeholders::_1); - info.ret = MetaType::Void; - info.params.append(qMakePair(MetaType::String, QStringLiteral("info"))); - _scriptInfo.insert(QStringLiteral("test_b"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_c), - this, std::placeholders::_1); - info.ret = MetaType::Void; - info.params.append( - qMakePair(MetaType::Int | MetaType::Array, QStringLiteral("c"))); - _scriptInfo.insert(QStringLiteral("test_c"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_d), - this, std::placeholders::_1); - info.ret = MetaType::Void; - info.params.append(qMakePair(MetaType::Hash, QStringLiteral("d"))); - _scriptInfo.insert(QStringLiteral("test_d"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_e), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - _scriptInfo.insert(QStringLiteral("test_e"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_f), - this, std::placeholders::_1); - info.ret = MetaType::Byte | MetaType::Array; - _scriptInfo.insert(QStringLiteral("test_f"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_g), - this, std::placeholders::_1); - info.ret = MetaType::String; - _scriptInfo.insert(QStringLiteral("test_g"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = - std::bind(QOverload::of(&TestPlugin::test_h), - this, std::placeholders::_1); - info.ret = MetaType::Hash; - _scriptInfo.insert(QStringLiteral("test_h"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &TestPlugin::createTestShareMem), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - info.params.append( - qMakePair(MetaType::String, QStringLiteral("nameID"))); - _scriptInfo.insert(QStringLiteral("createTestShareMem"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &TestPlugin::destoryTestShareMem), - this, std::placeholders::_1); - info.ret = MetaType::Void; - _scriptInfo.insert(QStringLiteral("destoryTestShareMem"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &TestPlugin::printLogTestSharedMemData), - this, std::placeholders::_1); - info.ret = MetaType::Void; - _scriptInfo.insert(QStringLiteral("printLogTestSharedMemData"), info); - } - - { - _scriptUnsafe.insert(QStringLiteral("array@ colorTable()"), - std::bind(QOverload &>::of( - &TestPlugin::colorTable), - this, std::placeholders::_1)); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &TestPlugin::setPluginMetaTestEnabled), - this, std::placeholders::_1); - info.ret = MetaType::Void; - info.params.append(qMakePair(MetaType::Bool, QStringLiteral("b"))); - _scriptInfo.insert(QStringLiteral("setPluginMetaTestEnabled"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &TestPlugin::pluginMetaTestEnabled), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - _scriptInfo.insert(QStringLiteral("pluginMetaTestEnabled"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&TestPlugin::testCrash), this, - std::placeholders::_1); - info.ret = MetaType::Void; - _scriptInfo.insert(QStringLiteral("testCrash"), info); - } + WING_INIT_STATIC_API; } TestPlugin::~TestPlugin() { destoryTestShareMem(); } @@ -326,11 +191,6 @@ TestPlugin::registeredEditorViewWidgets() const { return _evws; } -QHash -TestPlugin::registeredScriptUnsafeFns() const { - return _scriptUnsafe; -} - QVariant TestPlugin::test_a(const QVariantList ¶ms) { if (!params.isEmpty()) { return getScriptCallError(-1, tr("InvalidParamsCount")); @@ -413,8 +273,7 @@ QVariant TestPlugin::test_h(const QVariantList ¶ms) { return test_h(); } -WingHex::IWingPlugin::UNSAFE_RET -TestPlugin::colorTable(const QList ¶ms) { +WingHex::UNSAFE_RET TestPlugin::colorTable(const QList ¶ms) { if (!params.isEmpty()) { return generateScriptCallError(-1, tr("InvalidParamsCount")); } @@ -427,7 +286,7 @@ TestPlugin::colorTable(const QList ¶ms) { auto invoked = invokeService(QStringLiteral("WingAngelAPI"), "vector2AsArray", - qReturnArg(array), MetaType::Color, colors); + qReturnArg(array), WingHex::MetaType::Meta_Color, colors); if (invoked) { if (array) { qDeleteAll(colors); @@ -491,6 +350,19 @@ QVariant TestPlugin::testCrash(const QVariantList ¶ms) { return {}; } +void TestPlugin::testGenericAdd(WingHex::asIWingGeneric *param) { + auto g = QScopedPointer(createParamContext(param)); + + auto arg0 = g->argDWord(0); + auto arg1 = g->argDWord(1); + + g->setReturnDWord(arg0 + arg1); +} + +void TestPlugin::testRaiseScriptException(WingHex::asIWingGeneric *) { + raiseContextException(__func__, true); +} + void TestPlugin::test_a() { logDebug(__FUNCTION__); } void TestPlugin::test_b(const QString &b) { @@ -608,15 +480,9 @@ void TestPlugin::testCrash() { abort(); } -QHash -TestPlugin::registeredScriptFns() const { - return _scriptInfo; -} - WingHex::IWingPlugin::RegisteredEvents TestPlugin::registeredEvents() const { RegisteredEvents evs; evs.setFlag(RegisteredEvent::AppReady); - evs.setFlag(RegisteredEvent::ScriptUnSafeFnRegistering); return evs; } @@ -626,3 +492,113 @@ void TestPlugin::eventReady() { Qt::AutoConnection, qReturnArg(ret), QStringLiteral(R"(print("Hello, this is TestPlugin!");)")); } + +void TestPlugin::onRegisterScriptObj(WingHex::IWingAngel *o) { + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of(&TestPlugin::test_a), + this, std::placeholders::_1), + QStringLiteral("test_a")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of(&TestPlugin::test_b), + this, std::placeholders::_1), + QStringLiteral("test_b"), + {qMakePair(WingHex::MetaType::Meta_String, QStringLiteral("info"))}); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of(&TestPlugin::test_c), + this, std::placeholders::_1), + QStringLiteral("test_c"), + {qMakePair(WingHex::MetaType::Meta_Int | WingHex::MetaType::Meta_Array, + QStringLiteral("c"))}); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of(&TestPlugin::test_d), + this, std::placeholders::_1), + QStringLiteral("test_d"), + {qMakePair(WingHex::MetaType::Meta_Hash, QStringLiteral("d"))}); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Bool, + std::bind(QOverload::of(&TestPlugin::test_e), + this, std::placeholders::_1), + QStringLiteral("test_e")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Byte | WingHex::MetaType::Meta_Array, + std::bind(QOverload::of(&TestPlugin::test_f), + this, std::placeholders::_1), + QStringLiteral("test_f")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_String, + std::bind(QOverload::of(&TestPlugin::test_g), + this, std::placeholders::_1), + QStringLiteral("test_g")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Hash, + std::bind(QOverload::of(&TestPlugin::test_h), + this, std::placeholders::_1), + QStringLiteral("test_h")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Bool, + std::bind(QOverload::of( + &TestPlugin::createTestShareMem), + this, std::placeholders::_1), + QStringLiteral("createTestShareMem"), + {qMakePair(WingHex::MetaType::Meta_String, QStringLiteral("nameID"))}); + + o->registerGlobalFunction(WingHex::MetaType::Meta_Void, + std::bind(QOverload::of( + &TestPlugin::destoryTestShareMem), + this, std::placeholders::_1), + QStringLiteral("destoryTestShareMem")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of( + &TestPlugin::printLogTestSharedMemData), + this, std::placeholders::_1), + QStringLiteral("printLogTestSharedMemData")); + + o->registerGlobalFunction( + QStringLiteral("array@ colorTable()"), + std::bind(QOverload &>::of(&TestPlugin::colorTable), + this, std::placeholders::_1)); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of( + &TestPlugin::setPluginMetaTestEnabled), + this, std::placeholders::_1), + QStringLiteral("setPluginMetaTestEnabled"), + {qMakePair(WingHex::MetaType::Meta_Bool, QStringLiteral("b"))}); + + o->registerGlobalFunction(WingHex::MetaType::Meta_Bool, + std::bind(QOverload::of( + &TestPlugin::pluginMetaTestEnabled), + this, std::placeholders::_1), + QStringLiteral("pluginMetaTestEnabled")); + + o->registerGlobalFunction( + WingHex::MetaType::Meta_Void, + std::bind(QOverload::of(&TestPlugin::testCrash), + this, std::placeholders::_1), + QStringLiteral("testCrash")); + + o->registerGlobalFunction( + "int testAdd(int a,int b)", asWINGFUNCTION(TestPlugin::testGenericAdd), + WingHex::IWingAngel::asCallConvTypes::asCALL_GENERIC); + + o->registerGlobalFunction( + "void raiseScriptException()", + asWINGFUNCTION(TestPlugin::testRaiseScriptException), + WingHex::IWingAngel::asCallConvTypes::asCALL_GENERIC); +} diff --git a/TestPlugin/testplugin.h b/TestPlugin/testplugin.h index 8afad84..6d3818f 100644 --- a/TestPlugin/testplugin.h +++ b/TestPlugin/testplugin.h @@ -60,14 +60,14 @@ public: registeredSettingPages() const override; virtual QList> registeredEditorViewWidgets() const override; - virtual QHash registeredScriptFns() const override; - - virtual QHash - registeredScriptUnsafeFns() const override; virtual RegisteredEvents registeredEvents() const override; virtual void eventReady() override; + // IWingPluginCoreBase interface +public: + virtual void onRegisterScriptObj(WingHex::IWingAngel *o) override; + private: QVariant test_a(const QVariantList ¶ms); QVariant test_b(const QVariantList ¶ms); @@ -79,7 +79,7 @@ private: QVariant test_g(const QVariantList ¶ms); QVariant test_h(const QVariantList ¶ms); - UNSAFE_RET colorTable(const QList ¶ms); + WingHex::UNSAFE_RET colorTable(const QList ¶ms); QVariant createTestShareMem(const QVariantList ¶ms); QVariant destoryTestShareMem(const QVariantList ¶ms); @@ -90,6 +90,10 @@ private: QVariant testCrash(const QVariantList ¶ms); + static void testGenericAdd(WingHex::asIWingGeneric *param); + + static void testRaiseScriptException(WingHex::asIWingGeneric *); + private: void test_a(); void test_b(const QString &b); @@ -119,13 +123,10 @@ private: bool ENABLE_META = false; - QHash _scriptInfo; QList _winfo; QList _rtbinfo; QList _setpages; QList> _evws; - - QHash _scriptUnsafe; }; #endif // TESTPLUGIN_H diff --git a/WingPlugin b/WingPlugin index ec5bcd4..cdaf256 160000 --- a/WingPlugin +++ b/WingPlugin @@ -1 +1 @@ -Subproject commit ec5bcd41309e175aa262f367011c1ad9fe7e9b31 +Subproject commit cdaf256c8a44e724cc295e5b23cc291ac2414c02 diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index 8b3e057..2ee3284 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -847,18 +847,18 @@ MainWindow - + File 文件 - - + + View 视图 - + About 关于 @@ -879,322 +879,322 @@ 选长: - + Edit 编辑 - + Script 脚本 - - - + + + Plugin 插件 - + Setting 设置 - - + + Log 日志 - + ExportFindResult 导出搜索结果 - + ClearFindResult 清空记录 - - + + FindResult 搜索结果 - - - - - - - + + + + + + + Copy 复制 - - - - - + + + + + CopyToClipBoard 数据已拷贝到粘贴板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 数值 - - + + CheckSum 校验和 - - + + DeleteBookMark 删除书签 - - + + ClearBookMark 清空书签 - - - - + + + + BookMark 书签 - - + + DecodeText 解码字符串 - + ScriptConsole 脚本控制台 - - + + Basic 基础 - + New 新建 - + OpenF 打开文件 - + OpenWorkSpace 打开工作区 - + RecentFiles 最近打开 - - - + + + Reload 重新加载 - - + + Save 保存 - + SaveAs 另存为 - + ConvertWS 转为工作区 - + Export 导出 - + SaveSel 保存选区字节 - - - - + + + + General 基本 - + Undo 撤销 - + Redo 恢复 - + Cut 剪切 - + Paste 粘贴 - + Delete 删除 - + Clone 克隆 - + Lookup 查询 - + Find 查找 - + Goto 跳转 - - + + Encoding 编码 - + FileInfo 文件信息 - - + + Hex 十六进制 - + CutHex 剪切(十六进制) - + CopyHex 复制(十六进制) - + PasteHex 粘贴(十六进制) - - + + Fill 填充 - + FillZero 填充零 - - - - + + + + MetaData 标注 - + DeleteMetadata 删除标注 - + ClearMetadata 清空标注 - + MetaDataEdit 编辑标注 - + DeleteMetaData 删除标注 - + ClearMetaData 清空标注 - + Display 显示 - + ViewText 文本预览 - + Scale 缩放 @@ -1229,832 +1229,837 @@ 加载插件中: - + SetupConsole 启动脚本控制台 - + SetupScriptManager 启动脚本管理器 - + SetupScriptService 启动脚本服务 - + SetupScriptEditor 构建脚本编辑器 - + SetupSetDialog 构建设置窗体 - + SetupPlgWidgets 启动插件组件 - + SetupDockingLayout 恢复 Dock 布局 - + SetupWaiting 启动即将完成 - + SetupFinished 启动完毕 - + NoExtension 无扩展 - - + + ExportResult 导出结果 - + NothingToSave 没有保存的数据 - + OpenExt 打开 - 拓展 - + ResetScale 重置缩放 - + ShowMetafg 标注前景色 - + ShowMetabg 标注背景色 - + ShowMetaComment 批注 - + MetaShowAll 显示所有标注 - + MetaHideAll 隐藏所有标注 - + FileStatus 文件状态 - + InfoSave 是否保存 - + ReadOnly 可读写 - + SetLocked 启用/禁用锁定编辑 - + ErrUnLock 锁定编辑失败 - + SetOver 启用/禁用改变大小 - + InputRequest 输入请求 - + ScriptEngineInitFailed 脚本引擎启动失败,将自动禁用该功能。 - + UnsignedHex 无符号 Hex - + BgScriptOutputHere 后台脚本执行将会在这里输出 - + SelectAll 全选 - - + + Clear 清空 - + AbortScript 终止脚本 - + BgScriptOutput 后台脚本输出 - + ErrUnOver 锁定文件大小失败 - + Window 窗体 - + Editor 编辑器 - + Tools 工具 - + HexEditorLayout 编辑器布局 - + SetBaseAddr 设置基址 - + addressBase 基址 - + inputAddressBase 请输入基址 - + WarnBigBaseAddress 基址过大,你得到的地址将会不正确! - + ErrBaseAddress 非法基址输入 - + SetColInfo 显示/隐藏地址栏 - + SetHeaderInfo 显示/隐藏表头 - + SetAsciiString 显示/隐藏解码字符串 - + Layout 布局 - + Fullscreen 全屏 - + Default 默认 - - - + + + LayoutRestoring... 恢复布局中... - + RestoreLayout 恢复布局 - - + + SaveLayout 保存布局 - - + + ExportLog 导出日志 - - + + ClearLog 清空日志 - + InsepctQt 监视 Qt - + ScriptEditor 脚本编辑器 - + Scripts 脚本仓库 - + PluginFunctions 插件功能 - + ScriptSetting 脚本设置 - + PluginSettings 插件设置 - + Info 信息 - + Software 软件 - + Sponsor 赞助 - + CheckUpdate 检查更新 - + Wiki 网页 Wiki - + + EngineConfigError + + + + AboutQT 关于 QT - + SetPageIDEmptyTryUseName 设置页 ID 为空,尝试使用名称作为 ID - + SetPageDupNameIgnored 设置页重复的 ID 名称,已忽略加载 - + Plugin %1 contains a duplicate ID (%2) that is already registered by plugin %3 插件 %1 包含重复 ID (%2),该 ID 已被插件 %3 注册 - - + + ChooseFile 选择文件 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 错误 - - + + FileNotExist 文件不存在! - - - - - + + + + + FilePermission 因文件权限无法继续! - + ProjectFile (*.wingpro) 项目文件 (*.wingpro) - + ReloadSuccessfully 文件重新加载成功! - + ReloadUnSuccessfully 文件重新加载失败! - - - - + + + + ChooseSaveFile 请选择保存文件路径: - + PasteFailedNote 粘贴失败,请注意权限或者内容长度 - + NoMoreClone 克隆已到上限,无法继续操作! - + FindFininishBusy 查找任务繁忙,请勿重复查找! - + MayTooMuchFindResult 搜索数量已到达上限,结果可能不全,建议请按区段搜索。 - + SaveLayoutSuccess 保存布局成功 - + SaveLayoutError 保存布局失败 - + HasClonedView 该编辑页已被克隆编辑,如果关闭,相关联的页也会被关闭,你确认继续吗? - + FileCloseBigFile 大文件读取模式下目标文件被关闭,该标签将会被关闭。 - - + + ReloadNeededYesOrNo 目标文件被修改,是否重新加载? - + SaveWorkSpace 保存工作区 - + WingHexWorkSpace (*.wingpro) 羽云十六进制工作区 (*.wingpro) - + ConfirmSave 正在关闭未保存的文件或工作区,你确定保存吗? - + [Info] 【信息】 - + [Warn] 【警告】 - + [Error] 【错误】 - + ConfirmAPPSave 你尝试关闭程序,但仍存在未保存的文件或工作区,你确定保存这些更改吗? - - - + + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作区错误! - - + + Warn 警告 - + Opening... 打开文件中... - + WorkSpaceOpening... 打开工作区中... - + Reloading... 重载文件中... - + Saving... 保存中... - + SaveNewFirst 请首先保存新建的文件 - + AlreadyWorkSpace 已经是工作区,无需转化 - + ConvWorkSpaceFailed 转化为工作区失败 - + ConvWorkSpaceSuccess 转化为工作区成功 - + SavingAs... 另存为中... - + SaveUnSuccessfully 保存失败! - + Exporting... 导出中... - + ChooseExportFile 请选择导出文件路径: - + ExportSuccessfully 导出成功! - + ExportUnSuccessfully 导出失败! - + SavingSel... 保存选中字节中... - + SaveSelSuccess 保存选区字节成功! - + SaveSelError 保存选区字节失败,因文件不具有可写权限! - - + + CutToClipBoard 数据已剪切到粘贴板! - - + + UnCutToClipBoard 由于保持大小限制,数据剪切到粘贴板失败! - - + + UnCopyToClipBoard 由于保持大小限制,数据剪切到复制板失败! - - + + Finding... 查找中... - + DeleteSuccess 删除成功 - + DeleteFailed 删除失败 - + FindFininish 查找结果完毕! - + PleaseInputFill 请输入填充字节值 - + FillInputTruncWarn 填充输入数值过大,将会被截断填充 - + FillInputError 填充字节输入错误 - - + + InputComment 请输入批注: - - + + BookmarkDelSuccess 删除书签成功 - + BookmarkDelNoItem 无书签可删除 - + BookmarkClearSuccess 书签清空完毕 - - - + + + NoSelection 没有选区,无法继续的操作! - + NoMetaData 无可编辑标记 - + PleaseClearSel 请清空选择 - + MetaDelSuccess 元数据删除成功 - + MetaDelNoItem 无元数据可删除 - + MetaClearSuccess 元数据清空完毕 - + FindResultExporting... 查找结果导出中... - - + + EmptyFindResult 没有可导出的搜索结果! - + SaveFindResult 导出搜索结果成功! - + SaveFindResultError 导出结果失败! - + TooManyBytesDecode 超出解码字节限制…… - + NoTextFileMayInvalid 该文件不是文本文件,以文本方式预览并不是一个好的方式,你确认继续吗? - + LayoutSaving... 布局保存中... - - + + PleaseInput 请输入 - + LogExporting... 日志导出中... - + ExportLogError 导出日志失败! - + ExportLogSuccess 导出日志成功,路径: - + ClearLogSuccess 清空日志成功! - + BadNetwork 无法与远程服务器的更新检查建立连接,请检查网络。 - + NewestVersion 当前软件为最新版本 - - + + OlderVersion 你使用的软件为老版本,建议到 Github 和 Gitee 的仓库发行版下载更新。 - + CheckingUpdate 检查更新中…… - + Too much opened files 打开的文件过多,无法继续操作! - + FilePermissionSure2Quit 因文件权限无法保存,你确认要退出吗? - + UnknownErrorSure2Quit 因未知错误无法保存,你确认要退出吗? - + WorkSpaceUnSavedSure2Quit 工作区文件无法保存,你确认要退出吗? - + CopyLimit 拷贝字节超出限制 - + ErrOpenFileBelow 打开文件出现错误(由于权限不足),如下为打开错误的文件: @@ -2302,205 +2307,173 @@ PluginSystem - + LoadingPlugin 加载插件中: - - + + InvalidPluginBrokenInfo 加载插件失败:损坏的插件数据 - - + + PluginBlockByManager - + AppClosingCanceled: 程序关闭被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 总计发现设备拓展插件数目: - + PluginManagerNeedSingleton - - RegisterScriptFnUnSupportedTypes: - 因脚本函数含有未支持的类型而注册失败: - - - - - RegisterScriptFnInvalidSig: - 因脚本函数签名非法而注册失败: - - - - - RegisterScriptFnConflitSig: - 因脚本函数签名冲突而注册失败: - - - - InvalidEnumName: - 非法枚举名: - - - - InvalidEnumValue: - 非法枚举值: - - - - InvalidMarcosRegister: - 非法宏注册: - - - - + + ErrLoadPluginSDKVersion 插件加载失败:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加载失败:非法插件名称! - - + + ErrLoadInitPlugin 插件加载失败:初始化插件失败! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 注册插件对象中…… - + ExtPluginAuthor : 设备拓展插件作者: - + ExtPluginWidgetRegister 设备拓展注册插件对象中…… - + ErrLoadInitExtPlugin 设备拓展插件加载失败:初始化插件失败! - + ChooseFile 选择文件 - - + + Error 错误 - + FileNotExist 文件不存在! - + FilePermission 因文件权限无法继续! - + EmptyNameDockWidget: 空的贴边组件名: - + InvalidNameDockWidget: 无效贴边组件名: - + InvalidNullDockWidget: 无效空贴边组件: - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 - + UnsafePluginDir 不安全的插件目录,请将插件目录设置为仅管理员账户可写 - - + + InvalidPluginID 加载插件失败:非法插件标识符 - + InvalidDupPlugin 加载插件失败:重复的插件标识符 - + FoundPluginCount 总计发现插件数目: - + PluginLoadingFailedSummary 有依赖插件加载失败总结 - + - Dependencies: - 依赖: - + PUID: 插件唯一标志符: - + Version: 版本: - + PluginLoadingFinished 加载插件完毕! @@ -2848,1597 +2821,1597 @@ ScriptMachine - + AngelScript callstack: AngelScript 调用堆栈: - + - Exception '%1' in '%2' — 在 ‘%2’ 中发生异常 ‘%1’ - + ExecNotAllowedInRoot 在管理员权限执行第三方命令为非法操作 - - + + Code must be exec in the main thread 脚本代码必须在主线程执行 - + Script failed to pre-processed 脚本代码预处理失败 - - - + + + Script failed to build 脚本编译失败 - + Cannot find 'int main()' or 'void main()' 无法找到程序入口点: "int main()" 或者 "void main()" - + Debugging, waiting for commands. 调试中,等待调试命令。 - + Failed while initializing global variables 初始化全局变量失败 - + Run: 执行脚本: - - + + The script failed with an exception 异常被抛出,脚本执行失败 - - + + The script was aborted 脚本被终止 - - + + The script terminated unexpectedly 脚本异常退出 - + The script exited with 脚本退出返回值: - + '%1' is already declared "%1" 已被声明 - + Abstract class '%1' cannot be instantiated 无法实例化抽象类 "%1" - + Accessing private property '%1' of parent class 非法访问父类的私有属性 "%1" - + Attribute '%1' informed multiple times 属性 "%1" 已被多次通知 - + Can't form arrays of subtype '%1' 无法创建子类型 "%1" 的数组 - + Can't inherit from class '%1' marked as final 无法从标记为 final 的类 "%1" 继承 - + Cannot access non-static member '%1' like this 无法和像使用 this 一样访问非静态成员 "%1" - + Can't construct handle '%1'. Use ref cast instead 无法构造句柄 "%1" 。请改用引用强制转换 - + Can't implicitly convert from '%1' to '%2'. 无法从 "%1' 隐式转换为 "%2"。 - + Compiling %1 正在编译 %1 - + Compiling auto generated %1 编译自动生成的 %1 - + Implemented property accessor '%1' does not expect index argument 已实现的属性访问器 "%1" 不需要索引参数 - + Implemented property accessor '%1' expects index argument 已实现的属性访问器 "%1" 需要索引参数 - + Data type can't be '%1' 数据类型不能为 "%1" - + All subsequent parameters after the first default value must have default values in function '%1' 在函数 "%1" 中,第一个默认值之后的所有后续参数都必须具有默认值 - + The method in the derived class must have the same return type as in the base class: '%1' 派生类中的方法必须具有与基类相同的返回类型:"%1" - + The name of the destructor '%1::~%2' must be the same as the class 析构函数 "%1::~%2" 的名称必须与类相同 - + Expected '%1' 应为 "%1" - + Expected '%1' or '%2' 应为 ”%1“ 或 ”%2“ - + Expression must be of boolean type, instead found '%1' 表达式必须是布尔类型,但实际使用的是 "%1" - + Expression '%1' is a data type 表达式 "%1" 是一种数据类型 - + External shared entity '%1' not found 未找到外部共享实体 "%1" - + External shared entity '%1' cannot redefine the original entity 外部共享实体 "%1" 无法重新定义原始实体 - + Failed while compiling default arg for parameter %1 in function '%2' 为函数 "%2" 中的参数 %1 编译默认参数时失败 - + Function '%1' not found 未找到函数 "%1" - + The property '%1' has mismatching types for the get and set accessors 属性 "%1" 的 get 和 set 访问器类型不匹配 - + Variable '%1' hides another variable of same name in outer scope 变量 "%1" 隐藏了外部作用域中另一个同名变量 - + Identifier '%1' is not a data type 标识符 "%1" 不是数据类型 - + Identifier '%1' is not a data type in global namespace 标识符 "%1" 不是全局命名空间中的数据类型 - + Identifier '%1' is not a data type in namespace '%2' or parent 标识符 "%1" 不是命名空间 "%2" 或其父级中的数据类型 - + Illegal operation on '%1' 对 "%1" 的非法操作 - + Illegal variable name '%1'. 非法变量名 "%1"。 - + Illegal access to inherited private property '%1' 非法访问继承的私有属性 "%1" - + Initialization lists cannot be used with '%1' 初始化列表不能与 "%1" 一起使用 - + Attempting to instantiate invalid template type '%1<%2>' 尝试实例化无效的模板类型 "%1<%2>" - + Instead found '%1' 而是找到了 "%1" - + Instead found identifier '%1' 而是找到标识符 "%1" - + Instead found reserved keyword '%1' 而是找到了保留关键字 "%1" - + Interface '%1' cannot be instantiated 无法实例化接口 "%1" - + Invalid unicode escape sequence, expected %1 hex digits 无效的 Unicode 转义序列,预期为 %1 个十六进制数字 - + Method '%1' declared as final and cannot be overridden 方法 "%1" 已声明为 final,因此无法被覆盖 - + Method '%1' marked as override but does not replace any base class or interface method 方法 "%1" 标记为覆盖,但并未替换任何基类或接口方法 - + Method '%1::%2' is missing the return type, nor is it the same name as object to be a constructor 方法 "%1::%2" 缺少返回类型,并且其名称与构造函数对象不同 - + Method '%1' is not part of object '%2' 方法 "%1" 不是对象 "%2" 的一部分 - + Missing implementation of '%1' 缺少 "%1" 的实现 - + Missing definition of '%1' 缺少 "%1" 的定义 - + Mixin class cannot be declared as '%1' Mixin 类不能声明为 "%1" - + Multiple matching signatures to '%1' "%1" 有多个匹配的签名 - + Found multiple get accessors for property '%1' 发现属性 "%1" 的多个 get 访问器 - + Found multiple set accessors for property '%1' 发现属性 "%1" 的多个集合访问器 - + Namespace '%1' doesn't exist. 命名空间 "%1" 不存在。 - - - - - - - - - - - - + + + + + + + + + + + + Name conflict. 名称冲突。 - + '%1' is an extended data type. "%1" 是扩展数据类型。 - + '%1' is a global property. "%1" 是全局属性。 - + '%1' is a named type. "%1" 是被命名的类型。 - + '%1' is a funcdef. "%1" 是一个函数签名定义。 - + '%1' is a global function. "%1" 是一个全局函数。 - + '%1' is a mixin class. "%1" 是一个 Mixin 类。 - + '%1' is a virtual property. "%1" 是虚拟属性。 - + '%1' is a class. "%1" 是一个类。 - + '%1' is an interface. "%1" 是一个接口。 - + '%1' is an object property. "%1" 是一个对象属性。 - + '%1' is a class method. "%1" 是一个类方法。 - + '%1' is already used. ”%1“ 已被使用。 - + No appropriate opHndlAssign method found in '%1' for handle assignment 在 "%1" 中未找到适当的 opHndlAssign 方法用于句柄分配 - + No conversion from '%1' to '%2' available. 无法进行从 "%1" 到 "%2" 的转换。 - + No conversion from '%1' to math type available. 无法将 "%1" 转换为数学类型。 - + No default constructor for object of type '%1'. "%1" 类型对象没有默认构造函数。 - + No appropriate opAssign method found in '%1' for value assignment 在 "%1" 中未找到适合赋值的 opAssign 方法 - + No copy constructor for object of type '%1'. 没有 "%1" 类型对象的复制构造函数。 - + No matching signatures to '%1' 没有与 "%1" 匹配的签名 - + No matching operator that takes the type '%1' found 未找到采用类型 "%1" 的匹配运算符 - + No matching operator that takes the types '%1' and '%2' found 未找到采用类型 "%1" 和 "%2" 的匹配运算符 - + No matching symbol '%1' 没有匹配的符号 "%1" - + Expression doesn't form a function call. '%1' evaluates to the non-function type '%2' 表达式不构成函数调用。"%1" 计算结果为非函数类型 "%2" - + '%1' is not declared "%1" 未被声明 - + '%1' is not initialized. ”%1“ 未初始化。 - + '%1' is not a member of '%2' ”%1“ 不是 ”%2“ 的成员 - + Type '%1' doesn't support the indexing operator 类型 "%1" 不支持索引运算符 - + Parameter type can't be '%1', because the type cannot be instantiated. 参数类型不能是 "%1",因为该类型无法实例化。 - + Previous error occurred while attempting to compile initialization list for type '%1' 尝试编译类型 "%1" 的初始化列表时发生先前的错误 - + Illegal call to private method '%1' 非法调用私有方法 "%1" - + Illegal access to private property '%1' 非法访问私有属性 "%1" - + Illegal call to protected method '%1' 非法调用受保护的方法 "%1" - + Illegal access to protected property '%1' 非法访问受保护的属性 "%1" - + Return type can't be '%1' 返回类型不能是 "%1" - + Shared code cannot access non-shared global variable '%1' 共享代码无法访问非共享全局变量 "%1" - + Shared code cannot call non-shared function '%1' 共享代码无法调用非共享函数 "%1" - + Shared type cannot implement non-shared interface '%1' 共享类型无法实现非共享接口 "%1" - + Shared class cannot inherit from non-shared class '%1' 共享类不能从非共享类 "%1" 继承 - + Shared code cannot use non-shared type '%1' 共享代码不能使用非共享类型 "%1" - + Shared type '%1' doesn't match the original declaration in other module 共享类型 "%1" 与其他模块中的原始声明不匹配 - + Template '%1' expects %2 sub type(s) 模板 "%1" 需要 %2 个子类型 - + Type '%1' cannot be a reference 类型 "%1" 不能是引用 - + Type '%1' is not available for this module 类型 "%1" 不适用于此模块 - + Type '%1' is not a template type 类型 "%1" 不是模板类型 - + Unexpected token '%1' 意外标记 "%1" - + Use of uninitialized global variable '%1'. 使用未初始化的全局变量 "%1"。 - + Unknown scope '%1' 未知作用域 "%1" - + Where '%1' is '%2' 其中 "%1" 是 "%2" - + Failed to initialize global variable '%1' 无法初始化全局变量 "%1" - + Exception '%1' in '%2' "%2" 中的异常 "%1" - + Type '%1' is missing behaviours 类型 "%1" 缺少的行为 - + Can't pass type '%1' by value unless the application type is informed in the registration 除非在注册时告知应用程序类型,否则无法按值传递类型 "%1" - + Can't return type '%1' by value unless the application type is informed in the registration 除非在注册时告知应用程序类型,否则无法按值返回类型 "%1" - + Don't support passing type '%1' by value to application in native calling convention on this platform 不支持在此平台上按照本机调用约定将类型 "%1" 按值传递给应用程序 - + Don't support returning type '%1' by value from application in native calling convention on this platform 不支持在此平台上按照本机调用约定从应用程序返回类型 "%1" 的值 - + Object {%1}. GC cannot destroy an object of type '%2' as it doesn't know how many references to there are. 对象 {%1}。GC 无法销毁类型为 "%2" 的对象,因为它不知道有多少个引用。 - + Object {%1}. GC cannot destroy an object of type '%2' as it can't see all references. Current ref count is %3. 对象 {%1}。GC 无法销毁类型为 "%2" 的对象,因为它无法看到所有引用。当前引用计数为 %3。 - + Object type '%1' doesn't exist 对象类型 "%1" 不存在 - + Cannot register. The template type instance '%1' has already been generated. 无法注册。模板类型实例 "%1" 已生成。 - + Template type '%1' doesn't exist 模板类型 "%1" 不存在 - + Template subtype '%1' doesn't exist 模板子类型 "%1" 不存在 - + Failed to read subtype of template type '%1' 无法读取模板类型 "%1" 的子类型 - + Failed in call to function '%1' (Code: %2, %3) 调用函数 "%1" 失败(代码:%2,%3) - + Failed in call to function '%1' with '%2' (Code: %3, %4) 使用 "%2" 调用函数 "%1" 失败(代码:%3,%4) - + Failed in call to function '%1' with '%2' and '%3' (Code: %4, %5) 使用 "%2" 和 "%3" 调用函数 "%1" 失败(代码:%4,%5) - + Type '%1' is still used by function '%2' 类型 "%1" 仍被函数 "%2" 使用 - + The builtin type in previous message is named '%1' 上一条消息中的内置类型名为 "%1" - + The function in previous message is named '%1'. The func type is %2 上一条消息中的函数名为 "%1"。函数类型为 %2 - + The script object of type '%1' is being resurrected illegally during destruction 类型为 "%1" 的脚本对象在销毁过程中被非法复活 - + LoadByteCode failed. The bytecode is invalid. Number of bytes read from stream: %1 LoadByteCode 失败。字节码无效。从流中读取的字节数:%1 - + Function '%1' appears to have been compiled without JIT entry points 函数 "%1" 似乎已在无 JIT 入口点的情况下进行编译 - + There is an external reference to an object in module '%1', preventing it from being deleted 存在对模块 "%1" 中对象的外部引用,导致无法删除该对象 - + Output argument expression is not assignable 输出参数表达式不可分配 - + Auto is not allowed here 这里禁止使用 auto 关键字 - + Can't find unambiguous implicit conversion to make both expressions have the same type 无法找到明确的隐式转换来使两个表达式具有相同的类型 - + Both conditions must call constructor 两个条件都必须调用构造函数 - + Base class doesn't have default constructor. Make explicit call to base constructor 基类没有默认构造函数。明确调用基类构造函数 - + Base class doesn't have copy constructor or default constructor and assign operator. Make explicit call to base constructor 基类没有复制构造函数或默认构造函数和赋值运算符。明确调用基类构造函数 - + Candidates are: 候选包括: - + Can't call a constructor in loops 无法在循环中调用构造函数 - + Can't call a constructor in switch 无法在 switch 中调用构造函数 - + Can't call a constructor multiple times 无法多次调用构造函数 - + Can't create delegate 无法创建委托 - + Can't create delegate for types that do not support handles 无法为不支持句柄的类型创建委托 - + Cannot flag function that will not be auto generated as deleted 无法将不会自动生成的函数标记为已删除 - + Conflict with explicit declaration of function and deleted function 与函数的显式声明和已删除函数冲突 - + Can't implement itself, or another interface that implements this interface 无法实现自身,也无法实现此接口的其他接口 - + Can't inherit from multiple classes 不能从多个类继承 - + Can't inherit from itself, or another class that inherits from this class 不能从其自身或从该类继承的其他类继承 - + Can't pass class method as arg directly. Use a delegate object instead 无法直接将类方法作为参数传递。请改用委托对象 - + Unable to resolve auto type 无法解析自动类型 - + Can't return reference to local value. 无法返回对本地值的引用。 - + Can't return value when return type is 'void' 返回类型为 "void" 时无法返回值 - + Implicit conversion changed sign of value 隐式转换改变了值的符号 - + A class cannot be both abstract and final 一个类不能同时是 abstract 和 final - + Compound assignments with property accessors on value types are not supported 不支持对值类型使用属性访问器的复合赋值 - + Compound assignments with indexed property accessors are not supported 不支持使用索引属性访问器的复合赋值 - + Compound assignments with property accessors require both get and set accessors 具有属性访问器的复合赋值需要 get 和 set 访问器 - + Variables cannot be declared in switch cases, except inside statement blocks 变量不能在 switch 语句中声明,除非在语句块内 - + The default case must be the last one default 情况必须是最后一个 - + The type of the default argument expression doesn't match the function parameter type 默认参数表达式的类型与函数参数类型不匹配 - + Deleted functions cannot have implementation 已删除的函数不能有实现 - + The destructor must not have any parameters 析构函数不能有任何参数 - + Value assignment on reference types is not allowed. Did you mean to do a handle assignment? 不允许对引用类型进行值分配。是要进行句柄分配吗? - + Compound assignment on reference types is not allowed 不允许对引用类型进行复合赋值 - + Duplicate named argument 重复命名参数 - + Duplicate switch case 重复的 switch case - + Else with empty statement else 中使用空语句 - + Empty list element is not allowed 不允许空列表元素 - + Empty switch statement 空的 switch 语句 - + Expected constant 应为常量 - + Expected data type 应为数据类型 - + Expected expression value 应为表达值 - + Expected identifier 应为标识符 - + Expected a list enclosed by { } to match pattern 应为用 { } 括起来的列表与模式匹配 - + Expected method or property 应为方法或属性 - + Expected one of: 应为为以下之一: - + Expected operator 应为操作符 - + Expected post operator 应为右操作符 - + Expected pre operator 应为左操作符 - + Expected string 应为字符串 - + Expression doesn't evaluate to a function 表达式无法计算函数值 - + Previous error occurred while attempting to create a temporary copy of object 尝试创建对象的临时副本时发生上一个错误 - + Float value truncated in implicit conversion to integer 浮点值在隐式转换为整数时被截断 - + Found multiple matching enum values 找到多个匹配的枚举值 - + A function with the same name and parameters already exists 具有相同名称和参数的函数已存在 - + Global variables have been disabled by the application 全局变量已被应用程序禁用 - + It is not allowed to perform a handle assignment on a non-handle property 不允许对非句柄属性执行句柄分配 - + The operand is implicitly converted to handle in order to compare them 操作数被隐式转换为句柄,以便进行比较 - + Handle to handle is not allowed 不允许使用句柄 - + If with empty statement 如果带有空语句 - + Illegal member type 非法成员类型 - + Illegal operation on this datatype 对该数据类型的非法操作 - + Illegal target type for reference cast 非法引用转换的目标类型 - + Interfaces can only implement other interfaces 接口只能实现其他接口 - + Invalid 'break' 无效的 break 关键字 - + Invalid character literal 无效的字符 - + Invalid 'continue' 无效的 continue 关键字 - + Invalid escape sequence 无效的转义序列 - + Invalid expression: ambiguous name 无效表达式:二义性名称 - + Invalid expression: stand-alone anonymous function 无效表达式:独立匿名函数 - + Invalid operation on method 方法操作无效 - + Invalid reference. Property accessors cannot be used in combined read/write operations 引用无效。属性访问器不能用于组合读/写操作。 - + Invalid scope resolution 范围解析无效 - + Invalid signature for virtual property 虚拟属性签名无效 - + Invalid type 类型无效 - + Invalid unicode code point 无效的 Unicode 代码点 - + Invalid unicode sequence in source 源代码中的 Unicode 序列无效 - + Invalid use of named arguments 命名参数的使用无效 - + The method cannot be named with the class name 该方法不能以类名命名 - + Mixin classes cannot have constructors or destructors Mixin 类不能有构造函数或析构函数 - + Mixin class cannot inherit from classes Mixin 类不能从类继承 - + Mixin classes cannot have child types Mixin 类不能有子类型 - + Found more than one matching operator 找到多个匹配的运算符 - + Multiline strings are not allowed in this application 此应用程序不允许使用多行字符串 - + Only objects have constructors 只有对象才有构造函数 - + Must return a value 必须返回一个值 - + Detected named argument with old syntax 检测到具有旧语法的命名参数 - + No appropriate indexing operator found 未找到合适的索引运算符 - + No appropriate opEquals method found 未找到合适的 opEquals 方法 - + The application doesn't support the default array type. 该应用程序不支持默认数组类型。 - + Non-const method call on read-only object reference 只读对象引用上的非常量方法调用 - + Non-terminated string literal 未终止的字符串 - + Not all paths return a value 并非所有路径都会返回值 - + Not enough values to match pattern 没有足够的值来模式匹配 - + Implicit conversion of value is not exact 值的隐式转换并不准确 - + Expression is not an l-value 表达式不是左值 - + Not a valid reference 无效引用 - + Not a valid lvalue 不是有效的左值 - + Nothing was built in the module 模块中没有构建任何内容 - + Object handle is not supported for this type 此类型不支持对象句柄 - + Only object types that support object handles can use &inout. Use &in or &out instead 只有支持对象句柄的对象类型才能使用 &inout。请改用 &in 或 &out - + A cast operator has one argument 强制类型转换运算符有一个参数 - + The code must contain one and only one function 代码必须包含一个且只能包含一个函数 - + The code must contain one and only one global variable 代码必须包含一个且只能有一个全局变量 - + Both operands must be handles when comparing identity 比较时,两个操作数都必须是句柄 - + The overloaded functions are identical on initial parameters without default arguments 重载函数在初始参数上相同,没有默认参数 - + Parameter already declared 参数已声明 - + Positional arguments cannot be passed after named arguments 位置参数不能在命名参数之后传递 - + Potentially matching non-const method is hidden on read-only object reference 可能匹配的非 const 方法隐藏在只读对象引用中 - + Property accessor with index must have 1 and only 1 index argument 带索引的属性访问器必须有 1 个且只能有 1 个索引参数 - + Property accessors have been disabled by the application 应用程序已禁用属性访问器 - + Property accessor must be implemented 必须实现属性访问器 - + Class properties cannot be declared as const 类属性不能声明为 const - + The property has no get accessor 该属性没有 get 访问器 - + The property has no set accessor 该属性没有设置访问器 - + Virtual property must have at least one get or set accessor 虚拟属性必须至少有一个 get 或 set 访问器 - + Resulting reference cannot be returned. Returned references must not refer to local variables. 无法返回结果引用。返回的引用不得引用局部变量。 - + Resulting reference cannot be returned. There are deferred arguments that may invalidate it. 无法返回结果引用。存在可能使其无效的延迟参数。 - + Resulting reference cannot be returned. The expression uses objects that during cleanup may invalidate it. 无法返回结果引用。表达式使用的对象在清理过程中可能会使其失效。 - + Reference is read-only 引用是只读的 - + Reference is temporary 参考是临时的 - + Reference types cannot be passed by value in function parameters 引用类型不能在函数参数中按值传递 - + Reference types cannot be returned by value from functions 引用类型不能通过函数返回值 - + The script section is empty 脚本节区为空 - + Signed/Unsigned mismatch 有符号/无符号不匹配 - + Strings are not recognized by the application 应用程序无法识别字符串 - + Case expressions must be literal constants case 表达式必须是文字常量 - + Switch expressions must be integral numbers switch 表达式必须是整数 - + The function has too many jump labels to handle. Split the function into smaller ones. 该函数的跳转标签过多,无法处理。请将函数拆分为较小的函数。 - + Too many values to match pattern 与模式匹配的值过多 - + Unexpected end of file 意外的文件结束 - + Unexpected variable declaration 意外的变量声明 - + Unreachable code 无法访问的代码 - + Virtual property contains unrecognized aspect 虚拟属性包含未被认可的部分 - + Unused script node 未使用的脚本节点 - + Value is too large for data type 对于数据类型来说,值太大 - + Void cannot be an operand in expressions void 不能作为表达式中的操作数 - + Warnings are treated as errors by the application 应用程序将警告视为错误 - + While parsing argument list 解析参数列表时 - + While parsing expression 解析表达式时 - + While parsing initialization list 解析初始化列表时 - + While parsing namespace 解析命名空间时 - + While parsing statement block 解析语句块时 - + Previous error occurred while including mixin 包含 mixin 时发生先前错误 - + Autohandles cannot be used with types that have been registered with NOCOUNT 自动句柄不能与已使用 NOCOUNT 注册的类型一起使用 - + First parameter to template factory must be a reference. This will be used to pass the object type of the template 模板工厂的第一个参数必须是引用。这将用于传递模板的对象类型 - + Invalid configuration. Verify the registered application interface. 配置无效。请验证已注册的应用程序接口。 - + A value type must be registered with a non-zero size 值类型必须注册为非零大小 - + The behaviour is not compatible with the type 行为与类型不兼容 - + A garbage collected ref type must have the addref, release, and all gc behaviours 垃圾收集引用类型必须具有 addref、release 和所有 gc 行为 - + A garbage collected value type must have the gc enum references behaviour 垃圾收集值类型必须具有 gc 枚举引用行为 - + A scoped reference type must have the release behaviour 作用域引用类型必须具有释放行为 - + A reference type must have the addref and release behaviours 引用类型必须具有 addref 和 release 行为 - + A non-pod value type must have at least one constructor and the destructor behaviours 非 pod 值类型必须至少有一个构造函数和析构函数行为 - + Template list factory expects two reference parameters. The last is the pointer to the initialization buffer 模板列表工厂需要两个引用参数。最后一个是指向初始化缓冲区的指针 - + List factory expects only one reference parameter. The pointer to the initialization buffer will be passed in this parameter 列表工厂仅需要一个引用参数。指向初始化缓冲区的指针将在此参数中传递 - + AddScriptObjectToGC called with null pointer 使用空指针调用 AddScriptObjectToGC - + An exception occurred in a nested call 嵌套调用中发生异常 - + Uh oh! The engine's reference count is increasing while it is being destroyed. Make sure references needed for clean-up are immediately released 哎呀!引擎的引用计数在被销毁时不断增加。确保立即释放清理所需的引用 - + The module is still in use and cannot be rebuilt. Discard it and request another module 该模块仍在使用中,无法重建。丢弃它并请求另一个模块 - + Property 属性 - + System function 系统函数 - + Variable declaration 变量声明 - + Stack overflow 栈溢出 - + Null pointer access 空指针访问 - + Divide by zero 除以零 - + Overflow in integer division 整数除法溢出 - + Overflow in exponent operation 指数运算溢出 - + Unrecognized byte code 无法识别的字节码 - + Invalid calling convention 无效调用约定 - + Unbound function called 未绑定的函数被调用 - + Out of range 越界 - + Caught an exception from the application 捕获应用程序异常 - + Mismatching types in value assignment 值分配中的类型不匹配 - + Too many nested calls 嵌套调用过多 - - + + Assert failed 断言失败 - + BadDecl: 错误的声明: - + GlobalBadDecl 错误的全局声明 @@ -5261,31 +5234,40 @@ 纯文本 + + WingAngel + + + + RegisterScriptFnUnSupportedTypes: + 因脚本函数含有未支持的类型而注册失败: + + WingAngelAPI - + AngelScriptService AngelScript 服务 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 为 AngelScript 脚本提供调用主机 API 能力的内部插件。 - + NotSupportedQMetaType: 不支持的 QT 数据元类型: - - + + Get Exception While ScriptCall: (%1) %2 脚本调用发生异常:(%1)%2 - + InvalidRetType: need 无效返回值:需要 @@ -5293,41 +5275,41 @@ WingCStruct - + WingCStruct 羽云文件结构分析器 - + Providing basic support for analyzing file structures 提供基础的文件结构分析支持 - - - - - - - - - - - - - + + + + + + + + + + + + + InvalidParamsCount 非法参数个数 - - - - - - - - + + + + + + + + InvalidParam 非法参数 diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index b456b1d..e31687d 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -847,18 +847,18 @@ MainWindow - + File - - + + View 視圖 - + About 關於 @@ -879,322 +879,322 @@ 選長: - + Edit 編輯 - + Script 腳本 - - - + + + Plugin 插件 - + Setting 設置 - - + + Log 日誌 - + ExportFindResult 導出搜索結果 - + ClearFindResult 清空記錄 - - + + FindResult 搜索結果 - - - - - - - + + + + + + + Copy 複製 - - - - - + + + + + CopyToClipBoard 數據已拷貝到粘貼板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 數值 - - + + CheckSum 校驗和 - - + + DeleteBookMark 刪除書簽 - - + + ClearBookMark 清空書簽 - - - - + + + + BookMark 書簽 - - + + DecodeText 解碼字串 - + ScriptConsole 腳本控制臺 - - + + Basic 基礎 - + New 新建 - + OpenF 打開檔 - + OpenWorkSpace 打開工作區 - + RecentFiles 最近打開 - - - + + + Reload 重新加載 - - + + Save 保存 - + SaveAs 另存為 - + ConvertWS 轉為工作區 - + Export 導出 - + SaveSel 保存選區位元組 - - - - + + + + General 基本 - + Undo 撤銷 - + Redo 恢復 - + Cut 剪切 - + Paste 粘貼 - + Delete 刪除 - + Clone 克隆 - + Lookup 查詢 - + Find 查找 - + Goto 跳轉 - - + + Encoding 編碼 - + FileInfo 檔資訊 - - + + Hex 十六進制 - + CutHex 剪切(十六進制) - + CopyHex 複製(十六進制) - + PasteHex 粘貼(十六進制) - - + + Fill 填充 - + FillZero 填充零 - - - - + + + + MetaData 標注 - + DeleteMetadata 刪除標注 - + ClearMetadata 清空標注 - + MetaDataEdit 編輯標注 - + DeleteMetaData 刪除標注 - + ClearMetaData 清空標注 - + Display 顯示 - + ViewText 文本預覽 - + Scale 縮放 @@ -1229,832 +1229,837 @@ 加載插件中: - + SetupConsole 啟動腳本控制臺 - + SetupScriptManager 啟動腳本管理器 - + SetupScriptService 啟動腳本服務 - + SetupScriptEditor 構建腳本編輯器 - + SetupSetDialog 構建設置窗體 - + SetupPlgWidgets 啟動插件組件 - + SetupDockingLayout 恢復 Dock 佈局 - + SetupWaiting 啟動即將完成 - + SetupFinished 啟動完畢 - + NoExtension 無擴展 - - + + ExportResult 導出結果 - + NothingToSave 沒有保存的數據 - + OpenExt 打開 - 拓展 - + ResetScale 重置縮放 - + ShowMetafg 標注前景色 - + ShowMetabg 標注背景色 - + ShowMetaComment 批註 - + MetaShowAll 顯示所有標注 - + MetaHideAll 隱藏所有標注 - + FileStatus 檔狀態 - + InfoSave 是否保存 - + ReadOnly 可讀寫 - + SetLocked 啟用/禁用鎖定編輯 - + ErrUnLock 鎖定編輯失敗 - + SetOver 啟用/禁用改變大小 - + InputRequest 輸入請求 - + ScriptEngineInitFailed 腳本引擎啟動失敗,將自動禁用該功能。 - + UnsignedHex 無符號 Hex - + BgScriptOutputHere 後臺腳本執行將會在這裏輸出 - + SelectAll 全選 - - + + Clear 清空 - + AbortScript 終止腳本 - + BgScriptOutput 後臺腳本輸出 - + ErrUnOver 鎖定檔大小失敗 - + Window 窗體 - + Editor 編輯器 - + Tools 工具 - + HexEditorLayout 編輯器佈局 - + SetBaseAddr 設置基址 - + addressBase 基址 - + inputAddressBase 請輸入基址 - + WarnBigBaseAddress 基址過大,你得到的地址將會不正確! - + ErrBaseAddress 非法基址輸入 - + SetColInfo 顯示/隱藏地址欄 - + SetHeaderInfo 顯示/隱藏表頭 - + SetAsciiString 顯示/隱藏解碼字串 - + Layout 佈局 - + Fullscreen 全屏 - + Default 默認 - - - + + + LayoutRestoring... 恢復佈局中... - + RestoreLayout 恢復佈局 - - + + SaveLayout 保存佈局 - - + + ExportLog 導出日誌 - - + + ClearLog 清空日誌 - + InsepctQt 監視 Qt - + ScriptEditor 腳本編輯器 - + Scripts 腳本倉庫 - + PluginFunctions 插件功能 - + ScriptSetting 腳本設置 - + PluginSettings 插件設置 - + Info 資訊 - + Software 軟體 - + Sponsor 贊助 - + CheckUpdate 檢查更新 - + Wiki 網頁 Wiki - + + EngineConfigError + + + + AboutQT 關於 QT - + SetPageIDEmptyTryUseName 設置頁 ID 為空,嘗試使用名稱作為 ID - + SetPageDupNameIgnored 設置頁重複的 ID 名稱,已忽略加載 - + Plugin %1 contains a duplicate ID (%2) that is already registered by plugin %3 插件 %1 包含重複 ID (%2),該 ID 已被插件 %3 註冊 - - + + ChooseFile 選擇檔 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 錯誤 - - + + FileNotExist 檔不存在! - - - - - + + + + + FilePermission 因檔許可權無法繼續! - + ProjectFile (*.wingpro) 專案檔 (*.wingpro) - + ReloadSuccessfully 檔重新加載成功! - + ReloadUnSuccessfully 檔重新加載失敗! - - - - + + + + ChooseSaveFile 請選擇保存檔路徑: - + PasteFailedNote 粘貼失敗,請注意許可權或者內容長度 - + NoMoreClone 克隆已到上限,無法繼續操作! - + FindFininishBusy 查找任務繁忙,請勿重複查找! - + MayTooMuchFindResult 搜索數量已到達上限,結果可能不全,建議請按區段搜索。 - + SaveLayoutSuccess 保存佈局成功 - + SaveLayoutError 保存佈局失敗 - + HasClonedView 該編輯頁已被克隆編輯,如果關閉,相關聯的頁也會被關閉,你確認繼續嗎? - + FileCloseBigFile 大檔讀取模式下目的檔案被關閉,該標籤將會被關閉。 - - + + ReloadNeededYesOrNo 目的檔案被修改,是否重新載入? - + SaveWorkSpace 保存工作區 - + WingHexWorkSpace (*.wingpro) 羽雲十六進制工作區 (*.wingpro) - + ConfirmSave 正在關閉未保存的檔或工作區,你確定保存嗎? - + [Info] 【資訊】 - + [Warn] 【警告】 - + [Error] 【錯誤】 - + ConfirmAPPSave 你嘗試關閉程式,但仍存在未保存的檔或工作區,你確定保存這些更改嗎? - - - + + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作區錯誤! - - + + Warn 警告 - + Opening... 打開檔中... - + WorkSpaceOpening... 打開工作區中... - + Reloading... 重載檔中... - + Saving... 保存中... - + SaveNewFirst 請首先保存新建的檔 - + AlreadyWorkSpace 已經是工作區,無需轉化 - + ConvWorkSpaceFailed 轉化為工作區失敗 - + ConvWorkSpaceSuccess 轉化為工作區成功 - + SavingAs... 另存為中... - + SaveUnSuccessfully 保存失敗! - + Exporting... 導出中... - + ChooseExportFile 請選擇導出檔路徑: - + ExportSuccessfully 導出成功! - + ExportUnSuccessfully 導出失敗! - + SavingSel... 保存選中位元組中... - + SaveSelSuccess 保存選區位元組成功! - + SaveSelError 保存選區位元組失敗,因檔不具有可寫許可權! - - + + CutToClipBoard 數據已剪切到粘貼板! - - + + UnCutToClipBoard 由於保持大小限制,數據剪切到粘貼板失敗! - - + + UnCopyToClipBoard 由於保持大小限制,數據剪切到複製板失敗! - - + + Finding... 查找中... - + DeleteSuccess 刪除成功 - + DeleteFailed 刪除失敗 - + FindFininish 查找結果完畢! - + PleaseInputFill 請輸入填充位元組值 - + FillInputTruncWarn 填充輸入數值過大,將會被截斷填充 - + FillInputError 填充位元組輸入錯誤 - - + + InputComment 請輸入批註: - - + + BookmarkDelSuccess 刪除書簽成功 - + BookmarkDelNoItem 無書簽可刪除 - + BookmarkClearSuccess 書簽清空完畢 - - - + + + NoSelection 沒有選區,無法繼續的操作! - + NoMetaData 無可編輯標記 - + PleaseClearSel 請清空選擇 - + MetaDelSuccess 元數據刪除成功 - + MetaDelNoItem 無元數據可刪除 - + MetaClearSuccess 元數據清空完畢 - + FindResultExporting... 查找結果導出中... - - + + EmptyFindResult 沒有可導出的搜索結果! - + SaveFindResult 導出搜索結果成功! - + SaveFindResultError 導出結果失敗! - + TooManyBytesDecode 超出解碼位元組限制…… - + NoTextFileMayInvalid 該檔不是文本檔,以文本方式預覽並不是一個好的方式,你確認繼續嗎? - + LayoutSaving... 佈局保存中... - - + + PleaseInput 請輸入 - + LogExporting... 日誌導出中... - + ExportLogError 導出日誌失敗! - + ExportLogSuccess 導出日誌成功,路徑: - + ClearLogSuccess 清空日誌成功! - + BadNetwork 無法與遠程伺服器的更新檢查建立連接,請檢查網路。 - + NewestVersion 當前軟體為最新版本 - - + + OlderVersion 你使用的軟體為老版本,建議到 Github 和 Gitee 的倉庫發行版下載更新。 - + CheckingUpdate 檢查更新中…… - + Too much opened files 打開的檔過多,無法繼續操作! - + FilePermissionSure2Quit 因檔許可權無法保存,你確認要退出嗎? - + UnknownErrorSure2Quit 因未知錯誤無法保存,你確認要退出嗎? - + WorkSpaceUnSavedSure2Quit 工作區檔無法保存,你確認要退出嗎? - + CopyLimit 拷貝位元組超出限制 - + ErrOpenFileBelow 打開檔出現錯誤(由於許可權不足),如下為打開錯誤的檔: @@ -2302,205 +2307,173 @@ PluginSystem - + LoadingPlugin 加載插件中: - - + + InvalidPluginBrokenInfo 加載插件失敗:損壞的插件數據 - - + + PluginBlockByManager - + AppClosingCanceled: 程式關閉被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 總計發現設備拓展插件數目: - + PluginManagerNeedSingleton - - RegisterScriptFnUnSupportedTypes: - 因腳本函數含有未支持的類型而註冊失敗: - - - - - RegisterScriptFnInvalidSig: - 因腳本函數簽名非法而註冊失敗: - - - - - RegisterScriptFnConflitSig: - 因腳本函數簽名衝突而註冊失敗: - - - - InvalidEnumName: - 非法枚舉名: - - - - InvalidEnumValue: - 非法枚舉值: - - - - InvalidMarcosRegister: - 非法宏註冊: - - - - + + ErrLoadPluginSDKVersion 插件加載失敗:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加載失敗:非法插件名稱! - - + + ErrLoadInitPlugin 插件加載失敗:初始化插件失敗! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 註冊插件對象中…… - + ExtPluginAuthor : 設備拓展插件作者: - + ExtPluginWidgetRegister 設備拓展註冊插件對象中…… - + ErrLoadInitExtPlugin 設備拓展插件加載失敗:初始化插件失敗! - + ChooseFile 選擇檔 - - + + Error 錯誤 - + FileNotExist 檔不存在! - + FilePermission 因檔許可權無法繼續! - + EmptyNameDockWidget: 空的貼邊組件名: - + InvalidNameDockWidget: 無效貼邊組件名: - + InvalidNullDockWidget: 無效空貼邊組件: - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 - + UnsafePluginDir 不安全的插件目錄,請將插件目錄設置為僅管理員帳戶可寫 - - + + InvalidPluginID 加載插件失敗:非法插件識別字 - + InvalidDupPlugin 加載插件失敗:重複的插件識別字 - + FoundPluginCount 總計發現插件數目: - + PluginLoadingFailedSummary 有依賴插件加載失敗總結 - + - Dependencies: - 依賴: - + PUID: 插件唯一標誌符: - + Version: 版本: - + PluginLoadingFinished 加載插件完畢! @@ -2848,1597 +2821,1597 @@ ScriptMachine - + AngelScript callstack: AngelScript 調用堆疊: - + - Exception '%1' in '%2' — 在 ‘%2’ 中發生異常 ‘%1’ - + ExecNotAllowedInRoot 在管理員許可權執行第三方命令為非法操作 - - + + Code must be exec in the main thread 腳本代碼必須在主線程執行 - + Script failed to pre-processed 腳本代碼預處理失敗 - - - + + + Script failed to build 腳本編譯失敗 - + Cannot find 'int main()' or 'void main()' 無法找到程式入口點: "int main()" 或者 "void main()" - + Debugging, waiting for commands. 調試中,等待調試命令。 - + Failed while initializing global variables 初始化全局變數失敗 - + Run: 執行腳本: - - + + The script failed with an exception 異常被拋出,腳本執行失敗 - - + + The script was aborted 腳本被終止 - - + + The script terminated unexpectedly 腳本異常退出 - + The script exited with 腳本退出返回值: - + '%1' is already declared "%1" 已被聲明 - + Abstract class '%1' cannot be instantiated 無法實例化抽象類 "%1" - + Accessing private property '%1' of parent class 非法訪問父類的私有屬性 "%1" - + Attribute '%1' informed multiple times 屬性 "%1" 已被多次通知 - + Can't form arrays of subtype '%1' 無法創建子類型 "%1" 的數組 - + Can't inherit from class '%1' marked as final 無法從標記為 final 的類 "%1" 繼承 - + Cannot access non-static member '%1' like this 無法和像使用 this 一樣訪問非靜態成員 "%1" - + Can't construct handle '%1'. Use ref cast instead 無法構造句柄 "%1" 。請改用引用強制轉換 - + Can't implicitly convert from '%1' to '%2'. 無法從 "%1' 隱式轉換為 "%2"。 - + Compiling %1 正在編譯 %1 - + Compiling auto generated %1 編譯自動生成的 %1 - + Implemented property accessor '%1' does not expect index argument 已實現的屬性訪問器 "%1" 不需要索引參數 - + Implemented property accessor '%1' expects index argument 已實現的屬性訪問器 "%1" 需要索引參數 - + Data type can't be '%1' 數據類型不能為 "%1" - + All subsequent parameters after the first default value must have default values in function '%1' 在函數 "%1" 中,第一個默認值之後的所有後續參數都必須具有默認值 - + The method in the derived class must have the same return type as in the base class: '%1' 派生類中的方法必須具有與基類相同的返回類型:"%1" - + The name of the destructor '%1::~%2' must be the same as the class 析構函數 "%1::~%2" 的名稱必須與類相同 - + Expected '%1' 應為 "%1" - + Expected '%1' or '%2' 應為 ”%1“ 或 ”%2“ - + Expression must be of boolean type, instead found '%1' 運算式必須是布爾類型,但實際使用的是 "%1" - + Expression '%1' is a data type 運算式 "%1" 是一種數據類型 - + External shared entity '%1' not found 未找到外部共用實體 "%1" - + External shared entity '%1' cannot redefine the original entity 外部共用實體 "%1" 無法重新定義原始實體 - + Failed while compiling default arg for parameter %1 in function '%2' 為函數 "%2" 中的參數 %1 編譯默認參數時失敗 - + Function '%1' not found 未找到函數 "%1" - + The property '%1' has mismatching types for the get and set accessors 屬性 "%1" 的 get 和 set 訪問器類型不匹配 - + Variable '%1' hides another variable of same name in outer scope 變數 "%1" 隱藏了外部作用域中另一個同名變數 - + Identifier '%1' is not a data type 識別字 "%1" 不是數據類型 - + Identifier '%1' is not a data type in global namespace 識別字 "%1" 不是全局命名空間中的數據類型 - + Identifier '%1' is not a data type in namespace '%2' or parent 識別字 "%1" 不是命名空間 "%2" 或其父級中的數據類型 - + Illegal operation on '%1' 對 "%1" 的非法操作 - + Illegal variable name '%1'. 非法變數名 "%1"。 - + Illegal access to inherited private property '%1' 非法訪問繼承的私有屬性 "%1" - + Initialization lists cannot be used with '%1' 初始化列表不能與 "%1" 一起使用 - + Attempting to instantiate invalid template type '%1<%2>' 嘗試實例化無效的範本類型 "%1<%2>" - + Instead found '%1' 而是找到了 "%1" - + Instead found identifier '%1' 而是找到識別字 "%1" - + Instead found reserved keyword '%1' 而是找到了保留關鍵字 "%1" - + Interface '%1' cannot be instantiated 無法實例化介面 "%1" - + Invalid unicode escape sequence, expected %1 hex digits 無效的 Unicode 轉義序列,預期為 %1 個十六進制數字 - + Method '%1' declared as final and cannot be overridden 方法 "%1" 已聲明為 final,因此無法被覆蓋 - + Method '%1' marked as override but does not replace any base class or interface method 方法 "%1" 標記為覆蓋,但並未替換任何基類或介面方法 - + Method '%1::%2' is missing the return type, nor is it the same name as object to be a constructor 方法 "%1::%2" 缺少返回類型,並且其名稱與構造函數對象不同 - + Method '%1' is not part of object '%2' 方法 "%1" 不是對象 "%2" 的一部分 - + Missing implementation of '%1' 缺少 "%1" 的實現 - + Missing definition of '%1' 缺少 "%1" 的定義 - + Mixin class cannot be declared as '%1' Mixin 類不能聲明為 "%1" - + Multiple matching signatures to '%1' "%1" 有多個匹配的簽名 - + Found multiple get accessors for property '%1' 發現屬性 "%1" 的多個 get 訪問器 - + Found multiple set accessors for property '%1' 發現屬性 "%1" 的多個集合訪問器 - + Namespace '%1' doesn't exist. 命名空間 "%1" 不存在。 - - - - - - - - - - - - + + + + + + + + + + + + Name conflict. 名稱衝突。 - + '%1' is an extended data type. "%1" 是擴展數據類型。 - + '%1' is a global property. "%1" 是全局屬性。 - + '%1' is a named type. "%1" 是被命名的類型。 - + '%1' is a funcdef. "%1" 是一個函數簽名定義。 - + '%1' is a global function. "%1" 是一個全局函數。 - + '%1' is a mixin class. "%1" 是一個 Mixin 類。 - + '%1' is a virtual property. "%1" 是虛擬屬性。 - + '%1' is a class. "%1" 是一個類。 - + '%1' is an interface. "%1" 是一個介面。 - + '%1' is an object property. "%1" 是一個對象屬性。 - + '%1' is a class method. "%1" 是一個類方法。 - + '%1' is already used. ”%1“ 已被使用。 - + No appropriate opHndlAssign method found in '%1' for handle assignment 在 "%1" 中未找到適當的 opHndlAssign 方法用於句柄分配 - + No conversion from '%1' to '%2' available. 無法進行從 "%1" 到 "%2" 的轉換。 - + No conversion from '%1' to math type available. 無法將 "%1" 轉換為數學類型。 - + No default constructor for object of type '%1'. "%1" 類型對象沒有默認構造函數。 - + No appropriate opAssign method found in '%1' for value assignment 在 "%1" 中未找到適合賦值的 opAssign 方法 - + No copy constructor for object of type '%1'. 沒有 "%1" 類型對象的複製構造函數。 - + No matching signatures to '%1' 沒有與 "%1" 匹配的簽名 - + No matching operator that takes the type '%1' found 未找到採用類型 "%1" 的匹配運算符 - + No matching operator that takes the types '%1' and '%2' found 未找到採用類型 "%1" 和 "%2" 的匹配運算符 - + No matching symbol '%1' 沒有匹配的符號 "%1" - + Expression doesn't form a function call. '%1' evaluates to the non-function type '%2' 運算式不構成函數調用。"%1" 計算結果為非函數類型 "%2" - + '%1' is not declared "%1" 未被聲明 - + '%1' is not initialized. ”%1“ 未初始化。 - + '%1' is not a member of '%2' ”%1“ 不是 ”%2“ 的成員 - + Type '%1' doesn't support the indexing operator 類型 "%1" 不支持索引運算符 - + Parameter type can't be '%1', because the type cannot be instantiated. 參數類型不能是 "%1",因為該類型無法實例化。 - + Previous error occurred while attempting to compile initialization list for type '%1' 嘗試編譯類型 "%1" 的初始化列表時發生先前的錯誤 - + Illegal call to private method '%1' 非法調用私有方法 "%1" - + Illegal access to private property '%1' 非法訪問私有屬性 "%1" - + Illegal call to protected method '%1' 非法調用受保護的方法 "%1" - + Illegal access to protected property '%1' 非法訪問受保護的屬性 "%1" - + Return type can't be '%1' 返回類型不能是 "%1" - + Shared code cannot access non-shared global variable '%1' 共用代碼無法訪問非共用全局變數 "%1" - + Shared code cannot call non-shared function '%1' 共用代碼無法調用非共用函數 "%1" - + Shared type cannot implement non-shared interface '%1' 共用類型無法實現非共用介面 "%1" - + Shared class cannot inherit from non-shared class '%1' 共用類不能從非共用類 "%1" 繼承 - + Shared code cannot use non-shared type '%1' 共用代碼不能使用非共用類型 "%1" - + Shared type '%1' doesn't match the original declaration in other module 共用類型 "%1" 與其他模組中的原始聲明不匹配 - + Template '%1' expects %2 sub type(s) 範本 "%1" 需要 %2 個子類型 - + Type '%1' cannot be a reference 類型 "%1" 不能是引用 - + Type '%1' is not available for this module 類型 "%1" 不適用於此模組 - + Type '%1' is not a template type 類型 "%1" 不是範本類型 - + Unexpected token '%1' 意外標記 "%1" - + Use of uninitialized global variable '%1'. 使用未初始化的全局變數 "%1"。 - + Unknown scope '%1' 未知作用域 "%1" - + Where '%1' is '%2' 其中 "%1" 是 "%2" - + Failed to initialize global variable '%1' 無法初始化全局變數 "%1" - + Exception '%1' in '%2' "%2" 中的異常 "%1" - + Type '%1' is missing behaviours 類型 "%1" 缺少的行為 - + Can't pass type '%1' by value unless the application type is informed in the registration 除非在註冊時告知應用程式類型,否則無法按值傳遞類型 "%1" - + Can't return type '%1' by value unless the application type is informed in the registration 除非在註冊時告知應用程式類型,否則無法按值返回類型 "%1" - + Don't support passing type '%1' by value to application in native calling convention on this platform 不支持在此平臺上按照本機調用約定將類型 "%1" 按值傳遞給應用程式 - + Don't support returning type '%1' by value from application in native calling convention on this platform 不支持在此平臺上按照本機調用約定從應用程式返回類型 "%1" 的值 - + Object {%1}. GC cannot destroy an object of type '%2' as it doesn't know how many references to there are. 對象 {%1}。GC 無法銷毀類型為 "%2" 的對象,因為它不知道有多少個引用。 - + Object {%1}. GC cannot destroy an object of type '%2' as it can't see all references. Current ref count is %3. 對象 {%1}。GC 無法銷毀類型為 "%2" 的對象,因為它無法看到所有引用。當前引用計數為 %3。 - + Object type '%1' doesn't exist 對象類型 "%1" 不存在 - + Cannot register. The template type instance '%1' has already been generated. 無法註冊。範本類型實例 "%1" 已生成。 - + Template type '%1' doesn't exist 範本類型 "%1" 不存在 - + Template subtype '%1' doesn't exist 範本子類型 "%1" 不存在 - + Failed to read subtype of template type '%1' 無法讀取範本類型 "%1" 的子類型 - + Failed in call to function '%1' (Code: %2, %3) 調用函數 "%1" 失敗(代碼:%2,%3) - + Failed in call to function '%1' with '%2' (Code: %3, %4) 使用 "%2" 調用函數 "%1" 失敗(代碼:%3,%4) - + Failed in call to function '%1' with '%2' and '%3' (Code: %4, %5) 使用 "%2" 和 "%3" 調用函數 "%1" 失敗(代碼:%4,%5) - + Type '%1' is still used by function '%2' 類型 "%1" 仍被函數 "%2" 使用 - + The builtin type in previous message is named '%1' 上一條消息中的內置類型名為 "%1" - + The function in previous message is named '%1'. The func type is %2 上一條消息中的函數名為 "%1"。函數類型為 %2 - + The script object of type '%1' is being resurrected illegally during destruction 類型為 "%1" 的腳本對象在銷毀過程中被非法復活 - + LoadByteCode failed. The bytecode is invalid. Number of bytes read from stream: %1 LoadByteCode 失敗。位元組碼無效。從流中讀取的位元組數:%1 - + Function '%1' appears to have been compiled without JIT entry points 函數 "%1" 似乎已在無 JIT 入口點的情況下進行編譯 - + There is an external reference to an object in module '%1', preventing it from being deleted 存在對模組 "%1" 中對象的外部引用,導致無法刪除該對象 - + Output argument expression is not assignable 輸出參數運算式不可分配 - + Auto is not allowed here 這裏禁止使用 auto 關鍵字 - + Can't find unambiguous implicit conversion to make both expressions have the same type 無法找到明確的隱式轉換來使兩個運算式具有相同的類型 - + Both conditions must call constructor 兩個條件都必須調用構造函數 - + Base class doesn't have default constructor. Make explicit call to base constructor 基類沒有默認構造函數。明確調用基類構造函數 - + Base class doesn't have copy constructor or default constructor and assign operator. Make explicit call to base constructor 基類沒有複製構造函數或默認構造函數和賦值運算符。明確調用基類構造函數 - + Candidates are: 候選包括: - + Can't call a constructor in loops 無法在迴圈中調用構造函數 - + Can't call a constructor in switch 無法在 switch 中調用構造函數 - + Can't call a constructor multiple times 無法多次調用構造函數 - + Can't create delegate 無法創建委託 - + Can't create delegate for types that do not support handles 無法為不支持句柄的類型創建委託 - + Cannot flag function that will not be auto generated as deleted 無法將不會自動生成的函數標記為已刪除 - + Conflict with explicit declaration of function and deleted function 與函數的顯式聲明和已刪除函數衝突 - + Can't implement itself, or another interface that implements this interface 無法實現自身,也無法實現此介面的其他介面 - + Can't inherit from multiple classes 不能從多個類繼承 - + Can't inherit from itself, or another class that inherits from this class 不能從其自身或從該類繼承的其他類繼承 - + Can't pass class method as arg directly. Use a delegate object instead 無法直接將類方法作為參數傳遞。請改用委託對象 - + Unable to resolve auto type 無法解析自動類型 - + Can't return reference to local value. 無法返回對本地值的引用。 - + Can't return value when return type is 'void' 返回類型為 "void" 時無法返回值 - + Implicit conversion changed sign of value 隱式轉換改變了值的符號 - + A class cannot be both abstract and final 一個類不能同時是 abstract 和 final - + Compound assignments with property accessors on value types are not supported 不支持對值類型使用屬性訪問器的複合賦值 - + Compound assignments with indexed property accessors are not supported 不支持使用索引屬性訪問器的複合賦值 - + Compound assignments with property accessors require both get and set accessors 具有屬性訪問器的複合賦值需要 get 和 set 訪問器 - + Variables cannot be declared in switch cases, except inside statement blocks 變數不能在 switch 語句中聲明,除非在語句塊內 - + The default case must be the last one default 情況必須是最後一個 - + The type of the default argument expression doesn't match the function parameter type 默認參數運算式的類型與函數參數類型不匹配 - + Deleted functions cannot have implementation 已刪除的函數不能有實現 - + The destructor must not have any parameters 析構函數不能有任何參數 - + Value assignment on reference types is not allowed. Did you mean to do a handle assignment? 不允許對引用類型進行值分配。是要進行句柄分配嗎? - + Compound assignment on reference types is not allowed 不允許對引用類型進行複合賦值 - + Duplicate named argument 重複命名參數 - + Duplicate switch case 重複的 switch case - + Else with empty statement else 中使用空語句 - + Empty list element is not allowed 不允許空列表元素 - + Empty switch statement 空的 switch 語句 - + Expected constant 應為常量 - + Expected data type 應為數據類型 - + Expected expression value 應為表達值 - + Expected identifier 應為識別字 - + Expected a list enclosed by { } to match pattern 應為用 { } 括起來的列表與模式匹配 - + Expected method or property 應為方法或屬性 - + Expected one of: 應為為以下之一: - + Expected operator 應為操作符 - + Expected post operator 應為右操作符 - + Expected pre operator 應為左操作符 - + Expected string 應為字串 - + Expression doesn't evaluate to a function 運算式無法計算函數值 - + Previous error occurred while attempting to create a temporary copy of object 嘗試創建對象的臨時副本時發生上一個錯誤 - + Float value truncated in implicit conversion to integer 浮點值在隱式轉換為整數時被截斷 - + Found multiple matching enum values 找到多個匹配的枚舉值 - + A function with the same name and parameters already exists 具有相同名稱和參數的函數已存在 - + Global variables have been disabled by the application 全局變數已被應用程式禁用 - + It is not allowed to perform a handle assignment on a non-handle property 不允許對非句柄屬性執行句柄分配 - + The operand is implicitly converted to handle in order to compare them 運算元被隱式轉換為句柄,以便進行比較 - + Handle to handle is not allowed 不允許使用句柄 - + If with empty statement 如果帶有空語句 - + Illegal member type 非法成員類型 - + Illegal operation on this datatype 對該數據類型的非法操作 - + Illegal target type for reference cast 非法引用轉換的目標類型 - + Interfaces can only implement other interfaces 介面只能實現其他介面 - + Invalid 'break' 無效的 break 關鍵字 - + Invalid character literal 無效的字元 - + Invalid 'continue' 無效的 continue 關鍵字 - + Invalid escape sequence 無效的轉義序列 - + Invalid expression: ambiguous name 無效運算式:二義性名稱 - + Invalid expression: stand-alone anonymous function 無效運算式:獨立匿名函數 - + Invalid operation on method 方法操作無效 - + Invalid reference. Property accessors cannot be used in combined read/write operations 引用無效。屬性訪問器不能用於組合讀/寫操作。 - + Invalid scope resolution 範圍解析無效 - + Invalid signature for virtual property 虛擬屬性簽名無效 - + Invalid type 類型無效 - + Invalid unicode code point 無效的 Unicode 代碼點 - + Invalid unicode sequence in source 源代碼中的 Unicode 序列無效 - + Invalid use of named arguments 命名參數的使用無效 - + The method cannot be named with the class name 該方法不能以類名命名 - + Mixin classes cannot have constructors or destructors Mixin 類不能有構造函數或析構函數 - + Mixin class cannot inherit from classes Mixin 類不能從類繼承 - + Mixin classes cannot have child types Mixin 類不能有子類型 - + Found more than one matching operator 找到多個匹配的運算符 - + Multiline strings are not allowed in this application 此應用程式不允許使用多行字串 - + Only objects have constructors 只有對象才有構造函數 - + Must return a value 必須返回一個值 - + Detected named argument with old syntax 檢測到具有舊語法的命名參數 - + No appropriate indexing operator found 未找到合適的索引運算符 - + No appropriate opEquals method found 未找到合適的 opEquals 方法 - + The application doesn't support the default array type. 該應用程式不支持默認數組類型。 - + Non-const method call on read-only object reference 只讀對象引用上的非常量方法調用 - + Non-terminated string literal 未終止的字串 - + Not all paths return a value 並非所有路徑都會返回值 - + Not enough values to match pattern 沒有足夠的值來模式匹配 - + Implicit conversion of value is not exact 值的隱式轉換並不準確 - + Expression is not an l-value 運算式不是左值 - + Not a valid reference 無效引用 - + Not a valid lvalue 不是有效的左值 - + Nothing was built in the module 模組中沒有構建任何內容 - + Object handle is not supported for this type 此類型不支持對象句柄 - + Only object types that support object handles can use &inout. Use &in or &out instead 只有支持對象句柄的對象類型才能使用 &inout。請改用 &in 或 &out - + A cast operator has one argument 強制類型轉換運算符有一個參數 - + The code must contain one and only one function 代碼必須包含一個且只能包含一個函數 - + The code must contain one and only one global variable 代碼必須包含一個且只能有一個全局變數 - + Both operands must be handles when comparing identity 比較時,兩個運算元都必須是句柄 - + The overloaded functions are identical on initial parameters without default arguments 重載函數在初始參數上相同,沒有默認參數 - + Parameter already declared 參數已聲明 - + Positional arguments cannot be passed after named arguments 位置參數不能在命名參數之後傳遞 - + Potentially matching non-const method is hidden on read-only object reference 可能匹配的非 const 方法隱藏在只讀對象引用中 - + Property accessor with index must have 1 and only 1 index argument 帶索引的屬性訪問器必須有 1 個且只能有 1 個索引參數 - + Property accessors have been disabled by the application 應用程式已禁用屬性訪問器 - + Property accessor must be implemented 必須實現屬性訪問器 - + Class properties cannot be declared as const 類屬性不能聲明為 const - + The property has no get accessor 該屬性沒有 get 訪問器 - + The property has no set accessor 該屬性沒有設置訪問器 - + Virtual property must have at least one get or set accessor 虛擬屬性必須至少有一個 get 或 set 訪問器 - + Resulting reference cannot be returned. Returned references must not refer to local variables. 無法返回結果引用。返回的引用不得引用局部變數。 - + Resulting reference cannot be returned. There are deferred arguments that may invalidate it. 無法返回結果引用。存在可能使其無效的延遲參數。 - + Resulting reference cannot be returned. The expression uses objects that during cleanup may invalidate it. 無法返回結果引用。運算式使用的對象在清理過程中可能會使其失效。 - + Reference is read-only 引用是只讀的 - + Reference is temporary 參考是臨時的 - + Reference types cannot be passed by value in function parameters 引用類型不能在函數參數中按值傳遞 - + Reference types cannot be returned by value from functions 引用類型不能通過函數返回值 - + The script section is empty 腳本節區為空 - + Signed/Unsigned mismatch 有符號/無符號不匹配 - + Strings are not recognized by the application 應用程式無法識別字串 - + Case expressions must be literal constants case 運算式必須是文字常量 - + Switch expressions must be integral numbers switch 運算式必須是整數 - + The function has too many jump labels to handle. Split the function into smaller ones. 該函數的跳轉標籤過多,無法處理。請將函數拆分為較小的函數。 - + Too many values to match pattern 與模式匹配的值過多 - + Unexpected end of file 意外的檔結束 - + Unexpected variable declaration 意外的變數聲明 - + Unreachable code 無法訪問的代碼 - + Virtual property contains unrecognized aspect 虛擬屬性包含未被認可的部分 - + Unused script node 未使用的腳本節點 - + Value is too large for data type 對於數據類型來說,值太大 - + Void cannot be an operand in expressions void 不能作為運算式中的運算元 - + Warnings are treated as errors by the application 應用程式將警告視為錯誤 - + While parsing argument list 解析參數列表時 - + While parsing expression 解析運算式時 - + While parsing initialization list 解析初始化列表時 - + While parsing namespace 解析命名空間時 - + While parsing statement block 解析語句塊時 - + Previous error occurred while including mixin 包含 mixin 時發生先前錯誤 - + Autohandles cannot be used with types that have been registered with NOCOUNT 自動句柄不能與已使用 NOCOUNT 註冊的類型一起使用 - + First parameter to template factory must be a reference. This will be used to pass the object type of the template 範本工廠的第一個參數必須是引用。這將用於傳遞範本的對象類型 - + Invalid configuration. Verify the registered application interface. 配置無效。請驗證已註冊的應用程式介面。 - + A value type must be registered with a non-zero size 值類型必須註冊為非零大小 - + The behaviour is not compatible with the type 行為與類型不相容 - + A garbage collected ref type must have the addref, release, and all gc behaviours 垃圾收集引用類型必須具有 addref、release 和所有 gc 行為 - + A garbage collected value type must have the gc enum references behaviour 垃圾收集值類型必須具有 gc 枚舉引用行為 - + A scoped reference type must have the release behaviour 作用域引用類型必須具有釋放行為 - + A reference type must have the addref and release behaviours 引用類型必須具有 addref 和 release 行為 - + A non-pod value type must have at least one constructor and the destructor behaviours 非 pod 值類型必須至少有一個構造函數和析構函數行為 - + Template list factory expects two reference parameters. The last is the pointer to the initialization buffer 範本列表工廠需要兩個引用參數。最後一個是指向初始化緩衝區的指針 - + List factory expects only one reference parameter. The pointer to the initialization buffer will be passed in this parameter 列表工廠僅需要一個引用參數。指向初始化緩衝區的指針將在此參數中傳遞 - + AddScriptObjectToGC called with null pointer 使用空指針調用 AddScriptObjectToGC - + An exception occurred in a nested call 嵌套調用中發生異常 - + Uh oh! The engine's reference count is increasing while it is being destroyed. Make sure references needed for clean-up are immediately released 哎呀!引擎的引用計數在被銷毀時不斷增加。確保立即釋放清理所需的引用 - + The module is still in use and cannot be rebuilt. Discard it and request another module 該模組仍在使用中,無法重建。丟棄它並請求另一個模組 - + Property 屬性 - + System function 系統函數 - + Variable declaration 變數聲明 - + Stack overflow 棧溢出 - + Null pointer access 空指針訪問 - + Divide by zero 除以零 - + Overflow in integer division 整數除法溢出 - + Overflow in exponent operation 指數運算溢出 - + Unrecognized byte code 無法識別的位元組碼 - + Invalid calling convention 無效調用約定 - + Unbound function called 未綁定的函數被調用 - + Out of range 越界 - + Caught an exception from the application 捕獲應用程式異常 - + Mismatching types in value assignment 值分配中的類型不匹配 - + Too many nested calls 嵌套調用過多 - - + + Assert failed 斷言失敗 - + BadDecl: 錯誤的聲明: - + GlobalBadDecl 錯誤的全局聲明 @@ -5261,31 +5234,40 @@ 純文字 + + WingAngel + + + + RegisterScriptFnUnSupportedTypes: + 因腳本函數含有未支持的類型而註冊失敗: + + WingAngelAPI - + AngelScriptService AngelScript 服務 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 為 AngelScript 腳本提供調用主機 API 能力的內部插件。 - + NotSupportedQMetaType: 不支持的 QT 數據元類型: - - + + Get Exception While ScriptCall: (%1) %2 腳本調用發生異常:(%1)%2 - + InvalidRetType: need 無效返回值:需要 @@ -5293,41 +5275,41 @@ WingCStruct - + WingCStruct 羽雲檔結構分析器 - + Providing basic support for analyzing file structures 提供基礎的檔結構分析支持 - - - - - - - - - - - - - + + + + + + + + + + + + + InvalidParamsCount 非法參數個數 - - - - - - - - + + + + + + + + InvalidParam 非法參數 diff --git a/src/class/pluginsystem.cpp b/src/class/pluginsystem.cpp index cd92ca4..27a252a 100644 --- a/src/class/pluginsystem.cpp +++ b/src/class/pluginsystem.cpp @@ -16,15 +16,15 @@ */ #include "pluginsystem.h" -#include "AngelScript/sdk/angelscript/source/as_builder.h" #include "Qt-Advanced-Docking-System/src/DockAreaWidget.h" #include "class/languagemanager.h" #include "class/logger.h" -#include "class/scriptmachine.h" #include "class/settingmanager.h" #include "class/skinmanager.h" +#include "class/wingangel.h" #include "class/wingcstruct.h" #include "class/wingfiledialog.h" +#include "class/winggeneric.h" #include "class/winginputdialog.h" #include "class/wingmessagebox.h" #include "control/toast.h" @@ -74,17 +74,6 @@ PluginSystem::PluginSystem(QObject *parent) : QObject(parent) { PluginSystem::~PluginSystem() {} -void PluginSystem::initCheckingEngine() { - _engine = dynamic_cast(asCreateScriptEngine()); - Q_ASSERT(_engine); - - // basic checking environment - ScriptMachine::registerEngineAddon(_engine); - _angelplg->installBasicTypes(_engine); -} - -void PluginSystem::finalizeCheckingEngine() { _engine->ShutDownAndRelease(); } - // ========================================================================= void PluginSystem::toast(const QObject *sender, const QPixmap &icon, @@ -2498,6 +2487,33 @@ bool PluginSystem::closeAllFiles(const QObject *sender) { return true; } +void PluginSystem::__raiseContextException(const QObject *sender, + const QString &exception, + bool allowCatch) { + if (passByFailedGuard(sender, __func__, {})) { + return; + } + + auto ctx = asGetActiveContext(); + if (ctx) { + auto info = exception.toUtf8(); + ctx->SetException(info, allowCatch); + } +} + +IWingGeneric *PluginSystem::__createParamContext(const QObject *sender, + void *ctx) { + if (passByFailedGuard(sender, __func__, {})) { + return nullptr; + } + + auto gen = reinterpret_cast(ctx); + if (gen) { + return new WingGeneric(gen); + } + return nullptr; +} + bool PluginSystem::passByFailedGuard(const QObject *sender, const char *func, const QVariantList ¶ms) { if (_manager && sender != _manager) { @@ -2520,6 +2536,30 @@ bool PluginSystem::checkErrAllAllowAndReport(const QObject *sender, return false; } +void PluginSystem::doneRegisterScriptObj() { + Q_ASSERT(_angelplg); + // ok, then, we will register all script objects + auto api = + QScopedPointer(new WingAngel(_angelplg, _scriptMarcos)); + auto ptr = api.data(); + if (_manager) { + ptr->setCurrentPluginSession(_manInfo->id.toUtf8()); + _manager->onRegisterScriptObj(ptr); + } + + for (auto &p : _loadedplgs) { + auto puid = getPUID(p); + ptr->setCurrentPluginSession(puid.toUtf8()); + p->onRegisterScriptObj(ptr); + } + + for (auto &p : _loadeddevs) { + auto puid = getPUID(p); + ptr->setCurrentPluginSession(puid.toUtf8()); + p->onRegisterScriptObj(ptr); + } +} + const std::optional &PluginSystem::monitorManagerInfo() const { return _manInfo; } @@ -3218,6 +3258,7 @@ PluginInfo PluginSystem::parsePluginMetadata(const QJsonObject &meta) { PluginInfo info; info.id = meta["Id"].toString().trimmed(); + info.SDKVersion = meta["SDK"].toInt(); info.version = QVersionNumber::fromString(meta["Version"].toString().trimmed()); @@ -3264,7 +3305,7 @@ PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) { return PluginStatus::InvalidID; } - if (!isValidIdentifier(meta.id)) { + if (!Utilities::isValidIdentifier(meta.id)) { return PluginStatus::InvalidID; } @@ -3284,23 +3325,6 @@ PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) { return PluginStatus::Valid; } -bool PluginSystem::isValidIdentifier(const QString &str) { - if (str.isEmpty()) { - return false; - } - auto pch = str.cbegin(); - if (pch->isDigit()) { - return false; - } - pch++; - for (; pch != str.cend(); pch++) { - if (!pch->isLetterOrNumber() && *pch != '_') { - return false; - } - } - return true; -} - bool PluginSystem::checkPluginCanOpenedFile(IWingPlugin *plg) { if (plg == nullptr) { return false; @@ -3750,6 +3774,7 @@ void PluginSystem::try2LoadManagerPlugin() { applyFunctionTables(p, _plgFns); _manager = p; + registerPluginDetectMarco(m.id); // translate the meta-data m.author = p->retranslate(m.author); @@ -3764,223 +3789,9 @@ void PluginSystem::try2LoadManagerPlugin() { } } -void PluginSystem::registerFns(IWingPlugin *plg) { - if (_angelplg == nullptr) { - return; - } - - Q_ASSERT(plg); - auto fns = plg->registeredScriptFns(); - if (fns.isEmpty()) { - return; - } - - // checking functions - asCBuilder c(_engine, nullptr); - - auto id = getPluginID(plg); - auto rawID = id.toUtf8(); - - QList fnlist; - - auto r = _engine->SetDefaultNamespace(rawID); - if (Q_UNLIKELY(r < 0)) { - _engine->configFailed = false; - return; - } - - // - QHash rfns; - for (auto p = fns.constKeyValueBegin(); p != fns.constKeyValueEnd(); ++p) { - auto func = new asCScriptFunction(_engine, nullptr, asFUNC_SYSTEM); - - auto &fn = p->second; - auto sig = getScriptFnSig(p->first, fn); - if (sig.isEmpty()) { - Logger::critical(tr("RegisterScriptFnUnSupportedTypes:") + id + - QStringLiteral("::") + p->first); - func->Release(); - continue; - } - - auto r = c.ParseFunctionDeclaration(nullptr, sig.toLatin1(), func, true, - nullptr, nullptr, - _engine->defaultNamespace); - if (r < 0) { - Logger::critical(tr("RegisterScriptFnInvalidSig:") + sig); - func->Release(); - continue; - } - - r = c.CheckNameConflict(func->name.AddressOf(), 0, 0, - _engine->defaultNamespace, false, false, false); - if (r < 0) { - Logger::critical(tr("RegisterScriptFnConflitSig:") + sig); - func->Release(); - continue; - } - - fnlist.append(func); - - // register functions with internal hacking - func->id = _engine->GetNextScriptFunctionId(); - _engine->AddScriptFunction(func); - rfns.insert(sig, p->second); - } - - // clear the internal hacking functions - for (auto &fn : fnlist) { - _engine->RemoveScriptFunction(fn); - } - _engine->SetDefaultNamespace(""); - - fnlist.clear(); - - Q_ASSERT(_angelplg); - _angelplg->registerScriptFns(_pinfos.value(plg).id, rfns); -} - -void PluginSystem::registerUnSafeFns(IWingPlugin *plg) { - if (_angelplg == nullptr) { - return; - } - - Q_ASSERT(plg); - - auto fns = plg->registeredScriptUnsafeFns(); - if (fns.isEmpty()) { - return; - } - - // checking functions - asCBuilder c(_engine, nullptr); - - auto id = getPluginID(plg); - auto rawID = id.toUtf8(); - - QList fnlist; - - auto r = _engine->SetDefaultNamespace(rawID); - if (Q_UNLIKELY(r < 0)) { - _engine->configFailed = false; - return; - } - - // - QHash rfns; - for (auto p = fns.constKeyValueBegin(); p != fns.constKeyValueEnd(); ++p) { - auto func = new asCScriptFunction(_engine, nullptr, asFUNC_SYSTEM); - auto sig = p->first; - auto r = c.ParseFunctionDeclaration(nullptr, sig.toLatin1(), func, true, - nullptr, nullptr, - _engine->defaultNamespace); - if (r < 0) { - Logger::critical(tr("RegisterScriptFnInvalidSig:") + sig); - func->funcType = asFUNC_DUMMY; - continue; - } - - r = c.CheckNameConflict(func->name.AddressOf(), 0, 0, - _engine->defaultNamespace, false, false, false); - if (r < 0) { - Logger::critical(tr("RegisterScriptFnConflitSig:") + sig); - func->funcType = asFUNC_DUMMY; - continue; - } - - fnlist.append(func); - - // register functions with internal hacking - func->id = _engine->GetNextScriptFunctionId(); - _engine->AddScriptFunction(func); - rfns.insert(sig, p->second); - } - - // clear the internal hacking functions - for (auto &fn : fnlist) { - _engine->RemoveScriptFunction(fn); - } - _engine->SetDefaultNamespace(""); - - fnlist.clear(); - - Q_ASSERT(_angelplg); - _angelplg->registerUnSafeScriptFns(_pinfos.value(plg).id, rfns); -} - -void PluginSystem::registerEnums(IWingPlugin *plg) { - Q_ASSERT(plg); - auto objs = plg->registeredScriptEnums(); - if (objs.isEmpty()) { - return; - } - - decltype(objs) passedEnums; - - // checking enums - // Here we just register the enum in real action. - // If failed, we can hack and restore the engine. - auto id = getPluginID(plg); - auto r = _engine->SetDefaultNamespace(id.toUtf8()); - if (Q_UNLIKELY(r < 0)) { - _engine->configFailed = false; - return; - } - - // not neccssary to really restore when failed, 'cause of unique - // namespace - for (auto el = objs.constKeyValueBegin(); el != objs.constKeyValueEnd(); - ++el) { - auto ename = el->first.toUtf8(); - auto r = _engine->RegisterEnum(ename); - if (r < 0) { - Logger::critical(tr("InvalidEnumName:") + el->first); - _engine->configFailed = false; - continue; - } - - bool hasNoError = true; - for (auto &ev : el->second) { - r = _engine->RegisterEnumValue(ename, ev.first.toUtf8(), ev.second); - if (r < 0) { - Logger::critical( - tr("InvalidEnumValue:") + el->first + QStringLiteral("::") + - ev.first + QStringLiteral(" (") + - QString::number(ev.second) + QStringLiteral(")")); - _engine->configFailed = false; - hasNoError = false; - break; - } - } - - if (hasNoError) { - passedEnums.insert(el->first, el->second); - } - } - - Q_ASSERT(_angelplg); - _angelplg->registerScriptEnums(id, passedEnums); -} - -void PluginSystem::registerMarcos(IWingPlugin *plg) { - Q_ASSERT(plg); - - auto id = getPUID(plg).toUpper(); - auto sep = QStringLiteral("_"); +void PluginSystem::registerPluginDetectMarco(const QString &id) { + static auto sep = QStringLiteral("_"); _scriptMarcos.append(sep + id + sep); - - QStringList invalidMarco; - for (auto &m : plg->registerScriptMarcos()) { - if (isValidIdentifier(m)) { - _scriptMarcos.append(sep + id + sep + m + sep); - } else { - invalidMarco.append(m); - } - } - - if (!invalidMarco.isEmpty()) { - Logger::warning(tr("InvalidMarcosRegister:") + invalidMarco.join(", ")); - } } void PluginSystem::registerEvents(IWingPlugin *plg) { @@ -4039,10 +3850,6 @@ void PluginSystem::registerEvents(IWingPlugin *plg) { if (evs.testFlag(IWingPlugin::RegisteredEvent::PluginFileClosed)) { _evplgs[IWingPlugin::RegisteredEvent::PluginFileClosed].append(plg); } - - if (evs.testFlag(IWingPlugin::RegisteredEvent::ScriptUnSafeFnRegistering)) { - registerUnSafeFns(plg); - } } void PluginSystem::applyFunctionTables(QObject *plg, const CallTable &fns) { @@ -4050,146 +3857,6 @@ void PluginSystem::applyFunctionTables(QObject *plg, const CallTable &fns) { plg->setProperty("__CALL_POINTER__", quintptr(this)); } -QString PluginSystem::type2AngelScriptString(uint type, bool isArg, - bool noModifier) { - auto isArray = !!(type & WingHex::IWingPlugin::Array); - auto isList = !!(type & WingHex::IWingPlugin::List); - auto isContainer = isArray || isList; - if (isContainer) { - if (isArray && isList) { - return {}; - } - } - - QString retype; - bool complexType = false; - - type = IWingPlugin::MetaType(type & WingHex::IWingPlugin::MetaTypeMask); - switch (type) { - case WingHex::IWingPlugin::Void: - retype = QStringLiteral("void"); - break; - case WingHex::IWingPlugin::Bool: - retype = QStringLiteral("bool"); - break; - case WingHex::IWingPlugin::Int: - retype = QStringLiteral("int"); - break; - case WingHex::IWingPlugin::UInt: - retype = QStringLiteral("uint"); - break; - case WingHex::IWingPlugin::Int8: - retype = QStringLiteral("int8"); - break; - case WingHex::IWingPlugin::UInt8: - retype = QStringLiteral("uint8"); - break; - case WingHex::IWingPlugin::Int16: - retype = QStringLiteral("int16"); - break; - case WingHex::IWingPlugin::UInt16: - retype = QStringLiteral("uint16"); - break; - case WingHex::IWingPlugin::Int64: - retype = QStringLiteral("int64"); - break; - case WingHex::IWingPlugin::UInt64: - retype = QStringLiteral("uint64"); - break; - case WingHex::IWingPlugin::Float: - retype = QStringLiteral("float"); - break; - case WingHex::IWingPlugin::Double: - retype = QStringLiteral("double"); - break; - case WingHex::IWingPlugin::String: - retype = QStringLiteral("string"); - break; - case WingHex::IWingPlugin::Char: - retype = QStringLiteral("char"); - break; - case WingHex::IWingPlugin::Byte: - retype = QStringLiteral("byte"); - break; - case WingHex::IWingPlugin::Color: - retype = QStringLiteral("color"); - complexType = true; - break; - case WingHex::IWingPlugin::Map: - case WingHex::IWingPlugin::Hash: - retype = QStringLiteral("dictionary"); - complexType = true; - break; - default: - return {}; - } - - if (isArray || isList) { - retype.append(QStringLiteral("[]")); - } - - if (isArg) { - if (!noModifier && (isContainer || complexType)) { - retype.append(QStringLiteral(" &in")) - .prepend(QStringLiteral("const ")); - } - } else { - if (!noModifier) { - // if it's a return type, only array and array are - // supported in AngelScript - // ( array -> QByteArray , array -> QStringList ), - // other array types are not suported. PRs are welcomed !!! - // IT'S TOO COMPLEX TO SUPPORT QVARIANTLIST !!! - - // You can use unsafe registering to support - // extensive scripting system. - // It will be faster and flexible but not easy to implement. - if (isContainer) { - if (type != WingHex::IWingPlugin::Byte && - type != WingHex::IWingPlugin::String) { - return {}; - } - - retype.append(QStringLiteral("@")); - } - - if (complexType) { - retype.append(QStringLiteral("@")); - } - } - } - - return retype.trimmed(); -} - -QString PluginSystem::getScriptFnSig(const QString &fnName, - const IWingPlugin::ScriptFnInfo &fninfo) { - if (fnName.isEmpty()) { - return {}; - } - - QString sig; - - auto ret = type2AngelScriptString(fninfo.ret, false); - if (ret.isEmpty()) { - return {}; - } - - sig += ret + QStringLiteral(" ") + fnName + QStringLiteral("("); - - QStringList params; - for (auto ¶m : fninfo.params) { - auto ret = type2AngelScriptString(param.first, true); - if (ret.isEmpty()) { - return {}; - } - - params << ret + QStringLiteral(" ") + param.second; - } - - return sig + params.join(',') + QStringLiteral(")"); -} - QString PluginSystem::getPUID(IWingPluginBase *p) { if (p) { return PluginSystem::instance().getPluginID(p); @@ -4251,6 +3918,8 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, _loadedplgs.append(p); _pinfos.insert(p, meta); + registerPluginDetectMarco(meta.id); + Logger::info(tr("PluginName :") + p->pluginName()); Logger::debug(tr("PluginAuthor :") + meta.author); Logger::debug(tr("PluginWidgetRegister")); @@ -4276,9 +3945,6 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, registeredSettingPages(QVariant::fromValue(p), p->registeredSettingPages()); - registerFns(p); - registerEnums(p); - registerMarcos(p); registerEvents(p); // prepare for file contenxt @@ -4320,8 +3986,7 @@ void PluginSystem::loadPlugin(IWingDevice *p, PluginInfo &meta, _loadeddevs.append(p); _pinfos.insert(p, meta); - - registerMarcoDevice(p); + registerPluginDetectMarco(meta.id); // ok register into menu open auto menu = @@ -4448,12 +4113,6 @@ void PluginSystem::registerPluginDockWidgets(IWingPluginBase *p) { } } -void PluginSystem::registerMarcoDevice(IWingDevice *plg) { - auto id = getPUID(plg).toUpper(); - auto sep = QStringLiteral("_"); - _scriptMarcos.append(sep + id + sep); -} - void PluginSystem::registerRibbonTools( const QList &tools) { if (!tools.isEmpty()) { @@ -4557,15 +4216,13 @@ void PluginSystem::loadAllPlugin() { QJsonDocument doc = QJsonDocument::fromJson(angelapi); auto meta = parsePluginMetadata(doc.object()); + Q_ASSERT(checkPluginMetadata(meta, true) == PluginStatus::Valid); retranslateMetadata(_angelplg, meta); loadPlugin(_angelplg, meta, std::nullopt); } Logger::newLine(); - // ok, setup checking engine - initCheckingEngine(); - { QFile cstructjson(QStringLiteral( ":/com.wingsummer.winghex/src/class/WingCStruct.json")); @@ -4577,9 +4234,11 @@ void PluginSystem::loadAllPlugin() { QJsonDocument doc = QJsonDocument::fromJson(cstruct); auto meta = parsePluginMetadata(doc.object()); + Q_ASSERT(checkPluginMetadata(meta, true) == PluginStatus::Valid); // internal plugin has no filename - if (_manager->onLoadingPlugin({}, meta)) { + if (_manager == nullptr || + (_manager && _manager->onLoadingPlugin({}, meta))) { auto cstructplg = new WingCStruct; QDir setd(Utilities::getAppDataPath()); auto plgset = QStringLiteral("plgset"); @@ -4626,9 +4285,6 @@ void PluginSystem::loadAllPlugin() { } Logger::newLine(); - - // loading finished, delete the checking engine - finalizeCheckingEngine(); } void PluginSystem::destory() { diff --git a/src/class/pluginsystem.h b/src/class/pluginsystem.h index 070beeb..ee6da57 100644 --- a/src/class/pluginsystem.h +++ b/src/class/pluginsystem.h @@ -136,6 +136,8 @@ public: void loadAllPlugin(); void unloadAllPlugin(); + void doneRegisterScriptObj(); + void destory(); const QList &plugins() const; @@ -167,9 +169,6 @@ public: static QString getPUID(IWingPluginBase *p); - static QString type2AngelScriptString(uint type, bool isArg, - bool noModifier = false); - private: void loadExtPlugin(); @@ -207,22 +206,13 @@ private: PluginStatus checkPluginMetadata(const PluginInfo &meta, bool isPlg); - static bool isValidIdentifier(const QString &str); - void retranslateMetadata(IWingPluginBase *plg, PluginInfo &meta); private: - void registerFns(IWingPlugin *plg); - void registerUnSafeFns(IWingPlugin *plg); - void registerEnums(IWingPlugin *plg); - void registerMarcos(IWingPlugin *plg); void registerEvents(IWingPlugin *plg); void applyFunctionTables(QObject *plg, const CallTable &fns); - static QString getScriptFnSig(const QString &fnName, - const IWingPlugin::ScriptFnInfo &fninfo); - bool isPluginLoaded(const WingDependency &d); bool isPluginLoaded(const QString &id); @@ -245,7 +235,7 @@ private: const std::optional &setdir); private: - void registerMarcoDevice(IWingDevice *plg); + void registerPluginDetectMarco(const QString &id); private: void registerRibbonTools(const QList &tools); @@ -319,10 +309,6 @@ private: PluginSystem(QObject *parent = nullptr); ~PluginSystem(); - void initCheckingEngine(); - - void finalizeCheckingEngine(); - // IWingPluginBase API public slots: WING_API void toast(const QObject *sender, const QPixmap &icon, @@ -712,6 +698,14 @@ public slots: // extension WING_API bool closeAllFiles(const QObject *sender); + // generic call support + WING_API WingHex::IWingGeneric *__createParamContext(const QObject *sender, + void *ctx); + + WING_API void __raiseContextException(const QObject *sender, + const QString &exception, + bool allowCatch = true); + private: WingHex::IWingPlugin *checkPluginAndReport(const QObject *sender, const char *func); @@ -742,13 +736,10 @@ private: UniqueIdGenerator m_idGen; - QHash> _scfns; - IWingManager *_manager = nullptr; std::optional _manInfo; WingAngelAPI *_angelplg = nullptr; - asCScriptEngine *_engine = nullptr; QStringList _scriptMarcos; QList _pragmaedPlg; diff --git a/src/class/scriptmachine.cpp b/src/class/scriptmachine.cpp index 02c64d8..843677a 100644 --- a/src/class/scriptmachine.cpp +++ b/src/class/scriptmachine.cpp @@ -27,6 +27,7 @@ #include "AngelScript/sdk/add_on/scriptmath/scriptmath.h" #include "AngelScript/sdk/add_on/scriptmath/scriptmathcomplex.h" #include "AngelScript/sdk/add_on/weakref/weakref.h" +#include "AngelScript/sdk/angelscript/source/as_scriptengine.h" #include "angelobjstring.h" #include "class/appmanager.h" @@ -145,6 +146,16 @@ bool ScriptMachine::isRunning(ConsoleMode mode) const { return _ctx.value(mode) != nullptr; } +bool ScriptMachine::isEngineConfigError() const { + if (_engine) { + auto e = dynamic_cast(_engine); + if (e) { + return e->configFailed; + } + } + return true; +} + #define INS_1 "const ?&in = null" #define INS_2 INS_1 ", " INS_1 #define INS_4 INS_2 ", " INS_2 diff --git a/src/class/scriptmachine.h b/src/class/scriptmachine.h index f8eb6dc..6601707 100644 --- a/src/class/scriptmachine.h +++ b/src/class/scriptmachine.h @@ -116,6 +116,7 @@ public: bool init(); bool isInited() const; bool isRunning(ConsoleMode mode) const; + bool isEngineConfigError() const; static void registerEngineAddon(asIScriptEngine *engine); static void registerEngineAssert(asIScriptEngine *engine); @@ -150,15 +151,15 @@ public: bool isDebugMode(ConsoleMode mode = Scripting); public slots: - bool executeCode(ConsoleMode mode, const QString &code); + bool executeCode(ScriptMachine::ConsoleMode mode, const QString &code); // only scripting mode can be debugged - bool executeScript(ConsoleMode mode, const QString &script, + bool executeScript(ScriptMachine::ConsoleMode mode, const QString &script, bool isInDebug = false, int *retCode = nullptr); int evaluateDefine(const QString &code, bool &result); void abortDbgScript(); - void abortScript(ConsoleMode mode); + void abortScript(ScriptMachine::ConsoleMode mode); void abortScript(); protected: diff --git a/src/class/skinmanager.h b/src/class/skinmanager.h index 2dc9a7a..d9bc23e 100644 --- a/src/class/skinmanager.h +++ b/src/class/skinmanager.h @@ -19,6 +19,7 @@ #define SKINMANAGER_H #include +#include #include class SkinManager { diff --git a/src/class/wingangel.cpp b/src/class/wingangel.cpp new file mode 100644 index 0000000..bef5c87 --- /dev/null +++ b/src/class/wingangel.cpp @@ -0,0 +1,597 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ + +#include "wingangel.h" +#include "define.h" +#include "wingangelapi.h" + +#include "logger.h" +#include "scriptmachine.h" +#include "utilities.h" + +inline asSFuncPtr asCSFuncPtr(const WingHex::asFuncPtr &ptr) { + // some checks + static_assert(std::is_standard_layout_v, + "asSFuncPtr must be standard layout"); + static_assert(std::is_standard_layout_v, + "WingHex::asFuncPtr must be standard layout"); + static_assert(sizeof(asSFuncPtr) == sizeof(WingHex::asFuncPtr), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(alignof(asSFuncPtr) == alignof(WingHex::asFuncPtr), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(asSFuncPtr, ptr) == + offsetof(WingHex::asFuncPtr, ptr), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(asSFuncPtr, flag) == + offsetof(WingHex::asFuncPtr, flag), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(sizeof(asSFuncPtr::ptr) == sizeof(WingHex::asFuncPtr::ptr), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(std::is_same_v, + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(asSFuncPtr, flag) == + offsetof(WingHex::asFuncPtr, flag), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + + using StructM = decltype(std::declval().ptr.m); + using StructF = decltype(std::declval().ptr.f); + + using wStructM = decltype(std::declval().ptr.m); + using wStructF = decltype(std::declval().ptr.f); + + static_assert(offsetof(StructM, mthd) == offsetof(wStructM, mthd), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(StructF, func) == offsetof(wStructF, func), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(StructM, dummy) == offsetof(wStructM, dummy), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(offsetof(StructF, dummy) == offsetof(wStructF, dummy), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(sizeof(StructM::mthd) == sizeof(wStructM::mthd), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(sizeof(StructF::func) == sizeof(wStructF::func), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(sizeof(StructM::dummy) == sizeof(wStructM::dummy), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + static_assert(sizeof(StructF::dummy) == sizeof(wStructF::dummy), + "asSFuncPtr is not same as WingHex::asFuncPtr"); + + // just so simple + asSFuncPtr ret; + std::memcpy(&ret, &ptr, sizeof(ret)); + return ret; +} + +// some checks +static_assert(asEBehaviours::asBEHAVE_CONSTRUCT == + int(WingHex::IWingAngel::asBEHAVE_CONSTRUCT), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_LIST_CONSTRUCT == + int(WingHex::IWingAngel::asBEHAVE_LIST_CONSTRUCT), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_DESTRUCT == + int(WingHex::IWingAngel::asBEHAVE_DESTRUCT), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_FACTORY == + int(WingHex::IWingAngel::asBEHAVE_FACTORY), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_LIST_FACTORY == + int(WingHex::IWingAngel::asBEHAVE_LIST_FACTORY), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_ADDREF == + int(WingHex::IWingAngel::asBEHAVE_ADDREF), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_RELEASE == + int(WingHex::IWingAngel::asBEHAVE_RELEASE), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_GET_WEAKREF_FLAG == + int(WingHex::IWingAngel::asBEHAVE_GET_WEAKREF_FLAG), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_TEMPLATE_CALLBACK == + int(WingHex::IWingAngel::asBEHAVE_TEMPLATE_CALLBACK), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_FIRST_GC == + int(WingHex::IWingAngel::asBEHAVE_FIRST_GC), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_GETREFCOUNT == + int(WingHex::IWingAngel::asBEHAVE_GETREFCOUNT), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_SETGCFLAG == + int(WingHex::IWingAngel::asBEHAVE_SETGCFLAG), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_GETGCFLAG == + int(WingHex::IWingAngel::asBEHAVE_GETGCFLAG), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_ENUMREFS == + int(WingHex::IWingAngel::asBEHAVE_ENUMREFS), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_RELEASEREFS == + int(WingHex::IWingAngel::asBEHAVE_RELEASEREFS), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_LAST_GC == + int(WingHex::IWingAngel::asBEHAVE_LAST_GC), + "asEBehaviours check failed"); +static_assert(asEBehaviours::asBEHAVE_RELEASEREFS == + int(WingHex::IWingAngel::asBEHAVE_RELEASEREFS), + "asEBehaviours check failed"); + +static_assert(asERetCodes::asSUCCESS == int(WingHex::asRetCodes::asSUCCESS), + "asERetCodes check failed"); +static_assert(asERetCodes::asERROR == int(WingHex::asRetCodes::asERROR), + "asERetCodes check failed"); +static_assert(asERetCodes::asCONTEXT_ACTIVE == + int(WingHex::asRetCodes::asCONTEXT_ACTIVE), + "asERetCodes check failed"); +static_assert(asERetCodes::asCONTEXT_NOT_FINISHED == + int(WingHex::asRetCodes::asCONTEXT_NOT_FINISHED), + "asERetCodes check failed"); +static_assert(asERetCodes::asCONTEXT_NOT_PREPARED == + int(WingHex::asRetCodes::asCONTEXT_NOT_PREPARED), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_ARG == + int(WingHex::asRetCodes::asINVALID_ARG), + "asERetCodes check failed"); +static_assert(asERetCodes::asNO_FUNCTION == + int(WingHex::asRetCodes::asNO_FUNCTION), + "asERetCodes check failed"); +static_assert(asERetCodes::asNOT_SUPPORTED == + int(WingHex::asRetCodes::asNOT_SUPPORTED), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_NAME == + int(WingHex::asRetCodes::asINVALID_NAME), + "asERetCodes check failed"); +static_assert(asERetCodes::asNAME_TAKEN == + int(WingHex::asRetCodes::asNAME_TAKEN), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_DECLARATION == + int(WingHex::asRetCodes::asINVALID_DECLARATION), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_OBJECT == + int(WingHex::asRetCodes::asINVALID_OBJECT), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_TYPE == + int(WingHex::asRetCodes::asINVALID_TYPE), + "asERetCodes check failed"); +static_assert(asERetCodes::asALREADY_REGISTERED == + int(WingHex::asRetCodes::asALREADY_REGISTERED), + "asERetCodes check failed"); +static_assert(asERetCodes::asMULTIPLE_FUNCTIONS == + int(WingHex::asRetCodes::asMULTIPLE_FUNCTIONS), + "asERetCodes check failed"); +static_assert(asERetCodes::asNO_MODULE == int(WingHex::asRetCodes::asNO_MODULE), + "asERetCodes check failed"); +static_assert(asERetCodes::asNO_GLOBAL_VAR == + int(WingHex::asRetCodes::asNO_GLOBAL_VAR), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_CONFIGURATION == + int(WingHex::asRetCodes::asINVALID_CONFIGURATION), + "asERetCodes check failed"); +static_assert(asERetCodes::asINVALID_INTERFACE == + int(WingHex::asRetCodes::asINVALID_INTERFACE), + "asERetCodes check failed"); +static_assert(asERetCodes::asCANT_BIND_ALL_FUNCTIONS == + int(WingHex::asRetCodes::asCANT_BIND_ALL_FUNCTIONS), + "asERetCodes check failed"); +static_assert( + asERetCodes::asLOWER_ARRAY_DIMENSION_NOT_REGISTERED == + int(WingHex::asRetCodes::asLOWER_ARRAY_DIMENSION_NOT_REGISTERED), + "asERetCodes check failed"); +static_assert(asERetCodes::asWRONG_CONFIG_GROUP == + int(WingHex::asRetCodes::asWRONG_CONFIG_GROUP), + "asERetCodes check failed"); +static_assert(asERetCodes::asCONFIG_GROUP_IS_IN_USE == + int(WingHex::asRetCodes::asCONFIG_GROUP_IS_IN_USE), + "asERetCodes check failed"); +static_assert(asERetCodes::asILLEGAL_BEHAVIOUR_FOR_TYPE == + int(WingHex::asRetCodes::asILLEGAL_BEHAVIOUR_FOR_TYPE), + "asERetCodes check failed"); +static_assert(asERetCodes::asWRONG_CALLING_CONV == + int(WingHex::asRetCodes::asWRONG_CALLING_CONV), + "asERetCodes check failed"); +static_assert(asERetCodes::asBUILD_IN_PROGRESS == + int(WingHex::asRetCodes::asBUILD_IN_PROGRESS), + "asERetCodes check failed"); +static_assert(asERetCodes::asINIT_GLOBAL_VARS_FAILED == + int(WingHex::asRetCodes::asINIT_GLOBAL_VARS_FAILED), + "asERetCodes check failed"); +static_assert(asERetCodes::asOUT_OF_MEMORY == + int(WingHex::asRetCodes::asOUT_OF_MEMORY), + "asERetCodes check failed"); +static_assert(asERetCodes::asMODULE_IS_IN_USE == + int(WingHex::asRetCodes::asMODULE_IS_IN_USE), + "asERetCodes check failed"); + +WingAngel::WingAngel(WingAngelAPI *api, QStringList &marcos) + : _api(api), _scriptMarcos(marcos) { + Q_ASSERT(api); +} + +bool WingAngel::setCurrentPluginSession(const QByteArray &ns) { + if (ns != _plgsess) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->SetDefaultNamespace(ns.data()); + if (ret != asSUCCESS) { + return false; + } + _plgsess = ns; + } + return true; +} + +WingHex::asRetCodes +WingAngel::registerGlobalFunction(uint retMetaType, const ScriptFn &fn, + const QString &fnName, + const QVector> ¶ms) { + auto sig = getScriptFnSig(retMetaType, fn, fnName, params); + if (sig.isEmpty()) { + Logger::critical(tr("RegisterScriptFnUnSupportedTypes:") + _plgsess + + QStringLiteral("::") + fnName); + return WingHex::asRetCodes::asINVALID_ARG; + } + + auto engine = ScriptMachine::instance().engine(); + + auto ret = engine->RegisterGlobalFunction( + sig.toUtf8(), asFUNCTION(WingAngelAPI::script_call), + asECallConvTypes::asCALL_GENERIC); + + if (ret < 0) { + // TODO + return returnValue(ret); + } + + auto &sfns = _api->_sfns; + auto id = sfns.size(); + + auto f = engine->GetFunctionById(ret); + if (f) { + f->SetUserData(_api, AsUserDataType::UserData_API); + f->SetUserData(reinterpret_cast(id), + AsUserDataType::UserData_PluginFn); + } else { + return WingHex::asRetCodes::asINVALID_ARG; + } + + WingScriptInternal::ScriptFnInfo info; + info.ret = retMetaType; + info.fn = fn; + info.params = params; + + sfns.append(info); + + return WingHex::asRetCodes::asSUCCESS; +} + +WingHex::asRetCodes +WingAngel::registerGlobalFunction(const QString &decl, + const WingHex::UNSAFE_SCFNPTR &fn) { + if (decl.isEmpty()) { + Logger::critical(tr("RegisterScriptFnUnSupportedTypes:") + _plgsess + + QStringLiteral("::") + decl); + return WingHex::asRetCodes::asINVALID_ARG; + } + + auto engine = ScriptMachine::instance().engine(); + + auto ret = engine->RegisterGlobalFunction( + decl.toUtf8(), asFUNCTION(WingAngelAPI::script_unsafe_call), + asECallConvTypes::asCALL_GENERIC); + + if (ret < 0) { + // TODO + return returnValue(ret); + } + + auto &sfns = _api->_usfns; + auto id = sfns.size(); + + auto f = engine->GetFunctionById(ret); + if (f) { + f->SetUserData(_api, AsUserDataType::UserData_API); + f->SetUserData(reinterpret_cast(id), + AsUserDataType::UserData_PluginFn); + } else { + return WingHex::asRetCodes::asINVALID_ARG; + } + + sfns.append(fn); + + return WingHex::asRetCodes::asSUCCESS; +} + +void WingAngel::registerScriptMarco(const QString &marco) { + if (Utilities::isValidIdentifier(marco)) { + static auto sep = QStringLiteral("_"); + _scriptMarcos.append(sep + _plgsess + sep + marco + sep); + } else { + + // TODO + } +} + +void WingAngel::registerScriptMarcos(const QStringList &marcos) { + for (auto &m : marcos) { + registerScriptMarco(m); + } +} + +WingHex::asRetCodes +WingAngel::registerGlobalFunction(const char *declaration, + const WingHex::asFuncPtr &funcPointer, + asCallConvTypes callConv, void *auxiliary) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterGlobalFunction( + declaration, asCSFuncPtr(funcPointer), asDWORD(callConv), auxiliary); + return returnValue(ret); +} + +WingHex::asRetCodes +WingAngel::registerInterfaceMethod(const char *intf, const char *declaration) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterInterfaceMethod(intf, declaration); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerInterface(const char *name) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterInterface(name); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerObjectBehaviour( + const char *obj, asBehaviours behaviour, const char *declaration, + const WingHex::asFuncPtr &funcPointer, asCallConvTypes callConv, + void *auxiliary, int compositeOffset, bool isCompositeIndirect) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterObjectBehaviour( + obj, asEBehaviours(behaviour), declaration, asCSFuncPtr(funcPointer), + asECallConvTypes(callConv), auxiliary, compositeOffset, + isCompositeIndirect); + return returnValue(ret); +} + +WingHex::asRetCodes +WingAngel::registerObjectMethod(const char *obj, const char *declaration, + const WingHex::asFuncPtr &funcPointer, + asCallConvTypes callConv, void *auxiliary, + int compositeOffset, bool isCompositeIndirect) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterObjectMethod( + obj, declaration, asCSFuncPtr(funcPointer), asECallConvTypes(callConv), + auxiliary, compositeOffset, isCompositeIndirect); + return returnValue(ret); +} + +WingHex::asRetCodes +WingAngel::registerObjectProperty(const char *obj, const char *declaration, + int byteOffset, int compositeOffset, + bool isCompositeIndirect) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterObjectProperty( + obj, declaration, byteOffset, compositeOffset, isCompositeIndirect); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerObjectType(const char *obj, int byteSize, + quint64 flags) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterObjectType(obj, byteSize, flags); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerGlobalProperty(const char *declaration, + void *pointer) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterGlobalProperty(declaration, pointer); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerTypedef(const char *type, + const char *decl) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterTypedef(type, decl); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerFuncdef(const char *decl) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterFuncdef(decl); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerEnumValue(const char *type, + const char *name, int value) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterEnumValue(type, name, value); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::registerEnum(const char *type) { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->RegisterEnum(type); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::restoreDefaultNamespace() { + auto engine = ScriptMachine::instance().engine(); + auto ret = engine->SetDefaultNamespace(_plgsess); + return returnValue(ret); +} + +WingHex::asRetCodes WingAngel::setDefaultNamespace(const char *nameSpace) { + auto engine = ScriptMachine::instance().engine(); + if (nameSpace) { + if (qstrlen(nameSpace) > 1024) { + return WingHex::asRetCodes::asINVALID_NAME; + } + auto ns = _plgsess.append(QByteArrayLiteral("::")).append(nameSpace); + auto ret = engine->SetDefaultNamespace(ns.data()); + return returnValue(ret); + } else { + return restoreDefaultNamespace(); + } +} + +QString WingAngel::getScriptFnSig(uint retMetaType, const ScriptFn &fn, + const QString &fnName, + const QVector> ¶ms) { + if (fnName.isEmpty()) { + return {}; + } + + QString sig; + + auto ret = type2AngelScriptString(retMetaType, false); + if (ret.isEmpty()) { + return {}; + } + + sig += ret + QStringLiteral(" ") + fnName + QStringLiteral("("); + + QStringList _params; + for (auto ¶m : params) { + auto ret = type2AngelScriptString(param.first, true); + if (ret.isEmpty()) { + return {}; + } + + _params << ret + QStringLiteral(" ") + param.second; + } + + return sig + _params.join(',') + QStringLiteral(")"); +} + +QString WingAngel::type2AngelScriptString(uint type, bool isArg, + bool noModifier) { + auto isArray = !!(type & WingHex::Meta_Array); + auto isList = !!(type & WingHex::Meta_List); + auto isContainer = isArray || isList; + if (isContainer) { + if (isArray && isList) { + return {}; + } + } + + QString retype; + bool complexType = false; + + type = WingHex::MetaType(type & WingHex::MetaTypeMask); + switch (type) { + case WingHex::Meta_Void: + retype = QStringLiteral("void"); + break; + case WingHex::Meta_Bool: + retype = QStringLiteral("bool"); + break; + case WingHex::Meta_Int: + retype = QStringLiteral("int"); + break; + case WingHex::Meta_UInt: + retype = QStringLiteral("uint"); + break; + case WingHex::Meta_Int8: + retype = QStringLiteral("int8"); + break; + case WingHex::Meta_UInt8: + retype = QStringLiteral("uint8"); + break; + case WingHex::Meta_Int16: + retype = QStringLiteral("int16"); + break; + case WingHex::Meta_UInt16: + retype = QStringLiteral("uint16"); + break; + case WingHex::Meta_Int64: + retype = QStringLiteral("int64"); + break; + case WingHex::Meta_UInt64: + retype = QStringLiteral("uint64"); + break; + case WingHex::Meta_Float: + retype = QStringLiteral("float"); + break; + case WingHex::Meta_Double: + retype = QStringLiteral("double"); + break; + case WingHex::Meta_String: + retype = QStringLiteral("string"); + break; + case WingHex::Meta_Char: + retype = QStringLiteral("char"); + break; + case WingHex::Meta_Byte: + retype = QStringLiteral("byte"); + break; + case WingHex::Meta_Color: + retype = QStringLiteral("color"); + complexType = true; + break; + case WingHex::Meta_Map: + case WingHex::Meta_Hash: + retype = QStringLiteral("dictionary"); + complexType = true; + break; + default: + return {}; + } + + if (isArray || isList) { + retype.append(QStringLiteral("[]")); + } + + if (isArg) { + if (!noModifier && (isContainer || complexType)) { + retype.append(QStringLiteral(" &in")) + .prepend(QStringLiteral("const ")); + } + } else { + if (!noModifier) { + // if it's a return type, only array and array are + // supported in AngelScript + // ( array -> QByteArray , array -> QStringList ), + // other array types are not suported. PRs are welcomed !!! + // IT'S TOO COMPLEX TO SUPPORT QVARIANTLIST !!! + + // You can use unsafe registering to support + // extensive scripting system. + // It will be faster and flexible but not easy to implement. + if (isContainer) { + if (type != WingHex::Meta_Byte && + type != WingHex::Meta_String) { + return {}; + } + + retype.append(QStringLiteral("@")); + } + + if (complexType) { + retype.append(QStringLiteral("@")); + } + } + } + + return retype.trimmed(); +} + +WingHex::asRetCodes WingAngel::returnValue(int ret) { + if (ret < 0) { + return WingHex::asRetCodes(ret); + } else { + return WingHex::asRetCodes::asSUCCESS; + } +} diff --git a/src/class/wingangel.h b/src/class/wingangel.h new file mode 100644 index 0000000..06b584a --- /dev/null +++ b/src/class/wingangel.h @@ -0,0 +1,107 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ + +#ifndef WINGANGEL_H +#define WINGANGEL_H + +#include "WingPlugin/iwingangel.h" + +#include + +class WingAngelAPI; + +class WingAngel : public WingHex::IWingAngel { + Q_DECLARE_TR_FUNCTIONS(WingAngel) + +public: + WingAngel(WingAngelAPI *api, QStringList &marcos); + +public: + bool setCurrentPluginSession(const QByteArray &ns); + + // IWingAngel interface +public: + virtual WingHex::asRetCodes registerGlobalFunction( + uint retMetaType, const ScriptFn &fn, const QString &fnName, + const QVector> ¶ms) override; + + virtual WingHex::asRetCodes + registerGlobalFunction(const QString &decl, + const WingHex::UNSAFE_SCFNPTR &fn) override; + + virtual void registerScriptMarco(const QString &marco) override; + virtual void registerScriptMarcos(const QStringList &marcos) override; + virtual WingHex::asRetCodes + setDefaultNamespace(const char *nameSpace) override; + virtual WingHex::asRetCodes restoreDefaultNamespace() override; + virtual WingHex::asRetCodes registerEnum(const char *type) override; + virtual WingHex::asRetCodes + registerEnumValue(const char *type, const char *name, int value) override; + virtual WingHex::asRetCodes registerFuncdef(const char *decl) override; + virtual WingHex::asRetCodes registerTypedef(const char *type, + const char *decl) override; + virtual WingHex::asRetCodes registerGlobalProperty(const char *declaration, + void *pointer) override; + virtual WingHex::asRetCodes + registerObjectType(const char *obj, int byteSize, quint64 flags) override; + + virtual WingHex::asRetCodes + registerObjectProperty(const char *obj, const char *declaration, + int byteOffset, int compositeOffset, + bool isCompositeIndirect) override; + virtual WingHex::asRetCodes + registerObjectMethod(const char *obj, const char *declaration, + const WingHex::asFuncPtr &funcPointer, + asCallConvTypes callConv, void *auxiliary, + int compositeOffset, + bool isCompositeIndirect) override; + + virtual WingHex::asRetCodes registerObjectBehaviour( + const char *obj, asBehaviours behaviour, const char *declaration, + const WingHex::asFuncPtr &funcPointer, asCallConvTypes callConv, + void *auxiliary, int compositeOffset, + bool isCompositeIndirect) override; + + virtual WingHex::asRetCodes registerInterface(const char *name) override; + + virtual WingHex::asRetCodes + registerInterfaceMethod(const char *intf, const char *declaration) override; + + virtual WingHex::asRetCodes + registerGlobalFunction(const char *declaration, + const WingHex::asFuncPtr &funcPointer, + asCallConvTypes callConv, void *auxiliary) override; + +private: + static QString getScriptFnSig(uint retMetaType, const ScriptFn &fn, + const QString &fnName, + const QVector> ¶ms); + + static QString type2AngelScriptString(uint type, bool isArg, + bool noModifier = false); + +private: + WingHex::asRetCodes returnValue(int ret); + +private: + WingAngelAPI *_api; + QByteArray _plgsess; + + QStringList &_scriptMarcos; +}; + +#endif // WINGANGEL_H diff --git a/src/class/wingangelapi.cpp b/src/class/wingangelapi.cpp index ca61051..ffb6850 100644 --- a/src/class/wingangelapi.cpp +++ b/src/class/wingangelapi.cpp @@ -18,9 +18,9 @@ #include "wingangelapi.h" #include "AngelScript/sdk/angelscript/include/angelscript.h" +#include "WingPlugin/iwingangel.h" #include "class/angelscripthelper.h" #include "class/logger.h" -#include "class/pluginsystem.h" #include "class/scriptmachine.h" #include "class/wingfiledialog.h" #include "class/winginputdialog.h" @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef Q_OS_WIN #undef MessageBox @@ -67,8 +68,8 @@ QString WingAngelAPI::retranslate(const QString &str) { return QApplication::tr(str.toLatin1()); } -QStringList WingAngelAPI::registerScriptMarcos() const { - return {"EXEC_BASE", "AS_ARRAY_EXT", "AS_DICTIONARY_EXT"}; +void WingAngelAPI::onRegisterScriptObj(WingHex::IWingAngel *o) { + o->registerScriptMarcos({"EXEC_BASE", "AS_ARRAY_EXT", "AS_DICTIONARY_EXT"}); } WingHex::IWingPlugin::RegisteredEvents WingAngelAPI::registeredEvents() const { @@ -91,48 +92,6 @@ void WingAngelAPI::eventPluginFile(PluginFileEvent e, FileType type, } } -void WingAngelAPI::registerUnSafeScriptFns( - const QString &ns, const QHash &rfns) { - Q_ASSERT(!ns.isEmpty()); - if (rfns.isEmpty()) { - return; - } - - auto id = _usfns.size(); - for (auto p = rfns.constKeyValueBegin(); p != rfns.constKeyValueEnd(); - p++) { - _urfns[ns][p->first] = id; - id++; - _usfns.append(p->second); - } -} - -void WingAngelAPI::registerScriptEnums( - const QString &ns, const QHash>> &objs) { - Q_ASSERT(!ns.isEmpty()); - if (objs.isEmpty()) { - return; - } - - _objs.insert(ns, objs); -} - -void WingAngelAPI::registerScriptFns(const QString &ns, - const QHash &rfns) { - Q_ASSERT(!ns.isEmpty()); - if (rfns.isEmpty()) { - return; - } - - auto id = _sfns.size(); - for (auto p = rfns.constKeyValueBegin(); p != rfns.constKeyValueEnd(); - p++) { - _rfns[ns][p->first] = id; - id++; - _sfns.append(p->second); - } -} - void WingAngelAPI::installAPI(ScriptMachine *machine) { Q_ASSERT(machine); auto engine = machine->engine(); @@ -148,9 +107,7 @@ void WingAngelAPI::installAPI(ScriptMachine *machine) { installHexReaderAPI(engine); installHexControllerAPI(engine); - installScriptEnums(engine); - installScriptFns(engine); - installScriptUnSafeFns(engine); + // plugin script objects will be install later } void WingAngelAPI::installBasicTypes(asIScriptEngine *engine) { @@ -1082,89 +1039,6 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) { engine->SetDefaultNamespace(""); } -void WingAngelAPI::installScriptFns(asIScriptEngine *engine) { - for (auto pfns = _rfns.constKeyValueBegin(); - pfns != _rfns.constKeyValueEnd(); pfns++) { - auto ns = pfns->first; - int r = engine->SetDefaultNamespace(ns.toUtf8()); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - auto &pfn = pfns->second; - for (auto p = pfn.constKeyValueBegin(); p != pfn.constKeyValueEnd(); - p++) { - auto sig = p->first; - auto id = p->second; - auto r = engine->RegisterGlobalFunction( - sig.toUtf8(), asFUNCTION(script_call), asCALL_GENERIC); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - // r is the AngelScript function ID - auto fn = engine->GetFunctionById(r); - fn->SetUserData(this, AsUserDataType::UserData_API); - fn->SetUserData(reinterpret_cast(id), - AsUserDataType::UserData_PluginFn); - } - engine->SetDefaultNamespace(""); - } -} - -void WingAngelAPI::installScriptUnSafeFns(asIScriptEngine *engine) { - for (auto pfns = _urfns.constKeyValueBegin(); - pfns != _urfns.constKeyValueEnd(); pfns++) { - auto ns = pfns->first; - int r = engine->SetDefaultNamespace(ns.toUtf8()); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - auto &pfn = pfns->second; - for (auto p = pfn.constKeyValueBegin(); p != pfn.constKeyValueEnd(); - p++) { - auto sig = p->first; - auto id = p->second; - auto r = engine->RegisterGlobalFunction( - sig.toUtf8(), asFUNCTION(script_unsafe_call), asCALL_GENERIC); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - // r is the AngelScript function ID - auto fn = engine->GetFunctionById(r); - fn->SetUserData(this, AsUserDataType::UserData_API); - fn->SetUserData(reinterpret_cast(id), - AsUserDataType::UserData_PluginFn); - } - engine->SetDefaultNamespace(""); - } -} - -void WingAngelAPI::installScriptEnums(asIScriptEngine *engine) { - for (auto pobjs = _objs.constKeyValueBegin(); - pobjs != _objs.constKeyValueEnd(); ++pobjs) { - auto ns = pobjs->first; - int r = engine->SetDefaultNamespace(ns.toUtf8()); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - auto &pobj = pobjs->second; - for (auto p = pobj.constKeyValueBegin(); p != pobj.constKeyValueEnd(); - p++) { - auto en = p->first.toUtf8(); - r = engine->RegisterEnum(en.data()); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - for (auto &e : p->second) { - auto ev = e.first.toUtf8(); - r = engine->RegisterEnumValue(en.data(), ev.data(), e.second); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - } - } - engine->SetDefaultNamespace(""); - } -} - void WingAngelAPI::registerAPI(asIScriptEngine *engine, const asSFuncPtr &fn, const char *sig) { auto r = @@ -1563,12 +1437,13 @@ QVariant WingAngelAPI::qvariantGet(asIScriptEngine *engine, const void *raw, return {}; } -bool WingAngelAPI::getQVariantGetFlag(const ScriptFnInfo &info, int index) { +bool WingAngelAPI::getQVariantGetFlag( + const WingScriptInternal::ScriptFnInfo &info, int index) { auto ¶ms = info.params; Q_ASSERT(index >= 0 && index < params.size()); auto minfo = params.at(index).first; - return !!(minfo & MetaType::List) || !!(minfo & MetaType::Hash); + return !!(minfo & WingHex::Meta_List) || !!(minfo & WingHex::Meta_Hash); } int WingAngelAPI::qvariantCastASID(asIScriptEngine *engine, @@ -1696,6 +1571,118 @@ bool WingAngelAPI::isTempBuffered(QMetaType::Type type) { } } +QString WingAngelAPI::type2AngelScriptString(uint type, bool isArg, + bool noModifier) { + auto isArray = !!(type & WingHex::Meta_Array); + auto isList = !!(type & WingHex::Meta_List); + auto isContainer = isArray || isList; + if (isContainer) { + if (isArray && isList) { + return {}; + } + } + + QString retype; + bool complexType = false; + + type = WingHex::MetaType(type & WingHex::MetaTypeMask); + switch (type) { + case WingHex::Meta_Void: + retype = QStringLiteral("void"); + break; + case WingHex::Meta_Bool: + retype = QStringLiteral("bool"); + break; + case WingHex::Meta_Int: + retype = QStringLiteral("int"); + break; + case WingHex::Meta_UInt: + retype = QStringLiteral("uint"); + break; + case WingHex::Meta_Int8: + retype = QStringLiteral("int8"); + break; + case WingHex::Meta_UInt8: + retype = QStringLiteral("uint8"); + break; + case WingHex::Meta_Int16: + retype = QStringLiteral("int16"); + break; + case WingHex::Meta_UInt16: + retype = QStringLiteral("uint16"); + break; + case WingHex::Meta_Int64: + retype = QStringLiteral("int64"); + break; + case WingHex::Meta_UInt64: + retype = QStringLiteral("uint64"); + break; + case WingHex::Meta_Float: + retype = QStringLiteral("float"); + break; + case WingHex::Meta_Double: + retype = QStringLiteral("double"); + break; + case WingHex::Meta_String: + retype = QStringLiteral("string"); + break; + case WingHex::Meta_Char: + retype = QStringLiteral("char"); + break; + case WingHex::Meta_Byte: + retype = QStringLiteral("byte"); + break; + case WingHex::Meta_Color: + retype = QStringLiteral("color"); + complexType = true; + break; + case WingHex::Meta_Map: + case WingHex::Meta_Hash: + retype = QStringLiteral("dictionary"); + complexType = true; + break; + default: + return {}; + } + + if (isArray || isList) { + retype.append(QStringLiteral("[]")); + } + + if (isArg) { + if (!noModifier && (isContainer || complexType)) { + retype.append(QStringLiteral(" &in")) + .prepend(QStringLiteral("const ")); + } + } else { + if (!noModifier) { + // if it's a return type, only array and array are + // supported in AngelScript + // ( array -> QByteArray , array -> QStringList ), + // other array types are not suported. PRs are welcomed !!! + // IT'S TOO COMPLEX TO SUPPORT QVARIANTLIST !!! + + // You can use unsafe registering to support + // extensive scripting system. + // It will be faster and flexible but not easy to implement. + if (isContainer) { + if (type != WingHex::Meta_Byte && + type != WingHex::Meta_String) { + return {}; + } + + retype.append(QStringLiteral("@")); + } + + if (complexType) { + retype.append(QStringLiteral("@")); + } + } + } + + return retype.trimmed(); +} + void WingAngelAPI::script_call(asIScriptGeneric *gen) { auto fn = gen->GetFunction(); @@ -1780,7 +1767,7 @@ void WingAngelAPI::script_call(asIScriptGeneric *gen) { } auto rettype = fns.ret; - auto r = PluginSystem::type2AngelScriptString(rettype, false, true); + auto r = type2AngelScriptString(rettype, false, true); if (r == QStringLiteral("int")) { r = QStringLiteral("int32"); } else if (r == QStringLiteral("uint")) { @@ -1829,7 +1816,7 @@ void WingAngelAPI::script_unsafe_call(asIScriptGeneric *gen) { QList params; auto total = gen->GetArgCount(); - WingHex::IWingPlugin::UNSAFE_RET ret; + WingHex::UNSAFE_RET ret; for (decltype(total) i = 0; i < total; ++i) { auto raw = gen->GetAddressOfArg(i); params.append(raw); @@ -1997,11 +1984,11 @@ WingAngelAPI::retriveAsDictionary(const WingHex::SenderInfo &sender, } void *WingAngelAPI::vector2AsArray(const WingHex::SenderInfo &sender, - MetaType type, + WingHex::MetaType type, const QVector &content) { Q_UNUSED(sender); - auto typeStr = PluginSystem::type2AngelScriptString( - MetaType(type | MetaType::Array), false, true); + auto typeStr = type2AngelScriptString( + WingHex::MetaType(type | WingHex::MetaType::Meta_Array), false, true); if (typeStr.isEmpty()) { return nullptr; } @@ -2018,14 +2005,15 @@ void *WingAngelAPI::vector2AsArray(const WingHex::SenderInfo &sender, } void *WingAngelAPI::list2AsArray(const WingHex::SenderInfo &sender, - MetaType type, const QList &content) { + WingHex::MetaType type, + const QList &content) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) static_assert(std::is_same_v, QVector>); return vector2AsArray(sender, type, content); #else Q_UNUSED(sender); - auto typeStr = PluginSystem::type2AngelScriptString( - MetaType(type | MetaType::Array), false, true); + auto typeStr = type2AngelScriptString(MetaType(type | MetaType::Meta_Array), + false, true); if (typeStr.isEmpty()) { return nullptr; } @@ -2054,7 +2042,7 @@ void WingAngelAPI::deleteAsArray(const WingHex::SenderInfo &sender, void *WingAngelAPI::newAsDictionary( const WingHex::SenderInfo &sender, - const QHash> &content) { + const QHash> &content) { Q_UNUSED(sender); auto engine = ScriptMachine::instance().engine(); auto dic = CScriptDictionary::Create(engine); @@ -2062,8 +2050,7 @@ void *WingAngelAPI::newAsDictionary( for (auto p = content.constKeyValueBegin(); p != content.constKeyValueEnd(); ++p) { auto key = p->first; - auto typeStr = - PluginSystem::type2AngelScriptString(p->second.first, false, true); + auto typeStr = type2AngelScriptString(p->second.first, false, true); auto id = engine->GetTypeIdByDecl(typeStr.toUtf8()); if (id < 0) { continue; diff --git a/src/class/wingangelapi.h b/src/class/wingangelapi.h index a0bb6af..01c2cd0 100644 --- a/src/class/wingangelapi.h +++ b/src/class/wingangelapi.h @@ -29,10 +29,22 @@ class asIScriptEngine; class ScriptMachine; class ScriptingConsole; +namespace WingScriptInternal { + +struct ScriptFnInfo { + uint ret; // MetaType + QVector> params; + std::function fn; +}; + +} // namespace WingScriptInternal + class WingAngelAPI : public WingHex::IWingPlugin { Q_OBJECT Q_INTERFACES(WingHex::IWingPlugin) + friend class WingAngel; + public: WingAngelAPI(); virtual ~WingAngelAPI(); @@ -48,25 +60,14 @@ public: virtual QString retranslate(const QString &str) override; - virtual QStringList registerScriptMarcos() const override; - private: + virtual void onRegisterScriptObj(WingHex::IWingAngel *o) override; + virtual void eventPluginFile(PluginFileEvent e, FileType type, const QString &newfileName, int handle, const QString &oldfileName) override; public: - void - registerScriptFns(const QString &ns, - const QHash &rfns); - void registerUnSafeScriptFns( - const QString &ns, - const QHash &rfns); - - void - registerScriptEnums(const QString &ns, - const QHash>> &objs); - void installAPI(ScriptMachine *machine); void installBasicTypes(asIScriptEngine *engine); @@ -84,6 +85,10 @@ public: *reinterpret_cast(&buffer) = v; } +public: + static QString type2AngelScriptString(uint type, bool isArg, + bool noModifier); + private: void installLogAPI(asIScriptEngine *engine); void installExtAPI(asIScriptEngine *engine); @@ -94,9 +99,6 @@ private: void installHexBaseType(asIScriptEngine *engine); void installHexReaderAPI(asIScriptEngine *engine); void installHexControllerAPI(asIScriptEngine *engine); - void installScriptFns(asIScriptEngine *engine); - void installScriptUnSafeFns(asIScriptEngine *engine); - void installScriptEnums(asIScriptEngine *engine); private: void registerAPI(asIScriptEngine *engine, const asSFuncPtr &fn, @@ -125,9 +127,8 @@ private: static QVariant qvariantGet(asIScriptEngine *engine, const void *raw, int typeID, bool flag); - static bool - getQVariantGetFlag(const WingHex::IWingPlugin::ScriptFnInfo &info, - int index); + static bool getQVariantGetFlag(const WingScriptInternal::ScriptFnInfo &info, + int index); template static const T *getDereferencePointer(const void *value, bool isHandle) { @@ -169,17 +170,17 @@ private: retriveAsDictionary(const WingHex::SenderInfo &sender, void *dic); WING_SERVICE void *vector2AsArray(const WingHex::SenderInfo &sender, - MetaType type, + WingHex::MetaType type, const QVector &content); WING_SERVICE void *list2AsArray(const WingHex::SenderInfo &sender, - MetaType type, + WingHex::MetaType type, const QList &content); WING_SERVICE void deleteAsArray(const WingHex::SenderInfo &sender, void *array); - WING_SERVICE void * - newAsDictionary(const WingHex::SenderInfo &sender, - const QHash> &content); + WING_SERVICE void *newAsDictionary( + const WingHex::SenderInfo &sender, + const QHash> &content); WING_SERVICE void deleteAsDictionary(const WingHex::SenderInfo &sender, void *dic); @@ -284,13 +285,8 @@ private: QFileDialog::Options options); private: - QVector _sfns; - QHash> _rfns; - - QVector _usfns; - QHash> _urfns; - - QHash>>> _objs; + QVector _sfns; + QVector _usfns; QVector _handles; }; diff --git a/src/class/wingcstruct.cpp b/src/class/wingcstruct.cpp index 2d019fd..350aa6e 100644 --- a/src/class/wingcstruct.cpp +++ b/src/class/wingcstruct.cpp @@ -17,164 +17,12 @@ #include "wingcstruct.h" +#include "WingPlugin/iwingangel.h" #include "scriptaddon/scriptqdictionary.h" #include "utilities.h" #include "wingangelapi.h" -WingCStruct::WingCStruct() : WingHex::IWingPlugin() { - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::addStruct), this, - std::placeholders::_1); - info.ret = MetaType::Bool; - - info.params.append( - qMakePair(MetaType::String, QStringLiteral("header"))); - - _scriptInfo.insert(QStringLiteral("addStruct"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind(QOverload::of( - &WingCStruct::addStructFromFile), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - - info.params.append( - qMakePair(MetaType::String, QStringLiteral("fileName"))); - - _scriptInfo.insert(QStringLiteral("addStructFromFile"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::resetEnv), this, - std::placeholders::_1); - info.ret = MetaType::Void; - - _scriptInfo.insert(QStringLiteral("resetEnv"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::setStructPadding), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - - info.params.append(qMakePair(MetaType::Int, QStringLiteral("padding"))); - - _scriptInfo.insert(QStringLiteral("setStructPadding"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::structPadding), - this, std::placeholders::_1); - info.ret = MetaType::Int; - - _scriptInfo.insert(QStringLiteral("structPadding"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::structPadding), - this, std::placeholders::_1); - info.ret = MetaType::Int; - - _scriptInfo.insert(QStringLiteral("structPadding"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::structTypes), - this, std::placeholders::_1); - info.ret = MetaType::String | MetaType::Array; - - _scriptInfo.insert(QStringLiteral("structTypes"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::sizeofStruct), - this, std::placeholders::_1); - info.ret = getqsizetypeMetaType(); - info.params.append(qMakePair(MetaType::String, QStringLiteral("type"))); - _scriptInfo.insert(QStringLiteral("sizeofStruct"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::existStruct), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - info.params.append(qMakePair(MetaType::String, QStringLiteral("type"))); - _scriptInfo.insert(QStringLiteral("existStruct"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::constDefines), - this, std::placeholders::_1); - info.ret = MetaType::String | MetaType::Array; - - _scriptInfo.insert(QStringLiteral("constDefines"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::existDefineValue), - this, std::placeholders::_1); - info.ret = MetaType::Bool; - info.params.append(qMakePair(MetaType::String, QStringLiteral("type"))); - - _scriptInfo.insert(QStringLiteral("existDefineValue"), info); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::defineValue), - this, std::placeholders::_1); - info.ret = MetaType::Int; - info.params.append(qMakePair(MetaType::String, QStringLiteral("type"))); - - _scriptInfo.insert(QStringLiteral("defineValue"), info); - } - - // nested dictionary is not supported, so unsafe registering will help - { - _scriptUnsafe.insert( - QStringLiteral("dictionary@ read(") + getqsizeTypeAsString() + - (" offset, const string &in type)"), - std::bind(QOverload &>::of(&WingCStruct::read), - this, std::placeholders::_1)); - } - - { - WingHex::IWingPlugin::ScriptFnInfo info; - info.fn = std::bind( - QOverload::of(&WingCStruct::readRaw), this, - std::placeholders::_1); - info.ret = MetaType::Byte | MetaType::Array; - - info.params.append( - qMakePair(getqsizetypeMetaType(), QStringLiteral("offset"))); - info.params.append(qMakePair(MetaType::String, QStringLiteral("type"))); - - _scriptInfo.insert(QStringLiteral("readRaw"), info); - } -} +WingCStruct::WingCStruct() : WingHex::IWingPlugin() {} WingCStruct::~WingCStruct() {} @@ -203,7 +51,6 @@ QString WingCStruct::retranslate(const QString &str) { WingCStruct::RegisteredEvents WingCStruct::registeredEvents() const { RegisteredEvents evs; - evs.setFlag(RegisteredEvent::ScriptUnSafeFnRegistering); evs.setFlag(RegisteredEvent::ScriptPragma); evs.setFlag(RegisteredEvent::ScriptPragmaInit); return evs; @@ -213,11 +60,6 @@ QList WingCStruct::registeredSettingPages() const { return _setpgs; } -QHash -WingCStruct::registeredScriptFns() const { - return _scriptInfo; -} - bool WingCStruct::eventOnScriptPragma(const QString &script, const QStringList &comments) { // #pragma WingCStruct Arch [32 | 64] @@ -288,9 +130,99 @@ bool WingCStruct::eventOnScriptPragma(const QString &script, void WingCStruct::eventOnScriptPragmaInit() { resetEnv(); } -QHash -WingCStruct::registeredScriptUnsafeFns() const { - return _scriptUnsafe; +void WingCStruct::onRegisterScriptObj(WingHex::IWingAngel *o) { + o->registerGlobalFunction( + WingHex::Meta_Bool, + std::bind(QOverload::of(&WingCStruct::addStruct), + this, std::placeholders::_1), + QStringLiteral("addStruct"), + {qMakePair(WingHex::Meta_String, QStringLiteral("header"))}); + + o->registerGlobalFunction( + WingHex::Meta_Bool, + std::bind(QOverload::of( + &WingCStruct::addStructFromFile), + this, std::placeholders::_1), + QStringLiteral("addStructFromFile"), + {qMakePair(WingHex::Meta_String, QStringLiteral("fileName"))}); + + o->registerGlobalFunction( + WingHex::Meta_Void, + std::bind(QOverload::of(&WingCStruct::resetEnv), + this, std::placeholders::_1), + QStringLiteral("resetEnv")); + + o->registerGlobalFunction( + WingHex::Meta_Bool, + std::bind( + QOverload::of(&WingCStruct::setStructPadding), + this, std::placeholders::_1), + QStringLiteral("setStructPadding"), + {qMakePair(WingHex::Meta_Int, QStringLiteral("padding"))}); + + o->registerGlobalFunction(WingHex::Meta_Int, + std::bind(QOverload::of( + &WingCStruct::structPadding), + this, std::placeholders::_1), + QStringLiteral("structPadding")); + + o->registerGlobalFunction(WingHex::Meta_String | WingHex::Meta_Array, + std::bind(QOverload::of( + &WingCStruct::structTypes), + this, std::placeholders::_1), + QStringLiteral("structTypes")); + + o->registerGlobalFunction( + getqsizetypeMetaType(), + std::bind( + QOverload::of(&WingCStruct::sizeofStruct), + this, std::placeholders::_1), + QStringLiteral("sizeofStruct"), + {qMakePair(WingHex::Meta_String, QStringLiteral("type"))}); + + o->registerGlobalFunction( + WingHex::Meta_Bool, + std::bind( + QOverload::of(&WingCStruct::existStruct), + this, std::placeholders::_1), + QStringLiteral("existStruct"), + {qMakePair(WingHex::Meta_String, QStringLiteral("type"))}); + + o->registerGlobalFunction(WingHex::Meta_String | WingHex::Meta_Array, + std::bind(QOverload::of( + &WingCStruct::constDefines), + this, std::placeholders::_1), + QStringLiteral("constDefines")); + + o->registerGlobalFunction( + WingHex::Meta_Bool, + std::bind( + QOverload::of(&WingCStruct::existDefineValue), + this, std::placeholders::_1), + QStringLiteral("existDefineValue"), + {qMakePair(WingHex::Meta_String, QStringLiteral("type"))}); + + o->registerGlobalFunction( + WingHex::Meta_Int, + std::bind( + QOverload::of(&WingCStruct::defineValue), + this, std::placeholders::_1), + QStringLiteral("defineValue"), + {qMakePair(WingHex::Meta_String, QStringLiteral("type"))}); + + // nested dictionary is not supported, so unsafe registering will help + o->registerGlobalFunction( + QStringLiteral("dictionary@ read(") + getqsizeTypeAsString() + + (" offset, const string &in type)"), + std::bind(QOverload &>::of(&WingCStruct::read), + this, std::placeholders::_1)); + + o->registerGlobalFunction( + WingHex::Meta_Byte | WingHex::Meta_Array, + std::bind(QOverload::of(&WingCStruct::readRaw), + this, std::placeholders::_1), + QStringLiteral("readRaw"), + {qMakePair(WingHex::Meta_String, QStringLiteral("type"))}); } bool WingCStruct::addStruct(const QString &header) { @@ -713,9 +645,9 @@ CScriptArray *WingCStruct::convert2AsArray(const QVariantList &array, return arr; } -WingHex::IWingPlugin::MetaType WingCStruct::getqsizetypeMetaType() const { - return sizeof(qsizetype) == sizeof(quint64) ? MetaType::Int64 - : MetaType::Int32; +WingHex::MetaType WingCStruct::getqsizetypeMetaType() const { + return sizeof(qsizetype) == sizeof(quint64) ? WingHex::MetaType::Meta_Int64 + : WingHex::MetaType::Meta_Int32; } QVariant WingCStruct::addStruct(const QVariantList ¶ms) { @@ -834,8 +766,7 @@ QVariant WingCStruct::defineValue(const QVariantList ¶ms) { return defineValue(type); } -WingHex::IWingPlugin::UNSAFE_RET -WingCStruct::read(const QList ¶ms) { +WingHex::UNSAFE_RET WingCStruct::read(const QList ¶ms) { if (params.size() != 2) { return generateScriptCallError(-1, tr("InvalidParamsCount")); } diff --git a/src/class/wingcstruct.h b/src/class/wingcstruct.h index 2d75326..1670f8e 100644 --- a/src/class/wingcstruct.h +++ b/src/class/wingcstruct.h @@ -48,12 +48,13 @@ public: virtual RegisteredEvents registeredEvents() const override; virtual QList registeredSettingPages() const override; - virtual QHash registeredScriptFns() const override; virtual bool eventOnScriptPragma(const QString &script, const QStringList &comments) override; virtual void eventOnScriptPragmaInit() override; - virtual QHash - registeredScriptUnsafeFns() const override; + + // IWingPluginCoreBase interface +public: + virtual void onRegisterScriptObj(WingHex::IWingAngel *o) override; private: // basic @@ -78,7 +79,7 @@ private: WING_SERVICE QByteArray readRaw(qsizetype offset, const QString &type); private: - MetaType getqsizetypeMetaType() const; + WingHex::MetaType getqsizetypeMetaType() const; QString getqsizeTypeAsString() const; @@ -111,15 +112,13 @@ private: QVariant existDefineValue(const QVariantList ¶ms); QVariant defineValue(const QVariantList ¶ms); - UNSAFE_RET read(const QList ¶ms); + WingHex::UNSAFE_RET read(const QList ¶ms); QVariant readRaw(const QVariantList ¶ms); private: CTypeParser _parser; QList _setpgs; - QHash _scriptInfo; - QHash _scriptUnsafe; }; #endif // WINGCSTRUCT_H diff --git a/src/class/winggeneric.cpp b/src/class/winggeneric.cpp new file mode 100644 index 0000000..21daec4 --- /dev/null +++ b/src/class/winggeneric.cpp @@ -0,0 +1,100 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ + +#include "winggeneric.h" + +#include "angelscript.h" + +WingGeneric::WingGeneric(asIScriptGeneric *gen) : _gen(gen) {} + +int WingGeneric::argCount() const { return _gen->GetArgCount(); } + +int WingGeneric::argTypeId(uint arg, quint32 *flags) const { + static_assert(sizeof(quint32) == sizeof(asDWORD), + "asDWORD is same with quint32"); + return _gen->GetArgTypeId(arg, reinterpret_cast(flags)); +} + +QString WingGeneric::argTypeName(uint arg, quint32 *flags) { + auto e = _gen->GetEngine(); + auto str = e->GetTypeDeclaration(argTypeId(arg, flags)); + if (str) { + return str; + } else { + return {}; + } +} + +uchar WingGeneric::argByte(uint arg) { return _gen->GetArgByte(arg); } + +quint16 WingGeneric::argWord(uint arg) { return _gen->GetArgWord(arg); } + +quint32 WingGeneric::argDWord(uint arg) { return _gen->GetArgDWord(arg); } + +quint64 WingGeneric::argQWord(uint arg) { return _gen->GetArgQWord(arg); } + +float WingGeneric::argFloat(uint arg) { return _gen->GetArgFloat(arg); } + +double WingGeneric::argDouble(uint arg) { return _gen->GetArgDouble(arg); } + +void *WingGeneric::argAddress(uint arg) { return _gen->GetArgAddress(arg); } + +void *WingGeneric::argObject(uint arg) { return _gen->GetArgObject(arg); } + +void *WingGeneric::addressOfArg(uint arg) { return _gen->GetAddressOfArg(arg); } + +int WingGeneric::returnTypeId(quint32 *flags) const { + static_assert(sizeof(quint32) == sizeof(asDWORD), + "asDWORD is same with quint32"); + return _gen->GetReturnTypeId(reinterpret_cast(flags)); +} + +WingHex::asRetCodes WingGeneric::setReturnByte(uchar val) { + return WingHex::asRetCodes(_gen->SetReturnByte(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnWord(quint16 val) { + return WingHex::asRetCodes(_gen->SetReturnWord(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnDWord(quint32 val) { + return WingHex::asRetCodes(_gen->SetReturnDWord(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnQWord(quint64 val) { + return WingHex::asRetCodes(_gen->SetReturnQWord(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnFloat(float val) { + return WingHex::asRetCodes(_gen->SetReturnFloat(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnDouble(double val) { + return WingHex::asRetCodes(_gen->SetReturnDouble(val)); +} + +WingHex::asRetCodes WingGeneric::setReturnAddress(void *addr) { + return WingHex::asRetCodes(_gen->SetReturnAddress(addr)); +} + +WingHex::asRetCodes WingGeneric::setReturnObject(void *obj) { + return WingHex::asRetCodes(_gen->SetReturnObject(obj)); +} + +void *WingGeneric::addressOfReturnLocation() { + return _gen->GetAddressOfReturnLocation(); +} diff --git a/src/class/winggeneric.h b/src/class/winggeneric.h new file mode 100644 index 0000000..c06ba76 --- /dev/null +++ b/src/class/winggeneric.h @@ -0,0 +1,58 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ + +#ifndef WINGGENERIC_H +#define WINGGENERIC_H + +#include "WingPlugin/iwingangel.h" + +class asIScriptGeneric; + +class WingGeneric : public WingHex::IWingGeneric { +public: + explicit WingGeneric(asIScriptGeneric *gen); + + // IWingGeneric interface +public: + int argCount() const override; + int argTypeId(uint arg, quint32 *flags) const override; + QString argTypeName(uint arg, quint32 *flags) override; + uchar argByte(uint arg) override; + quint16 argWord(uint arg) override; + quint32 argDWord(uint arg) override; + quint64 argQWord(uint arg) override; + float argFloat(uint arg) override; + double argDouble(uint arg) override; + void *argAddress(uint arg) override; + void *argObject(uint arg) override; + void *addressOfArg(uint arg) override; + int returnTypeId(quint32 *flags) const override; + WingHex::asRetCodes setReturnByte(uchar val) override; + WingHex::asRetCodes setReturnWord(quint16 val) override; + WingHex::asRetCodes setReturnDWord(quint32 val) override; + WingHex::asRetCodes setReturnQWord(quint64 val) override; + WingHex::asRetCodes setReturnFloat(float val) override; + WingHex::asRetCodes setReturnDouble(double val) override; + WingHex::asRetCodes setReturnAddress(void *addr) override; + WingHex::asRetCodes setReturnObject(void *obj) override; + void *addressOfReturnLocation() override; + +private: + asIScriptGeneric *_gen; +}; + +#endif // WINGGENERIC_H diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp index b140fd4..284013c 100644 --- a/src/dialog/mainwindow.cpp +++ b/src/dialog/mainwindow.cpp @@ -234,26 +234,62 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() { auto &sm = ScriptMachine::instance(); auto smr = sm.init(); if (smr) { - ScriptMachine::RegCallBacks callbacks; - callbacks.getInputFn = [this]() -> QString { - return m_scriptConsole->getInput(); - }; - callbacks.clearFn = [this]() { m_scriptConsole->clearConsole(); }; - callbacks.printMsgFn = - [this](const ScriptMachine::MessageInfo &message) { - m_scriptConsole->onOutput(message); - }; - sm.registerCallBack(ScriptMachine::Interactive, callbacks); + plg.doneRegisterScriptObj(); + auto cfgerr = sm.isEngineConfigError(); - callbacks.getInputFn = [this]() -> QString { - return WingInputDialog::getText(this, tr("InputRequest"), - tr("PleaseInput")); - }; - callbacks.clearFn = [this]() { m_bgScriptOutput->clear(); }; - callbacks.printMsgFn = - std::bind(&MainWindow::onOutputBgScriptOutput, this, - std::placeholders::_1); - sm.registerCallBack(ScriptMachine::Background, callbacks); + // At this time, AngelScript service plugin has started + if (cfgerr) { + m_scriptConsole->initOutput(); + m_scriptConsole->setMode(QConsoleWidget::Output); + m_scriptConsole->stdErr(tr("EngineConfigError")); + + m_scriptConsole->setEnabled(false); + + // configure error, so disable all script feature + WingHex::WingRibbonToolBoxInfo::RibbonCatagories catagories; + m_ribbonMaps[catagories.SCRIPT]->setEnabled(false); + } else { + ScriptMachine::RegCallBacks callbacks; + callbacks.getInputFn = [this]() -> QString { + return m_scriptConsole->getInput(); + }; + callbacks.clearFn = [this]() { + m_scriptConsole->clearConsole(); + }; + callbacks.printMsgFn = + [this](const ScriptMachine::MessageInfo &message) { + m_scriptConsole->onOutput(message); + }; + sm.registerCallBack(ScriptMachine::Interactive, callbacks); + + callbacks.getInputFn = [this]() -> QString { + return WingInputDialog::getText(this, tr("InputRequest"), + tr("PleaseInput")); + }; + callbacks.clearFn = [this]() { m_bgScriptOutput->clear(); }; + callbacks.printMsgFn = + std::bind(&MainWindow::onOutputBgScriptOutput, this, + std::placeholders::_1); + sm.registerCallBack(ScriptMachine::Background, callbacks); + + if (splash) + splash->setInfoText(tr("SetupConsole")); + + m_scriptConsole->init(); + if (splash) + splash->setInfoText(tr("SetupScriptManager")); + + if (splash) + splash->setInfoText(tr("SetupScriptService")); + + m_scriptConsole->initOutput(); + m_scriptConsole->setMode(QConsoleWidget::Input); + + if (splash) + splash->setInfoText(tr("SetupScriptEditor")); + m_scriptDialog = new ScriptingDialog(this); + m_scriptDialog->initConsole(); + } } else { QMessageBox::critical(this, qAppName(), tr("ScriptEngineInitFailed")); @@ -261,25 +297,6 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() { set.save(SettingManager::SCRIPT); throw CrashCode::ScriptInitFailed; } - - // At this time, AngelScript service plugin has started - if (splash) - splash->setInfoText(tr("SetupConsole")); - - m_scriptConsole->init(); - if (splash) - splash->setInfoText(tr("SetupScriptManager")); - - if (splash) - splash->setInfoText(tr("SetupScriptService")); - - m_scriptConsole->initOutput(); - m_scriptConsole->setMode(QConsoleWidget::Input); - - if (splash) - splash->setInfoText(tr("SetupScriptEditor")); - m_scriptDialog = new ScriptingDialog(this); - m_scriptDialog->initConsole(); } // connect settings signals diff --git a/src/utilities.h b/src/utilities.h index ebfda9b..5181c59 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -313,6 +313,23 @@ public: return dec->toUnicode(buffer); #endif } + + static bool isValidIdentifier(const QString &str) { + if (str.isEmpty()) { + return false; + } + auto pch = str.cbegin(); + if (pch->isDigit()) { + return false; + } + pch++; + for (; pch != str.cend(); pch++) { + if (!pch->isLetterOrNumber() && *pch != '_') { + return false; + } + } + return true; + } }; #endif // UTILITIES_H