From 33c8607e153e964176e0553f91d04eeb22a7df95 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Mon, 15 Aug 2022 21:00:45 +0200 Subject: [PATCH] Proper handling of enum classes for scripting --- .../scripting/RenderScriptingInterface.cpp | 10 +++- .../src/scripting/RenderScriptingInterface.h | 3 +- .../script-engine/src/ScriptEngineCast.h | 46 ++++++++++++++++++- .../src/qtscript/ScriptObjectQtProxy.cpp | 11 +++-- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 8388653827..ecaee570b7 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -1,16 +1,24 @@ // // Created by Sam Gondelman on 5/16/19 // Copyright 2013-2019 High Fidelity, Inc. +// Copyright 2022 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "RenderScriptingInterface.h" +#include + #include "LightingModel.h" #include #include "ScreenName.h" +STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){ + auto scriptEngine = manager->engine().get(); + + scriptRegisterMetaType(scriptEngine, scriptValueFromEnumClass, scriptValueToEnumClass, "RenderMethod"); +}); RenderScriptingInterface* RenderScriptingInterface::getInstance() { static RenderScriptingInterface sharedInstance; @@ -22,8 +30,6 @@ std::once_flag RenderScriptingInterface::registry_flag; RenderScriptingInterface::RenderScriptingInterface() { std::call_once(registry_flag, [] { qmlRegisterType("RenderEnums", 1, 0, "RenderEnums"); - qRegisterMetaType("RenderScriptingInterface::RenderMethod"); - qDebug() << "qRegisterMetaType(\"RenderScriptingInterface::RenderMethod\")"; }); } diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index d4ff879e22..27088daf97 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -61,8 +61,7 @@ public: * @typedef {number} Render.RenderMethod */ // RenderMethod enum type - //enum class RenderMethod { - enum RenderMethod { + enum class RenderMethod { DEFERRED = render::Args::RenderMethod::DEFERRED, FORWARD = render::Args::RenderMethod::FORWARD, }; diff --git a/libraries/script-engine/src/ScriptEngineCast.h b/libraries/script-engine/src/ScriptEngineCast.h index 7ab6b02f38..ae2282bd34 100644 --- a/libraries/script-engine/src/ScriptEngineCast.h +++ b/libraries/script-engine/src/ScriptEngineCast.h @@ -4,6 +4,7 @@ // // Created by Heather Anderson on 5/9/2021. // Copyright 2021 Vircadia contributors. +// Copyright 2022 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -18,6 +19,8 @@ // Object conversion helpers (copied from QScriptEngine) #include +#include +#include #include "ScriptEngine.h" #include "ScriptValue.h" @@ -66,10 +69,15 @@ inline QVariant scriptvalue_cast(const ScriptValue& value) { template int scriptRegisterMetaType(ScriptEngine* eng, ScriptValue (*toScriptValue)(ScriptEngine*, const T& t), - bool (*fromScriptValue)(const ScriptValue&, T& t), + bool (*fromScriptValue)(const ScriptValue&, T& t), const char* name = "", T* = 0) { - const int id = qRegisterMetaType(); // make sure it's registered + int id; + if (strlen(name) > 0) { // make sure it's registered + id = qRegisterMetaType(name); + } else { + id = qRegisterMetaType(); + } eng->registerCustomType(id, reinterpret_cast(toScriptValue), reinterpret_cast(fromScriptValue)); return id; @@ -98,6 +106,40 @@ bool scriptValueToSequence(const ScriptValue& value, Container& cont) { return true; } +template +ScriptValue scriptValueFromEnumClass(ScriptEngine* eng, const T& enumValue) { + ScriptValue a = eng->newValue(static_cast(enumValue)); + return a; +} + +template +bool scriptValueToEnumClass(const ScriptValue& value, T& enumValue) { + if(!value.isNumber()){ + qDebug() << "ScriptValue \"" << value.toQObject()->metaObject()->className() << "\" is not a number"; + return false; + } + QMetaEnum metaEnum = QMetaEnum::fromType(); + if (!metaEnum.isValid()) { + qDebug() << "Invalid QMetaEnum"; + return false; + } + bool isValid = false; + int enumInteger = static_cast(value.toInteger()); + for(int i = 0; i < metaEnum.keyCount(); i++){ + if (metaEnum.value(i) == enumInteger) { + isValid = true; + break; + } + } + if (isValid) { + enumValue = static_cast(enumInteger); + return true; + } else { + qDebug() << "ScriptValue has invalid value " << value.toInteger() << " for enum" << metaEnum.name(); + return false; + } +} + template int scriptRegisterSequenceMetaType(ScriptEngine* engine, T* = 0) { diff --git a/libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp b/libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp index f350041566..c551920ac2 100644 --- a/libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp +++ b/libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp @@ -209,12 +209,13 @@ void ScriptObjectQtProxy::investigate() { } } else { int parameterCount = method.parameterCount(); - if (name.toString() == "getRenderMethod"){ - qDebug() << name << " " << QMetaType(method.returnType()).name(); - if(method.returnType() == QMetaType::UnknownType) { - qDebug() << "Method with QMetaType::UnknownType"; + if(method.returnType() == QMetaType::UnknownType) { + qCritical() << "Method " << metaObject->className() << "::" << name << " has QMetaType::UnknownType return value"; + } + for (int i = 0; i < method.parameterCount(); i++) { + if (method.parameterType(i) == QMetaType::UnknownType) { + qCritical() << "Parameter " << i << "in method " << metaObject->className() << "::" << name << " is of type QMetaType::UnknownType"; } - printf("getRenderMethod"); } if (nameLookup == methodNames.end()) { MethodDef& methodDef = _methods.insert(idx, MethodDef()).value();