mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 06:32:57 +02:00
first pass creating Qt <-> QtScript interface
This commit is contained in:
parent
bd04554150
commit
bc6eaf25dc
63 changed files with 1711 additions and 298 deletions
|
@ -430,9 +430,10 @@ ScriptValue worldDetailQualityToScriptValue(ScriptEngine* engine, const WorldDet
|
|||
return engine->newValue(worldDetailQuality);
|
||||
}
|
||||
|
||||
void worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality) {
|
||||
bool worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality) {
|
||||
worldDetailQuality =
|
||||
static_cast<WorldDetailQuality>(std::min(std::max(object.toInt32(), (int)WORLD_DETAIL_LOW), (int)WORLD_DETAIL_HIGH));
|
||||
return true;
|
||||
}
|
||||
|
||||
void LODManager::setLODQualityLevel(float quality) {
|
||||
|
|
|
@ -383,6 +383,6 @@ private:
|
|||
};
|
||||
|
||||
ScriptValue worldDetailQualityToScriptValue(ScriptEngine* engine, const WorldDetailQuality& worldDetailQuality);
|
||||
void worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality);
|
||||
bool worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality);
|
||||
|
||||
#endif // hifi_LODManager_h
|
||||
|
|
|
@ -5707,16 +5707,18 @@ ScriptValue audioListenModeToScriptValue(ScriptEngine* engine, const AudioListen
|
|||
return engine->newValue(audioListenerMode);
|
||||
}
|
||||
|
||||
void audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode) {
|
||||
bool audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode) {
|
||||
audioListenerMode = static_cast<AudioListenerMode>(object.toUInt16());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue driveKeysToScriptValue(ScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys) {
|
||||
return engine->newValue(driveKeys);
|
||||
}
|
||||
|
||||
void driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys) {
|
||||
bool driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys) {
|
||||
driveKeys = static_cast<MyAvatar::DriveKeys>(object.toUInt16());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3120,10 +3120,10 @@ private:
|
|||
};
|
||||
|
||||
ScriptValue audioListenModeToScriptValue(ScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||
void audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode);
|
||||
bool audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode);
|
||||
|
||||
ScriptValue driveKeysToScriptValue(ScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys);
|
||||
void driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys);
|
||||
bool driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys);
|
||||
|
||||
bool isWearableEntity(const EntityItemPointer& entity);
|
||||
|
||||
|
|
|
@ -451,8 +451,9 @@ ScriptValue pickTypesToScriptValue(ScriptEngine* engine, const PickQuery::PickTy
|
|||
return engine->newValue(pickType);
|
||||
}
|
||||
|
||||
void pickTypesFromScriptValue(const ScriptValue& object, PickQuery::PickType& pickType) {
|
||||
bool pickTypesFromScriptValue(const ScriptValue& object, PickQuery::PickType& pickType) {
|
||||
pickType = static_cast<PickQuery::PickType>(object.toUInt16());
|
||||
return true;
|
||||
}
|
||||
|
||||
void PickScriptingInterface::registerMetaTypes(ScriptEngine* engine) {
|
||||
|
|
|
@ -136,7 +136,7 @@ ScriptValue DownloadInfoResultToScriptValue(ScriptEngine* engine, const Download
|
|||
return object;
|
||||
}
|
||||
|
||||
void DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoResult& result) {
|
||||
bool DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoResult& result) {
|
||||
QList<QVariant> downloading = object.property("downloading").toVariant().toList();
|
||||
result.downloading.clear();
|
||||
for (int i = 0; i < downloading.count(); i += 1) {
|
||||
|
@ -144,6 +144,7 @@ void DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoRe
|
|||
}
|
||||
|
||||
result.pending = object.property("pending").toVariant().toFloat();
|
||||
return true;
|
||||
}
|
||||
|
||||
DownloadInfoResult AccountServicesScriptingInterface::getDownloadInfo() {
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
Q_DECLARE_METATYPE(DownloadInfoResult)
|
||||
|
||||
ScriptValue DownloadInfoResultToScriptValue(ScriptEngine* engine, const DownloadInfoResult& result);
|
||||
void DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoResult& result);
|
||||
bool DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoResult& result);
|
||||
|
||||
class AccountServicesScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -101,10 +101,11 @@ ScriptValue interactiveWindowPointerToScriptValue(ScriptEngine* engine, const In
|
|||
return engine->newQObject(in, ScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
void interactiveWindowPointerFromScriptValue(const ScriptValue& object, InteractiveWindowPointer& out) {
|
||||
bool interactiveWindowPointerFromScriptValue(const ScriptValue& object, InteractiveWindowPointer& out) {
|
||||
if (const auto interactiveWindow = qobject_cast<InteractiveWindowPointer>(object.toQObject())) {
|
||||
out = interactiveWindow;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void InteractiveWindow::forwardKeyPressEvent(int key, int modifiers) {
|
||||
|
|
|
@ -411,7 +411,7 @@ private:
|
|||
typedef InteractiveWindow* InteractiveWindowPointer;
|
||||
|
||||
ScriptValue interactiveWindowPointerToScriptValue(ScriptEngine* engine, const InteractiveWindowPointer& in);
|
||||
void interactiveWindowPointerFromScriptValue(const ScriptValue& object, InteractiveWindowPointer& out);
|
||||
bool interactiveWindowPointerFromScriptValue(const ScriptValue& object, InteractiveWindowPointer& out);
|
||||
|
||||
void registerInteractiveWindowMetaType(ScriptEngine* engine);
|
||||
|
||||
|
|
|
@ -1126,7 +1126,7 @@ ScriptValue RayToOverlayIntersectionResultToScriptValue(ScriptEngine* engine, co
|
|||
return obj;
|
||||
}
|
||||
|
||||
void RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, RayToOverlayIntersectionResult& value) {
|
||||
bool RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, RayToOverlayIntersectionResult& value) {
|
||||
value.intersects = object.property("intersects").toVariant().toBool();
|
||||
ScriptValue overlayIDValue = object.property("overlayID");
|
||||
quuidFromScriptValue(overlayIDValue, value.overlayID);
|
||||
|
@ -1142,6 +1142,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, Ra
|
|||
vec3FromScriptValue(surfaceNormal, value.surfaceNormal);
|
||||
}
|
||||
value.extraInfo = object.property("extraInfo").toVariant().toMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlays::isLoaded(const QUuid& id) {
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
};
|
||||
Q_DECLARE_METATYPE(RayToOverlayIntersectionResult);
|
||||
ScriptValue RayToOverlayIntersectionResultToScriptValue(ScriptEngine* engine, const RayToOverlayIntersectionResult& value);
|
||||
void RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, RayToOverlayIntersectionResult& value);
|
||||
bool RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, RayToOverlayIntersectionResult& value);
|
||||
|
||||
class ParabolaToOverlayIntersectionResult {
|
||||
public:
|
||||
|
|
|
@ -66,10 +66,10 @@ ScriptValue injectorOptionsToScriptValue(ScriptEngine* engine, const AudioInject
|
|||
* @property {boolean} ignorePenumbra=false - <p class="important">Deprecated: This property is deprecated and will be
|
||||
* removed.</p>
|
||||
*/
|
||||
void injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOptions& injectorOptions) {
|
||||
bool injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOptions& injectorOptions) {
|
||||
if (!object.isObject()) {
|
||||
qWarning() << "Audio injector options is not an object.";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (injectorOptions.positionSet == false) {
|
||||
|
@ -126,4 +126,5 @@ void injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOpti
|
|||
qCWarning(audio) << "Unknown audio injector option:" << it->name();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,6 @@ public:
|
|||
Q_DECLARE_METATYPE(AudioInjectorOptions);
|
||||
|
||||
ScriptValue injectorOptionsToScriptValue(ScriptEngine* engine, const AudioInjectorOptions& injectorOptions);
|
||||
void injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOptions& injectorOptions);
|
||||
bool injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOptions& injectorOptions);
|
||||
|
||||
#endif // hifi_AudioInjectorOptions_h
|
||||
|
|
|
@ -32,8 +32,9 @@ ScriptValue injectorToScriptValue(ScriptEngine* engine, ScriptAudioInjector* con
|
|||
return engine->newQObject(in, ScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
void injectorFromScriptValue(const ScriptValue& object, ScriptAudioInjector*& out) {
|
||||
bool injectorFromScriptValue(const ScriptValue& object, ScriptAudioInjector*& out) {
|
||||
out = qobject_cast<ScriptAudioInjector*>(object.toQObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptAudioInjector::ScriptAudioInjector(const AudioInjectorPointer& injector) :
|
||||
|
|
|
@ -152,7 +152,7 @@ private:
|
|||
Q_DECLARE_METATYPE(ScriptAudioInjector*)
|
||||
|
||||
ScriptValue injectorToScriptValue(ScriptEngine* engine, ScriptAudioInjector* const& in);
|
||||
void injectorFromScriptValue(const ScriptValue& object, ScriptAudioInjector*& out);
|
||||
bool injectorFromScriptValue(const ScriptValue& object, ScriptAudioInjector*& out);
|
||||
|
||||
#endif // hifi_ScriptAudioInjector_h
|
||||
|
||||
|
|
|
@ -428,10 +428,11 @@ ScriptValue soundSharedPointerToScriptValue(ScriptEngine* engine, const SharedSo
|
|||
return engine->newQObject(new SoundScriptingInterface(in), ScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
void soundSharedPointerFromScriptValue(const ScriptValue& object, SharedSoundPointer& out) {
|
||||
bool soundSharedPointerFromScriptValue(const ScriptValue& object, SharedSoundPointer& out) {
|
||||
if (auto soundInterface = qobject_cast<SoundScriptingInterface*>(object.toQObject())) {
|
||||
out = soundInterface->getSound();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SoundScriptingInterface::SoundScriptingInterface(const SharedSoundPointer& sound) : _sound(sound) {
|
||||
|
|
|
@ -172,6 +172,6 @@ private:
|
|||
|
||||
Q_DECLARE_METATYPE(SharedSoundPointer)
|
||||
ScriptValue soundSharedPointerToScriptValue(ScriptEngine* engine, const SharedSoundPointer& in);
|
||||
void soundSharedPointerFromScriptValue(const ScriptValue& object, SharedSoundPointer& out);
|
||||
bool soundSharedPointerFromScriptValue(const ScriptValue& object, SharedSoundPointer& out);
|
||||
|
||||
#endif // hifi_Sound_h
|
||||
|
|
|
@ -3176,7 +3176,7 @@ ScriptValue RayToAvatarIntersectionResultToScriptValue(ScriptEngine* engine, con
|
|||
return obj;
|
||||
}
|
||||
|
||||
void RayToAvatarIntersectionResultFromScriptValue(const ScriptValue& object, RayToAvatarIntersectionResult& value) {
|
||||
bool RayToAvatarIntersectionResultFromScriptValue(const ScriptValue& object, RayToAvatarIntersectionResult& value) {
|
||||
value.intersects = object.property("intersects").toVariant().toBool();
|
||||
ScriptValue avatarIDValue = object.property("avatarID");
|
||||
quuidFromScriptValue(avatarIDValue, value.avatarID);
|
||||
|
@ -3193,6 +3193,7 @@ void RayToAvatarIntersectionResultFromScriptValue(const ScriptValue& object, Ray
|
|||
}
|
||||
value.jointIndex = object.property("jointIndex").toInt32();
|
||||
value.extraInfo = object.property("extraInfo").toVariant().toMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
// these coefficients can be changed via JS for experimental tuning
|
||||
|
@ -3226,7 +3227,7 @@ ScriptValue AvatarEntityMapToScriptValue(ScriptEngine* engine, const AvatarEntit
|
|||
return obj;
|
||||
}
|
||||
|
||||
void AvatarEntityMapFromScriptValue(const ScriptValue& object, AvatarEntityMap& value) {
|
||||
bool AvatarEntityMapFromScriptValue(const ScriptValue& object, AvatarEntityMap& value) {
|
||||
ScriptValueIteratorPointer itr(object.newIterator());
|
||||
while (itr->hasNext()) {
|
||||
itr->next();
|
||||
|
@ -3240,6 +3241,7 @@ void AvatarEntityMapFromScriptValue(const ScriptValue& object, AvatarEntityMap&
|
|||
OVERTE_IGNORE_DEPRECATED_END
|
||||
value[EntityID] = binaryEntityProperties;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const float AvatarData::DEFAULT_BUBBLE_SCALE = 2.4f; // magic number determined empirically
|
||||
|
|
|
@ -1972,7 +1972,7 @@ public:
|
|||
};
|
||||
Q_DECLARE_METATYPE(RayToAvatarIntersectionResult)
|
||||
ScriptValue RayToAvatarIntersectionResultToScriptValue(ScriptEngine* engine, const RayToAvatarIntersectionResult& results);
|
||||
void RayToAvatarIntersectionResultFromScriptValue(const ScriptValue& object, RayToAvatarIntersectionResult& results);
|
||||
bool RayToAvatarIntersectionResultFromScriptValue(const ScriptValue& object, RayToAvatarIntersectionResult& results);
|
||||
|
||||
// No JSDoc because it's not provided as a type to the script engine.
|
||||
class ParabolaToAvatarIntersectionResult {
|
||||
|
@ -1990,7 +1990,7 @@ public:
|
|||
Q_DECLARE_METATYPE(AvatarEntityMap)
|
||||
|
||||
ScriptValue AvatarEntityMapToScriptValue(ScriptEngine* engine, const AvatarEntityMap& value);
|
||||
void AvatarEntityMapFromScriptValue(const ScriptValue& object, AvatarEntityMap& value);
|
||||
bool AvatarEntityMapFromScriptValue(const ScriptValue& object, AvatarEntityMap& value);
|
||||
|
||||
// faux joint indexes (-1 means invalid)
|
||||
const int NO_JOINT_INDEX = 65535; // -1
|
||||
|
|
|
@ -18,10 +18,11 @@ ScriptValue avatarDataToScriptValue(ScriptEngine* engine, ScriptAvatarData* cons
|
|||
return engine->newQObject(in, ScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
void avatarDataFromScriptValue(const ScriptValue& object, ScriptAvatarData*& out) {
|
||||
bool avatarDataFromScriptValue(const ScriptValue& object, ScriptAvatarData*& out) {
|
||||
// This is not implemented because there are no slots/properties that take an AvatarSharedPointer from a script
|
||||
assert(false);
|
||||
out = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace controller {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void Pose::fromScriptValue(const ScriptValue& object, Pose& pose) {
|
||||
bool Pose::fromScriptValue(const ScriptValue& object, Pose& pose) {
|
||||
auto translation = object.property("translation");
|
||||
auto rotation = object.property("rotation");
|
||||
auto velocity = object.property("velocity");
|
||||
|
@ -67,6 +67,7 @@ namespace controller {
|
|||
} else {
|
||||
pose.valid = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Pose Pose::transform(const glm::mat4& mat) const {
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace controller {
|
|||
Pose postTransform(const glm::mat4& mat) const;
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const Pose& event);
|
||||
static void fromScriptValue(const ScriptValue& object, Pose& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, Pose& event);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,9 @@ ScriptValue inputControllerToScriptValue(ScriptEngine* engine, controller::Input
|
|||
return engine->newQObject(in, ScriptEngine::QtOwnership);
|
||||
}
|
||||
|
||||
void inputControllerFromScriptValue(const ScriptValue& object, controller::InputController*& out) {
|
||||
bool inputControllerFromScriptValue(const ScriptValue& object, controller::InputController*& out) {
|
||||
out = qobject_cast<controller::InputController*>(object.toQObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
|
||||
|
|
|
@ -393,13 +393,13 @@ int poseMetaTypeId = qRegisterMetaType<controller::Pose>("Pose");
|
|||
int handMetaTypeId = qRegisterMetaType<controller::Hand>();
|
||||
|
||||
ScriptValue inputToScriptValue(ScriptEngine* engine, const Input& input);
|
||||
void inputFromScriptValue(const ScriptValue& object, Input& input);
|
||||
bool inputFromScriptValue(const ScriptValue& object, Input& input);
|
||||
ScriptValue actionToScriptValue(ScriptEngine* engine, const Action& action);
|
||||
void actionFromScriptValue(const ScriptValue& object, Action& action);
|
||||
bool actionFromScriptValue(const ScriptValue& object, Action& action);
|
||||
ScriptValue inputPairToScriptValue(ScriptEngine* engine, const Input::NamedPair& inputPair);
|
||||
void inputPairFromScriptValue(const ScriptValue& object, Input::NamedPair& inputPair);
|
||||
bool inputPairFromScriptValue(const ScriptValue& object, Input::NamedPair& inputPair);
|
||||
ScriptValue handToScriptValue(ScriptEngine* engine, const controller::Hand& hand);
|
||||
void handFromScriptValue(const ScriptValue& object, controller::Hand& hand);
|
||||
bool handFromScriptValue(const ScriptValue& object, controller::Hand& hand);
|
||||
|
||||
ScriptValue inputToScriptValue(ScriptEngine* engine, const Input& input) {
|
||||
ScriptValue obj = engine->newObject();
|
||||
|
@ -410,8 +410,9 @@ ScriptValue inputToScriptValue(ScriptEngine* engine, const Input& input) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void inputFromScriptValue(const ScriptValue& object, Input& input) {
|
||||
bool inputFromScriptValue(const ScriptValue& object, Input& input) {
|
||||
input.id = object.property("id").toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue actionToScriptValue(ScriptEngine* engine, const Action& action) {
|
||||
|
@ -422,8 +423,9 @@ ScriptValue actionToScriptValue(ScriptEngine* engine, const Action& action) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void actionFromScriptValue(const ScriptValue& object, Action& action) {
|
||||
bool actionFromScriptValue(const ScriptValue& object, Action& action) {
|
||||
action = Action(object.property("action").toVariant().toInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue inputPairToScriptValue(ScriptEngine* engine, const Input::NamedPair& inputPair) {
|
||||
|
@ -433,17 +435,19 @@ ScriptValue inputPairToScriptValue(ScriptEngine* engine, const Input::NamedPair&
|
|||
return obj;
|
||||
}
|
||||
|
||||
void inputPairFromScriptValue(const ScriptValue& object, Input::NamedPair& inputPair) {
|
||||
bool inputPairFromScriptValue(const ScriptValue& object, Input::NamedPair& inputPair) {
|
||||
inputFromScriptValue(object.property("input"), inputPair.first);
|
||||
inputPair.second = QString(object.property("inputName").toVariant().toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue handToScriptValue(ScriptEngine* engine, const controller::Hand& hand) {
|
||||
return engine->newValue((int)hand);
|
||||
}
|
||||
|
||||
void handFromScriptValue(const ScriptValue& object, controller::Hand& hand) {
|
||||
bool handFromScriptValue(const ScriptValue& object, controller::Hand& hand) {
|
||||
hand = Hand(object.toVariant().toInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
void UserInputMapper::registerControllerTypes(ScriptEngine* engine) {
|
||||
|
|
|
@ -2588,20 +2588,22 @@ ScriptValue EntityItemNonDefaultPropertiesToScriptValue(ScriptEngine* engine, co
|
|||
return properties.copyToScriptValue(engine, true);
|
||||
}
|
||||
|
||||
void EntityItemPropertiesFromScriptValueIgnoreReadOnly(const ScriptValue &object, EntityItemProperties& properties) {
|
||||
bool EntityItemPropertiesFromScriptValueIgnoreReadOnly(const ScriptValue &object, EntityItemProperties& properties) {
|
||||
properties.copyFromScriptValue(object, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EntityItemPropertiesFromScriptValueHonorReadOnly(const ScriptValue &object, EntityItemProperties& properties) {
|
||||
bool EntityItemPropertiesFromScriptValueHonorReadOnly(const ScriptValue &object, EntityItemProperties& properties) {
|
||||
properties.copyFromScriptValue(object, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue EntityPropertyFlagsToScriptValue(ScriptEngine* engine, const EntityPropertyFlags& flags) {
|
||||
return EntityItemProperties::entityPropertyFlagsToScriptValue(engine, flags);
|
||||
}
|
||||
|
||||
void EntityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags) {
|
||||
EntityItemProperties::entityPropertyFlagsFromScriptValue(object, flags);
|
||||
bool EntityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags) {
|
||||
return EntityItemProperties::entityPropertyFlagsFromScriptValue(object, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2610,7 +2612,7 @@ ScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(ScriptEngine*
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags) {
|
||||
bool EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags) {
|
||||
if (object.isString()) {
|
||||
EntityPropertyInfo propertyInfo;
|
||||
if (getPropertyInfo(object.toString(), propertyInfo)) {
|
||||
|
@ -2627,6 +2629,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const ScriptValue&
|
|||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static QHash<QString, EntityPropertyInfo> _propertyInfos;
|
||||
|
@ -3027,10 +3030,11 @@ ScriptValue EntityPropertyInfoToScriptValue(ScriptEngine* engine, const EntityPr
|
|||
return obj;
|
||||
}
|
||||
|
||||
void EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo) {
|
||||
bool EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo) {
|
||||
propertyInfo.propertyEnum = (EntityPropertyList)object.property("propertyEnum").toVariant().toUInt();
|
||||
propertyInfo.minimum = object.property("minimum").toVariant();
|
||||
propertyInfo.maximum = object.property("maximum").toVariant();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Implement support for edit packets that can span an MTU sized buffer. We need to implement a mechanism for the
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
void copyFromJSONString(ScriptEngine& scriptEngine, const QString& jsonString);
|
||||
|
||||
static ScriptValue entityPropertyFlagsToScriptValue(ScriptEngine* engine, const EntityPropertyFlags& flags);
|
||||
static void entityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags);
|
||||
static bool entityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags);
|
||||
|
||||
static bool getPropertyInfo(const QString& propertyName, EntityPropertyInfo& propertyInfo);
|
||||
|
||||
|
@ -543,16 +543,16 @@ private:
|
|||
Q_DECLARE_METATYPE(EntityItemProperties);
|
||||
ScriptValue EntityItemPropertiesToScriptValue(ScriptEngine* engine, const EntityItemProperties& properties);
|
||||
ScriptValue EntityItemNonDefaultPropertiesToScriptValue(ScriptEngine* engine, const EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueIgnoreReadOnly(const ScriptValue& object, EntityItemProperties& properties);
|
||||
void EntityItemPropertiesFromScriptValueHonorReadOnly(const ScriptValue& object, EntityItemProperties& properties);
|
||||
bool EntityItemPropertiesFromScriptValueIgnoreReadOnly(const ScriptValue& object, EntityItemProperties& properties);
|
||||
bool EntityItemPropertiesFromScriptValueHonorReadOnly(const ScriptValue& object, EntityItemProperties& properties);
|
||||
|
||||
Q_DECLARE_METATYPE(EntityPropertyFlags);
|
||||
ScriptValue EntityPropertyFlagsToScriptValue(ScriptEngine* engine, const EntityPropertyFlags& flags);
|
||||
void EntityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags);
|
||||
bool EntityPropertyFlagsFromScriptValue(const ScriptValue& object, EntityPropertyFlags& flags);
|
||||
|
||||
Q_DECLARE_METATYPE(EntityPropertyInfo);
|
||||
ScriptValue EntityPropertyInfoToScriptValue(ScriptEngine* engine, const EntityPropertyInfo& propertyInfo);
|
||||
void EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo);
|
||||
bool EntityPropertyInfoFromScriptValue(const ScriptValue& object, EntityPropertyInfo& propertyInfo);
|
||||
|
||||
// define these inline here so the macros work
|
||||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
|
|
|
@ -1690,7 +1690,7 @@ ScriptValue RayToEntityIntersectionResultToScriptValue(ScriptEngine* engine, con
|
|||
return obj;
|
||||
}
|
||||
|
||||
void RayToEntityIntersectionResultFromScriptValue(const ScriptValue& object, RayToEntityIntersectionResult& value) {
|
||||
bool RayToEntityIntersectionResultFromScriptValue(const ScriptValue& object, RayToEntityIntersectionResult& value) {
|
||||
value.intersects = object.property("intersects").toVariant().toBool();
|
||||
value.accurate = object.property("accurate").toVariant().toBool();
|
||||
ScriptValue entityIDValue = object.property("entityID");
|
||||
|
@ -1707,6 +1707,7 @@ void RayToEntityIntersectionResultFromScriptValue(const ScriptValue& object, Ray
|
|||
vec3FromScriptValue(surfaceNormal, value.surfaceNormal);
|
||||
}
|
||||
value.extraInfo = object.property("extraInfo").toVariant().toMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::polyVoxWorker(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor) {
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
};
|
||||
Q_DECLARE_METATYPE(RayToEntityIntersectionResult)
|
||||
ScriptValue RayToEntityIntersectionResultToScriptValue(ScriptEngine* engine, const RayToEntityIntersectionResult& results);
|
||||
void RayToEntityIntersectionResultFromScriptValue(const ScriptValue& object, RayToEntityIntersectionResult& results);
|
||||
bool RayToEntityIntersectionResultFromScriptValue(const ScriptValue& object, RayToEntityIntersectionResult& results);
|
||||
|
||||
class ParabolaToEntityIntersectionResult {
|
||||
public:
|
||||
|
|
|
@ -325,14 +325,14 @@ namespace scriptable {
|
|||
}
|
||||
return engine->newQObject(object, ScriptEngine::QtOwnership, ScriptEngine::AutoCreateDynamicProperties);
|
||||
},
|
||||
[](const ScriptValue& value, QPointer<T>& out) {
|
||||
[](const ScriptValue& value, QPointer<T>& out) -> bool {
|
||||
auto obj = value.toQObject();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
||||
#endif
|
||||
if (auto tmp = qobject_cast<T*>(obj)) {
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
if (auto tmp = static_cast<T*>(obj)) {
|
||||
|
@ -340,10 +340,11 @@ namespace scriptable {
|
|||
qCInfo(graphics_scripting) << "qpointer_qobject_cast -- via static_cast" << obj << tmp << value.toString();
|
||||
#endif
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
out = nullptr;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -352,8 +353,9 @@ namespace scriptable {
|
|||
return scriptValueFromSequence(engine, vector);
|
||||
}
|
||||
|
||||
void qVectorScriptableMaterialLayerFromScriptValue(const ScriptValue& array, QVector<scriptable::ScriptableMaterialLayer>& result) {
|
||||
bool qVectorScriptableMaterialLayerFromScriptValue(const ScriptValue& array, QVector<scriptable::ScriptableMaterialLayer>& result) {
|
||||
scriptValueToSequence(array, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
|
@ -625,8 +627,9 @@ namespace scriptable {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void scriptableMaterialFromScriptValue(const ScriptValue &object, scriptable::ScriptableMaterial& material) {
|
||||
bool scriptableMaterialFromScriptValue(const ScriptValue& object, scriptable::ScriptableMaterial& material) {
|
||||
// No need to convert from ScriptValue to ScriptableMaterial
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptValue scriptableMaterialLayerToScriptValue(ScriptEngine* engine, const scriptable::ScriptableMaterialLayer &materialLayer) {
|
||||
|
@ -636,8 +639,9 @@ namespace scriptable {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void scriptableMaterialLayerFromScriptValue(const ScriptValue &object, scriptable::ScriptableMaterialLayer& materialLayer) {
|
||||
bool scriptableMaterialLayerFromScriptValue(const ScriptValue& object, scriptable::ScriptableMaterialLayer& materialLayer) {
|
||||
// No need to convert from ScriptValue to ScriptableMaterialLayer
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptValue multiMaterialMapToScriptValue(ScriptEngine* engine, const scriptable::MultiMaterialMap& map) {
|
||||
|
@ -648,8 +652,9 @@ namespace scriptable {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void multiMaterialMapFromScriptValue(const ScriptValue& map, scriptable::MultiMaterialMap& result) {
|
||||
bool multiMaterialMapFromScriptValue(const ScriptValue& map, scriptable::MultiMaterialMap& result) {
|
||||
// No need to convert from ScriptValue to MultiMaterialMap
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> int registerDebugEnum(ScriptEngine* engine, const DebugEnums<T>& debugEnums) {
|
||||
|
@ -659,8 +664,9 @@ namespace scriptable {
|
|||
[](ScriptEngine* engine, const T& topology) -> ScriptValue {
|
||||
return engine->newValue(instance.value(topology));
|
||||
},
|
||||
[](const ScriptValue& value, T& topology) {
|
||||
[](const ScriptValue& value, T& topology) -> bool {
|
||||
topology = instance.key(value.toString());
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ ScriptValue KeyEvent::toScriptValue(ScriptEngine* engine, const KeyEvent& event)
|
|||
return obj;
|
||||
}
|
||||
|
||||
void KeyEvent::fromScriptValue(const ScriptValue& object, KeyEvent& event) {
|
||||
bool KeyEvent::fromScriptValue(const ScriptValue& object, KeyEvent& event) {
|
||||
|
||||
event.isValid = false; // assume the worst
|
||||
event.isMeta = object.property("isMeta").toVariant().toBool();
|
||||
|
@ -281,6 +281,7 @@ void KeyEvent::fromScriptValue(const ScriptValue& object, KeyEvent& event) {
|
|||
}
|
||||
event.isValid = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue isShifted = object.property("isShifted");
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
operator QKeySequence() const;
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const KeyEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, KeyEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, KeyEvent& event);
|
||||
|
||||
int key;
|
||||
QString text;
|
||||
|
|
|
@ -35,9 +35,10 @@ ScriptValue midiEventToScriptValue(ScriptEngine* engine, const MIDIEvent& event)
|
|||
return obj;
|
||||
}
|
||||
|
||||
void midiEventFromScriptValue(const ScriptValue &object, MIDIEvent& event) {
|
||||
bool midiEventFromScriptValue(const ScriptValue &object, MIDIEvent& event) {
|
||||
event.deltaTime = object.property(MIDI_DELTA_TIME_PROP_NAME).toVariant().toDouble();
|
||||
event.type = object.property(MIDI_EVENT_TYPE_PROP_NAME).toVariant().toUInt();
|
||||
event.data1 = object.property(MIDI_DATA_1_PROP_NAME).toVariant().toUInt();
|
||||
event.data2 = object.property(MIDI_DATA_2_PROP_NAME).toVariant().toUInt();
|
||||
return true;
|
||||
}
|
|
@ -33,7 +33,7 @@ Q_DECLARE_METATYPE(MIDIEvent)
|
|||
void registerMIDIMetaTypes(ScriptEngine* engine);
|
||||
|
||||
ScriptValue midiEventToScriptValue(ScriptEngine* engine, const MIDIEvent& event);
|
||||
void midiEventFromScriptValue(const ScriptValue &object, MIDIEvent& event);
|
||||
bool midiEventFromScriptValue(const ScriptValue &object, MIDIEvent& event);
|
||||
|
||||
#endif // hifi_MIDIEvent_h
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ ScriptValue menuItemPropertiesToScriptValue(ScriptEngine* engine, const MenuItem
|
|||
* @property {string} [afterItem] - The name of the menu item to place this menu item after.
|
||||
* @property {string} [grouping] - The name of grouping to add this menu item to.
|
||||
*/
|
||||
void menuItemPropertiesFromScriptValue(const ScriptValue& object, MenuItemProperties& properties) {
|
||||
bool menuItemPropertiesFromScriptValue(const ScriptValue& object, MenuItemProperties& properties) {
|
||||
properties.menuName = object.property("menuName").toVariant().toString();
|
||||
properties.menuItemName = object.property("menuItemName").toVariant().toString();
|
||||
properties.isCheckable = object.property("isCheckable").toVariant().toBool();
|
||||
|
@ -99,6 +99,7 @@ void menuItemPropertiesFromScriptValue(const ScriptValue& object, MenuItemProper
|
|||
properties.beforeItem = object.property("beforeItem").toVariant().toString();
|
||||
properties.afterItem = object.property("afterItem").toVariant().toString();
|
||||
properties.grouping = object.property("grouping").toVariant().toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ private:
|
|||
};
|
||||
Q_DECLARE_METATYPE(MenuItemProperties)
|
||||
ScriptValue menuItemPropertiesToScriptValue(ScriptEngine* engine, const MenuItemProperties& props);
|
||||
void menuItemPropertiesFromScriptValue(const ScriptValue& object, MenuItemProperties& props);
|
||||
bool menuItemPropertiesFromScriptValue(const ScriptValue& object, MenuItemProperties& props);
|
||||
void registerMenuItemProperties(ScriptEngine* engine);
|
||||
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ ScriptValue MouseEvent::toScriptValue(ScriptEngine* engine, const MouseEvent& ev
|
|||
return obj;
|
||||
}
|
||||
|
||||
void MouseEvent::fromScriptValue(const ScriptValue& object, MouseEvent& event) {
|
||||
bool MouseEvent::fromScriptValue(const ScriptValue& object, MouseEvent& event) {
|
||||
// nothing for now...
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
MouseEvent(const QMouseEvent& event);
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const MouseEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, MouseEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, MouseEvent& event);
|
||||
|
||||
ScriptValue toScriptValue(ScriptEngine* engine) const { return MouseEvent::toScriptValue(engine, *this); }
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ ScriptValue PointerEvent::toScriptValue(ScriptEngine* engine, const PointerEvent
|
|||
return obj;
|
||||
}
|
||||
|
||||
void PointerEvent::fromScriptValue(const ScriptValue& object, PointerEvent& event) {
|
||||
bool PointerEvent::fromScriptValue(const ScriptValue& object, PointerEvent& event) {
|
||||
if (object.isObject()) {
|
||||
ScriptValue type = object.property("type");
|
||||
QString typeStr = type.isString() ? type.toString() : "Move";
|
||||
|
@ -263,6 +263,7 @@ void PointerEvent::fromScriptValue(const ScriptValue& object, PointerEvent& even
|
|||
|
||||
event._keyboardModifiers = (Qt::KeyboardModifiers)(object.property("keyboardModifiers").toUInt32());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* typeToStringMap[PointerEvent::NumEventTypes] = { "Press", "DoublePress", "Release", "Move" };
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
Button button = NoButtons, uint32_t buttons = NoButtons, Qt::KeyboardModifiers keyboardModifiers = Qt::NoModifier);
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const PointerEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, PointerEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, PointerEvent& event);
|
||||
|
||||
ScriptValue toScriptValue(ScriptEngine* engine) const { return PointerEvent::toScriptValue(engine, *this); }
|
||||
|
||||
|
|
23
libraries/script-engine/src/ScriptContext.cpp
Normal file
23
libraries/script-engine/src/ScriptContext.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// ScriptContext.h
|
||||
// libraries/script-engine/src
|
||||
//
|
||||
// Created by Heather Anderson on 12/5/21.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptContext.h"
|
||||
|
||||
#include "Scriptable.h"
|
||||
|
||||
ScriptContextGuard::ScriptContextGuard(ScriptContext* context) {
|
||||
_oldContext = Scriptable::context();
|
||||
Scriptable::setContext(context);
|
||||
}
|
||||
|
||||
ScriptContextGuard::~ScriptContextGuard() {
|
||||
Scriptable::setContext(_oldContext);
|
||||
}
|
|
@ -67,6 +67,15 @@ protected:
|
|||
~ScriptContext() {} // prevent explicit deletion of base class
|
||||
};
|
||||
|
||||
class ScriptContextGuard {
|
||||
public:
|
||||
ScriptContextGuard(ScriptContext* context);
|
||||
~ScriptContextGuard();
|
||||
|
||||
private:
|
||||
ScriptContext* _oldContext;
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptContext_h
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -49,7 +49,7 @@ class ScriptEngine {
|
|||
public:
|
||||
typedef ScriptValue (*FunctionSignature)(ScriptContext*, ScriptEngine*);
|
||||
typedef ScriptValue (*MarshalFunction)(ScriptEngine*, const void*);
|
||||
typedef void (*DemarshalFunction)(const ScriptValue&, void*);
|
||||
typedef bool (*DemarshalFunction)(const ScriptValue&, void*);
|
||||
|
||||
enum ValueOwnership {
|
||||
QtOwnership = 0,
|
||||
|
@ -136,8 +136,8 @@ public:
|
|||
|
||||
public: // not for public use, but I don't like how Qt strings this along with private friend functions
|
||||
virtual ScriptValue create(int type, const void* ptr) = 0;
|
||||
virtual bool convert(const ScriptValue& value, int type, void* ptr) = 0;
|
||||
virtual void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df, const ScriptValue& prototype) = 0;
|
||||
virtual QVariant convert(const ScriptValue& value, int type) = 0;
|
||||
virtual void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df) = 0;
|
||||
|
||||
protected:
|
||||
~ScriptEngine() {} // prevent explicit deletion of base class
|
||||
|
|
|
@ -42,13 +42,16 @@ inline ScriptValue scriptValueFromValue<QVariant>(ScriptEngine* engine, const QV
|
|||
|
||||
template <typename T>
|
||||
inline T scriptvalue_cast(const ScriptValue& value) {
|
||||
T t;
|
||||
const int id = qMetaTypeId<T>();
|
||||
|
||||
auto engine = value.engine();
|
||||
if (engine && engine->convert(value, id, &t)) {
|
||||
return t;
|
||||
} else if (value.isVariant()) {
|
||||
if (engine) {
|
||||
QVariant varValue = engine->convert(value, id);
|
||||
if (varValue.isValid()) {
|
||||
return varValue.value<T>();
|
||||
}
|
||||
}
|
||||
if (value.isVariant()) {
|
||||
return qvariant_cast<T>(value.toVariant());
|
||||
}
|
||||
|
||||
|
@ -63,13 +66,12 @@ inline QVariant scriptvalue_cast<QVariant>(const ScriptValue& value) {
|
|||
template <typename T>
|
||||
int scriptRegisterMetaType(ScriptEngine* eng,
|
||||
ScriptValue (*toScriptValue)(ScriptEngine*, const T& t),
|
||||
void (*fromScriptValue)(const ScriptValue&, T& t),
|
||||
const ScriptValue& prototype = ScriptValue(),
|
||||
bool (*fromScriptValue)(const ScriptValue&, T& t),
|
||||
T* = 0)
|
||||
{
|
||||
const int id = qRegisterMetaType<T>(); // make sure it's registered
|
||||
eng->registerCustomType(id, reinterpret_cast<ScriptEngine::MarshalFunction>(toScriptValue),
|
||||
reinterpret_cast<ScriptEngine::DemarshalFunction>(fromScriptValue), prototype);
|
||||
reinterpret_cast<ScriptEngine::DemarshalFunction>(fromScriptValue));
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -87,19 +89,19 @@ ScriptValue scriptValueFromSequence(ScriptEngine* eng, const Container& cont) {
|
|||
}
|
||||
|
||||
template <class Container>
|
||||
void scriptValueToSequence(const ScriptValue& value, Container& cont) {
|
||||
bool scriptValueToSequence(const ScriptValue& value, Container& cont) {
|
||||
quint32 len = value.property(QLatin1String("length")).toUInt32();
|
||||
for (quint32 i = 0; i < len; ++i) {
|
||||
ScriptValue item = value.property(i);
|
||||
cont.push_back(scriptvalue_cast<typename Container::value_type>(item));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int scriptRegisterSequenceMetaType(ScriptEngine* engine,
|
||||
const ScriptValue& prototype = ScriptValue(),
|
||||
T* = 0) {
|
||||
return scriptRegisterMetaType<T>(engine, scriptValueFromSequence, scriptValueToSequence, prototype);
|
||||
return scriptRegisterMetaType<T>(engine, scriptValueFromSequence, scriptValueToSequence);
|
||||
}
|
||||
|
||||
#endif // hifi_ScriptEngineCast_h
|
||||
|
|
|
@ -538,8 +538,9 @@ static ScriptValue scriptableResourceToScriptValue(ScriptEngine* engine,
|
|||
return object;
|
||||
}
|
||||
|
||||
static void scriptableResourceFromScriptValue(const ScriptValue& value, ScriptableResourceRawPtr& resource) {
|
||||
static bool scriptableResourceFromScriptValue(const ScriptValue& value, ScriptableResourceRawPtr& resource) {
|
||||
resource = static_cast<ScriptableResourceRawPtr>(value.toQObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
/*@jsdoc
|
||||
|
@ -578,8 +579,9 @@ ScriptValue externalResourceBucketToScriptValue(ScriptEngine* engine, ExternalRe
|
|||
return engine->newValue((int)in);
|
||||
}
|
||||
|
||||
void externalResourceBucketFromScriptValue(const ScriptValue& object, ExternalResource::Bucket& out) {
|
||||
bool externalResourceBucketFromScriptValue(const ScriptValue& object, ExternalResource::Bucket& out) {
|
||||
out = static_cast<ExternalResource::Bucket>(object.toInt32());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptManager::resetModuleCache(bool deleteScriptCache) {
|
||||
|
@ -722,6 +724,11 @@ void ScriptManager::init() {
|
|||
}));
|
||||
}
|
||||
|
||||
// registers a global object by name
|
||||
void ScriptManager::registerValue(const QString& valueName, ScriptValue value) {
|
||||
_engine->globalObject().setProperty(valueName, value);
|
||||
}
|
||||
|
||||
// Unregister the handlers for this eventName and entityID.
|
||||
void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QString& eventName, const ScriptValue& handler) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
|
|
|
@ -275,6 +275,15 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
|
||||
|
||||
/*@jsdoc
|
||||
* registers a global object by name.
|
||||
* @function Script.registerValue
|
||||
* @param {string} valueName
|
||||
* @param {value} value
|
||||
*/
|
||||
/// registers a global object by name
|
||||
Q_INVOKABLE void registerValue(const QString& valueName, ScriptValue value);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE - these are intended to be public interfaces available to scripts
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ ScriptValue vec2ToScriptValue(ScriptEngine* engine, const glm::vec2& vec2) {
|
|||
return value;
|
||||
}
|
||||
|
||||
void vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2) {
|
||||
bool vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2) {
|
||||
if (object.isNumber()) {
|
||||
vec2 = glm::vec2(object.toVariant().toFloat());
|
||||
} else if (object.isArray()) {
|
||||
|
@ -122,6 +122,7 @@ void vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2) {
|
|||
vec2.x = x.toVariant().toFloat();
|
||||
vec2.y = y.toVariant().toFloat();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3) {
|
||||
|
@ -174,7 +175,7 @@ ScriptValue vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3)
|
|||
return value;
|
||||
}
|
||||
|
||||
void vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
|
||||
bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
|
||||
if (object.isNumber()) {
|
||||
vec3 = glm::vec3(object.toVariant().toFloat());
|
||||
} else if (object.isString()) {
|
||||
|
@ -220,6 +221,7 @@ void vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3) {
|
|||
vec3.y = y.toVariant().toFloat();
|
||||
vec3.z = z.toVariant().toFloat();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue u8vec3ToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3) {
|
||||
|
@ -272,7 +274,7 @@ ScriptValue u8vec3ColorToScriptValue(ScriptEngine* engine, const glm::u8vec3& ve
|
|||
return value;
|
||||
}
|
||||
|
||||
void u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3) {
|
||||
bool u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3) {
|
||||
if (object.isNumber()) {
|
||||
vec3 = glm::vec3(object.toVariant().toUInt());
|
||||
} else if (object.isString()) {
|
||||
|
@ -318,6 +320,7 @@ void u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3) {
|
|||
vec3.y = y.toVariant().toUInt();
|
||||
vec3.z = z.toVariant().toUInt();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue vec4toScriptValue(ScriptEngine* engine, const glm::vec4& vec4) {
|
||||
|
@ -329,11 +332,12 @@ ScriptValue vec4toScriptValue(ScriptEngine* engine, const glm::vec4& vec4) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void vec4FromScriptValue(const ScriptValue& object, glm::vec4& vec4) {
|
||||
bool vec4FromScriptValue(const ScriptValue& object, glm::vec4& vec4) {
|
||||
vec4.x = object.property("x").toVariant().toFloat();
|
||||
vec4.y = object.property("y").toVariant().toFloat();
|
||||
vec4.z = object.property("z").toVariant().toFloat();
|
||||
vec4.w = object.property("w").toVariant().toFloat();
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue mat4toScriptValue(ScriptEngine* engine, const glm::mat4& mat4) {
|
||||
|
@ -357,7 +361,7 @@ ScriptValue mat4toScriptValue(ScriptEngine* engine, const glm::mat4& mat4) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4) {
|
||||
bool mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4) {
|
||||
mat4[0][0] = object.property("r0c0").toVariant().toFloat();
|
||||
mat4[0][1] = object.property("r1c0").toVariant().toFloat();
|
||||
mat4[0][2] = object.property("r2c0").toVariant().toFloat();
|
||||
|
@ -374,6 +378,7 @@ void mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4) {
|
|||
mat4[3][1] = object.property("r1c3").toVariant().toFloat();
|
||||
mat4[3][2] = object.property("r2c3").toVariant().toFloat();
|
||||
mat4[3][3] = object.property("r3c3").toVariant().toFloat();
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qVectorVec3ColorToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& vector) {
|
||||
|
@ -404,7 +409,7 @@ QVector<glm::vec3> qVectorVec3FromScriptValue(const ScriptValue& array) {
|
|||
return newVector;
|
||||
}
|
||||
|
||||
void qVectorVec3FromScriptValue(const ScriptValue& array, QVector<glm::vec3>& vector) {
|
||||
bool qVectorVec3FromScriptValue(const ScriptValue& array, QVector<glm::vec3>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
@ -412,6 +417,7 @@ void qVectorVec3FromScriptValue(const ScriptValue& array, QVector<glm::vec3>& ve
|
|||
vec3FromScriptValue(array.property(i), newVec3);
|
||||
vector << newVec3;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue quatToScriptValue(ScriptEngine* engine, const glm::quat& quat) {
|
||||
|
@ -427,7 +433,7 @@ ScriptValue quatToScriptValue(ScriptEngine* engine, const glm::quat& quat) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void quatFromScriptValue(const ScriptValue& object, glm::quat& quat) {
|
||||
bool quatFromScriptValue(const ScriptValue& object, glm::quat& quat) {
|
||||
quat.x = object.property("x").toVariant().toFloat();
|
||||
quat.y = object.property("y").toVariant().toFloat();
|
||||
quat.z = object.property("z").toVariant().toFloat();
|
||||
|
@ -440,6 +446,7 @@ void quatFromScriptValue(const ScriptValue& object, glm::quat& quat) {
|
|||
} else {
|
||||
quat = glm::quat();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qVectorQuatToScriptValue(ScriptEngine* engine, const QVector<glm::quat>& vector) {
|
||||
|
@ -482,12 +489,13 @@ ScriptValue qVectorQUuidToScriptValue(ScriptEngine* engine, const QVector<QUuid>
|
|||
return array;
|
||||
}
|
||||
|
||||
void qVectorQUuidFromScriptValue(const ScriptValue& array, QVector<QUuid>& vector) {
|
||||
bool qVectorQUuidFromScriptValue(const ScriptValue& array, QVector<QUuid>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
vector << array.property(i).toVariant().toUuid();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<QUuid> qVectorQUuidFromScriptValue(const ScriptValue& array) {
|
||||
|
@ -523,20 +531,22 @@ ScriptValue qVectorIntToScriptValue(ScriptEngine* engine, const QVector<uint32_t
|
|||
return array;
|
||||
}
|
||||
|
||||
void qVectorFloatFromScriptValue(const ScriptValue& array, QVector<float>& vector) {
|
||||
bool qVectorFloatFromScriptValue(const ScriptValue& array, QVector<float>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
vector << array.property(i).toVariant().toFloat();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void qVectorIntFromScriptValue(const ScriptValue& array, QVector<uint32_t>& vector) {
|
||||
bool qVectorIntFromScriptValue(const ScriptValue& array, QVector<uint32_t>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
vector << array.property(i).toVariant().toInt();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<glm::quat> qVectorQuatFromScriptValue(const ScriptValue& array) {
|
||||
|
@ -551,7 +561,7 @@ QVector<glm::quat> qVectorQuatFromScriptValue(const ScriptValue& array) {
|
|||
return newVector;
|
||||
}
|
||||
|
||||
void qVectorQuatFromScriptValue(const ScriptValue& array, QVector<glm::quat>& vector) {
|
||||
bool qVectorQuatFromScriptValue(const ScriptValue& array, QVector<glm::quat>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
@ -559,6 +569,7 @@ void qVectorQuatFromScriptValue(const ScriptValue& array, QVector<glm::quat>& ve
|
|||
quatFromScriptValue(array.property(i), newQuat);
|
||||
vector << newQuat;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<bool> qVectorBoolFromScriptValue(const ScriptValue& array) {
|
||||
|
@ -571,12 +582,13 @@ QVector<bool> qVectorBoolFromScriptValue(const ScriptValue& array) {
|
|||
return newVector;
|
||||
}
|
||||
|
||||
void qVectorBoolFromScriptValue(const ScriptValue& array, QVector<bool>& vector) {
|
||||
bool qVectorBoolFromScriptValue(const ScriptValue& array, QVector<bool>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
vector << array.property(i).toBool();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qRectToScriptValue(ScriptEngine* engine, const QRect& rect) {
|
||||
|
@ -588,11 +600,12 @@ ScriptValue qRectToScriptValue(ScriptEngine* engine, const QRect& rect) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void qRectFromScriptValue(const ScriptValue& object, QRect& rect) {
|
||||
bool qRectFromScriptValue(const ScriptValue& object, QRect& rect) {
|
||||
rect.setX(object.property("x").toVariant().toInt());
|
||||
rect.setY(object.property("y").toVariant().toInt());
|
||||
rect.setWidth(object.property("width").toVariant().toInt());
|
||||
rect.setHeight(object.property("height").toVariant().toInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qRectFToScriptValue(ScriptEngine* engine, const QRectF& rect) {
|
||||
|
@ -604,11 +617,12 @@ ScriptValue qRectFToScriptValue(ScriptEngine* engine, const QRectF& rect) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void qRectFFromScriptValue(const ScriptValue& object, QRectF& rect) {
|
||||
bool qRectFFromScriptValue(const ScriptValue& object, QRectF& rect) {
|
||||
rect.setX(object.property("x").toVariant().toFloat());
|
||||
rect.setY(object.property("y").toVariant().toFloat());
|
||||
rect.setWidth(object.property("width").toVariant().toFloat());
|
||||
rect.setHeight(object.property("height").toVariant().toFloat());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qColorToScriptValue(ScriptEngine* engine, const QColor& color) {
|
||||
|
@ -639,7 +653,7 @@ ScriptValue aaCubeToScriptValue(ScriptEngine* engine, const AACube& aaCube) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube) {
|
||||
bool aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube) {
|
||||
glm::vec3 corner;
|
||||
corner.x = object.property("x").toVariant().toFloat();
|
||||
corner.y = object.property("y").toVariant().toFloat();
|
||||
|
@ -647,9 +661,10 @@ void aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube) {
|
|||
float scale = object.property("scale").toVariant().toFloat();
|
||||
|
||||
aaCube.setBox(corner, scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
void qColorFromScriptValue(const ScriptValue& object, QColor& color) {
|
||||
bool qColorFromScriptValue(const ScriptValue& object, QColor& color) {
|
||||
if (object.isNumber()) {
|
||||
color.setRgb(object.toUInt32());
|
||||
|
||||
|
@ -661,14 +676,16 @@ void qColorFromScriptValue(const ScriptValue& object, QColor& color) {
|
|||
color.setRgb(object.property("red").toInt32(), object.property("green").toInt32(), object.property("blue").toInt32(),
|
||||
alphaValue.isNumber() ? alphaValue.toInt32() : 255);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue qURLToScriptValue(ScriptEngine* engine, const QUrl& url) {
|
||||
return engine->newValue(url.toString());
|
||||
}
|
||||
|
||||
void qURLFromScriptValue(const ScriptValue& object, QUrl& url) {
|
||||
bool qURLFromScriptValue(const ScriptValue& object, QUrl& url) {
|
||||
url = object.toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue pickRayToScriptValue(ScriptEngine* engine, const PickRay& pickRay) {
|
||||
|
@ -680,7 +697,7 @@ ScriptValue pickRayToScriptValue(ScriptEngine* engine, const PickRay& pickRay) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void pickRayFromScriptValue(const ScriptValue& object, PickRay& pickRay) {
|
||||
bool pickRayFromScriptValue(const ScriptValue& object, PickRay& pickRay) {
|
||||
ScriptValue originValue = object.property("origin");
|
||||
if (originValue.isValid()) {
|
||||
auto x = originValue.property("x");
|
||||
|
@ -703,6 +720,7 @@ void pickRayFromScriptValue(const ScriptValue& object, PickRay& pickRay) {
|
|||
pickRay.direction.z = z.toVariant().toFloat();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -726,8 +744,9 @@ ScriptValue collisionToScriptValue(ScriptEngine* engine, const Collision& collis
|
|||
return obj;
|
||||
}
|
||||
|
||||
void collisionFromScriptValue(const ScriptValue& object, Collision& collision) {
|
||||
bool collisionFromScriptValue(const ScriptValue& object, Collision& collision) {
|
||||
// TODO: implement this when we know what it means to accept collision events from JS
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptValue quuidToScriptValue(ScriptEngine* engine, const QUuid& uuid) {
|
||||
|
@ -738,14 +757,15 @@ ScriptValue quuidToScriptValue(ScriptEngine* engine, const QUuid& uuid) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void quuidFromScriptValue(const ScriptValue& object, QUuid& uuid) {
|
||||
bool quuidFromScriptValue(const ScriptValue& object, QUuid& uuid) {
|
||||
if (object.isNull()) {
|
||||
uuid = QUuid();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
QString uuidAsString = object.toVariant().toString();
|
||||
QUuid fromString(uuidAsString);
|
||||
uuid = fromString;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -761,9 +781,10 @@ ScriptValue qSizeFToScriptValue(ScriptEngine* engine, const QSizeF& qSizeF) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
void qSizeFFromScriptValue(const ScriptValue& object, QSizeF& qSizeF) {
|
||||
bool qSizeFFromScriptValue(const ScriptValue& object, QSizeF& qSizeF) {
|
||||
qSizeF.setWidth(object.property("width").toVariant().toFloat());
|
||||
qSizeF.setHeight(object.property("height").toVariant().toFloat());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -802,16 +823,18 @@ ScriptValue animationDetailsToScriptValue(ScriptEngine* engine, const AnimationD
|
|||
return obj;
|
||||
}
|
||||
|
||||
void animationDetailsFromScriptValue(const ScriptValue& object, AnimationDetails& details) {
|
||||
bool animationDetailsFromScriptValue(const ScriptValue& object, AnimationDetails& details) {
|
||||
// nothing for now...
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptValue meshToScriptValue(ScriptEngine* engine, MeshProxy* const& in) {
|
||||
return engine->newQObject(in, ScriptEngine::QtOwnership);
|
||||
}
|
||||
|
||||
void meshFromScriptValue(const ScriptValue& value, MeshProxy*& out) {
|
||||
bool meshFromScriptValue(const ScriptValue& value, MeshProxy*& out) {
|
||||
out = qobject_cast<MeshProxy*>(value.toQObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue meshesToScriptValue(ScriptEngine* engine, const MeshProxyList& in) {
|
||||
|
@ -822,7 +845,7 @@ ScriptValue meshesToScriptValue(ScriptEngine* engine, const MeshProxyList& in) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void meshesFromScriptValue(const ScriptValue& value, MeshProxyList& out) {
|
||||
bool meshesFromScriptValue(const ScriptValue& value, MeshProxyList& out) {
|
||||
ScriptValueIteratorPointer itr(value.newIterator());
|
||||
|
||||
qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32();
|
||||
|
@ -836,6 +859,7 @@ void meshesFromScriptValue(const ScriptValue& value, MeshProxyList& out) {
|
|||
qDebug() << "null meshProxy";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -849,8 +873,8 @@ ScriptValue meshFaceToScriptValue(ScriptEngine* engine, const MeshFace& meshFace
|
|||
return obj;
|
||||
}
|
||||
|
||||
void meshFaceFromScriptValue(const ScriptValue& object, MeshFace& meshFaceResult) {
|
||||
qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices);
|
||||
bool meshFaceFromScriptValue(const ScriptValue& object, MeshFace& meshFaceResult) {
|
||||
return qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices);
|
||||
}
|
||||
|
||||
ScriptValue qVectorMeshFaceToScriptValue(ScriptEngine* engine, const QVector<MeshFace>& vector) {
|
||||
|
@ -861,7 +885,7 @@ ScriptValue qVectorMeshFaceToScriptValue(ScriptEngine* engine, const QVector<Mes
|
|||
return array;
|
||||
}
|
||||
|
||||
void qVectorMeshFaceFromScriptValue(const ScriptValue& array, QVector<MeshFace>& result) {
|
||||
bool qVectorMeshFaceFromScriptValue(const ScriptValue& array, QVector<MeshFace>& result) {
|
||||
int length = array.property("length").toInteger();
|
||||
result.clear();
|
||||
|
||||
|
@ -870,18 +894,21 @@ void qVectorMeshFaceFromScriptValue(const ScriptValue& array, QVector<MeshFace>&
|
|||
meshFaceFromScriptValue(array.property(i), meshFace);
|
||||
result << meshFace;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue stencilMaskModeToScriptValue(ScriptEngine* engine, const StencilMaskMode& stencilMode) {
|
||||
return engine->newValue((int)stencilMode);
|
||||
}
|
||||
|
||||
void stencilMaskModeFromScriptValue(const ScriptValue& object, StencilMaskMode& stencilMode) {
|
||||
bool stencilMaskModeFromScriptValue(const ScriptValue& object, StencilMaskMode& stencilMode) {
|
||||
stencilMode = StencilMaskMode(object.toVariant().toInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
void promiseFromScriptValue(const ScriptValue& object, std::shared_ptr<MiniPromise>& promise) {
|
||||
bool promiseFromScriptValue(const ScriptValue& object, std::shared_ptr<MiniPromise>& promise) {
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
ScriptValue promiseToScriptValue(ScriptEngine* engine, const std::shared_ptr<MiniPromise>& promise) {
|
||||
return engine->newQObject(promise.get());
|
||||
|
@ -891,8 +918,8 @@ ScriptValue EntityItemIDtoScriptValue(ScriptEngine* engine, const EntityItemID&
|
|||
return quuidToScriptValue(engine, id);
|
||||
}
|
||||
|
||||
void EntityItemIDfromScriptValue(const ScriptValue &object, EntityItemID& id) {
|
||||
quuidFromScriptValue(object, id);
|
||||
bool EntityItemIDfromScriptValue(const ScriptValue& object, EntityItemID& id) {
|
||||
return quuidFromScriptValue(object, id);
|
||||
}
|
||||
|
||||
QVector<EntityItemID> qVectorEntityItemIDFromScriptValue(const ScriptValue& array) {
|
||||
|
|
|
@ -52,7 +52,7 @@ void registerMetaTypes(ScriptEngine* engine);
|
|||
* @property {number} r3c3 - Row 3, column 3 value.
|
||||
*/
|
||||
ScriptValue mat4toScriptValue(ScriptEngine* engine, const glm::mat4& mat4);
|
||||
void mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4);
|
||||
bool mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4);
|
||||
|
||||
/**jsdoc
|
||||
* A 2-dimensional vector.
|
||||
|
@ -69,7 +69,7 @@ void mat4FromScriptValue(const ScriptValue& object, glm::mat4& mat4);
|
|||
* color.v = 0.8; // { x: 0.7, y: 0.8 }
|
||||
*/
|
||||
ScriptValue vec2ToScriptValue(ScriptEngine* engine, const glm::vec2& vec2);
|
||||
void vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2);
|
||||
bool vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2);
|
||||
|
||||
/**jsdoc
|
||||
* A 3-dimensional vector. See also the {@link Vec3(0)|Vec3} object.
|
||||
|
@ -93,7 +93,7 @@ void vec2FromScriptValue(const ScriptValue& object, glm::vec2& vec2);
|
|||
*/
|
||||
ScriptValue vec3ToScriptValue(ScriptEngine* engine, const glm::vec3& vec3);
|
||||
ScriptValue vec3ColorToScriptValue(ScriptEngine* engine, const glm::vec3& vec3);
|
||||
void vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3);
|
||||
bool vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3);
|
||||
|
||||
/**jsdoc
|
||||
* A color vector. See also the {@link Vec3(0)|Vec3} object.
|
||||
|
@ -135,7 +135,7 @@ void vec3FromScriptValue(const ScriptValue& object, glm::vec3& vec3);
|
|||
*/
|
||||
ScriptValue u8vec3ToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3);
|
||||
ScriptValue u8vec3ColorToScriptValue(ScriptEngine* engine, const glm::u8vec3& vec3);
|
||||
void u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3);
|
||||
bool u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3);
|
||||
|
||||
/**jsdoc
|
||||
* A 4-dimensional vector.
|
||||
|
@ -147,11 +147,11 @@ void u8vec3FromScriptValue(const ScriptValue& object, glm::u8vec3& vec3);
|
|||
* @property {number} w - W-coordinate of the vector.
|
||||
*/
|
||||
ScriptValue vec4toScriptValue(ScriptEngine* engine, const glm::vec4& vec4);
|
||||
void vec4FromScriptValue(const ScriptValue& object, glm::vec4& vec4);
|
||||
bool vec4FromScriptValue(const ScriptValue& object, glm::vec4& vec4);
|
||||
|
||||
// Quaternions
|
||||
ScriptValue quatToScriptValue(ScriptEngine* engine, const glm::quat& quat);
|
||||
void quatFromScriptValue(const ScriptValue& object, glm::quat& quat);
|
||||
bool quatFromScriptValue(const ScriptValue& object, glm::quat& quat);
|
||||
|
||||
/**jsdoc
|
||||
* Defines a rectangular portion of an image or screen, or similar.
|
||||
|
@ -163,63 +163,63 @@ void quatFromScriptValue(const ScriptValue& object, glm::quat& quat);
|
|||
*/
|
||||
class QRect;
|
||||
ScriptValue qRectToScriptValue(ScriptEngine* engine, const QRect& rect);
|
||||
void qRectFromScriptValue(const ScriptValue& object, QRect& rect);
|
||||
bool qRectFromScriptValue(const ScriptValue& object, QRect& rect);
|
||||
|
||||
class QRectF;
|
||||
ScriptValue qRectFToScriptValue(ScriptEngine* engine, const QRectF& rect);
|
||||
void qRectFFromScriptValue(const ScriptValue& object, QRectF& rect);
|
||||
bool qRectFFromScriptValue(const ScriptValue& object, QRectF& rect);
|
||||
|
||||
// QColor
|
||||
class QColor;
|
||||
ScriptValue qColorToScriptValue(ScriptEngine* engine, const QColor& color);
|
||||
void qColorFromScriptValue(const ScriptValue& object, QColor& color);
|
||||
bool qColorFromScriptValue(const ScriptValue& object, QColor& color);
|
||||
|
||||
class QUrl;
|
||||
ScriptValue qURLToScriptValue(ScriptEngine* engine, const QUrl& url);
|
||||
void qURLFromScriptValue(const ScriptValue& object, QUrl& url);
|
||||
bool qURLFromScriptValue(const ScriptValue& object, QUrl& url);
|
||||
|
||||
// vector<vec3>
|
||||
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
||||
ScriptValue qVectorVec3ToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& vector);
|
||||
ScriptValue qVectorVec3ColorToScriptValue(ScriptEngine* engine, const QVector<glm::vec3>& vector);
|
||||
void qVectorVec3FromScriptValue(const ScriptValue& array, QVector<glm::vec3>& vector);
|
||||
bool qVectorVec3FromScriptValue(const ScriptValue& array, QVector<glm::vec3>& vector);
|
||||
QVector<glm::vec3> qVectorVec3FromScriptValue(const ScriptValue& array);
|
||||
|
||||
// vector<quat>
|
||||
Q_DECLARE_METATYPE(QVector<glm::quat>)
|
||||
ScriptValue qVectorQuatToScriptValue(ScriptEngine* engine, const QVector<glm::quat>& vector);
|
||||
void qVectorQuatFromScriptValue(const ScriptValue& array, QVector<glm::quat>& vector);
|
||||
bool qVectorQuatFromScriptValue(const ScriptValue& array, QVector<glm::quat>& vector);
|
||||
QVector<glm::quat> qVectorQuatFromScriptValue(const ScriptValue& array);
|
||||
|
||||
// vector<bool>
|
||||
ScriptValue qVectorBoolToScriptValue(ScriptEngine* engine, const QVector<bool>& vector);
|
||||
void qVectorBoolFromScriptValue(const ScriptValue& array, QVector<bool>& vector);
|
||||
bool qVectorBoolFromScriptValue(const ScriptValue& array, QVector<bool>& vector);
|
||||
QVector<bool> qVectorBoolFromScriptValue(const ScriptValue& array);
|
||||
|
||||
// vector<float>
|
||||
ScriptValue qVectorFloatToScriptValue(ScriptEngine* engine, const QVector<float>& vector);
|
||||
void qVectorFloatFromScriptValue(const ScriptValue& array, QVector<float>& vector);
|
||||
bool qVectorFloatFromScriptValue(const ScriptValue& array, QVector<float>& vector);
|
||||
QVector<float> qVectorFloatFromScriptValue(const ScriptValue& array);
|
||||
|
||||
// vector<uint32_t>
|
||||
ScriptValue qVectorIntToScriptValue(ScriptEngine* engine, const QVector<uint32_t>& vector);
|
||||
void qVectorIntFromScriptValue(const ScriptValue& array, QVector<uint32_t>& vector);
|
||||
bool qVectorIntFromScriptValue(const ScriptValue& array, QVector<uint32_t>& vector);
|
||||
|
||||
ScriptValue qVectorQUuidToScriptValue(ScriptEngine* engine, const QVector<QUuid>& vector);
|
||||
void qVectorQUuidFromScriptValue(const ScriptValue& array, QVector<QUuid>& vector);
|
||||
bool qVectorQUuidFromScriptValue(const ScriptValue& array, QVector<QUuid>& vector);
|
||||
QVector<QUuid> qVectorQUuidFromScriptValue(const ScriptValue& array);
|
||||
|
||||
class AACube;
|
||||
ScriptValue aaCubeToScriptValue(ScriptEngine* engine, const AACube& aaCube);
|
||||
void aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube);
|
||||
bool aaCubeFromScriptValue(const ScriptValue& object, AACube& aaCube);
|
||||
|
||||
class PickRay;
|
||||
ScriptValue pickRayToScriptValue(ScriptEngine* engine, const PickRay& pickRay);
|
||||
void pickRayFromScriptValue(const ScriptValue& object, PickRay& pickRay);
|
||||
bool pickRayFromScriptValue(const ScriptValue& object, PickRay& pickRay);
|
||||
|
||||
class Collision;
|
||||
ScriptValue collisionToScriptValue(ScriptEngine* engine, const Collision& collision);
|
||||
void collisionFromScriptValue(const ScriptValue& object, Collision& collision);
|
||||
bool collisionFromScriptValue(const ScriptValue& object, Collision& collision);
|
||||
|
||||
/**jsdoc
|
||||
* UUIDs (Universally Unique IDentifiers) are used to uniquely identify entities, avatars, and the like. They are represented
|
||||
|
@ -229,42 +229,42 @@ void collisionFromScriptValue(const ScriptValue& object, Collision& collision);
|
|||
*/
|
||||
//Q_DECLARE_METATYPE(QUuid) // don't need to do this for QUuid since it's already a meta type
|
||||
ScriptValue quuidToScriptValue(ScriptEngine* engine, const QUuid& uuid);
|
||||
void quuidFromScriptValue(const ScriptValue& object, QUuid& uuid);
|
||||
bool quuidFromScriptValue(const ScriptValue& object, QUuid& uuid);
|
||||
|
||||
//Q_DECLARE_METATYPE(QSizeF) // Don't need to to this becase it's arleady a meta type
|
||||
class QSizeF;
|
||||
ScriptValue qSizeFToScriptValue(ScriptEngine* engine, const QSizeF& qSizeF);
|
||||
void qSizeFFromScriptValue(const ScriptValue& object, QSizeF& qSizeF);
|
||||
bool qSizeFFromScriptValue(const ScriptValue& object, QSizeF& qSizeF);
|
||||
|
||||
class AnimationDetails;
|
||||
ScriptValue animationDetailsToScriptValue(ScriptEngine* engine, const AnimationDetails& event);
|
||||
void animationDetailsFromScriptValue(const ScriptValue& object, AnimationDetails& event);
|
||||
bool animationDetailsFromScriptValue(const ScriptValue& object, AnimationDetails& event);
|
||||
|
||||
class MeshProxy;
|
||||
ScriptValue meshToScriptValue(ScriptEngine* engine, MeshProxy* const& in);
|
||||
void meshFromScriptValue(const ScriptValue& value, MeshProxy*& out);
|
||||
bool meshFromScriptValue(const ScriptValue& value, MeshProxy*& out);
|
||||
|
||||
class MeshProxyList;
|
||||
ScriptValue meshesToScriptValue(ScriptEngine* engine, const MeshProxyList& in);
|
||||
void meshesFromScriptValue(const ScriptValue& value, MeshProxyList& out);
|
||||
bool meshesFromScriptValue(const ScriptValue& value, MeshProxyList& out);
|
||||
|
||||
class MeshFace;
|
||||
ScriptValue meshFaceToScriptValue(ScriptEngine* engine, const MeshFace& meshFace);
|
||||
void meshFaceFromScriptValue(const ScriptValue& object, MeshFace& meshFaceResult);
|
||||
bool meshFaceFromScriptValue(const ScriptValue& object, MeshFace& meshFaceResult);
|
||||
ScriptValue qVectorMeshFaceToScriptValue(ScriptEngine* engine, const QVector<MeshFace>& vector);
|
||||
void qVectorMeshFaceFromScriptValue(const ScriptValue& array, QVector<MeshFace>& result);
|
||||
bool qVectorMeshFaceFromScriptValue(const ScriptValue& array, QVector<MeshFace>& result);
|
||||
|
||||
enum class StencilMaskMode;
|
||||
ScriptValue stencilMaskModeToScriptValue(ScriptEngine* engine, const StencilMaskMode& stencilMode);
|
||||
void stencilMaskModeFromScriptValue(const ScriptValue& object, StencilMaskMode& stencilMode);
|
||||
bool stencilMaskModeFromScriptValue(const ScriptValue& object, StencilMaskMode& stencilMode);
|
||||
|
||||
class MiniPromise;
|
||||
void promiseFromScriptValue(const ScriptValue& object, std::shared_ptr<MiniPromise>& promise);
|
||||
bool promiseFromScriptValue(const ScriptValue& object, std::shared_ptr<MiniPromise>& promise);
|
||||
ScriptValue promiseToScriptValue(ScriptEngine* engine, const std::shared_ptr<MiniPromise>& promise);
|
||||
|
||||
class EntityItemID;
|
||||
ScriptValue EntityItemIDtoScriptValue(ScriptEngine* engine, const EntityItemID& properties);
|
||||
void EntityItemIDfromScriptValue(const ScriptValue& object, EntityItemID& properties);
|
||||
bool EntityItemIDfromScriptValue(const ScriptValue& object, EntityItemID& properties);
|
||||
QVector<EntityItemID> qVectorEntityItemIDFromScriptValue(const ScriptValue& array);
|
||||
|
||||
#endif // #define hifi_ScriptValueUtils_h
|
||||
|
|
|
@ -44,6 +44,7 @@ ScriptValue SpatialEvent::toScriptValue(ScriptEngine* engine, const SpatialEvent
|
|||
return obj;
|
||||
}
|
||||
|
||||
void SpatialEvent::fromScriptValue(const ScriptValue& object,SpatialEvent& event) {
|
||||
bool SpatialEvent::fromScriptValue(const ScriptValue& object, SpatialEvent& event) {
|
||||
// nothing for now...
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
SpatialEvent(const SpatialEvent& other);
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const SpatialEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, SpatialEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, SpatialEvent& event);
|
||||
|
||||
glm::vec3 locTranslation;
|
||||
glm::quat locRotation;
|
||||
|
|
|
@ -245,6 +245,7 @@ ScriptValue TouchEvent::toScriptValue(ScriptEngine* engine, const TouchEvent& ev
|
|||
return obj;
|
||||
}
|
||||
|
||||
void TouchEvent::fromScriptValue(const ScriptValue& object, TouchEvent& event) {
|
||||
bool TouchEvent::fromScriptValue(const ScriptValue& object, TouchEvent& event) {
|
||||
// nothing for now...
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
TouchEvent(const QTouchEvent& event, const TouchEvent& other);
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const TouchEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, TouchEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, TouchEvent& event);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
|
|
|
@ -208,22 +208,25 @@ ScriptValue qWSCloseCodeToScriptValue(ScriptEngine* engine, const QWebSocketProt
|
|||
return engine->newValue(closeCode);
|
||||
}
|
||||
|
||||
void qWSCloseCodeFromScriptValue(const ScriptValue &object, QWebSocketProtocol::CloseCode &closeCode) {
|
||||
bool qWSCloseCodeFromScriptValue(const ScriptValue &object, QWebSocketProtocol::CloseCode &closeCode) {
|
||||
closeCode = (QWebSocketProtocol::CloseCode)object.toUInt16();
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue webSocketToScriptValue(ScriptEngine* engine, WebSocketClass* const &in) {
|
||||
return engine->newQObject(in, ScriptEngine::ScriptOwnership);
|
||||
}
|
||||
|
||||
void webSocketFromScriptValue(const ScriptValue &object, WebSocketClass* &out) {
|
||||
bool webSocketFromScriptValue(const ScriptValue &object, WebSocketClass* &out) {
|
||||
out = qobject_cast<WebSocketClass*>(object.toQObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptValue wscReadyStateToScriptValue(ScriptEngine* engine, const WebSocketClass::ReadyState& readyState) {
|
||||
return engine->newValue(readyState);
|
||||
}
|
||||
|
||||
void wscReadyStateFromScriptValue(const ScriptValue& object, WebSocketClass::ReadyState& readyState) {
|
||||
bool wscReadyStateFromScriptValue(const ScriptValue& object, WebSocketClass::ReadyState& readyState) {
|
||||
readyState = (WebSocketClass::ReadyState)object.toUInt16();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -253,13 +253,13 @@ Q_DECLARE_METATYPE(QWebSocketProtocol::CloseCode);
|
|||
Q_DECLARE_METATYPE(WebSocketClass::ReadyState);
|
||||
|
||||
ScriptValue qWSCloseCodeToScriptValue(ScriptEngine* engine, const QWebSocketProtocol::CloseCode& closeCode);
|
||||
void qWSCloseCodeFromScriptValue(const ScriptValue& object, QWebSocketProtocol::CloseCode& closeCode);
|
||||
bool qWSCloseCodeFromScriptValue(const ScriptValue& object, QWebSocketProtocol::CloseCode& closeCode);
|
||||
|
||||
ScriptValue webSocketToScriptValue(ScriptEngine* engine, WebSocketClass* const &in);
|
||||
void webSocketFromScriptValue(const ScriptValue &object, WebSocketClass* &out);
|
||||
bool webSocketFromScriptValue(const ScriptValue& object, WebSocketClass*& out);
|
||||
|
||||
ScriptValue wscReadyStateToScriptValue(ScriptEngine* engine, const WebSocketClass::ReadyState& readyState);
|
||||
void wscReadyStateFromScriptValue(const ScriptValue& object, WebSocketClass::ReadyState& readyState);
|
||||
bool wscReadyStateFromScriptValue(const ScriptValue& object, WebSocketClass::ReadyState& readyState);
|
||||
|
||||
#endif // hifi_WebSocketClass_h
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ ScriptValue WheelEvent::toScriptValue(ScriptEngine* engine, const WheelEvent& ev
|
|||
return obj;
|
||||
}
|
||||
|
||||
void WheelEvent::fromScriptValue(const ScriptValue& object, WheelEvent& event) {
|
||||
bool WheelEvent::fromScriptValue(const ScriptValue& object, WheelEvent& event) {
|
||||
// nothing for now...
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
WheelEvent(const QWheelEvent& event);
|
||||
|
||||
static ScriptValue toScriptValue(ScriptEngine* engine, const WheelEvent& event);
|
||||
static void fromScriptValue(const ScriptValue& object, WheelEvent& event);
|
||||
static bool fromScriptValue(const ScriptValue& object, WheelEvent& event);
|
||||
|
||||
int x;
|
||||
int y;
|
||||
|
|
|
@ -87,7 +87,8 @@ QScriptValue ArrayBufferClass::newInstance(qint32 size) {
|
|||
}
|
||||
|
||||
QScriptValue ArrayBufferClass::newInstance(const QByteArray& ba) {
|
||||
QScriptValue data = engine()->newVariant(QVariant::fromValue(ba));
|
||||
QScriptEngine* eng = engine();
|
||||
QScriptValue data = eng->newVariant(QVariant::fromValue(ba));
|
||||
return engine()->newObject(this, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,17 +49,13 @@
|
|||
#include "../ScriptValue.h"
|
||||
|
||||
#include "ScriptContextQtWrapper.h"
|
||||
#include "ScriptObjectQtProxy.h"
|
||||
#include "ScriptProgramQtWrapper.h"
|
||||
#include "ScriptValueQtWrapper.h"
|
||||
#include "ScriptContextQtAgent.h"
|
||||
|
||||
static const int MAX_DEBUG_VALUE_LENGTH { 80 };
|
||||
|
||||
static const QScriptEngine::QObjectWrapOptions DEFAULT_QOBJECT_WRAP_OPTIONS =
|
||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects;
|
||||
|
||||
Q_DECLARE_METATYPE(ScriptValue);
|
||||
|
||||
Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature)
|
||||
int qfunctionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>();
|
||||
|
||||
|
@ -311,21 +307,12 @@ void ScriptEngineQtScript::_debugDump(const QString& header, const QScriptValue&
|
|||
}
|
||||
#endif
|
||||
|
||||
static QScriptValue ScriptValueToQScriptValue(QScriptEngine* engine, const ScriptValue& src) {
|
||||
return ScriptValueQtWrapper::fullUnwrap(static_cast<ScriptEngineQtScript*>(engine), src);
|
||||
}
|
||||
|
||||
static void ScriptValueFromQScriptValue(const QScriptValue& src, ScriptValue& dest) {
|
||||
ScriptEngineQtScript* engine = static_cast<ScriptEngineQtScript*>(src.engine());
|
||||
dest = ScriptValue(new ScriptValueQtWrapper(engine, src));
|
||||
}
|
||||
|
||||
ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) :
|
||||
QScriptEngine(),
|
||||
_scriptManager(scriptManager),
|
||||
_arrayBufferClass(new ArrayBufferClass(this))
|
||||
{
|
||||
qScriptRegisterMetaType(this, ScriptValueToQScriptValue, ScriptValueFromQScriptValue);
|
||||
registerSystemTypes();
|
||||
|
||||
if (_scriptManager) {
|
||||
connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) {
|
||||
|
@ -343,10 +330,10 @@ ScriptEngineQtScript::ScriptEngineQtScript(ScriptManager* scriptManager) :
|
|||
}
|
||||
|
||||
QScriptValue null = QScriptEngine::nullValue();
|
||||
_nullValue = ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(null)));
|
||||
_nullValue = ScriptValue(new ScriptValueQtWrapper(this, std::move(null)));
|
||||
|
||||
QScriptValue undefined = QScriptEngine::undefinedValue();
|
||||
_undefinedValue = ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(undefined)));
|
||||
_undefinedValue = ScriptValue(new ScriptValueQtWrapper(this, std::move(undefined)));
|
||||
|
||||
QScriptEngine::setProcessEventsInterval(MSECS_PER_SECOND);
|
||||
|
||||
|
@ -417,7 +404,7 @@ void ScriptEngineQtScript::registerGlobalObject(const QString& name, QObject* ob
|
|||
|
||||
if (!QScriptEngine::globalObject().property(name).isValid()) {
|
||||
if (object) {
|
||||
QScriptValue value = QScriptEngine::newQObject(object, QScriptEngine::QtOwnership, DEFAULT_QOBJECT_WRAP_OPTIONS);
|
||||
QScriptValue value = ScriptObjectQtProxy::newQObject(this, object, ScriptEngine::QtOwnership);
|
||||
QScriptEngine::globalObject().setProperty(name, value);
|
||||
} else {
|
||||
QScriptEngine::globalObject().setProperty(name, QScriptValue());
|
||||
|
@ -747,7 +734,7 @@ void ScriptEngineQtScript::updateMemoryCost(const qint64& deltaSize) {
|
|||
|
||||
ScriptValue ScriptEngineQtScript::globalObject() const {
|
||||
QScriptValue global = QScriptEngine::globalObject(); // can't cache the value as it may change
|
||||
return ScriptValue(new ScriptValueQtWrapper(const_cast < ScriptEngineQtScript*>(this), std::move(global)));
|
||||
return ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(global)));
|
||||
}
|
||||
|
||||
ScriptManager* ScriptEngineQtScript::manager() const {
|
||||
|
@ -783,8 +770,7 @@ ScriptProgramPointer ScriptEngineQtScript::newProgram(const QString& sourceCode,
|
|||
ScriptValue ScriptEngineQtScript::newQObject(QObject* object,
|
||||
ScriptEngine::ValueOwnership ownership,
|
||||
const ScriptEngine::QObjectWrapOptions& options) {
|
||||
QScriptValue result = QScriptEngine::newQObject(object, static_cast<QScriptEngine::ValueOwnership>(ownership),
|
||||
(QScriptEngine::QObjectWrapOptions)((int)options | DEFAULT_QOBJECT_WRAP_OPTIONS));
|
||||
QScriptValue result = ScriptObjectQtProxy::newQObject(this, object, ownership, options);
|
||||
return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -824,7 +810,7 @@ ScriptValue ScriptEngineQtScript::newValue(const char* value) {
|
|||
}
|
||||
|
||||
ScriptValue ScriptEngineQtScript::newVariant(const QVariant& value) {
|
||||
QScriptValue result = QScriptEngine::newVariant(value);
|
||||
QScriptValue result = castVariantToValue(value);
|
||||
return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));
|
||||
}
|
||||
|
||||
|
@ -832,13 +818,6 @@ ScriptValue ScriptEngineQtScript::nullValue() {
|
|||
return _nullValue;
|
||||
}
|
||||
|
||||
void ScriptEngineQtScript::setDefaultPrototype(int metaTypeId, const ScriptValue& prototype){
|
||||
ScriptValueQtWrapper* unwrappedPrototype = ScriptValueQtWrapper::unwrap(prototype);
|
||||
if (unwrappedPrototype) {
|
||||
QScriptEngine::setDefaultPrototype(metaTypeId, unwrappedPrototype->toQtValue());
|
||||
}
|
||||
}
|
||||
|
||||
ScriptValue ScriptEngineQtScript::undefinedValue() {
|
||||
return _undefinedValue;
|
||||
}
|
||||
|
@ -928,112 +907,26 @@ bool ScriptEngineQtScript::raiseException(const ScriptValue& exception) {
|
|||
}
|
||||
|
||||
ScriptValue ScriptEngineQtScript::create(int type, const void* ptr) {
|
||||
QScriptValue result = qScriptValueFromValue_helper(this, type, ptr);
|
||||
return ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result)));
|
||||
QVariant variant(type, ptr);
|
||||
QScriptValue scriptValue = castVariantToValue(variant);
|
||||
return ScriptValue(new ScriptValueQtWrapper(this, std::move(scriptValue)));
|
||||
}
|
||||
|
||||
bool ScriptEngineQtScript::convert(const ScriptValue& value, int type, void* ptr) {
|
||||
QVariant ScriptEngineQtScript::convert(const ScriptValue& value, int type) {
|
||||
ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(value);
|
||||
if (unwrapped == nullptr) {
|
||||
return false;
|
||||
return QVariant();
|
||||
}
|
||||
return qscriptvalue_cast_helper(unwrapped->toQtValue(), type, ptr);
|
||||
}
|
||||
|
||||
template <int i>
|
||||
class CustomTypeInstance {
|
||||
public:
|
||||
static ScriptEngine::MarshalFunction marshalFunc;
|
||||
static ScriptEngine::DemarshalFunction demarshalFunc;
|
||||
|
||||
static QScriptValue internalMarshalFunc(QScriptEngine* engine, const void* src) {
|
||||
ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(engine);
|
||||
ScriptValue dest = marshalFunc(unwrappedEngine, src);
|
||||
return ScriptValueQtWrapper::fullUnwrap(unwrappedEngine, dest);
|
||||
}
|
||||
|
||||
static void internalDemarshalFunc(const QScriptValue& src, void* dest) {
|
||||
ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(src.engine());
|
||||
ScriptValue wrappedSrc(new ScriptValueQtWrapper(unwrappedEngine, src));
|
||||
demarshalFunc(wrappedSrc, dest);
|
||||
}
|
||||
};
|
||||
template <int i>
|
||||
ScriptEngine::MarshalFunction CustomTypeInstance<i>::marshalFunc;
|
||||
template <int i>
|
||||
ScriptEngine::DemarshalFunction CustomTypeInstance<i>::demarshalFunc;
|
||||
|
||||
// I would *LOVE* it if there was a different way to do this, jeez!
|
||||
// Qt requires two functions that have no parameters that give any context,
|
||||
// one of the must return a QScriptValue (so we can't void* them into generics and stick them in the templates).
|
||||
// This *has* to be done via templates but the whole point of this is to avoid leaking types into the rest of
|
||||
// the system that would require anyone other than us to have a dependency on QtScript
|
||||
#define CUSTOM_TYPE_ENTRY(idx) \
|
||||
case idx: \
|
||||
CustomTypeInstance<idx>::marshalFunc = marshalFunc; \
|
||||
CustomTypeInstance<idx>::demarshalFunc = demarshalFunc; \
|
||||
internalMarshalFunc = CustomTypeInstance<idx>::internalMarshalFunc; \
|
||||
internalDemarshalFunc = CustomTypeInstance<idx>::internalDemarshalFunc; \
|
||||
break;
|
||||
#define CUSTOM_TYPE_ENTRY_10(idx) \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10)); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 1); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 2); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 3); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 4); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 5); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 6); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 7); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 8); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 9);
|
||||
|
||||
void ScriptEngineQtScript::registerCustomType(int type,
|
||||
ScriptEngine::MarshalFunction marshalFunc,
|
||||
ScriptEngine::DemarshalFunction demarshalFunc,
|
||||
const ScriptValue& prototype)
|
||||
{
|
||||
QScriptValue unwrapped = ScriptValueQtWrapper::fullUnwrap(this, prototype);
|
||||
QScriptEngine::MarshalFunction internalMarshalFunc;
|
||||
QScriptEngine::DemarshalFunction internalDemarshalFunc;
|
||||
|
||||
if (_nextCustomType >= 300) { // have we ran out of translators?
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_nextCustomType++) {
|
||||
CUSTOM_TYPE_ENTRY_10(0);
|
||||
CUSTOM_TYPE_ENTRY_10(1);
|
||||
CUSTOM_TYPE_ENTRY_10(2);
|
||||
CUSTOM_TYPE_ENTRY_10(3);
|
||||
CUSTOM_TYPE_ENTRY_10(4);
|
||||
CUSTOM_TYPE_ENTRY_10(5);
|
||||
CUSTOM_TYPE_ENTRY_10(6);
|
||||
CUSTOM_TYPE_ENTRY_10(7);
|
||||
CUSTOM_TYPE_ENTRY_10(8);
|
||||
CUSTOM_TYPE_ENTRY_10(9);
|
||||
CUSTOM_TYPE_ENTRY_10(10);
|
||||
CUSTOM_TYPE_ENTRY_10(11);
|
||||
CUSTOM_TYPE_ENTRY_10(12);
|
||||
CUSTOM_TYPE_ENTRY_10(13);
|
||||
CUSTOM_TYPE_ENTRY_10(14);
|
||||
CUSTOM_TYPE_ENTRY_10(15);
|
||||
CUSTOM_TYPE_ENTRY_10(16);
|
||||
CUSTOM_TYPE_ENTRY_10(17);
|
||||
CUSTOM_TYPE_ENTRY_10(18);
|
||||
CUSTOM_TYPE_ENTRY_10(19);
|
||||
CUSTOM_TYPE_ENTRY_10(20);
|
||||
CUSTOM_TYPE_ENTRY_10(21);
|
||||
CUSTOM_TYPE_ENTRY_10(22);
|
||||
CUSTOM_TYPE_ENTRY_10(23);
|
||||
CUSTOM_TYPE_ENTRY_10(24);
|
||||
CUSTOM_TYPE_ENTRY_10(25);
|
||||
CUSTOM_TYPE_ENTRY_10(26);
|
||||
CUSTOM_TYPE_ENTRY_10(27);
|
||||
CUSTOM_TYPE_ENTRY_10(28);
|
||||
CUSTOM_TYPE_ENTRY_10(29);
|
||||
CUSTOM_TYPE_ENTRY_10(30);
|
||||
}
|
||||
|
||||
qScriptRegisterMetaType_helper(this, type, internalMarshalFunc, internalDemarshalFunc, unwrapped);
|
||||
|
||||
QVariant var;
|
||||
if (!castValueToVariant(unwrapped->toQtValue(), var, type)) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int destType = var.userType();
|
||||
if (destType != type) {
|
||||
var.convert(type); // if conversion fails then var is set to QVariant()
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include <memory>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QMetaEnum>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QString>
|
||||
|
@ -148,10 +150,11 @@ public: // public non-interface methods for other QtScript-specific classes to u
|
|||
|
||||
public: // not for public use, but I don't like how Qt strings this along with private friend functions
|
||||
virtual ScriptValue create(int type, const void* ptr) override;
|
||||
virtual bool convert(const ScriptValue& value, int type, void* ptr) override;
|
||||
virtual QVariant convert(const ScriptValue& value, int type) override;
|
||||
virtual void registerCustomType(int type, ScriptEngine::MarshalFunction marshalFunc,
|
||||
ScriptEngine::DemarshalFunction demarshalFunc,
|
||||
const ScriptValue& prototype) override;
|
||||
ScriptEngine::DemarshalFunction demarshalFunc) override;
|
||||
bool castValueToVariant(const QScriptValue& val, QVariant& dest, int destType);
|
||||
QScriptValue castVariantToValue(const QVariant& val);
|
||||
|
||||
protected:
|
||||
// like `newFunction`, but allows mapping inline C++ lambdas with captures as callable QScriptValues
|
||||
|
@ -162,9 +165,21 @@ protected:
|
|||
const QScriptValue& data = QScriptValue(),
|
||||
const QScriptEngine::ValueOwnership& ownership = QScriptEngine::AutoOwnership);
|
||||
|
||||
void registerSystemTypes();
|
||||
|
||||
protected:
|
||||
struct CustomMarshal {
|
||||
ScriptEngine::MarshalFunction marshalFunc;
|
||||
ScriptEngine::DemarshalFunction demarshalFunc;
|
||||
};
|
||||
using CustomMarshalMap = QHash<int, CustomMarshal>;
|
||||
using CustomPrototypeMap = QHash<int, QScriptValue>;
|
||||
|
||||
QPointer<ScriptManager> _scriptManager;
|
||||
|
||||
mutable QMutex _customTypeProtect;
|
||||
CustomMarshalMap _customTypes;
|
||||
CustomPrototypeMap _customPrototypes;
|
||||
int _nextCustomType = 0;
|
||||
ScriptValue _nullValue;
|
||||
ScriptValue _undefinedValue;
|
||||
|
|
|
@ -0,0 +1,538 @@
|
|||
//
|
||||
// ScriptEngineQtScript_cast.cpp
|
||||
// libraries/script-engine/src/qtscript
|
||||
//
|
||||
// Created by Heather Anderson 12/9/2021
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptEngineQtScript.h"
|
||||
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonValue>
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
#include "../ScriptValueIterator.h"
|
||||
|
||||
#include "ScriptObjectQtProxy.h"
|
||||
#include "ScriptValueQtWrapper.h"
|
||||
|
||||
template <int i>
|
||||
class CustomTypeInstance {
|
||||
public:
|
||||
static ScriptEngine::MarshalFunction marshalFunc;
|
||||
static ScriptEngine::DemarshalFunction demarshalFunc;
|
||||
|
||||
static QScriptValue internalMarshalFunc(QScriptEngine* engine, const void* src) {
|
||||
ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(engine);
|
||||
ScriptValue dest = marshalFunc(unwrappedEngine, src);
|
||||
return ScriptValueQtWrapper::fullUnwrap(unwrappedEngine, dest);
|
||||
}
|
||||
|
||||
static void internalDemarshalFunc(const QScriptValue& src, void* dest) {
|
||||
ScriptEngineQtScript* unwrappedEngine = static_cast<ScriptEngineQtScript*>(src.engine());
|
||||
ScriptValue wrappedSrc(new ScriptValueQtWrapper(unwrappedEngine, src));
|
||||
demarshalFunc(wrappedSrc, dest);
|
||||
}
|
||||
};
|
||||
template <int i>
|
||||
ScriptEngine::MarshalFunction CustomTypeInstance<i>::marshalFunc;
|
||||
template <int i>
|
||||
ScriptEngine::DemarshalFunction CustomTypeInstance<i>::demarshalFunc;
|
||||
|
||||
// I would *LOVE* it if there was a different way to do this, jeez!
|
||||
// Qt requires two functions that have no parameters that give any context,
|
||||
// one of the must return a QScriptValue (so we can't void* them into generics and stick them in the templates).
|
||||
// This *has* to be done via templates but the whole point of this is to avoid leaking types into the rest of
|
||||
// the system that would require anyone other than us to have a dependency on QtScript
|
||||
#define CUSTOM_TYPE_ENTRY(idx) \
|
||||
case idx: \
|
||||
CustomTypeInstance<idx>::marshalFunc = marshalFunc; \
|
||||
CustomTypeInstance<idx>::demarshalFunc = demarshalFunc; \
|
||||
internalMarshalFunc = CustomTypeInstance<idx>::internalMarshalFunc; \
|
||||
internalDemarshalFunc = CustomTypeInstance<idx>::internalDemarshalFunc; \
|
||||
break;
|
||||
#define CUSTOM_TYPE_ENTRY_10(idx) \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10)); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 1); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 2); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 3); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 4); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 5); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 6); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 7); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 8); \
|
||||
CUSTOM_TYPE_ENTRY((idx * 10) + 9);
|
||||
|
||||
void ScriptEngineQtScript::setDefaultPrototype(int metaTypeId, const ScriptValue& prototype) {
|
||||
ScriptValueQtWrapper* unwrappedPrototype = ScriptValueQtWrapper::unwrap(prototype);
|
||||
if (unwrappedPrototype) {
|
||||
const QScriptValue& scriptPrototype = unwrappedPrototype->toQtValue();
|
||||
QScriptEngine::setDefaultPrototype(metaTypeId, scriptPrototype);
|
||||
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
_customPrototypes.insert(metaTypeId, scriptPrototype);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngineQtScript::registerCustomType(int type,
|
||||
ScriptEngine::MarshalFunction marshalFunc,
|
||||
ScriptEngine::DemarshalFunction demarshalFunc)
|
||||
{
|
||||
QScriptEngine::MarshalFunction internalMarshalFunc;
|
||||
QScriptEngine::DemarshalFunction internalDemarshalFunc;
|
||||
|
||||
{
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
|
||||
// storing it in a map for our own benefit
|
||||
CustomMarshal& customType = _customTypes.insert(type, CustomMarshal()).value();
|
||||
customType.demarshalFunc = demarshalFunc;
|
||||
customType.marshalFunc = marshalFunc;
|
||||
|
||||
// creating a conversion for QtScript's benefit
|
||||
if (_nextCustomType >= 300) { // have we ran out of translators?
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_nextCustomType++) {
|
||||
CUSTOM_TYPE_ENTRY_10(0);
|
||||
CUSTOM_TYPE_ENTRY_10(1);
|
||||
CUSTOM_TYPE_ENTRY_10(2);
|
||||
CUSTOM_TYPE_ENTRY_10(3);
|
||||
CUSTOM_TYPE_ENTRY_10(4);
|
||||
CUSTOM_TYPE_ENTRY_10(5);
|
||||
CUSTOM_TYPE_ENTRY_10(6);
|
||||
CUSTOM_TYPE_ENTRY_10(7);
|
||||
CUSTOM_TYPE_ENTRY_10(8);
|
||||
CUSTOM_TYPE_ENTRY_10(9);
|
||||
CUSTOM_TYPE_ENTRY_10(10);
|
||||
CUSTOM_TYPE_ENTRY_10(11);
|
||||
CUSTOM_TYPE_ENTRY_10(12);
|
||||
CUSTOM_TYPE_ENTRY_10(13);
|
||||
CUSTOM_TYPE_ENTRY_10(14);
|
||||
CUSTOM_TYPE_ENTRY_10(15);
|
||||
CUSTOM_TYPE_ENTRY_10(16);
|
||||
CUSTOM_TYPE_ENTRY_10(17);
|
||||
CUSTOM_TYPE_ENTRY_10(18);
|
||||
CUSTOM_TYPE_ENTRY_10(19);
|
||||
CUSTOM_TYPE_ENTRY_10(20);
|
||||
CUSTOM_TYPE_ENTRY_10(21);
|
||||
CUSTOM_TYPE_ENTRY_10(22);
|
||||
CUSTOM_TYPE_ENTRY_10(23);
|
||||
CUSTOM_TYPE_ENTRY_10(24);
|
||||
CUSTOM_TYPE_ENTRY_10(25);
|
||||
CUSTOM_TYPE_ENTRY_10(26);
|
||||
CUSTOM_TYPE_ENTRY_10(27);
|
||||
CUSTOM_TYPE_ENTRY_10(28);
|
||||
CUSTOM_TYPE_ENTRY_10(29);
|
||||
CUSTOM_TYPE_ENTRY_10(30);
|
||||
}
|
||||
}
|
||||
|
||||
qScriptRegisterMetaType_helper(this, type, internalMarshalFunc, internalDemarshalFunc, QScriptValue());
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(ScriptValue);
|
||||
|
||||
static QScriptValue ScriptValueToQScriptValue(QScriptEngine* engine, const ScriptValue& src) {
|
||||
return ScriptValueQtWrapper::fullUnwrap(static_cast<ScriptEngineQtScript*>(engine), src);
|
||||
}
|
||||
|
||||
static void ScriptValueFromQScriptValue(const QScriptValue& src, ScriptValue& dest) {
|
||||
ScriptEngineQtScript* engine = static_cast<ScriptEngineQtScript*>(src.engine());
|
||||
dest = ScriptValue(new ScriptValueQtWrapper(engine, src));
|
||||
}
|
||||
|
||||
static ScriptValue StringListToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QStringList& src = *reinterpret_cast<const QStringList*>(pSrc);
|
||||
int len = src.length();
|
||||
ScriptValue dest = engine->newArray(len);
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
dest.setProperty(idx, engine->newValue(src.at(idx)));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool StringListFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
if(!src.isArray()) return false;
|
||||
QStringList& dest = *reinterpret_cast<QStringList*>(pDest);
|
||||
int len = src.property("length").toInteger();
|
||||
dest.clear();
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
dest.append(src.property(idx).toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue VariantListToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QVariantList& src = *reinterpret_cast<const QVariantList*>(pSrc);
|
||||
int len = src.length();
|
||||
ScriptValue dest = engine->newArray(len);
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
dest.setProperty(idx, engine->newVariant(src.at(idx)));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool VariantListFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
if(!src.isArray()) return false;
|
||||
QVariantList& dest = *reinterpret_cast<QVariantList*>(pDest);
|
||||
int len = src.property("length").toInteger();
|
||||
dest.clear();
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
dest.append(src.property(idx).toVariant());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue VariantMapToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QVariantMap& src = *reinterpret_cast<const QVariantMap*>(pSrc);
|
||||
ScriptValue dest = engine->newObject();
|
||||
for (QVariantMap::const_iterator iter = src.cbegin(); iter != src.cend(); ++iter) {
|
||||
dest.setProperty(iter.key(), engine->newVariant(iter.value()));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool VariantMapFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
QVariantMap& dest = *reinterpret_cast<QVariantMap*>(pDest);
|
||||
dest.clear();
|
||||
ScriptValueIteratorPointer iter = src.newIterator();
|
||||
while (iter->hasNext()) {
|
||||
iter->next();
|
||||
dest.insert(iter->name(), iter->value().toVariant());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue VariantHashToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QVariantHash& src = *reinterpret_cast<const QVariantHash*>(pSrc);
|
||||
ScriptValue dest = engine->newObject();
|
||||
for (QVariantHash::const_iterator iter = src.cbegin(); iter != src.cend(); ++iter) {
|
||||
dest.setProperty(iter.key(), engine->newVariant(iter.value()));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool VariantHashFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
QVariantHash& dest = *reinterpret_cast<QVariantHash*>(pDest);
|
||||
dest.clear();
|
||||
ScriptValueIteratorPointer iter = src.newIterator();
|
||||
while (iter->hasNext()) {
|
||||
iter->next();
|
||||
dest.insert(iter->name(), iter->value().toVariant());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue JsonValueToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QJsonValue& src = *reinterpret_cast<const QJsonValue*>(pSrc);
|
||||
return engine->newVariant(src.toVariant());
|
||||
}
|
||||
|
||||
static bool JsonValueFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
QJsonValue& dest = *reinterpret_cast<QJsonValue*>(pDest);
|
||||
dest = QJsonValue::fromVariant(src.toVariant());
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue JsonObjectToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QJsonObject& src = *reinterpret_cast<const QJsonObject*>(pSrc);
|
||||
QVariantMap map = src.toVariantMap();
|
||||
ScriptValue dest = engine->newObject();
|
||||
for (QVariantMap::const_iterator iter = map.cbegin(); iter != map.cend(); ++iter) {
|
||||
dest.setProperty(iter.key(), engine->newVariant(iter.value()));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool JsonObjectFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
QJsonObject& dest = *reinterpret_cast<QJsonObject*>(pDest);
|
||||
QVariantMap map;
|
||||
ScriptValueIteratorPointer iter = src.newIterator();
|
||||
while (iter->hasNext()) {
|
||||
iter->next();
|
||||
map.insert(iter->name(), iter->value().toVariant());
|
||||
}
|
||||
dest = QJsonObject::fromVariantMap(map);
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScriptValue JsonArrayToScriptValue(ScriptEngine* engine, const void* pSrc) {
|
||||
const QJsonArray& src = *reinterpret_cast<const QJsonArray*>(pSrc);
|
||||
QVariantList list = src.toVariantList();
|
||||
int len = list.length();
|
||||
ScriptValue dest = engine->newArray(len);
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
dest.setProperty(idx, engine->newVariant(list.at(idx)));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static bool JsonArrayFromScriptValue(const ScriptValue& src, void* pDest) {
|
||||
if(!src.isArray()) return false;
|
||||
QJsonArray& dest = *reinterpret_cast<QJsonArray*>(pDest);
|
||||
QVariantList list;
|
||||
int len = src.property("length").toInteger();
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
list.append(src.property(idx).toVariant());
|
||||
}
|
||||
dest = QJsonArray::fromVariantList(list);
|
||||
return true;
|
||||
}
|
||||
|
||||
// QMetaType::QJsonArray
|
||||
|
||||
void ScriptEngineQtScript::registerSystemTypes() {
|
||||
qScriptRegisterMetaType(this, ScriptValueToQScriptValue, ScriptValueFromQScriptValue);
|
||||
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QStringList, CustomMarshal()).value();
|
||||
customType.demarshalFunc = StringListFromScriptValue;
|
||||
customType.marshalFunc = StringListToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QVariantList, CustomMarshal()).value();
|
||||
customType.demarshalFunc = VariantListFromScriptValue;
|
||||
customType.marshalFunc = VariantListToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QVariantMap, CustomMarshal()).value();
|
||||
customType.demarshalFunc = VariantMapFromScriptValue;
|
||||
customType.marshalFunc = VariantMapToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QVariantHash, CustomMarshal()).value();
|
||||
customType.demarshalFunc = VariantHashFromScriptValue;
|
||||
customType.marshalFunc = VariantHashToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QJsonValue, CustomMarshal()).value();
|
||||
customType.demarshalFunc = JsonValueFromScriptValue;
|
||||
customType.marshalFunc = JsonValueToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QJsonObject, CustomMarshal()).value();
|
||||
customType.demarshalFunc = JsonObjectFromScriptValue;
|
||||
customType.marshalFunc = JsonObjectToScriptValue;
|
||||
}
|
||||
{
|
||||
CustomMarshal& customType = _customTypes.insert(QMetaType::QJsonArray, CustomMarshal()).value();
|
||||
customType.demarshalFunc = JsonArrayFromScriptValue;
|
||||
customType.marshalFunc = JsonArrayToScriptValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptEngineQtScript::castValueToVariant(const QScriptValue& val, QVariant& dest, int destType) {
|
||||
|
||||
// if we're not particularly interested in a specific type, try to detect if we're dealing with a registered type
|
||||
if (destType == QMetaType::UnknownType) {
|
||||
QObject* obj = ScriptObjectQtProxy::unwrap(val);
|
||||
if (obj) {
|
||||
for (const QMetaObject* metaObject = obj->metaObject(); metaObject; metaObject = metaObject->superClass()) {
|
||||
QByteArray typeName = QByteArray(metaObject->className()) + "*";
|
||||
int typeId = QMetaType::type(typeName.constData());
|
||||
if (typeId != QMetaType::UnknownType) {
|
||||
destType = typeId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (destType == qMetaTypeId<ScriptValue>()) {
|
||||
dest = QVariant::fromValue(ScriptValue(new ScriptValueQtWrapper(this, val)));
|
||||
return true;
|
||||
}
|
||||
|
||||
// do we have a registered handler for this type?
|
||||
ScriptEngine::DemarshalFunction demarshalFunc = nullptr;
|
||||
{
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
CustomMarshalMap::const_iterator lookup = _customTypes.find(destType);
|
||||
if (lookup != _customTypes.cend()) {
|
||||
demarshalFunc = lookup.value().demarshalFunc;
|
||||
}
|
||||
}
|
||||
if (demarshalFunc) {
|
||||
void* destStorage = QMetaType::create(destType);
|
||||
ScriptValue wrappedVal(new ScriptValueQtWrapper(this, val));
|
||||
bool success = demarshalFunc(wrappedVal, destStorage);
|
||||
dest = success ? QVariant(destType, destStorage) : QVariant();
|
||||
QMetaType::destroy(destType, destStorage);
|
||||
return success;
|
||||
} else {
|
||||
switch (destType) {
|
||||
case QMetaType::UnknownType:
|
||||
if (val.isUndefined()) {
|
||||
dest = QVariant();
|
||||
break;
|
||||
}
|
||||
if (val.isNull()) {
|
||||
dest = QVariant::fromValue(nullptr);
|
||||
break;
|
||||
}
|
||||
if (val.isBool()) {
|
||||
dest = QVariant::fromValue(val.toBool());
|
||||
break;
|
||||
}
|
||||
if (val.isString()) {
|
||||
dest = QVariant::fromValue(val.toString());
|
||||
break;
|
||||
}
|
||||
if (val.isNumber()) {
|
||||
dest = QVariant::fromValue(val.toNumber());
|
||||
break;
|
||||
}
|
||||
{
|
||||
QObject* obj = ScriptObjectQtProxy::unwrap(val);
|
||||
if (obj) {
|
||||
dest = QVariant::fromValue(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
QVariant var = ScriptVariantQtProxy::unwrap(val);
|
||||
if (var.isValid()) {
|
||||
dest = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dest = val.toVariant();
|
||||
break;
|
||||
case QMetaType::Bool:
|
||||
dest = QVariant::fromValue(val.toBool());
|
||||
break;
|
||||
case QMetaType::QDateTime:
|
||||
case QMetaType::QDate:
|
||||
Q_ASSERT(val.isDate());
|
||||
dest = QVariant::fromValue(val.toDateTime());
|
||||
break;
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULong:
|
||||
dest = QVariant::fromValue(val.toUInt32());
|
||||
break;
|
||||
case QMetaType::Int:
|
||||
case QMetaType::Long:
|
||||
case QMetaType::Short:
|
||||
dest = QVariant::fromValue(val.toInt32());
|
||||
break;
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Float:
|
||||
case QMetaType::ULongLong:
|
||||
case QMetaType::LongLong:
|
||||
dest = QVariant::fromValue(val.toNumber());
|
||||
break;
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QByteArray:
|
||||
dest = QVariant::fromValue(val.toString());
|
||||
break;
|
||||
case QMetaType::UShort:
|
||||
dest = QVariant::fromValue(val.toUInt16());
|
||||
break;
|
||||
case QMetaType::QObjectStar:
|
||||
dest = QVariant::fromValue(ScriptObjectQtProxy::unwrap(val));
|
||||
break;
|
||||
default:
|
||||
// check to see if this is a pointer to a QObject-derived object
|
||||
if (QMetaType::typeFlags(destType) & QMetaType::PointerToQObject) {
|
||||
dest = QVariant::fromValue(ScriptObjectQtProxy::unwrap(val));
|
||||
break;
|
||||
}
|
||||
// check to see if we have a registered prototype
|
||||
{
|
||||
QVariant var = ScriptVariantQtProxy::unwrap(val);
|
||||
if (var.isValid()) {
|
||||
dest = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// last chance, just convert it to a variant
|
||||
dest = val.toVariant();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return destType == QMetaType::UnknownType || dest.userType() == destType || dest.convert(destType);
|
||||
}
|
||||
|
||||
QScriptValue ScriptEngineQtScript::castVariantToValue(const QVariant& val) {
|
||||
int valTypeId = val.userType();
|
||||
|
||||
if (valTypeId == qMetaTypeId<ScriptValue>()) {
|
||||
// this is a wrapped ScriptValue, so just unwrap it and call it good
|
||||
ScriptValue innerVal = val.value<ScriptValue>();
|
||||
return ScriptValueQtWrapper::fullUnwrap(this, innerVal);
|
||||
}
|
||||
|
||||
// do we have a registered handler for this type?
|
||||
ScriptEngine::MarshalFunction marshalFunc = nullptr;
|
||||
{
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
CustomMarshalMap::const_iterator lookup = _customTypes.find(valTypeId);
|
||||
if (lookup != _customTypes.cend()) {
|
||||
marshalFunc = lookup.value().marshalFunc;
|
||||
}
|
||||
}
|
||||
if (marshalFunc) {
|
||||
ScriptValue wrappedVal = marshalFunc(this, val.constData());
|
||||
return ScriptValueQtWrapper::fullUnwrap(this, wrappedVal);
|
||||
}
|
||||
|
||||
switch (valTypeId) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
return QScriptValue(this, QScriptValue::UndefinedValue);
|
||||
case QMetaType::Nullptr:
|
||||
return QScriptValue(this, QScriptValue::NullValue);
|
||||
case QMetaType::Bool:
|
||||
return QScriptValue(this, val.toBool());
|
||||
case QMetaType::Int:
|
||||
case QMetaType::Long:
|
||||
case QMetaType::Short:
|
||||
return QScriptValue(this, val.toInt());
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULong:
|
||||
case QMetaType::UShort:
|
||||
return QScriptValue(this, val.toUInt());
|
||||
case QMetaType::Float:
|
||||
case QMetaType::LongLong:
|
||||
case QMetaType::ULongLong:
|
||||
case QMetaType::Double:
|
||||
return QScriptValue(this, val.toFloat());
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QByteArray:
|
||||
return QScriptValue(this, val.toString());
|
||||
case QMetaType::QVariant:
|
||||
return castVariantToValue(val.value<QVariant>());
|
||||
case QMetaType::QObjectStar:
|
||||
return ScriptObjectQtProxy::newQObject(this, val.value<QObject*>(), ScriptEngine::QtOwnership);
|
||||
case QMetaType::QDateTime:
|
||||
return static_cast<QScriptEngine*>(this)->newDate(val.value<QDateTime>());
|
||||
case QMetaType::QDate:
|
||||
return static_cast<QScriptEngine*>(this)->newDate(val.value<QDate>().startOfDay());
|
||||
default:
|
||||
// check to see if this is a pointer to a QObject-derived object
|
||||
if (QMetaType::typeFlags(valTypeId) & QMetaType::PointerToQObject) {
|
||||
return ScriptObjectQtProxy::newQObject(this, val.value<QObject*>(), ScriptEngine::QtOwnership);
|
||||
}
|
||||
// have we set a prototype'd variant?
|
||||
{
|
||||
QMutexLocker guard(&_customTypeProtect);
|
||||
CustomPrototypeMap::const_iterator lookup = _customPrototypes.find(valTypeId);
|
||||
if (lookup != _customPrototypes.cend()) {
|
||||
return ScriptVariantQtProxy::newVariant(this, val, lookup.value());
|
||||
}
|
||||
}
|
||||
// just do a generic variant
|
||||
return QScriptEngine::newVariant(val);
|
||||
}
|
||||
}
|
622
libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp
Normal file
622
libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp
Normal file
|
@ -0,0 +1,622 @@
|
|||
//
|
||||
// ScriptObjectQtProxy.cpp
|
||||
// libraries/script-engine/src/qtscript
|
||||
//
|
||||
// Created by Heather Anderson on 12/5/21.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptObjectQtProxy.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
#include <QtScript/QScriptContext>
|
||||
|
||||
#include "ScriptContextQtWrapper.h"
|
||||
#include "ScriptValueQtWrapper.h"
|
||||
|
||||
Q_DECLARE_METATYPE(QScriptContext*)
|
||||
Q_DECLARE_METATYPE(ScriptValue)
|
||||
Q_DECLARE_METATYPE(QScriptValue)
|
||||
|
||||
Q_DECLARE_METATYPE(QSharedPointer<ScriptObjectQtProxy>)
|
||||
Q_DECLARE_METATYPE(QSharedPointer<ScriptVariantQtProxy>)
|
||||
|
||||
// Used strictly to replace the "this" object value for property access. May expand to a full context element
|
||||
// if we find it necessary to, but hopefully not needed
|
||||
class ScriptPropertyContextQtWrapper final : public ScriptContext {
|
||||
public: // construction
|
||||
inline ScriptPropertyContextQtWrapper(const ScriptValue& object, ScriptContext* parentContext) :
|
||||
_parent(parentContext), _object(object) {}
|
||||
|
||||
public: // ScriptContext implementation
|
||||
virtual int argumentCount() const override { return _parent->argumentCount(); }
|
||||
virtual ScriptValue argument(int index) const override { return _parent->argument(index); }
|
||||
virtual QStringList backtrace() const override { return _parent->backtrace(); }
|
||||
virtual ScriptValue callee() const override { return _parent->callee(); }
|
||||
virtual ScriptEnginePointer engine() const override { return _parent->engine(); }
|
||||
virtual ScriptFunctionContextPointer functionContext() const override { return _parent->functionContext(); }
|
||||
virtual ScriptContextPointer parentContext() const override { return _parent->parentContext(); }
|
||||
virtual ScriptValue thisObject() const override { return _object; }
|
||||
virtual ScriptValue throwError(const QString& text) override { return _parent->throwError(text); }
|
||||
virtual ScriptValue throwValue(const ScriptValue& value) override { return _parent->throwValue(value); }
|
||||
|
||||
private: // storage
|
||||
ScriptContext* _parent;
|
||||
const ScriptValue& _object;
|
||||
};
|
||||
|
||||
QScriptValue ScriptObjectQtProxy::newQObject(ScriptEngineQtScript* engine, QObject* object,
|
||||
ScriptEngine::ValueOwnership ownership,
|
||||
const ScriptEngine::QObjectWrapOptions& options) {
|
||||
bool ownsObject;
|
||||
switch (ownership) {
|
||||
case ScriptEngine::QtOwnership:
|
||||
ownsObject = false;
|
||||
break;
|
||||
case ScriptEngine::ScriptOwnership:
|
||||
ownsObject = true;
|
||||
break;
|
||||
case ScriptEngine::AutoOwnership:
|
||||
ownsObject = !object->parent();
|
||||
break;
|
||||
}
|
||||
QScriptEngine* qengine = static_cast<QScriptEngine*>(engine);
|
||||
auto proxy = QSharedPointer<ScriptObjectQtProxy>::create(engine, object, ownsObject, options);
|
||||
return static_cast<QScriptEngine*>(engine)->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));
|
||||
}
|
||||
|
||||
ScriptObjectQtProxy* ScriptObjectQtProxy::unwrapProxy(const QScriptValue& val) {
|
||||
QScriptClass* scriptClass = val.scriptClass();
|
||||
return scriptClass ? dynamic_cast<ScriptObjectQtProxy*>(scriptClass) : nullptr;
|
||||
}
|
||||
|
||||
QObject* ScriptObjectQtProxy::unwrap(const QScriptValue& val) {
|
||||
if (val.isQObject()) {
|
||||
return val.toQObject();
|
||||
}
|
||||
ScriptObjectQtProxy* proxy = unwrapProxy(val);
|
||||
return proxy ? proxy->toQtValue() : nullptr;
|
||||
}
|
||||
|
||||
ScriptObjectQtProxy::~ScriptObjectQtProxy() {
|
||||
if (_ownsObject) {
|
||||
QObject* qobject = _object;
|
||||
if(qobject) qobject->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptObjectQtProxy::investigate() {
|
||||
QObject* qobject = _object;
|
||||
Q_ASSERT(qobject);
|
||||
if (!qobject) return;
|
||||
|
||||
const QMetaObject* metaObject = qobject->metaObject();
|
||||
_name = QString::fromLatin1(metaObject->className());
|
||||
|
||||
// discover properties
|
||||
int startIdx = _wrapOptions & ScriptEngine::ExcludeSuperClassProperties ? metaObject->propertyOffset() : 0;
|
||||
int num = metaObject->propertyCount();
|
||||
for (int idx = startIdx; idx < num; ++idx) {
|
||||
QMetaProperty prop = metaObject->property(idx);
|
||||
if (!prop.isScriptable()) continue;
|
||||
|
||||
// always exclude child objects (at least until we decide otherwise)
|
||||
int metaTypeId = prop.userType();
|
||||
if (metaTypeId != QMetaType::UnknownType) {
|
||||
QMetaType metaType(metaTypeId);
|
||||
if (metaType.flags() & QMetaType::PointerToQObject) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
PropertyDef& propDef = _props.insert(idx, PropertyDef()).value();
|
||||
propDef.name = _engine->toStringHandle(QString::fromLatin1(prop.name()));
|
||||
propDef.flags = QScriptValue::Undeletable | QScriptValue::PropertyGetter | QScriptValue::PropertySetter |
|
||||
QScriptValue::QObjectMember;
|
||||
if (prop.isConstant()) propDef.flags |= QScriptValue::ReadOnly;
|
||||
}
|
||||
|
||||
// discover methods
|
||||
startIdx = _wrapOptions & ScriptEngine::ExcludeSuperClassMethods ? metaObject->methodCount() : 0;
|
||||
num = metaObject->methodCount();
|
||||
QHash<QScriptString, int> methodNames;
|
||||
for (int idx = startIdx; idx < num; ++idx) {
|
||||
QMetaMethod method = metaObject->method(idx);
|
||||
|
||||
// perhaps keep this comment? Calls (like AudioScriptingInterface::playSound) seem to expect non-public methods to be script-accessible
|
||||
/* if (method.access() != QMetaMethod::Public) continue;*/
|
||||
|
||||
bool isSignal = false;
|
||||
QByteArray szName = method.name();
|
||||
|
||||
switch (method.methodType()) {
|
||||
case QMetaMethod::Constructor:
|
||||
continue;
|
||||
case QMetaMethod::Signal:
|
||||
isSignal = true;
|
||||
break;
|
||||
case QMetaMethod::Slot:
|
||||
if (_wrapOptions & ScriptEngine::ExcludeSlots) {
|
||||
continue;
|
||||
}
|
||||
if (szName == "deleteLater") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
QScriptString name = _engine->toStringHandle(QString::fromLatin1(szName));
|
||||
auto nameLookup = methodNames.find(name);
|
||||
if (isSignal) {
|
||||
if (nameLookup == methodNames.end()) {
|
||||
SignalDef& signalDef = _signals.insert(idx, SignalDef()).value();
|
||||
signalDef.name = name;
|
||||
signalDef.signal = method;
|
||||
methodNames.insert(name, idx);
|
||||
} else {
|
||||
int originalMethodId = nameLookup.value();
|
||||
SignalDefMap::iterator signalLookup = _signals.find(originalMethodId);
|
||||
Q_ASSERT(signalLookup != _signals.end());
|
||||
SignalDef& signalDef = signalLookup.value();
|
||||
Q_ASSERT(signalDef.signal.parameterCount() != method.parameterCount());
|
||||
if (signalDef.signal.parameterCount() < method.parameterCount()) {
|
||||
signalDef.signal = method;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nameLookup == methodNames.end()) {
|
||||
MethodDef& methodDef = _methods.insert(idx, MethodDef()).value();
|
||||
methodDef.name = name;
|
||||
methodDef.methods.append(method);
|
||||
methodNames.insert(name, idx);
|
||||
} else {
|
||||
int originalMethodId = nameLookup.value();
|
||||
MethodDefMap::iterator methodLookup = _methods.find(originalMethodId);
|
||||
Q_ASSERT(methodLookup != _methods.end());
|
||||
MethodDef& methodDef = methodLookup.value();
|
||||
methodDef.methods.append(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QScriptClass::QueryFlags ScriptObjectQtProxy::queryProperty(const QScriptValue& object, const QScriptString& name, QueryFlags flags, uint* id) {
|
||||
// check for properties
|
||||
for (PropertyDefMap::const_iterator trans = _props.cbegin(); trans != _props.cend(); ++trans) {
|
||||
const PropertyDef& propDef = trans.value();
|
||||
if (propDef.name != name) continue;
|
||||
*id = trans.key() | PROPERTY_TYPE;
|
||||
return flags & (HandlesReadAccess | HandlesWriteAccess);
|
||||
}
|
||||
|
||||
// check for methods
|
||||
for (MethodDefMap::const_iterator trans = _methods.cbegin(); trans != _methods.cend(); ++trans) {
|
||||
if (trans.value().name != name) continue;
|
||||
*id = trans.key() | METHOD_TYPE;
|
||||
return flags & (HandlesReadAccess | HandlesWriteAccess);
|
||||
}
|
||||
|
||||
// check for signals
|
||||
for (SignalDefMap::const_iterator trans = _signals.cbegin(); trans != _signals.cend(); ++trans) {
|
||||
if (trans.value().name != name) continue;
|
||||
*id = trans.key() | SIGNAL_TYPE;
|
||||
return flags & (HandlesReadAccess | HandlesWriteAccess);
|
||||
}
|
||||
|
||||
return QueryFlags();
|
||||
}
|
||||
|
||||
QScriptValue::PropertyFlags ScriptObjectQtProxy::propertyFlags(const QScriptValue& object, const QScriptString& name, uint id) {
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
return QScriptValue::PropertyFlags();
|
||||
}
|
||||
|
||||
switch (id & TYPE_MASK) {
|
||||
case PROPERTY_TYPE: {
|
||||
PropertyDefMap::const_iterator lookup = _props.find(id & ~TYPE_MASK);
|
||||
if (lookup == _props.cend()) return QScriptValue::PropertyFlags();
|
||||
const PropertyDef& propDef = lookup.value();
|
||||
return propDef.flags;
|
||||
}
|
||||
case METHOD_TYPE: {
|
||||
MethodDefMap::const_iterator lookup = _methods.find(id & ~TYPE_MASK);
|
||||
if (lookup == _methods.cend()) return QScriptValue::PropertyFlags();
|
||||
return QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::QObjectMember;
|
||||
}
|
||||
case SIGNAL_TYPE: {
|
||||
SignalDefMap::const_iterator lookup = _signals.find(id & ~TYPE_MASK);
|
||||
if (lookup == _signals.cend()) return QScriptValue::PropertyFlags();
|
||||
return QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::QObjectMember;
|
||||
}
|
||||
}
|
||||
return QScriptValue::PropertyFlags();
|
||||
}
|
||||
|
||||
QScriptValue ScriptObjectQtProxy::property(const QScriptValue& object, const QScriptString& name, uint id) {
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::ReferenceError, "Referencing deleted native object");
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
const QMetaObject* metaObject = qobject->metaObject();
|
||||
|
||||
switch (id & TYPE_MASK) {
|
||||
case PROPERTY_TYPE: {
|
||||
int propId = id & ~TYPE_MASK;
|
||||
PropertyDefMap::const_iterator lookup = _props.find(propId);
|
||||
if (lookup == _props.cend()) return QScriptValue();
|
||||
const PropertyDef& propDef = lookup.value();
|
||||
|
||||
QMetaProperty prop = metaObject->property(propId);
|
||||
ScriptValue scriptThis = ScriptValue(new ScriptValueQtWrapper(_engine, object));
|
||||
ScriptPropertyContextQtWrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
|
||||
QVariant varValue = prop.read(qobject);
|
||||
return _engine->castVariantToValue(varValue);
|
||||
}
|
||||
case METHOD_TYPE: {
|
||||
int methodId = id & ~TYPE_MASK;
|
||||
MethodDefMap::const_iterator lookup = _methods.find(methodId);
|
||||
if (lookup == _methods.cend()) return QScriptValue();
|
||||
return static_cast<QScriptEngine*>(_engine)->newObject(
|
||||
new ScriptMethodQtProxy(_engine, qobject, object, name, lookup.value().methods));
|
||||
}
|
||||
case SIGNAL_TYPE: {
|
||||
int signalId = id & ~TYPE_MASK;
|
||||
SignalDefMap::const_iterator defLookup = _signals.find(signalId);
|
||||
if (defLookup == _signals.cend()) return QScriptValue();
|
||||
|
||||
InstanceMap::const_iterator instLookup = _signalInstances.find(signalId);
|
||||
if (instLookup == _signalInstances.cend() || instLookup.value().isNull()) {
|
||||
instLookup = _signalInstances.insert(signalId,
|
||||
new ScriptSignalQtProxy(_engine, qobject, object, name, defLookup.value().signal));
|
||||
Q_ASSERT(instLookup != _signalInstances.cend());
|
||||
}
|
||||
ScriptSignalQtProxy* proxy = instLookup.value();
|
||||
|
||||
QScriptEngine::QObjectWrapOptions options = QScriptEngine::ExcludeSuperClassContents |
|
||||
QScriptEngine::ExcludeDeleteLater |
|
||||
QScriptEngine::PreferExistingWrapperObject;
|
||||
return static_cast<QScriptEngine*>(_engine)->newQObject(proxy, QScriptEngine::ScriptOwnership, options);
|
||||
}
|
||||
}
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
void ScriptObjectQtProxy::setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value) {
|
||||
if (!(id & PROPERTY_TYPE)) return;
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::ReferenceError, "Referencing deleted native object");
|
||||
return;
|
||||
}
|
||||
|
||||
int propId = id & ~TYPE_MASK;
|
||||
PropertyDefMap::const_iterator lookup = _props.find(propId);
|
||||
if (lookup == _props.cend()) return;
|
||||
const PropertyDef& propDef = lookup.value();
|
||||
if (propDef.flags & QScriptValue::ReadOnly) return;
|
||||
|
||||
const QMetaObject* metaObject = qobject->metaObject();
|
||||
QMetaProperty prop = metaObject->property(propId);
|
||||
|
||||
ScriptValue scriptThis = ScriptValue(new ScriptValueQtWrapper(_engine, object));
|
||||
ScriptPropertyContextQtWrapper ourContext(scriptThis, _engine->currentContext());
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
|
||||
int propTypeId = prop.userType();
|
||||
QVariant varValue;
|
||||
if(!_engine->castValueToVariant(value, varValue, propTypeId)) {
|
||||
QByteArray propTypeName = QMetaType(propTypeId).name();
|
||||
QByteArray valTypeName = value.toVariant().typeName();
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::TypeError, QString("Cannot convert %1 to %2").arg(valTypeName, propTypeName));
|
||||
return;
|
||||
}
|
||||
prop.write(qobject, varValue);
|
||||
}
|
||||
|
||||
ScriptVariantQtProxy::ScriptVariantQtProxy(ScriptEngineQtScript* engine, const QVariant& variant, QScriptValue scriptProto, ScriptObjectQtProxy* proto) :
|
||||
QScriptClass(engine), _engine(engine), _variant(variant), _scriptProto(scriptProto), _proto(proto) {
|
||||
_name = QString::fromLatin1(variant.typeName());
|
||||
}
|
||||
|
||||
QScriptValue ScriptVariantQtProxy::newVariant(ScriptEngineQtScript* engine, const QVariant& variant, QScriptValue proto) {
|
||||
QScriptEngine* qengine = static_cast<QScriptEngine*>(engine);
|
||||
ScriptObjectQtProxy* protoProxy = ScriptObjectQtProxy::unwrapProxy(proto);
|
||||
if (!protoProxy) {
|
||||
Q_ASSERT(protoProxy);
|
||||
return qengine->newVariant(variant);
|
||||
}
|
||||
auto proxy = QSharedPointer<ScriptVariantQtProxy>::create(engine, variant, proto, protoProxy);
|
||||
return static_cast<QScriptEngine*>(engine)->newObject(proxy.get(), qengine->newVariant(QVariant::fromValue(proxy)));
|
||||
}
|
||||
|
||||
ScriptVariantQtProxy* ScriptVariantQtProxy::unwrapProxy(const QScriptValue& val) {
|
||||
QScriptClass* scriptClass = val.scriptClass();
|
||||
return scriptClass ? dynamic_cast<ScriptVariantQtProxy*>(scriptClass) : nullptr;
|
||||
}
|
||||
|
||||
QVariant ScriptVariantQtProxy::unwrap(const QScriptValue& val) {
|
||||
ScriptVariantQtProxy* proxy = unwrapProxy(val);
|
||||
return proxy ? proxy->toQtValue() : QVariant();
|
||||
}
|
||||
|
||||
bool ScriptMethodQtProxy::supportsExtension(Extension extension) const {
|
||||
switch (extension) {
|
||||
case Callable:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ScriptMethodQtProxy::extension(Extension extension, const QVariant& argument) {
|
||||
if (extension != Callable) return QVariant();
|
||||
QScriptContext* context = qvariant_cast<QScriptContext*>(argument);
|
||||
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
context->throwError(QScriptContext::ReferenceError, "Referencing deleted native object");
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int scriptNumArgs = context->argumentCount();
|
||||
Q_ASSERT(scriptNumArgs < 10);
|
||||
int numArgs = std::min(scriptNumArgs, 10);
|
||||
|
||||
const int scriptValueTypeId = qMetaTypeId<ScriptValue>();
|
||||
|
||||
for (auto iter = _metas.cbegin(); iter != _metas.end(); ++iter) {
|
||||
const QMetaMethod& meta = *iter;
|
||||
int methodNumArgs = meta.parameterCount();
|
||||
if (methodNumArgs != numArgs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QList<ScriptValue> qScriptArgList;
|
||||
QList<QVariant> qVarArgList;
|
||||
QGenericArgument qGenArgs[10];
|
||||
int arg;
|
||||
bool conversionFailed = false;
|
||||
for (arg = 0; arg < numArgs && !conversionFailed; ++arg) {
|
||||
int methodArgTypeId = meta.parameterType(arg);
|
||||
QScriptValue argVal = context->argument(arg);
|
||||
if (methodArgTypeId == scriptValueTypeId) {
|
||||
qScriptArgList.append(ScriptValue(new ScriptValueQtWrapper(_engine, argVal)));
|
||||
qGenArgs[arg] = Q_ARG(ScriptValue, qScriptArgList.back());
|
||||
} else if (methodArgTypeId == QMetaType::QVariant) {
|
||||
qVarArgList.append(argVal.toVariant());
|
||||
qGenArgs[arg] = Q_ARG(QVariant, qVarArgList.back());
|
||||
} else {
|
||||
QVariant varArgVal;
|
||||
if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) {
|
||||
conversionFailed = true;
|
||||
break;
|
||||
/*QByteArray methodTypeName = QMetaType(methodArgTypeId).name();
|
||||
QByteArray argTypeName = argVal.toVariant().typeName();
|
||||
context->throwError(QScriptContext::TypeError,
|
||||
QString("Cannot convert %1 to %2").arg(argTypeName, methodTypeName));
|
||||
return QVariant();*/
|
||||
}
|
||||
qVarArgList.append(varArgVal);
|
||||
const QVariant& converted = qVarArgList.back();
|
||||
|
||||
// a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant
|
||||
// A const_cast is needed because calling data() would detach the QVariant.
|
||||
qGenArgs[arg] =
|
||||
QGenericArgument(QMetaType::typeName(converted.userType()), const_cast<void*>(converted.constData()));
|
||||
}
|
||||
}
|
||||
if (conversionFailed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ScriptContextQtWrapper ourContext(_engine, context);
|
||||
ScriptContextGuard guard(&ourContext);
|
||||
|
||||
int returnTypeId = meta.returnType();
|
||||
if (returnTypeId == QMetaType::Void) {
|
||||
bool success = meta.invoke(qobject, Qt::DirectConnection, qGenArgs[0], qGenArgs[1], qGenArgs[2], qGenArgs[3],
|
||||
qGenArgs[4], qGenArgs[5], qGenArgs[6], qGenArgs[7], qGenArgs[8], qGenArgs[9]);
|
||||
if (!success) {
|
||||
context->throwError("Native call failed");
|
||||
}
|
||||
return QVariant();
|
||||
} else if (returnTypeId == scriptValueTypeId) {
|
||||
ScriptValue result;
|
||||
bool success = meta.invoke(qobject, Qt::DirectConnection, Q_RETURN_ARG(ScriptValue, result), qGenArgs[0],
|
||||
qGenArgs[1], qGenArgs[2], qGenArgs[3], qGenArgs[4], qGenArgs[5], qGenArgs[6],
|
||||
qGenArgs[7], qGenArgs[8], qGenArgs[9]);
|
||||
if (!success) {
|
||||
context->throwError("Native call failed");
|
||||
return QVariant();
|
||||
}
|
||||
QScriptValue qResult = ScriptValueQtWrapper::fullUnwrap(_engine, result);
|
||||
return QVariant::fromValue(qResult);
|
||||
} else {
|
||||
// a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant
|
||||
const char* typeName = meta.typeName();
|
||||
QVariant qRetVal(returnTypeId, static_cast<void*>(NULL));
|
||||
QGenericReturnArgument sRetVal(typeName, const_cast<void*>(qRetVal.constData()));
|
||||
|
||||
bool success =
|
||||
meta.invoke(qobject, Qt::DirectConnection, sRetVal, qGenArgs[0], qGenArgs[1], qGenArgs[2], qGenArgs[3],
|
||||
qGenArgs[4], qGenArgs[5], qGenArgs[6], qGenArgs[7], qGenArgs[8], qGenArgs[9]);
|
||||
if (!success) {
|
||||
context->throwError("Native call failed");
|
||||
return QVariant();
|
||||
}
|
||||
QScriptValue qResult = _engine->castVariantToValue(qRetVal);
|
||||
return QVariant::fromValue(qResult);
|
||||
}
|
||||
}
|
||||
context->throwError("Native call failed: could not locate an overload with the requested arguments");
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// Adapted from https://doc.qt.io/archives/qq/qq16-dynamicqobject.html, for connecting to a signal without a compile-time definition for it
|
||||
int ScriptSignalQtProxy::qt_metacall(QMetaObject::Call call, int id, void** arguments) {
|
||||
id = ScriptSignalQtProxyBase::qt_metacall(call, id, arguments);
|
||||
if (id != 0 || call != QMetaObject::InvokeMetaMethod) {
|
||||
return id;
|
||||
}
|
||||
|
||||
QScriptValueList args;
|
||||
int numArgs = _meta.parameterCount();
|
||||
for (int arg = 0; arg < numArgs; ++arg) {
|
||||
int methodArgTypeId = _meta.parameterType(arg);
|
||||
QVariant argValue(methodArgTypeId, arguments[arg+1]);
|
||||
args.append(_engine->castVariantToValue(argValue));
|
||||
}
|
||||
|
||||
for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) {
|
||||
Connection& conn = *iter;
|
||||
conn.callback.call(conn.thisValue, args);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ScriptSignalQtProxy::discoverMetaCallIdx() {
|
||||
const QMetaObject* ourMeta = metaObject();
|
||||
return ourMeta->methodCount();
|
||||
}
|
||||
|
||||
ScriptSignalQtProxy::ConnectionList::iterator ScriptSignalQtProxy::findConnection(QScriptValue thisObject,
|
||||
QScriptValue callback) {
|
||||
for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) {
|
||||
Connection& conn = *iter;
|
||||
if (conn.callback.strictlyEquals(callback) && conn.thisValue.strictlyEquals(thisObject)) {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
return _connections.end();
|
||||
}
|
||||
|
||||
|
||||
void ScriptSignalQtProxy::connect(QScriptValue arg0, QScriptValue arg1) {
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::ReferenceError, "Referencing deleted native object");
|
||||
return;
|
||||
}
|
||||
|
||||
// untangle the arguments
|
||||
QScriptValue callback;
|
||||
QScriptValue callbackThis;
|
||||
if (arg1.isFunction()) {
|
||||
callbackThis = arg0;
|
||||
callback = arg1;
|
||||
} else {
|
||||
callback = arg0;
|
||||
}
|
||||
if (!callback.isFunction()) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::TypeError, "Function expected as argument to 'connect'");
|
||||
return;
|
||||
}
|
||||
|
||||
// are we already connected?
|
||||
ConnectionList::iterator lookup = findConnection(callbackThis, callback);
|
||||
if (lookup != _connections.end()) {
|
||||
return; // already exists
|
||||
}
|
||||
|
||||
// add a reference to ourselves to the destination callback
|
||||
QScriptValue destData = callback.data();
|
||||
Q_ASSERT(!destData.isValid() || destData.isArray());
|
||||
if (!destData.isArray()) {
|
||||
destData = static_cast<QScriptEngine*>(_engine)->newArray();
|
||||
}
|
||||
{
|
||||
QScriptValueList args;
|
||||
args << thisObject();
|
||||
destData.property("push").call(destData, args);
|
||||
}
|
||||
callback.setData(destData);
|
||||
|
||||
// add this to our internal list of connections
|
||||
Connection newConn;
|
||||
newConn.callback = callback;
|
||||
newConn.thisValue = callbackThis;
|
||||
_connections.append(newConn);
|
||||
|
||||
// inform Qt that we're connecting to this signal
|
||||
if (!_isConnected) {
|
||||
auto result = QMetaObject::connect(qobject, _meta.methodIndex(), this, _metaCallId);
|
||||
Q_ASSERT(result);
|
||||
_isConnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptSignalQtProxy::disconnect(QScriptValue arg0, QScriptValue arg1) {
|
||||
QObject* qobject = _object;
|
||||
if (!qobject) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::ReferenceError, "Referencing deleted native object");
|
||||
return;
|
||||
}
|
||||
|
||||
// untangle the arguments
|
||||
QScriptValue callback;
|
||||
QScriptValue callbackThis;
|
||||
if (arg1.isFunction()) {
|
||||
callbackThis = arg0;
|
||||
callback = arg1;
|
||||
} else {
|
||||
callback = arg0;
|
||||
}
|
||||
if (!callback.isFunction()) {
|
||||
QScriptContext* currentContext = static_cast<QScriptEngine*>(_engine)->currentContext();
|
||||
currentContext->throwError(QScriptContext::TypeError, "Function expected as argument to 'disconnect'");
|
||||
return;
|
||||
}
|
||||
|
||||
// locate this connection in our list of connections
|
||||
ConnectionList::iterator lookup = findConnection(callbackThis, callback);
|
||||
if (lookup == _connections.end()) {
|
||||
return; // not here
|
||||
}
|
||||
|
||||
// remove it from our internal list of connections
|
||||
_connections.erase(lookup);
|
||||
|
||||
// remove a reference to ourselves from the destination callback
|
||||
QScriptValue destData = callback.data();
|
||||
Q_ASSERT(destData.isArray());
|
||||
if (destData.isArray()) {
|
||||
QScriptValue qThis = thisObject();
|
||||
int len = destData.property("length").toInteger();
|
||||
bool foundIt = false;
|
||||
for (int idx = 0; idx < len && !foundIt; ++idx) {
|
||||
QScriptValue entry = destData.property(idx);
|
||||
if (entry.strictlyEquals(qThis)) {
|
||||
foundIt = true;
|
||||
QScriptValueList args;
|
||||
args << idx << 1;
|
||||
destData.property("splice").call(destData, args);
|
||||
}
|
||||
}
|
||||
Q_ASSERT(foundIt);
|
||||
}
|
||||
|
||||
// inform Qt that we're no longer connected to this signal
|
||||
if (_connections.empty()) {
|
||||
Q_ASSERT(_isConnected);
|
||||
bool result = QMetaObject::disconnect(qobject, _meta.methodIndex(), this, _metaCallId);
|
||||
Q_ASSERT(result);
|
||||
_isConnected = false;
|
||||
}
|
||||
}
|
205
libraries/script-engine/src/qtscript/ScriptObjectQtProxy.h
Normal file
205
libraries/script-engine/src/qtscript/ScriptObjectQtProxy.h
Normal file
|
@ -0,0 +1,205 @@
|
|||
//
|
||||
// ScriptObjectQtProxy.h
|
||||
// libraries/script-engine/src/qtscript
|
||||
//
|
||||
// Created by Heather Anderson on 12/5/21.
|
||||
// Copyright 2021 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/// @addtogroup ScriptEngine
|
||||
/// @{
|
||||
|
||||
#ifndef hifi_ScriptObjectQtProxy_h
|
||||
#define hifi_ScriptObjectQtProxy_h
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <QtScript/QScriptable>
|
||||
#include <QtScript/QScriptClass>
|
||||
#include <QtScript/QScriptString>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include "../ScriptEngine.h"
|
||||
#include "ScriptEngineQtScript.h"
|
||||
|
||||
class ScriptEngineQtScript;
|
||||
class ScriptSignalQtProxy;
|
||||
|
||||
/// [QtScript] (re-)implements the translation layer between ScriptValue and QObject. This object
|
||||
/// will focus exclusively on property get/set until function calls appear to be a problem
|
||||
class ScriptObjectQtProxy final : public QScriptClass {
|
||||
private: // implementation
|
||||
struct PropertyDef {
|
||||
QScriptString name;
|
||||
QScriptValue::PropertyFlags flags;
|
||||
};
|
||||
struct MethodDef {
|
||||
QScriptString name;
|
||||
QList<QMetaMethod> methods;
|
||||
};
|
||||
struct SignalDef {
|
||||
QScriptString name;
|
||||
QMetaMethod signal;
|
||||
};
|
||||
using PropertyDefMap = QHash<uint, PropertyDef>;
|
||||
using MethodDefMap = QHash<uint, MethodDef>;
|
||||
using SignalDefMap = QHash<uint, SignalDef>;
|
||||
using InstanceMap = QHash<uint, QPointer<ScriptSignalQtProxy> >;
|
||||
|
||||
static constexpr uint PROPERTY_TYPE = 0x1000;
|
||||
static constexpr uint METHOD_TYPE = 0x2000;
|
||||
static constexpr uint SIGNAL_TYPE = 0x3000;
|
||||
static constexpr uint TYPE_MASK = 0xF000;
|
||||
|
||||
public: // construction
|
||||
inline ScriptObjectQtProxy(ScriptEngineQtScript* engine, QObject* object, bool ownsObject, const ScriptEngine::QObjectWrapOptions& options) :
|
||||
QScriptClass(engine), _engine(engine), _object(object), _wrapOptions(options), _ownsObject(ownsObject) {
|
||||
investigate();
|
||||
}
|
||||
virtual ~ScriptObjectQtProxy();
|
||||
|
||||
static QScriptValue newQObject(ScriptEngineQtScript* engine,
|
||||
QObject* object,
|
||||
ScriptEngine::ValueOwnership ownership = ScriptEngine::QtOwnership,
|
||||
const ScriptEngine::QObjectWrapOptions& options = ScriptEngine::QObjectWrapOptions());
|
||||
static ScriptObjectQtProxy* unwrapProxy(const QScriptValue& val);
|
||||
static QObject* unwrap(const QScriptValue& val);
|
||||
inline QObject* toQtValue() const { return _object; }
|
||||
|
||||
public: // QScriptClass implementation
|
||||
virtual QString name() const override { return _name; }
|
||||
|
||||
virtual QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id) override;
|
||||
virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object, const QScriptString& name, uint id) override;
|
||||
virtual QueryFlags queryProperty(const QScriptValue& object, const QScriptString& name, QueryFlags flags, uint* id) override;
|
||||
virtual void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value) override;
|
||||
|
||||
private: // implementation
|
||||
void investigate();
|
||||
|
||||
private: // storage
|
||||
ScriptEngineQtScript* _engine;
|
||||
const ScriptEngine::QObjectWrapOptions _wrapOptions;
|
||||
PropertyDefMap _props;
|
||||
MethodDefMap _methods;
|
||||
SignalDefMap _signals;
|
||||
InstanceMap _signalInstances;
|
||||
const bool _ownsObject;
|
||||
QPointer<QObject> _object;
|
||||
QString _name;
|
||||
|
||||
Q_DISABLE_COPY(ScriptObjectQtProxy)
|
||||
};
|
||||
|
||||
/// [QtScript] (re-)implements the translation layer between ScriptValue and QVariant where a prototype is set.
|
||||
/// This object depends on a ScriptObjectQtProxy to provide the prototype's behavior
|
||||
class ScriptVariantQtProxy final : public QScriptClass {
|
||||
public: // construction
|
||||
ScriptVariantQtProxy(ScriptEngineQtScript* engine, const QVariant& variant, QScriptValue scriptProto, ScriptObjectQtProxy* proto);
|
||||
|
||||
static QScriptValue newVariant(ScriptEngineQtScript* engine, const QVariant& variant, QScriptValue proto);
|
||||
static ScriptVariantQtProxy* unwrapProxy(const QScriptValue& val);
|
||||
static QVariant unwrap(const QScriptValue& val);
|
||||
inline QVariant toQtValue() const { return _variant; }
|
||||
|
||||
public: // QScriptClass implementation
|
||||
virtual QString name() const override { return _name; }
|
||||
|
||||
virtual QScriptValue prototype() const override { return _scriptProto; }
|
||||
|
||||
virtual QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id) override {
|
||||
return _proto->property(object, name, id);
|
||||
}
|
||||
virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object, const QScriptString& name, uint id) override {
|
||||
return _proto->propertyFlags(object, name, id);
|
||||
}
|
||||
virtual QueryFlags queryProperty(const QScriptValue& object, const QScriptString& name, QueryFlags flags, uint* id) override {
|
||||
return _proto->queryProperty(object, name, flags, id);
|
||||
}
|
||||
virtual void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value) override {
|
||||
return _proto->setProperty(object, name, id, value);
|
||||
}
|
||||
|
||||
private: // storage
|
||||
ScriptEngineQtScript* _engine;
|
||||
QVariant _variant;
|
||||
QScriptValue _scriptProto;
|
||||
ScriptObjectQtProxy* _proto;
|
||||
QString _name;
|
||||
|
||||
Q_DISABLE_COPY(ScriptVariantQtProxy)
|
||||
};
|
||||
|
||||
class ScriptMethodQtProxy final : public QScriptClass {
|
||||
public: // construction
|
||||
inline ScriptMethodQtProxy(ScriptEngineQtScript* engine, QObject* object, QScriptValue lifetime, QString name, const QList<QMetaMethod>& metas) :
|
||||
QScriptClass(engine), _engine(engine), _object(object), _objectLifetime(lifetime), _name(name), _metas(metas) {}
|
||||
|
||||
public: // QScriptClass implementation
|
||||
virtual QString name() const override { return _name; }
|
||||
virtual bool supportsExtension(Extension extension) const override;
|
||||
virtual QVariant extension(Extension extension, const QVariant& argument = QVariant()) override;
|
||||
|
||||
private: // storage
|
||||
ScriptEngineQtScript* _engine;
|
||||
QPointer<QObject> _object;
|
||||
QScriptValue _objectLifetime;
|
||||
const QString _name;
|
||||
const QList<QMetaMethod> _metas;
|
||||
|
||||
Q_DISABLE_COPY(ScriptMethodQtProxy)
|
||||
};
|
||||
|
||||
// This abstract base class serves solely to declare the Q_INVOKABLE methods for ScriptSignalQtProxy
|
||||
// as we're overriding qt_metacall later for the signal callback yet still want to support
|
||||
// metacalls for the connect/disconnect API
|
||||
class ScriptSignalQtProxyBase : public QObject, protected QScriptable {
|
||||
Q_OBJECT
|
||||
public: // API
|
||||
Q_INVOKABLE virtual void connect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) = 0;
|
||||
Q_INVOKABLE virtual void disconnect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) = 0;
|
||||
};
|
||||
|
||||
class ScriptSignalQtProxy final : public ScriptSignalQtProxyBase {
|
||||
private: // storage
|
||||
struct Connection {
|
||||
QScriptValue thisValue;
|
||||
QScriptValue callback;
|
||||
};
|
||||
using ConnectionList = QList<Connection>;
|
||||
|
||||
public: // construction
|
||||
inline ScriptSignalQtProxy(ScriptEngineQtScript* engine, QObject* object, QScriptValue lifetime, QString name, const QMetaMethod& meta) :
|
||||
_engine(engine), _object(object), _objectLifetime(lifetime), _name(name), _meta(meta), _metaCallId(discoverMetaCallIdx()) {}
|
||||
|
||||
private: // implementation
|
||||
virtual int qt_metacall(QMetaObject::Call call, int id, void** arguments);
|
||||
int discoverMetaCallIdx();
|
||||
ConnectionList::iterator findConnection(QScriptValue thisObject, QScriptValue callback);
|
||||
|
||||
public: // API
|
||||
virtual void connect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) override;
|
||||
virtual void disconnect(QScriptValue arg0, QScriptValue arg1 = QScriptValue()) override;
|
||||
|
||||
private: // storage
|
||||
ScriptEngineQtScript* _engine;
|
||||
QPointer<QObject> _object;
|
||||
QScriptValue _objectLifetime;
|
||||
QString _name;
|
||||
const QMetaMethod _meta;
|
||||
const int _metaCallId;
|
||||
ConnectionList _connections;
|
||||
bool _isConnected{ false };
|
||||
|
||||
Q_DISABLE_COPY(ScriptSignalQtProxy)
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptObjectQtProxy_h
|
||||
|
||||
/// @}
|
|
@ -28,19 +28,27 @@ ScriptValueQtWrapper* ScriptValueQtWrapper::unwrap(const ScriptValue& val) {
|
|||
QScriptValue ScriptValueQtWrapper::fullUnwrap(const ScriptValue& value) const {
|
||||
ScriptValueQtWrapper* unwrapped = unwrap(value);
|
||||
if (unwrapped) {
|
||||
return unwrapped->toQtValue();
|
||||
if (unwrapped->engine().get() != _engine) {
|
||||
return static_cast<QScriptEngine*>(_engine)->toScriptValue(unwrapped->toVariant());
|
||||
} else {
|
||||
return unwrapped->toQtValue();
|
||||
}
|
||||
}
|
||||
QVariant varValue = value.toVariant();
|
||||
return static_cast<QScriptEngine*>(_engine)->newVariant(varValue);
|
||||
return _engine->castVariantToValue(varValue);
|
||||
}
|
||||
|
||||
QScriptValue ScriptValueQtWrapper::fullUnwrap(ScriptEngineQtScript* engine, const ScriptValue& value) {
|
||||
ScriptValueQtWrapper* unwrapped = unwrap(value);
|
||||
if (unwrapped) {
|
||||
return unwrapped->toQtValue();
|
||||
if (unwrapped->engine().get() != engine) {
|
||||
return static_cast<QScriptEngine*>(engine)->toScriptValue(unwrapped->toVariant());
|
||||
} else {
|
||||
return unwrapped->toQtValue();
|
||||
}
|
||||
}
|
||||
QVariant varValue = value.toVariant();
|
||||
return static_cast<QScriptEngine*>(engine)->newVariant(varValue);
|
||||
return engine->castVariantToValue(varValue);
|
||||
}
|
||||
|
||||
ScriptValue ScriptValueQtWrapper::call(const ScriptValue& thisObject, const ScriptValueList& args) {
|
||||
|
@ -157,11 +165,23 @@ quint32 ScriptValueQtWrapper::toUInt32() const {
|
|||
}
|
||||
|
||||
QVariant ScriptValueQtWrapper::toVariant() const {
|
||||
return _value.toVariant();
|
||||
QVariant dest;
|
||||
if (_engine->castValueToVariant(_value, dest, QMetaType::UnknownType)) {
|
||||
return dest;
|
||||
} else {
|
||||
Q_ASSERT(false);
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QObject* ScriptValueQtWrapper::toQObject() const {
|
||||
return _value.toQObject();
|
||||
QVariant dest;
|
||||
if (_engine->castValueToVariant(_value, dest, QMetaType::QObjectStar)) {
|
||||
return dest.value<QObject*>();
|
||||
} else {
|
||||
Q_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptValueQtWrapper::equals(const ScriptValue& other) const {
|
||||
|
|
|
@ -40,8 +40,9 @@ ScriptValue wrapperToScriptValue(ScriptEngine* engine, T* const &in) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void wrapperFromScriptValue(const ScriptValue& value, T* &out) {
|
||||
bool wrapperFromScriptValue(const ScriptValue& value, T* &out) {
|
||||
out = qobject_cast<T*>(value.toQObject());
|
||||
return !!out;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue