Proper handling of enum classes for scripting

This commit is contained in:
ksuprynowicz 2022-08-15 21:00:45 +02:00
parent 95434a26a8
commit 33c8607e15
4 changed files with 59 additions and 11 deletions

View file

@ -1,16 +1,24 @@
// //
// Created by Sam Gondelman on 5/16/19 // Created by Sam Gondelman on 5/16/19
// Copyright 2013-2019 High Fidelity, Inc. // Copyright 2013-2019 High Fidelity, Inc.
// Copyright 2022 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "RenderScriptingInterface.h" #include "RenderScriptingInterface.h"
#include <ScriptEngineCast.h>
#include "LightingModel.h" #include "LightingModel.h"
#include <QScreen> #include <QScreen>
#include "ScreenName.h" #include "ScreenName.h"
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType(scriptEngine, scriptValueFromEnumClass<RenderScriptingInterface::RenderMethod>, scriptValueToEnumClass<RenderScriptingInterface::RenderMethod>, "RenderMethod");
});
RenderScriptingInterface* RenderScriptingInterface::getInstance() { RenderScriptingInterface* RenderScriptingInterface::getInstance() {
static RenderScriptingInterface sharedInstance; static RenderScriptingInterface sharedInstance;
@ -22,8 +30,6 @@ std::once_flag RenderScriptingInterface::registry_flag;
RenderScriptingInterface::RenderScriptingInterface() { RenderScriptingInterface::RenderScriptingInterface() {
std::call_once(registry_flag, [] { std::call_once(registry_flag, [] {
qmlRegisterType<RenderScriptingInterface>("RenderEnums", 1, 0, "RenderEnums"); qmlRegisterType<RenderScriptingInterface>("RenderEnums", 1, 0, "RenderEnums");
qRegisterMetaType<RenderScriptingInterface::RenderMethod>("RenderScriptingInterface::RenderMethod");
qDebug() << "qRegisterMetaType<RenderScriptingInterface::RenderMethod>(\"RenderScriptingInterface::RenderMethod\")";
}); });
} }

View file

@ -61,8 +61,7 @@ public:
* @typedef {number} Render.RenderMethod * @typedef {number} Render.RenderMethod
*/ */
// RenderMethod enum type // RenderMethod enum type
//enum class RenderMethod { enum class RenderMethod {
enum RenderMethod {
DEFERRED = render::Args::RenderMethod::DEFERRED, DEFERRED = render::Args::RenderMethod::DEFERRED,
FORWARD = render::Args::RenderMethod::FORWARD, FORWARD = render::Args::RenderMethod::FORWARD,
}; };

View file

@ -4,6 +4,7 @@
// //
// Created by Heather Anderson on 5/9/2021. // Created by Heather Anderson on 5/9/2021.
// Copyright 2021 Vircadia contributors. // Copyright 2021 Vircadia contributors.
// Copyright 2022 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // 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) // Object conversion helpers (copied from QScriptEngine)
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtCore/QMetaEnum>
#include <QtCore/QDebug>
#include "ScriptEngine.h" #include "ScriptEngine.h"
#include "ScriptValue.h" #include "ScriptValue.h"
@ -66,10 +69,15 @@ inline QVariant scriptvalue_cast<QVariant>(const ScriptValue& value) {
template <typename T> template <typename T>
int scriptRegisterMetaType(ScriptEngine* eng, int scriptRegisterMetaType(ScriptEngine* eng,
ScriptValue (*toScriptValue)(ScriptEngine*, const T& t), ScriptValue (*toScriptValue)(ScriptEngine*, const T& t),
bool (*fromScriptValue)(const ScriptValue&, T& t), bool (*fromScriptValue)(const ScriptValue&, T& t), const char* name = "",
T* = 0) T* = 0)
{ {
const int id = qRegisterMetaType<T>(); // make sure it's registered int id;
if (strlen(name) > 0) { // make sure it's registered
id = qRegisterMetaType<T>(name);
} else {
id = qRegisterMetaType<T>();
}
eng->registerCustomType(id, reinterpret_cast<ScriptEngine::MarshalFunction>(toScriptValue), eng->registerCustomType(id, reinterpret_cast<ScriptEngine::MarshalFunction>(toScriptValue),
reinterpret_cast<ScriptEngine::DemarshalFunction>(fromScriptValue)); reinterpret_cast<ScriptEngine::DemarshalFunction>(fromScriptValue));
return id; return id;
@ -98,6 +106,40 @@ bool scriptValueToSequence(const ScriptValue& value, Container& cont) {
return true; return true;
} }
template <class T>
ScriptValue scriptValueFromEnumClass(ScriptEngine* eng, const T& enumValue) {
ScriptValue a = eng->newValue(static_cast<int>(enumValue));
return a;
}
template <class T>
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<T>();
if (!metaEnum.isValid()) {
qDebug() << "Invalid QMetaEnum";
return false;
}
bool isValid = false;
int enumInteger = static_cast<int>(value.toInteger());
for(int i = 0; i < metaEnum.keyCount(); i++){
if (metaEnum.value(i) == enumInteger) {
isValid = true;
break;
}
}
if (isValid) {
enumValue = static_cast<T>(enumInteger);
return true;
} else {
qDebug() << "ScriptValue has invalid value " << value.toInteger() << " for enum" << metaEnum.name();
return false;
}
}
template <typename T> template <typename T>
int scriptRegisterSequenceMetaType(ScriptEngine* engine, int scriptRegisterSequenceMetaType(ScriptEngine* engine,
T* = 0) { T* = 0) {

View file

@ -209,12 +209,13 @@ void ScriptObjectQtProxy::investigate() {
} }
} else { } else {
int parameterCount = method.parameterCount(); int parameterCount = method.parameterCount();
if (name.toString() == "getRenderMethod"){ if(method.returnType() == QMetaType::UnknownType) {
qDebug() << name << " " << QMetaType(method.returnType()).name(); qCritical() << "Method " << metaObject->className() << "::" << name << " has QMetaType::UnknownType return value";
if(method.returnType() == QMetaType::UnknownType) { }
qDebug() << "Method with QMetaType::UnknownType"; 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()) { if (nameLookup == methodNames.end()) {
MethodDef& methodDef = _methods.insert(idx, MethodDef()).value(); MethodDef& methodDef = _methods.insert(idx, MethodDef()).value();