feat: 充分的插件系统和脚本系统的绑定;

This commit is contained in:
寂静的羽夏 2025-06-29 22:18:11 +08:00
parent b42880aa7e
commit fb4f439e50
23 changed files with 2893 additions and 2479 deletions

View File

@ -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

View File

@ -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

View File

@ -269,60 +269,60 @@
<context>
<name>TestPlugin</name>
<message>
<location filename="../testplugin.cpp" line="204"/>
<location filename="../testplugin.cpp" line="69"/>
<source>Test</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="216"/>
<location filename="../testplugin.cpp" line="225"/>
<location filename="../testplugin.cpp" line="230"/>
<location filename="../testplugin.cpp" line="299"/>
<location filename="../testplugin.cpp" line="81"/>
<location filename="../testplugin.cpp" line="90"/>
<location filename="../testplugin.cpp" line="95"/>
<location filename="../testplugin.cpp" line="164"/>
<source>TestPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="234"/>
<location filename="../testplugin.cpp" line="99"/>
<source>Button - </source>
<translation> - </translation>
</message>
<message>
<location filename="../testplugin.cpp" line="238"/>
<location filename="../testplugin.cpp" line="103"/>
<source>Click</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="302"/>
<location filename="../testplugin.cpp" line="167"/>
<source>A Test Plugin for WingHexExplorer2.</source>
<translation>2</translation>
</message>
<message>
<location filename="../testplugin.cpp" line="336"/>
<location filename="../testplugin.cpp" line="344"/>
<location filename="../testplugin.cpp" line="353"/>
<location filename="../testplugin.cpp" line="374"/>
<location filename="../testplugin.cpp" line="390"/>
<location filename="../testplugin.cpp" line="397"/>
<location filename="../testplugin.cpp" line="404"/>
<location filename="../testplugin.cpp" line="411"/>
<location filename="../testplugin.cpp" line="419"/>
<location filename="../testplugin.cpp" line="448"/>
<location filename="../testplugin.cpp" line="456"/>
<location filename="../testplugin.cpp" line="464"/>
<location filename="../testplugin.cpp" line="472"/>
<location filename="../testplugin.cpp" line="481"/>
<location filename="../testplugin.cpp" line="488"/>
<location filename="../testplugin.cpp" line="196"/>
<location filename="../testplugin.cpp" line="204"/>
<location filename="../testplugin.cpp" line="213"/>
<location filename="../testplugin.cpp" line="234"/>
<location filename="../testplugin.cpp" line="250"/>
<location filename="../testplugin.cpp" line="257"/>
<location filename="../testplugin.cpp" line="264"/>
<location filename="../testplugin.cpp" line="271"/>
<location filename="../testplugin.cpp" line="278"/>
<location filename="../testplugin.cpp" line="307"/>
<location filename="../testplugin.cpp" line="315"/>
<location filename="../testplugin.cpp" line="323"/>
<location filename="../testplugin.cpp" line="331"/>
<location filename="../testplugin.cpp" line="340"/>
<location filename="../testplugin.cpp" line="347"/>
<source>InvalidParamsCount</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="367"/>
<location filename="../testplugin.cpp" line="383"/>
<location filename="../testplugin.cpp" line="227"/>
<location filename="../testplugin.cpp" line="243"/>
<source>InvalidParam</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="439"/>
<location filename="../testplugin.cpp" line="298"/>
<source>AllocArrayFailed</source>
<translation></translation>
</message>

View File

@ -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 <QApplication>
#include <QMenu>
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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::of(
&TestPlugin::printLogTestSharedMemData),
this, std::placeholders::_1);
info.ret = MetaType::Void;
_scriptInfo.insert(QStringLiteral("printLogTestSharedMemData"), info);
}
{
_scriptUnsafe.insert(QStringLiteral("array<color>@ colorTable()"),
std::bind(QOverload<const QList<void *> &>::of(
&TestPlugin::colorTable),
this, std::placeholders::_1));
}
{
WingHex::IWingPlugin::ScriptFnInfo info;
info.fn = std::bind(QOverload<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<QString, WingHex::IWingPlugin::UNSAFE_SCFNPTR>
TestPlugin::registeredScriptUnsafeFns() const {
return _scriptUnsafe;
}
QVariant TestPlugin::test_a(const QVariantList &params) {
if (!params.isEmpty()) {
return getScriptCallError(-1, tr("InvalidParamsCount"));
@ -413,8 +273,7 @@ QVariant TestPlugin::test_h(const QVariantList &params) {
return test_h();
}
WingHex::IWingPlugin::UNSAFE_RET
TestPlugin::colorTable(const QList<void *> &params) {
WingHex::UNSAFE_RET TestPlugin::colorTable(const QList<void *> &params) {
if (!params.isEmpty()) {
return generateScriptCallError(-1, tr("InvalidParamsCount"));
}
@ -427,7 +286,7 @@ TestPlugin::colorTable(const QList<void *> &params) {
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 &params) {
return {};
}
void TestPlugin::testGenericAdd(WingHex::asIWingGeneric *param) {
auto g = QScopedPointer<WingHex::IWingGeneric>(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<QString, WingHex::IWingPlugin::ScriptFnInfo>
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<const QVariantList &>::of(&TestPlugin::test_a),
this, std::placeholders::_1),
QStringLiteral("test_a"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Void,
std::bind(QOverload<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::of(&TestPlugin::test_e),
this, std::placeholders::_1),
QStringLiteral("test_e"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Byte | WingHex::MetaType::Meta_Array,
std::bind(QOverload<const QVariantList &>::of(&TestPlugin::test_f),
this, std::placeholders::_1),
QStringLiteral("test_f"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_String,
std::bind(QOverload<const QVariantList &>::of(&TestPlugin::test_g),
this, std::placeholders::_1),
QStringLiteral("test_g"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Hash,
std::bind(QOverload<const QVariantList &>::of(&TestPlugin::test_h),
this, std::placeholders::_1),
QStringLiteral("test_h"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Bool,
std::bind(QOverload<const QVariantList &>::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<const QVariantList &>::of(
&TestPlugin::destoryTestShareMem),
this, std::placeholders::_1),
QStringLiteral("destoryTestShareMem"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Void,
std::bind(QOverload<const QVariantList &>::of(
&TestPlugin::printLogTestSharedMemData),
this, std::placeholders::_1),
QStringLiteral("printLogTestSharedMemData"));
o->registerGlobalFunction(
QStringLiteral("array<color>@ colorTable()"),
std::bind(QOverload<const QList<void *> &>::of(&TestPlugin::colorTable),
this, std::placeholders::_1));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Void,
std::bind(QOverload<const QVariantList &>::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<const QVariantList &>::of(
&TestPlugin::pluginMetaTestEnabled),
this, std::placeholders::_1),
QStringLiteral("pluginMetaTestEnabled"));
o->registerGlobalFunction(
WingHex::MetaType::Meta_Void,
std::bind(QOverload<const QVariantList &>::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);
}

View File

@ -60,14 +60,14 @@ public:
registeredSettingPages() const override;
virtual QList<QSharedPointer<WingHex::WingEditorViewWidget::Creator>>
registeredEditorViewWidgets() const override;
virtual QHash<QString, ScriptFnInfo> registeredScriptFns() const override;
virtual QHash<QString, UNSAFE_SCFNPTR>
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 &params);
QVariant test_b(const QVariantList &params);
@ -79,7 +79,7 @@ private:
QVariant test_g(const QVariantList &params);
QVariant test_h(const QVariantList &params);
UNSAFE_RET colorTable(const QList<void *> &params);
WingHex::UNSAFE_RET colorTable(const QList<void *> &params);
QVariant createTestShareMem(const QVariantList &params);
QVariant destoryTestShareMem(const QVariantList &params);
@ -90,6 +90,10 @@ private:
QVariant testCrash(const QVariantList &params);
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<QString, WingHex::IWingPlugin::ScriptFnInfo> _scriptInfo;
QList<WingHex::WingDockWidgetInfo> _winfo;
QList<WingHex::WingRibbonToolBoxInfo> _rtbinfo;
QList<WingHex::SettingPage *> _setpages;
QList<QSharedPointer<WingHex::WingEditorViewWidget::Creator>> _evws;
QHash<QString, WingHex::IWingPlugin::UNSAFE_SCFNPTR> _scriptUnsafe;
};
#endif // TESTPLUGIN_H

@ -1 +1 @@
Subproject commit ec5bcd41309e175aa262f367011c1ad9fe7e9b31
Subproject commit cdaf256c8a44e724cc295e5b23cc291ac2414c02

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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<asCScriptEngine *>(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<asIScriptGeneric *>(ctx);
if (gen) {
return new WingGeneric(gen);
}
return nullptr;
}
bool PluginSystem::passByFailedGuard(const QObject *sender, const char *func,
const QVariantList &params) {
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<WingAngel>(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<PluginInfo> &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<asCScriptFunction *> fnlist;
auto r = _engine->SetDefaultNamespace(rawID);
if (Q_UNLIKELY(r < 0)) {
_engine->configFailed = false;
return;
}
// <signatures, std::function>
QHash<QString, IWingPlugin::ScriptFnInfo> 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<asCScriptFunction *> fnlist;
auto r = _engine->SetDefaultNamespace(rawID);
if (Q_UNLIKELY(r < 0)) {
_engine->configFailed = false;
return;
}
// <signatures, std::function>
QHash<QString, IWingPlugin::UNSAFE_SCFNPTR> 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<byte> and array<string> are
// supported in AngelScript
// ( array<byte> -> QByteArray , array<string> -> 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 &param : 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<WingRibbonToolBoxInfo> &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() {

View File

@ -136,6 +136,8 @@ public:
void loadAllPlugin();
void unloadAllPlugin();
void doneRegisterScriptObj();
void destory();
const QList<IWingPlugin *> &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<QDir> &setdir);
private:
void registerMarcoDevice(IWingDevice *plg);
void registerPluginDetectMarco(const QString &id);
private:
void registerRibbonTools(const QList<WingRibbonToolBoxInfo> &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<QString, QHash<QString, WingAngelAPI::ScriptFnInfo>> _scfns;
IWingManager *_manager = nullptr;
std::optional<PluginInfo> _manInfo;
WingAngelAPI *_angelplg = nullptr;
asCScriptEngine *_engine = nullptr;
QStringList _scriptMarcos;
QList<IWingPlugin *> _pragmaedPlg;

View File

@ -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<asCScriptEngine *>(_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

View File

@ -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:

View File

@ -19,6 +19,7 @@
#define SKINMANAGER_H
#include <QCoreApplication>
#include <QHash>
#include <QObject>
class SkinManager {

597
src/class/wingangel.cpp Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#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>,
"asSFuncPtr must be standard layout");
static_assert(std::is_standard_layout_v<WingHex::asFuncPtr>,
"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<decltype(asSFuncPtr::flag),
decltype(WingHex::asFuncPtr::flag)>,
"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<asSFuncPtr>().ptr.m);
using StructF = decltype(std::declval<asSFuncPtr>().ptr.f);
using wStructM = decltype(std::declval<WingHex::asFuncPtr>().ptr.m);
using wStructF = decltype(std::declval<WingHex::asFuncPtr>().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<QPair<uint, QString>> &params) {
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<void *>(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<void *>(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<QPair<uint, QString>> &params) {
if (fnName.isEmpty()) {
return {};
}
QString sig;
auto ret = type2AngelScriptString(retMetaType, false);
if (ret.isEmpty()) {
return {};
}
sig += ret + QStringLiteral(" ") + fnName + QStringLiteral("(");
QStringList _params;
for (auto &param : 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<byte> and array<string> are
// supported in AngelScript
// ( array<byte> -> QByteArray , array<string> -> 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;
}
}

107
src/class/wingangel.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef WINGANGEL_H
#define WINGANGEL_H
#include "WingPlugin/iwingangel.h"
#include <QCoreApplication>
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<QPair<uint, QString>> &params) 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<QPair<uint, QString>> &params);
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

View File

@ -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 <QJsonDocument>
#include <QMessageBox>
#include <QTemporaryFile>
#include <QThread>
#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<QString, UNSAFE_SCFNPTR> &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<QString, QList<QPair<QString, int>>> &objs) {
Q_ASSERT(!ns.isEmpty());
if (objs.isEmpty()) {
return;
}
_objs.insert(ns, objs);
}
void WingAngelAPI::registerScriptFns(const QString &ns,
const QHash<QString, ScriptFnInfo> &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<void *>(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<void *>(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 &params = 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<byte> and array<string> are
// supported in AngelScript
// ( array<byte> -> QByteArray , array<string> -> 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<void *> 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<void *> &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<void *> &content) {
WingHex::MetaType type,
const QList<void *> &content) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
static_assert(std::is_same_v<QList<int>, QVector<int>>);
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<QString, QPair<MetaType, void *>> &content) {
const QHash<QString, QPair<WingHex::MetaType, void *>> &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;

View File

@ -29,10 +29,22 @@ class asIScriptEngine;
class ScriptMachine;
class ScriptingConsole;
namespace WingScriptInternal {
struct ScriptFnInfo {
uint ret; // MetaType
QVector<QPair<uint, QString>> params;
std::function<QVariant(const QVariantList &)> 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<QString, IWingPlugin::ScriptFnInfo> &rfns);
void registerUnSafeScriptFns(
const QString &ns,
const QHash<QString, IWingPlugin::UNSAFE_SCFNPTR> &rfns);
void
registerScriptEnums(const QString &ns,
const QHash<QString, QList<QPair<QString, int>>> &objs);
void installAPI(ScriptMachine *machine);
void installBasicTypes(asIScriptEngine *engine);
@ -84,6 +85,10 @@ public:
*reinterpret_cast<T *>(&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,8 +127,7 @@ private:
static QVariant qvariantGet(asIScriptEngine *engine, const void *raw,
int typeID, bool flag);
static bool
getQVariantGetFlag(const WingHex::IWingPlugin::ScriptFnInfo &info,
static bool getQVariantGetFlag(const WingScriptInternal::ScriptFnInfo &info,
int index);
template <typename T>
@ -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<void *> &content);
WING_SERVICE void *list2AsArray(const WingHex::SenderInfo &sender,
MetaType type,
WingHex::MetaType type,
const QList<void *> &content);
WING_SERVICE void deleteAsArray(const WingHex::SenderInfo &sender,
void *array);
WING_SERVICE void *
newAsDictionary(const WingHex::SenderInfo &sender,
const QHash<QString, QPair<MetaType, void *>> &content);
WING_SERVICE void *newAsDictionary(
const WingHex::SenderInfo &sender,
const QHash<QString, QPair<WingHex::MetaType, void *>> &content);
WING_SERVICE void deleteAsDictionary(const WingHex::SenderInfo &sender,
void *dic);
@ -284,13 +285,8 @@ private:
QFileDialog::Options options);
private:
QVector<IWingPlugin::ScriptFnInfo> _sfns;
QHash<QString, QHash<QString, qsizetype>> _rfns;
QVector<IWingPlugin::UNSAFE_SCFNPTR> _usfns;
QHash<QString, QHash<QString, qsizetype>> _urfns;
QHash<QString, QHash<QString, QList<QPair<QString, int>>>> _objs;
QVector<WingScriptInternal::ScriptFnInfo> _sfns;
QVector<WingHex::UNSAFE_SCFNPTR> _usfns;
QVector<int> _handles;
};

View File

@ -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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QVariantList &>::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<const QList<void *> &>::of(&WingCStruct::read),
this, std::placeholders::_1));
}
{
WingHex::IWingPlugin::ScriptFnInfo info;
info.fn = std::bind(
QOverload<const QVariantList &>::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<WingHex::SettingPage *> WingCStruct::registeredSettingPages() const {
return _setpgs;
}
QHash<QString, WingCStruct::ScriptFnInfo>
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<QString, WingHex::IWingPlugin::UNSAFE_SCFNPTR>
WingCStruct::registeredScriptUnsafeFns() const {
return _scriptUnsafe;
void WingCStruct::onRegisterScriptObj(WingHex::IWingAngel *o) {
o->registerGlobalFunction(
WingHex::Meta_Bool,
std::bind(QOverload<const QVariantList &>::of(&WingCStruct::addStruct),
this, std::placeholders::_1),
QStringLiteral("addStruct"),
{qMakePair(WingHex::Meta_String, QStringLiteral("header"))});
o->registerGlobalFunction(
WingHex::Meta_Bool,
std::bind(QOverload<const QVariantList &>::of(
&WingCStruct::addStructFromFile),
this, std::placeholders::_1),
QStringLiteral("addStructFromFile"),
{qMakePair(WingHex::Meta_String, QStringLiteral("fileName"))});
o->registerGlobalFunction(
WingHex::Meta_Void,
std::bind(QOverload<const QVariantList &>::of(&WingCStruct::resetEnv),
this, std::placeholders::_1),
QStringLiteral("resetEnv"));
o->registerGlobalFunction(
WingHex::Meta_Bool,
std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::setStructPadding),
this, std::placeholders::_1),
QStringLiteral("setStructPadding"),
{qMakePair(WingHex::Meta_Int, QStringLiteral("padding"))});
o->registerGlobalFunction(WingHex::Meta_Int,
std::bind(QOverload<const QVariantList &>::of(
&WingCStruct::structPadding),
this, std::placeholders::_1),
QStringLiteral("structPadding"));
o->registerGlobalFunction(WingHex::Meta_String | WingHex::Meta_Array,
std::bind(QOverload<const QVariantList &>::of(
&WingCStruct::structTypes),
this, std::placeholders::_1),
QStringLiteral("structTypes"));
o->registerGlobalFunction(
getqsizetypeMetaType(),
std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::sizeofStruct),
this, std::placeholders::_1),
QStringLiteral("sizeofStruct"),
{qMakePair(WingHex::Meta_String, QStringLiteral("type"))});
o->registerGlobalFunction(
WingHex::Meta_Bool,
std::bind(
QOverload<const QVariantList &>::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<const QVariantList &>::of(
&WingCStruct::constDefines),
this, std::placeholders::_1),
QStringLiteral("constDefines"));
o->registerGlobalFunction(
WingHex::Meta_Bool,
std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::existDefineValue),
this, std::placeholders::_1),
QStringLiteral("existDefineValue"),
{qMakePair(WingHex::Meta_String, QStringLiteral("type"))});
o->registerGlobalFunction(
WingHex::Meta_Int,
std::bind(
QOverload<const QVariantList &>::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<const QList<void *> &>::of(&WingCStruct::read),
this, std::placeholders::_1));
o->registerGlobalFunction(
WingHex::Meta_Byte | WingHex::Meta_Array,
std::bind(QOverload<const QVariantList &>::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 &params) {
@ -834,8 +766,7 @@ QVariant WingCStruct::defineValue(const QVariantList &params) {
return defineValue(type);
}
WingHex::IWingPlugin::UNSAFE_RET
WingCStruct::read(const QList<void *> &params) {
WingHex::UNSAFE_RET WingCStruct::read(const QList<void *> &params) {
if (params.size() != 2) {
return generateScriptCallError(-1, tr("InvalidParamsCount"));
}

View File

@ -48,12 +48,13 @@ public:
virtual RegisteredEvents registeredEvents() const override;
virtual QList<WingHex::SettingPage *>
registeredSettingPages() const override;
virtual QHash<QString, ScriptFnInfo> registeredScriptFns() const override;
virtual bool eventOnScriptPragma(const QString &script,
const QStringList &comments) override;
virtual void eventOnScriptPragmaInit() override;
virtual QHash<QString, UNSAFE_SCFNPTR>
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 &params);
QVariant defineValue(const QVariantList &params);
UNSAFE_RET read(const QList<void *> &params);
WingHex::UNSAFE_RET read(const QList<void *> &params);
QVariant readRaw(const QVariantList &params);
private:
CTypeParser _parser;
QList<WingHex::SettingPage *> _setpgs;
QHash<QString, WingCStruct::ScriptFnInfo> _scriptInfo;
QHash<QString, WingHex::IWingPlugin::UNSAFE_SCFNPTR> _scriptUnsafe;
};
#endif // WINGCSTRUCT_H

100
src/class/winggeneric.cpp Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#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<asDWORD *>(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<asDWORD *>(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();
}

58
src/class/winggeneric.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#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

View File

@ -234,11 +234,28 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
auto &sm = ScriptMachine::instance();
auto smr = sm.init();
if (smr) {
plg.doneRegisterScriptObj();
auto cfgerr = sm.isEngineConfigError();
// 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.clearFn = [this]() {
m_scriptConsole->clearConsole();
};
callbacks.printMsgFn =
[this](const ScriptMachine::MessageInfo &message) {
m_scriptConsole->onOutput(message);
@ -254,15 +271,7 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
std::bind(&MainWindow::onOutputBgScriptOutput, this,
std::placeholders::_1);
sm.registerCallBack(ScriptMachine::Background, callbacks);
} else {
QMessageBox::critical(this, qAppName(),
tr("ScriptEngineInitFailed"));
set.setScriptEnabled(false);
set.save(SettingManager::SCRIPT);
throw CrashCode::ScriptInitFailed;
}
// At this time, AngelScript service plugin has started
if (splash)
splash->setInfoText(tr("SetupConsole"));
@ -281,6 +290,14 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
m_scriptDialog = new ScriptingDialog(this);
m_scriptDialog->initConsole();
}
} else {
QMessageBox::critical(this, qAppName(),
tr("ScriptEngineInitFailed"));
set.setScriptEnabled(false);
set.save(SettingManager::SCRIPT);
throw CrashCode::ScriptInitFailed;
}
}
// connect settings signals
connect(&set, &SettingManager::sigEditorfontSizeChanged, this,

View File

@ -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