Merge pull request #185 from overte-org/feature/v8

V8 scripting engine
This commit is contained in:
ksuprynowicz 2023-05-27 22:22:05 +02:00 committed by GitHub
commit e578fe2ab8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
443 changed files with 25466 additions and 14057 deletions

53
.gitignore vendored
View file

@ -11,13 +11,16 @@ CMakeCache.txt
CMakeFiles/
CMakeScripts/
cmake_install.cmake
build*/
/build*/
cmake-build-minsizerelease-visual-studio/
cmake-build-release-visual-studio/
cmake-build-relwithdebinfo-visual-studio/
release*/
debug*/
gprof*/
valgrind*/
ext/
cmake-build-debug-visual-studio/
/release*/
/debug*/
/gprof*/
/valgrind*/
/ext/
Makefile
*.user
@ -25,14 +28,14 @@ Makefile
*.iml
*.class
local.properties
android/gradle*
android/.gradle
android/**/src/main/jniLibs
android/**/libs
android/**/bin
android/**/src/main/res/values/libs.xml
android/**/src/main/assets
android/**/gradle*
/android/gradle*
/android/.gradle
/android/**/src/main/jniLibs
/android/**/libs
/android/**/bin
/android/**/src/main/res/values/libs.xml
/android/**/src/main/assets
/android/**/gradle*
*.class
# Visual Studio
@ -73,19 +76,16 @@ DerivedData
*.hmap
# ignore interface optional externals
interface/external/*/*
/interface/external/*/*
!interface/external/*/readme.txt
# Ignore interfaceCache for Linux users
interface/interfaceCache/
/interface/interfaceCache/
# ignore audio-client externals
libraries/audio-client/external/*/*
/libraries/audio-client/external/*/*
!libraries/audio-client/external/*/readme.txt
gvr-interface/assets/oculussig*
gvr-interface/libs/*
# ignore files for various dev environments
TAGS
*.sw[po]
@ -108,21 +108,22 @@ interface/compiledResources
*.rcc
# GPUCache
interface/resources/GPUCache/*
/interface/resources/GPUCache/*
# package lock file for JSDoc tool
tools/jsdoc/package-lock.json
/tools/jsdoc/package-lock.json
# Python compile artifacts
**/__pycache__
# ignore local unity project files for avatar exporter
tools/unity-avatar-exporter
/tools/unity-avatar-exporter
server-console/package-lock.json
vcpkg/
/server-console/package-lock.json
/vcpkg/
/tools/nitpick/compiledResources
qt/
/qt/
# Act local GitHub Actions
.secret

View file

@ -1,6 +1,6 @@
# Copyright 2013-2019 High Fidelity, Inc.
# Copyright 2019-2021 Vircadia contributors.
# Copyright 2020-2022 Overte e.V.
# Copyright 2020-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
# If we're running under the gradle build, HIFI_ANDROID will be set here, but
@ -12,6 +12,8 @@ else()
cmake_minimum_required(VERSION 3.2)
endif()
# 3.14 is the minimum version that supports symlinks on Windows
cmake_minimum_required(VERSION 3.14)
# Passing of variables to vcpkg
#
@ -192,7 +194,7 @@ else()
set(VCPKG_BUILD_TYPE_PARAM --vcpkg-build-type ${VCPKG_BUILD_TYPE})
endif()
execute_process(
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --vcpkg-skip-clean --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} ${VCPKG_BUILD_TYPE_PARAM}
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} ${VCPKG_BUILD_TYPE_PARAM}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULTS_VARIABLE PREBUILD_RET
)
# squelch the Policy CMP0074 warning without requiring an update to cmake 3.12.

View file

@ -1,6 +1,10 @@
# Copyright 2013-2019 High Fidelity, Inc.
# Copyright 2021-2022 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(TARGET_NAME assignment-client)
setup_hifi_project(Core Gui Network Script Quick WebSockets)
setup_hifi_project(Core Gui Network Quick WebSockets)
# Fix up the rpath so macdeployqt works
if (APPLE)

View file

@ -4,9 +4,11 @@
//
// Created by Stephen Birarda on 7/1/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "Agent.h"
@ -27,6 +29,7 @@
#include <DebugDraw.h>
#include <EntityScriptingInterface.h>
#include <LocationScriptingInterface.h>
#include <AudioScriptingInterface.h>
#include <MessagesClient.h>
#include <NetworkAccessManager.h>
#include <NodeList.h>
@ -34,7 +37,9 @@
#include <ResourceCache.h>
#include <ResourceScriptingInterface.h>
#include <ScriptCache.h>
#include <ScriptEngine.h>
#include <ScriptEngines.h>
#include <ScriptManager.h>
#include <SoundCacheScriptingInterface.h>
#include <SoundCache.h>
#include <UserActivityLoggerScriptingInterface.h>
@ -56,7 +61,7 @@
#include "entities/AssignmentParentFinder.h"
#include "AssignmentDynamicFactory.h"
#include "RecordingScriptingInterface.h"
#include <recording/RecordingScriptingInterface.h>
#include "AbstractAudioInterface.h"
#include "AgentScriptingInterface.h"
@ -180,7 +185,7 @@ static const QString AGENT_LOGGING_NAME = "agent";
void Agent::run() {
// Create ScriptEngines on threaded-assignment thread then move to main thread.
DependencyManager::set<ScriptEngines>(ScriptEngine::AGENT_SCRIPT)->moveToThread(qApp->thread());
DependencyManager::set<ScriptEngines>(ScriptManager::AGENT_SCRIPT)->moveToThread(qApp->thread());
DependencyManager::set<ScriptCache>();
@ -372,7 +377,7 @@ void Agent::executeScript() {
// the following block is scoped so that any shared pointers we take here
// are cleared before we call setFinished at the end of the function
{
_scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload);
_scriptManager = scriptManagerFactory(ScriptManager::AGENT_SCRIPT, _scriptContents, _payload);
// setup an Avatar for the script to use
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
@ -386,10 +391,11 @@ void Agent::executeScript() {
scriptedAvatar->getHeadOrientation();
// give this AvatarData object to the script engine
_scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data());
auto scriptEngine = _scriptManager->engine();
scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data());
// give scripts access to the Users object
_scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().data());
scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().data());
auto player = DependencyManager::get<recording::Deck>();
connect(player.data(), &recording::Deck::playbackStateChanged, [&player, &scriptedAvatar] {
@ -493,26 +499,26 @@ void Agent::executeScript() {
});
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
_scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data());
scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data());
// register ourselves to the script engine
_scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this));
scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this));
_scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
_scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCacheScriptingInterface>().data());
scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
QScriptValue webSocketServerConstructorValue = _scriptEngine->newFunction(WebSocketServerClass::constructor);
_scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
ScriptValue webSocketServerConstructorValue = scriptEngine->newFunction(WebSocketServerClass::constructor);
scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
_scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer);
scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer);
_scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
LocationScriptingInterface::locationSetter);
auto recordingInterface = DependencyManager::get<RecordingScriptingInterface>();
_scriptEngine->registerGlobalObject("Recording", recordingInterface.data());
scriptEngine->registerGlobalObject("Recording", recordingInterface.data());
entityScriptingInterface->init();
@ -522,8 +528,8 @@ void Agent::executeScript() {
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
DependencyManager::get<ScriptEngines>()->runScriptInitializers(_scriptEngine);
_scriptEngine->run();
DependencyManager::get<ScriptEngines>()->runScriptInitializers(_scriptManager);
_scriptManager->run();
Frame::clearFrameHandler(AUDIO_FRAME_TYPE);
Frame::clearFrameHandler(AVATAR_FRAME_TYPE);
@ -602,7 +608,7 @@ void Agent::setIsAvatar(bool isAvatar) {
// start the timer
_avatarQueryTimer->start(AVATAR_VIEW_PACKET_SEND_INTERVAL_MSECS);
connect(_scriptEngine.data(), &ScriptEngine::update,
connect(_scriptManager.get(), &ScriptManager::update,
scriptableAvatar.data(), &ScriptableAvatar::update, Qt::QueuedConnection);
// tell the avatarAudioTimer to start ticking
@ -638,7 +644,7 @@ void Agent::setIsAvatar(bool isAvatar) {
nodeList->sendPacket(std::move(packet), *node);
});
disconnect(_scriptEngine.data(), &ScriptEngine::update,
disconnect(_scriptManager.get(), &ScriptManager::update,
scriptableAvatar.data(), &ScriptableAvatar::update);
QMetaObject::invokeMethod(&_avatarAudioTimer, "stop");
@ -875,7 +881,7 @@ void Agent::aboutToFinish() {
// drop our shared pointer to the script engine, then ask ScriptEngines to shutdown scripting
// this ensures that the ScriptEngine goes down before ScriptEngines
_scriptEngine.clear();
_scriptManager.reset();
{
DependencyManager::get<ScriptEngines>()->shutdownScripting();
@ -895,8 +901,8 @@ void Agent::aboutToFinish() {
}
void Agent::stop() {
if (_scriptEngine) {
_scriptEngine->stop();
if (_scriptManager) {
_scriptManager->stop();
} else {
setFinished(true);
}

View file

@ -4,9 +4,11 @@
//
// Created by Stephen Birarda on 7/1/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_Agent_h
@ -15,12 +17,12 @@
#include <memory>
#include <vector>
#include <QtScript/QScriptEngine>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QtCore/QUrl>
#include <QtCore/QTimer>
#include <QUuid>
#include <QtCore/QSharedPointer>
#include <EntityEditPacketSender.h>
#include <EntityTree.h>
@ -29,11 +31,17 @@
#include <plugins/CodecPlugin.h>
#include <Sound.h>
#include "AudioGate.h"
#include "MixedAudioStream.h"
#include "entities/EntityTreeHeadlessViewer.h"
#include "avatars/ScriptableAvatar.h"
class ScriptEngine;
class ScriptManager;
using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
using ScriptManagerPointer = std::shared_ptr<ScriptManager>;
class Agent : public ThreadedAssignment {
Q_OBJECT
@ -90,7 +98,7 @@ private:
void encodeFrameOfZeros(QByteArray& encodedZeros);
void computeLoudness(const QByteArray* decodedBuffer, QSharedPointer<ScriptableAvatar>);
ScriptEnginePointer _scriptEngine;
ScriptManagerPointer _scriptManager;
EntityEditPacketSender _entityEditSender;
EntityTreeHeadlessViewer _entityViewer;

View file

@ -4,9 +4,11 @@
//
// Created by Clement on 7/22/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "ScriptableAvatar.h"
@ -17,16 +19,18 @@
#include <shared/QtHelpers.h>
#include <AnimUtil.h>
#include <AvatarHashMap.h>
#include <ClientTraitsHandler.h>
#include <GLMHelpers.h>
#include <ResourceRequestObserver.h>
#include <AvatarLogging.h>
#include <EntityItem.h>
#include <EntityItemProperties.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
ScriptableAvatar::ScriptableAvatar() {
ScriptableAvatar::ScriptableAvatar(): _scriptEngine(newScriptEngine()) {
_clientTraitsHandler.reset(new ClientTraitsHandler(this));
}
@ -311,7 +315,7 @@ AvatarEntityMap ScriptableAvatar::getAvatarEntityDataInternal(bool allProperties
EntityItemProperties properties = entity->getProperties(desiredProperties);
QByteArray blob;
EntityItemProperties::propertiesToBlob(_scriptEngine, sessionID, properties, blob, allProperties);
EntityItemProperties::propertiesToBlob(*_scriptEngine, sessionID, properties, blob, allProperties);
data[id] = blob;
}
});
@ -335,7 +339,7 @@ void ScriptableAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityDa
while (dataItr != avatarEntityData.end()) {
EntityItemProperties properties;
const QByteArray& blob = dataItr.value();
if (!blob.isNull() && EntityItemProperties::blobToProperties(_scriptEngine, blob, properties)) {
if (!blob.isNull() && EntityItemProperties::blobToProperties(*_scriptEngine, blob, properties)) {
newProperties[dataItr.key()] = properties;
}
++dataItr;
@ -415,7 +419,7 @@ void ScriptableAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArra
EntityItemPointer entity;
EntityItemProperties properties;
if (!EntityItemProperties::blobToProperties(_scriptEngine, entityData, properties)) {
if (!EntityItemProperties::blobToProperties(*_scriptEngine, entityData, properties)) {
// entityData is corrupt
return;
}

View file

@ -4,9 +4,11 @@
//
// Created by Clement on 7/22/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_ScriptableAvatar_h
@ -220,7 +222,7 @@ private:
QHash<QString, int> _fstJointIndices; ///< 1-based, since zero is returned for missing keys
QStringList _fstJointNames; ///< in order of depth-first traversal
QUrl _skeletonFBXURL;
mutable QScriptEngine _scriptEngine;
mutable ScriptEnginePointer _scriptEngine;
std::map<QUuid, EntityItemPointer> _entities;
/// Loads the joint indices, names from the FST file (if any)

View file

@ -4,9 +4,11 @@
//
// Created by Clément Brisset on 1/5/17.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "EntityScriptServer.h"
@ -14,7 +16,9 @@
#include <mutex>
#include <AudioConstants.h>
#include <AudioScriptingInterface.h>
#include <AudioInjectorManager.h>
#include <AvatarHashMap.h>
#include <ClientServerUtils.h>
#include <DebugDraw.h>
#include <EntityNodeData.h>
@ -130,7 +134,7 @@ void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<Receiv
replyPacketList->writePrimitive(messageID);
EntityScriptDetails details;
if (_entitiesScriptEngine->getEntityScriptDetails(entityID, details)) {
if (_entitiesScriptManager->getEntityScriptDetails(entityID, details)) {
replyPacketList->writePrimitive(true);
replyPacketList->writePrimitive(details.status);
replyPacketList->writeString(details.errorInfo);
@ -175,7 +179,7 @@ void EntityScriptServer::handleSettings() {
}
void EntityScriptServer::updateEntityPPS() {
int numRunningScripts = _entitiesScriptEngine->getNumRunningEntityScripts();
int numRunningScripts = _entitiesScriptManager->getNumRunningEntityScripts();
int pps;
if (std::numeric_limits<int>::max() / _entityPPSPerScript < numRunningScripts) {
qWarning() << QString("Integer multiplication would overflow, clamping to maxint: %1 * %2").arg(numRunningScripts).arg(_entityPPSPerScript);
@ -236,7 +240,7 @@ void EntityScriptServer::pushLogs() {
void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<ReceivedMessage> receivedMessage, SharedNodePointer senderNode) {
if (_entitiesScriptEngine && _entityViewer.getTree() && !_shuttingDown) {
if (_entitiesScriptManager && _entityViewer.getTree() && !_shuttingDown) {
auto entityID = QUuid::fromRfc4122(receivedMessage->read(NUM_BYTES_RFC4122_UUID));
auto method = receivedMessage->readString();
@ -250,13 +254,13 @@ void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<Recei
params << paramString;
}
_entitiesScriptEngine->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
_entitiesScriptManager->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
}
}
void EntityScriptServer::run() {
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<ScriptEngines>(ScriptManager::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
DependencyManager::set<AvatarHashMap>();
@ -446,7 +450,8 @@ void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) {
void EntityScriptServer::resetEntitiesScriptEngine() {
auto engineName = QString("about:Entities %1").arg(++_entitiesScriptEngineCount);
auto newEngine = scriptEngineFactory(ScriptEngine::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName);
auto newManager = scriptManagerFactory(ScriptManager::ENTITY_SERVER_SCRIPT, NO_SCRIPT, engineName);
auto newEngine = newManager->engine();
auto webSocketServerConstructorValue = newEngine->newFunction(WebSocketServerClass::constructor);
newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
@ -456,42 +461,42 @@ void EntityScriptServer::resetEntitiesScriptEngine() {
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
connect(newEngine.data(), &ScriptEngine::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
connect(newEngine.data(), &ScriptEngine::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
connect(newEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
connect(newEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
connect(newManager.get(), &ScriptManager::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
connect(newManager.get(), &ScriptManager::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
connect(newManager.get(), &ScriptManager::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
connect(newManager.get(), &ScriptManager::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
connect(newEngine.data(), &ScriptEngine::update, this, [this] {
connect(newManager.get(), &ScriptManager::update, this, [this] {
_entityViewer.queryOctree();
_entityViewer.getTree()->preUpdate();
_entityViewer.getTree()->update();
});
scriptEngines->runScriptInitializers(newEngine);
newEngine->runInThread();
auto newEngineSP = qSharedPointerCast<EntitiesScriptEngineProvider>(newEngine);
scriptEngines->runScriptInitializers(newManager);
newManager->runInThread();
std::shared_ptr<EntitiesScriptEngineProvider> newEngineSP = newManager;
// On the entity script server, these are the same
DependencyManager::get<EntityScriptingInterface>()->setPersistentEntitiesScriptEngine(newEngineSP);
DependencyManager::get<EntityScriptingInterface>()->setNonPersistentEntitiesScriptEngine(newEngineSP);
if (_entitiesScriptEngine) {
disconnect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptDetailsUpdated,
if (_entitiesScriptManager) {
disconnect(_entitiesScriptManager.get(), &ScriptManager::entityScriptDetailsUpdated,
this, &EntityScriptServer::updateEntityPPS);
}
_entitiesScriptEngine.swap(newEngine);
connect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptDetailsUpdated,
_entitiesScriptManager.swap(newManager);
connect(_entitiesScriptManager.get(), &ScriptManager::entityScriptDetailsUpdated,
this, &EntityScriptServer::updateEntityPPS);
}
void EntityScriptServer::clear() {
// unload and stop the engine
if (_entitiesScriptEngine) {
if (_entitiesScriptManager) {
// do this here (instead of in deleter) to avoid marshalling unload signals back to this thread
_entitiesScriptEngine->unloadAllEntityScripts();
_entitiesScriptEngine->stop();
_entitiesScriptEngine->waitTillDoneRunning();
_entitiesScriptManager->unloadAllEntityScripts();
_entitiesScriptManager->stop();
_entitiesScriptManager->waitTillDoneRunning();
}
_entityViewer.clear();
@ -503,8 +508,8 @@ void EntityScriptServer::clear() {
}
void EntityScriptServer::shutdownScriptEngine() {
if (_entitiesScriptEngine) {
_entitiesScriptEngine->disconnectNonEssentialSignals(); // disconnect all slots/signals from the script engine, except essential
if (_entitiesScriptManager) {
_entitiesScriptManager->disconnectNonEssentialSignals(); // disconnect all slots/signals from the script engine, except essential
}
_shuttingDown = true;
@ -513,7 +518,7 @@ void EntityScriptServer::shutdownScriptEngine() {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
scriptEngines->shutdownScripting();
_entitiesScriptEngine.clear();
_entitiesScriptManager.reset();
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
// our entity tree is going to go away so tell that to the EntityScriptingInterface
@ -531,8 +536,8 @@ void EntityScriptServer::addingEntity(const EntityItemID& entityID) {
}
void EntityScriptServer::deletingEntity(const EntityItemID& entityID) {
if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) {
_entitiesScriptEngine->unloadEntityScript(entityID, true);
if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptManager) {
_entitiesScriptManager->unloadEntityScript(entityID, true);
}
}
@ -543,20 +548,20 @@ void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID
}
void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, bool forceRedownload) {
if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) {
if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptManager) {
EntityItemPointer entity = _entityViewer.getTree()->findEntityByEntityItemID(entityID);
EntityScriptDetails details;
bool isRunning = _entitiesScriptEngine->getEntityScriptDetails(entityID, details);
bool isRunning = _entitiesScriptManager->getEntityScriptDetails(entityID, details);
if (entity && (forceRedownload || !isRunning || details.scriptText != entity->getServerScripts())) {
if (isRunning) {
_entitiesScriptEngine->unloadEntityScript(entityID, true);
_entitiesScriptManager->unloadEntityScript(entityID, true);
}
QString scriptUrl = entity->getServerScripts();
if (!scriptUrl.isEmpty()) {
scriptUrl = DependencyManager::get<ResourceManager>()->normalizeURL(scriptUrl);
_entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, forceRedownload);
_entitiesScriptManager->loadEntityScript(entityID, scriptUrl, forceRedownload);
}
}
}
@ -573,9 +578,9 @@ void EntityScriptServer::sendStatsPacket() {
QJsonObject scriptEngineStats;
int numberRunningScripts = 0;
const auto scriptEngine = _entitiesScriptEngine;
if (scriptEngine) {
numberRunningScripts = scriptEngine->getNumRunningEntityScripts();
const auto scriptManager = _entitiesScriptManager;
if (scriptManager) {
numberRunningScripts = scriptManager->getNumRunningEntityScripts();
}
scriptEngineStats["number_running_scripts"] = numberRunningScripts;
statsObject["script_engine_stats"] = scriptEngineStats;

View file

@ -4,9 +4,11 @@
//
// Created by Clément Brisset on 1/5/17.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_EntityScriptServer_h
@ -18,12 +20,14 @@
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QtCore/QUuid>
#include <QtCore/QSharedPointer>
#include <EntityEditPacketSender.h>
#include <plugins/CodecPlugin.h>
#include <ScriptEngine.h>
#include <SimpleEntitySimulation.h>
#include <ThreadedAssignment.h>
#include <ScriptManager.h>
#include "../entities/EntityTreeHeadlessViewer.h"
class EntityScriptServer : public ThreadedAssignment {
@ -76,7 +80,7 @@ private:
bool _shuttingDown { false };
static int _entitiesScriptEngineCount;
ScriptEnginePointer _entitiesScriptEngine;
ScriptManagerPointer _entitiesScriptManager;
SimpleEntitySimulationPointer _entitySimulation;
EntityEditPacketSender _entityEditSender;
EntityTreeHeadlessViewer _entityViewer;

View file

@ -2,9 +2,11 @@
# MemoryDebugger.cmake
#
# Copyright 2015 High Fidelity, Inc.
# Copyright 2023 Overte e.V.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
# SPDX-License-Identifier: Apache-2.0
#
macro(SETUP_MEMORY_DEBUGGER)
@ -16,7 +18,7 @@ if ("$ENV{OVERTE_MEMORY_DEBUGGING}")
SET( OVERTE_MEMORY_DEBUGGING true )
endif ()
if (OVERTE_MEMORY_DEBUGGING)
if ( OVERTE_MEMORY_DEBUGGING)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address -fsanitize-recover=address")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address")

View file

@ -0,0 +1,15 @@
#
# Copyright 2022-2023 Overte e.V.
# Created by dr Karol Suprynowicz on 2022/09/03
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
# SPDX-License-Identifier: Apache-2.0
#
macro(TARGET_V8)
find_package(V8 REQUIRED)
target_include_directories(${TARGET_NAME} PUBLIC ${V8_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${V8_LIBRARIES})
endmacro()

481
cmake/modules/FindV8.cmake Normal file
View file

@ -0,0 +1,481 @@
#
# CMake Find V8 Google JavaScript Engine by Parra Studios
# CMake script to find V8 JavaScript Engine.
#
# Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <vic798@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Modified by dr Karol Suprynowicz on 2022/09/03
# Copyright 2022-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
# Find V8 library and include paths
#
# V8_FOUND - True if V8 was found
# V8_INCLUDE_DIR - V8 headers path
# V8_LIBRARIES - List of V8 libraries
# V8_VERSION - V8 version
# V8_VERSION_MAJOR - V8 major version
# V8_VERSION_MINOR - V8 minor version
# V8_VERSION_PATCH - V8 patch version
# V8_VERSION_TWEAK - V8 patch version
# V8_VERSION_HEX - V8 version in hexadecimal format
# V8_EXECUTABLE - V8 shell
# Prevent vervosity if already included
if(V8_INCLUDE_DIR)
set(V8_FIND_QUIETLY TRUE)
endif()
# Debug flag
set(_V8_CMAKE_DEBUG TRUE)
# Include package manager
include(FindPackageHandleStandardArgs)
# V8 search paths
set(V8_PATHS
${VCPKG_INSTALL_ROOT}
${V8_HOME}
${V8_ROOT}
$ENV{ProgramFiles}/v8
$ENV{SystemDrive}/v8
$ENV{V8_HOME}
$ENV{EXTERNLIBS}/v8
${V8_DIR}
$ENV{V8_DIR}
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
/usr/freeware
)
# V8 platform dependant paths
if(NOT UNIX)
set(V8_PATHS_DEBUG
${V8_DIR}/build/Debug
)
set(V8_PATHS_RELEASE
${V8_DIR}/build/Release
)
else()
set(V8_PATHS_DEBUG
${V8_DIR}/out/ia32.debug
${V8_DIR}/out/x64.debug
${V8_DIR}/out/native
)
set(V8_PATHS_RELEASE
${V8_DIR}/out/ia32.release
${V8_DIR}/out/x64.release
${V8_DIR}/out/native
)
endif()
# V8 library paths
#set(V8_LIBRARY_PATH_SUFFIXES lib lib64 lib/x86_64-linux-gnu lib.target)
# Find include path
if(MSVC OR CMAKE_BUILD_TYPE EQUAL "Debug")
set(V8_HEADERS v8.h v8-debug.h v8-profiler.h v8stdint.h)
else()
set(V8_HEADERS v8.h v8stdint.h)
endif()
find_path(V8_INCLUDE_DIR ${V8_HEADERS}
PATHS ${V8_PATHS}
PATH_SUFFIXES include include/node
DOC "Google V8 JavaScript Engine Headers"
)
MESSAGE("V8 include dir: ${V8_INCLUDE_DIR}")
# Define library names
set(V8_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib v8D v8_baseD v8_base.ia32D v8_base.x64D libv8_baseD v8_baseD.lib v8_libbaseD v8_libbase.ia32D v8_libbase.x64D libv8_libbaseD v8_libbaseD.lib)
set(V8_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib v8 v8_base v8_base.ia32 v8_base.x64 libv8_base v8_base.lib v8_libbase v8_libbase.ia32 v8_libbase.x64 libv8_libbase v8_libbase.lib)
set(V8_PLATFORM_NAMES_DEBUG libnode.so.108 v8_libplatform.lib libnode libnode.so libnode.lib v8_libplatformD v8_libplatformD.a v8_libplatformD.lib)
set(V8_PLATFORM_NAMES_RELEASE libnode.so.108 v8_libplatform.lib libnode libnode.so libnode.lib v8_libplatform v8_libplatform.a)
set(V8_SAMPLER_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib v8_libsamplerD v8_libsamplerD.a v8_libsamplerD.lib)
set(V8_SAMPLER_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib v8_libsampler v8_libsampler.a v8_libsampler.lib)
set(V8_SNAPSHOT_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib v8_snapshotD libv8_snapshotD v8_snapshotD.lib)
set(V8_SNAPSHOT_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib v8_snapshot libv8_snapshot v8_snapshot.lib)
set(V8_ICU_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib icudataD icudataD.a icudataD.lib)
set(V8_ICU_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib icudata icudata.a icudata.lib)
set(V8_ICUUC_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib icuucD libicuucD)
set(V8_ICUUC_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib icuuc libicuuc)
set(V8_ICUI18N_NAMES_DEBUG libnode.so.108 libnode libnode.so libnode.lib icui18nD libicui18nD)
set(V8_ICUI18N_NAMES_RELEASE libnode.so.108 libnode libnode.so libnode.lib icui18n libicui18n)
# Find V8 base library debug
find_library(V8_LIBRARY_DEBUG
NAMES ${V8_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library (Debug)"
)
MESSAGE("V8_LIBRARY_DEBUG: ${V8_LIBRARY_DEBUG}")
# Find V8 base library release
find_library(V8_LIBRARY_RELEASE
NAMES ${V8_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library (Release)"
)
MESSAGE("V8_LIBRARY_RELEASE: ${V8_LIBRARY_RELEASE}")
# Find V8 platform library debug
find_library(V8_PLATFORM_LIBRARY_DEBUG
NAMES ${V8_PLATFORM_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Platform (Debug)"
)
MESSAGE("V8_PLATFORM_LIBRARY_DEBUG: ${V8_PLATFORM_LIBRARY_DEBUG}")
# Find V8 platform library release
find_library(V8_PLATFORM_LIBRARY_RELEASE
NAMES ${V8_PLATFORM_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Platform (Release)"
)
MESSAGE("V8_PLATFORM_LIBRARY_RELEASE: ${V8_PLATFORM_LIBRARY_RELEASE}")
# Find V8 platform library debug
find_library(V8_SAMPLER_LIBRARY_DEBUG
NAMES ${V8_SAMPLER_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Sampler (Debug)"
)
MESSAGE("V8_SAMPLER_LIBRARY_DEBUG: ${V8_SAMPLER_LIBRARY_DEBUG}")
# Find V8 platform library release
find_library(V8_SAMPLER_LIBRARY_RELEASE
NAMES ${V8_SAMPLER_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Sampler (Release)"
)
MESSAGE("V8_SAMPLER_LIBRARY_RELEASE: ${V8_SAMPLER_LIBRARY_RELEASE}")
# Find V8 snapshot library debug
find_library(V8_SNAPSHOT_LIBRARY_DEBUG
NAMES ${V8_SNAPSHOT_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Snapshot (Debug)"
)
MESSAGE("V8_SNAPSHOT_LIBRARY_DEBUG: ${V8_SNAPSHOT_LIBRARY_DEBUG}")
# Find V8 snapshot library release
find_library(V8_SNAPSHOT_LIBRARY_RELEASE
NAMES ${V8_SNAPSHOT_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library Snapshot (Release)"
)
MESSAGE("V8_SNAPSHOT_LIBRARY_RELEASE: ${V8_SNAPSHOT_LIBRARY_RELEASE}")
# Find V8 icu library debug
find_library(V8_ICU_LIBRARY_DEBUG
NAMES ${V8_ICU_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICU (Debug)"
)
MESSAGE("V8_ICU_LIBRARY_DEBUG: ${V8_ICU_LIBRARY_DEBUG}")
# Find V8 icu library release
find_library(V8_ICU_LIBRARY_RELEASE
NAMES ${V8_ICU_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICU (Release)"
)
MESSAGE("V8_ICU_LIBRARY_RELEASE: ${V8_ICU_LIBRARY_RELEASE}")
# Find V8 icuuc library debug
find_library(V8_ICUUC_LIBRARY_DEBUG
NAMES ${V8_ICUUC_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICUUC (Debug)"
)
MESSAGE("V8_ICUUC_LIBRARY_DEBUG: ${V8_ICUUC_LIBRARY_DEBUG}")
# Find V8 icuuc library release
find_library(V8_ICUUC_LIBRARY_RELEASE
NAMES ${V8_ICUUC_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICUUC (Release)"
)
MESSAGE("V8_ICUUC_LIBRARY_RELEASE: ${V8_ICUUC_LIBRARY_RELEASE}")
# Find V8 icui18n library debug
find_library(V8_ICUI18N_LIBRARY_DEBUG
NAMES ${V8_ICUI18N_NAMES_DEBUG}
PATHS ${V8_PATHS} ${V8_PATHS_DEBUG}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICUI18N (Debug)"
)
MESSAGE("V8_ICUI18N_LIBRARY_DEBUG: ${V8_ICUI18N_LIBRARY_DEBUG}")
# Find V8 icui18n library release
find_library(V8_ICUI18N_LIBRARY_RELEASE
NAMES ${V8_ICUI18N_NAMES_RELEASE}
PATHS ${V8_PATHS} ${V8_PATHS_RELEASE}
PATH_SUFFIXES ${V8_LIBRARY_PATH_SUFFIXES}
DOC "Google V8 JavaScript Engine Library ICUI18N (Release)"
)
MESSAGE("V8_ICUI18N_LIBRARY_RELEASE: ${V8_ICUI18N_LIBRARY_RELEASE}")
# Base build with snapshot
MESSAGE("1")
if(MSVC)
if(V8_LIBRARY_DEBUG AND V8_LIBRARY_RELEASE AND V8_SNAPSHOT_LIBRARY_DEBUG AND V8_SNAPSHOT_LIBRARY_RELEASE)
set(V8_LIBRARY
${V8_LIBRARY_DEBUG} ${V8_PLATFORM_LIBRARY_DEBUG} ${V8_SNAPSHOT_LIBRARY_DEBUG} # ${V8_ICU_LIBRARY_DEBUG}
${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE} ${V8_SNAPSHOT_LIBRARY_RELEASE} # ${V8_ICU_LIBRARY_RELEASE}
)
set(V8_LIBRARIES
optimized ${V8_LIBRARY_RELEASE} debug ${V8_LIBRARY_DEBUG}
optimized ${V8_PLATFORM_LIBRARY_RELEASE} debug ${V8_PLATFORM_LIBRARY_DEBUG}
# optimized ${V8_ICU_LIBRARY_RELEASE} debug ${V8_ICU_LIBRARY_DEBUG}
optimized ${V8_SNAPSHOT_LIBRARY_RELEASE} debug ${V8_SNAPSHOT_LIBRARY_DEBUG}
optimized Winmm.lib debug Winmm.lib
)
endif()
else()
MESSAGE("2")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
MESSAGE("3")
if(V8_LIBRARY_DEBUG AND V8_PLATFORM_LIBRARY_DEBUG AND V8_SAMPLER_LIBRARY_DEBUG)
set(V8_LIBRARY ${V8_LIBRARY_DEBUG} ${V8_PLATFORM_LIBRARY_DEBUG} ${V8_SAMPLER_LIBRARY_DEBUG}) # ${V8_ICU_LIBRARY_DEBUG})
elseif(V8_LIBRARY_DEBUG AND V8_PLATFORM_LIBRARY_DEBUG)
MESSAGE("4")
set(V8_LIBRARY ${V8_LIBRARY_DEBUG} ${V8_PLATFORM_LIBRARY_DEBUG}) # ${V8_SAMPLER_LIBRARY_DEBUG}) # ${V8_ICU_LIBRARY_DEBUG})
else()
if(V8_LIBRARY_RELEASE AND V8_PLATFORM_LIBRARY_RELEASE AND V8_SAMPLER_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE} ${V8_SAMPLER_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_DEBUG})
elseif(V8_LIBRARY_RELEASE AND V8_PLATFORM_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE}) # ${V8_SAMPLER_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_DEBUG})
endif()
endif()
else()
if(V8_LIBRARY_RELEASE AND V8_PLATFORM_LIBRARY_RELEASE AND V8_SAMPLER_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE} ${V8_SAMPLER_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_RELEASE})
elseif(V8_LIBRARY_RELEASE AND V8_PLATFORM_LIBRARY_RELEASE )
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE} ) # ${V8_SAMPLER_LIBRARY_RELEASE} ${V8_ICU_LIBRARY_RELEASE})
endif()
endif()
set(V8_LIBRARIES ${V8_LIBRARY})
endif()
# Set version libraries
set(V8_LIBRARIES_DEPENDS)
if (V8_LIBRARY_DEBUG)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_LIBRARY_DEBUG}.${V8_FIND_VERSION}
)
endif()
if (V8_LIBRARY_RELEASE)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_LIBRARY_RELEASE}.${V8_FIND_VERSION}
)
endif()
if(V8_ICU_LIBRARY_DEBUG)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICU_LIBRARY_DEBUG}.${ICU_FIND_VERSION}
)
endif()
if(V8_ICU_LIBRARY_RELEASE)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICU_LIBRARY_RELEASE}.${ICU_FIND_VERSION}
)
endif()
if(V8_ICUUC_LIBRARY_DEBUG)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICUUC_LIBRARY_DEBUG}.${ICU_FIND_VERSION}
)
endif()
if(V8_ICUUC_LIBRARY_RELEASE)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICUUC_LIBRARY_RELEASE}.${ICU_FIND_VERSION}
)
endif()
if(V8_ICUI18N_LIBRARY_DEBUG)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICUI18N_LIBRARY_DEBUG}.${ICU_FIND_VERSION}
)
endif()
if(V8_ICUI18N_LIBRARY_RELEASE)
set(V8_LIBRARIES_DEPENDS
${V8_LIBRARIES_DEPENDS}
${V8_ICUI18N_LIBRARY_RELEASE}.${ICU_FIND_VERSION}
)
endif()
MESSAGE("V8_LIBRARY: ${V8_LIBRARY}")
find_package_handle_standard_args(V8 DEFAULT_MSG V8_LIBRARY V8_INCLUDE_DIR)
# Base build
if(NOT V8_FOUND)
if(MSVC)
if(V8_LIBRARY_DEBUG AND V8_LIBRARY_RELEASE)
set(V8_LIBRARY
${V8_LIBRARY_DEBUG} ${V8_LIBRARY_RELEASE}
${V8_PLATFORM_LIBRARY_DEBUG} ${V8_PLATFORM_LIBRARY_RELEASE}
# ${V8_ICU_LIBRARY_DEBUG} ${V8_ICU_LIBRARY_RELEASE}
)
set(V8_LIBRARIES
optimized ${V8_LIBRARY_RELEASE} debug ${V8_LIBRARY_DEBUG}
optimized ${V8_PLATFORM_LIBRARY_RELEASE} debug ${V8_PLATFORM_LIBRARY_DEBUG}
# optimized ${V8_ICU_LIBRARY_RELEASE} debug ${V8_ICU_LIBRARY_DEBUG}
optimized Winmm.lib debug Winmm.lib
)
endif()
else()
if(CMAKE_BUILD_TYPE EQUAL "Debug")
if(V8_LIBRARY_DEBUG)
set(V8_LIBRARY ${V8_LIBRARY_DEBUG} ${V8_PLATFORM_LIBRARY_DEBUG}) # ${V8_ICU_LIBRARY_DEBUG})
endif()
else()
if(V8_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_RELEASE})
endif()
endif()
set(V8_LIBRARIES ${V8_LIBRARY})
endif()
find_package_handle_standard_args(V8 DEFAULT_MSG V8_LIBRARY V8_INCLUDE_DIR)
endif()
# Minimal build
if(NOT V8_FOUND)
if(MSVC)
if(V8_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_RELEASE})
set(V8_LIBRARIES
optimized ${V8_LIBRARY_RELEASE} debug ${V8_LIBRARY_RELEASE}
optimized ${V8_PLATFORM_LIBRARY_RELEASE} debug ${V8_PLATFORM_LIBRARY_RELEASE}
# optimized ${V8_ICU_LIBRARY_RELEASE} debug ${V8_ICU_LIBRARY_RELEASE}
optimized Winmm.lib debug Winmm.lib
)
endif()
else()
if(V8_LIBRARY_RELEASE)
set(V8_LIBRARY ${V8_LIBRARY_RELEASE} ${V8_PLATFORM_LIBRARY_RELEASE}) # ${V8_ICU_LIBRARY_RELEASE})
endif()
set(V8_LIBRARIES ${V8_LIBRARY})
endif()
find_package_handle_standard_args(V8 DEFAULT_MSG V8_LIBRARY V8_INCLUDE_DIR)
endif()
# Detect V8 version
if(V8_FOUND AND V8_INCLUDE_DIR)
file(READ ${V8_INCLUDE_DIR}/v8-version.h V8_VERSION_FILE)
string(REGEX MATCH "#define V8_MAJOR_VERSION ([0-9]+)" V8_VERSION_MAJOR_DEF ${V8_VERSION_FILE})
string(REGEX MATCH "([0-9]+)$" V8_VERSION_MAJOR ${V8_VERSION_MAJOR_DEF})
string(REGEX MATCH "#define V8_MINOR_VERSION ([0-9]+)" V8_VERSION_MINOR_DEF ${V8_VERSION_FILE})
string(REGEX MATCH "([0-9]+)$" V8_VERSION_MINOR ${V8_VERSION_MINOR_DEF})
string(REGEX MATCH "#define V8_BUILD_NUMBER ([0-9]+)" V8_VERSION_PATCH_DEF ${V8_VERSION_FILE})
string(REGEX MATCH "([0-9]+)$" V8_VERSION_PATCH ${V8_VERSION_PATCH_DEF})
string(REGEX MATCH "#define V8_PATCH_LEVEL ([0-9]+)" V8_VERSION_TWEAK_DEF ${V8_VERSION_FILE})
string(REGEX MATCH "([0-9]+)$" V8_VERSION_TWEAK ${V8_VERSION_TWEAK_DEF})
set(V8_VERSION "${V8_VERSION_MAJOR}.${V8_VERSION_MINOR}.${V8_VERSION_PATCH}.${V8_VERSION_TWEAK}")
set(V8_VERSION_HEX 0x0${V8_VERSION_MAJOR}${V8_VERSION_MINOR}${V8_VERSION_PATCH}${V8_VERSION_TWEAK})
string(LENGTH "${V8_VERSION_HEX}" V8_VERSION_HEX_LENGTH)
while(V8_VERSION_HEX_LENGTH LESS 8)
set(V8_VERSION_HEX "${V8_VERSION_HEX}0")
string(LENGTH "${V8_VERSION_HEX}" V8_VERSION_HEX_LENGTH)
endwhile()
endif()
# Detect V8 shell
set(V8_EXECUTABLE_NAMES d8)
find_program(V8_EXECUTABLE
NAMES ${V8_EXECUTABLE_NAMES}
)
mark_as_advanced(V8_LIBRARY V8_INCLUDE_DIR)
if(V8_FOUND)
set(V8_INCLUDE_DIRS ${V8_INCLUDE_DIR})
endif()
if(_V8_CMAKE_DEBUG)
message(STATUS "V8_INCLUDE_DIR: ${V8_INCLUDE_DIR}")
message(STATUS "V8_LIBRARIES: ${V8_LIBRARIES}")
message(STATUS "V8_LIBRARIES_DEPENDS: ${V8_LIBRARIES_DEPENDS}")
message(STATUS "V8_VERSION: ${V8_VERSION}")
message(STATUS "V8_VERSION_HEX: ${V8_VERSION_HEX}")
message(STATUS "V8_EXECUTABLE: ${V8_EXECUTABLE}")
endif()

View file

@ -1,4 +1,8 @@
# Copyright 2018-2019 High Fidelity, Inc.
# Copyright 2020 Vircadia contributors
# Copyright 2021-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
Source: hifi-deps
Version: 0.1.5-github-actions
Description: Collected dependencies for High Fidelity applications
Build-Depends: bullet3, draco, etc2comp, glad, glm, nvtt, openexr (!android), openssl (windows), opus, polyvox, tbb (!android), vhacd, webrtc (!android|!(linux&arm)), zlib
Build-Depends: bullet3, draco, etc2comp, glad, glm, node, nvtt, openexr (!android), openssl (windows), opus, polyvox, tbb (!android), vhacd, webrtc (!android|!(linux&arm)), zlib

6
cmake/ports/node/CONTROL Normal file
View file

@ -0,0 +1,6 @@
# Copyright 2023 Overte e.V.
# SPDX-License-Identifier: MIT
Source: node
Version: 18.14.2-1
Homepage: https://nodejs.org/
Description: Node.js JavaScript runtime.

View file

@ -0,0 +1,59 @@
# Copyright 2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(NODE_VERSION 18.14.2)
set(MASTER_COPY_SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src)
file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS)
if (ANDROID)
# TODO
elseif (WIN32)
vcpkg_download_distfile(
NODE_SOURCE_ARCHIVE
URLS "${EXTERNAL_BUILD_ASSETS}/dependencies/node/node-install-18.15.1-win-x64-release.tar.xz"
SHA512 892608a43ae32b0a82a0e3c7994934d0ce85639ea372c8e7feb7de44220211fa91878bd0744e1488054777807dd5b0c0677b59b44ab5e9fd35ecf222b38d8046
FILENAME node-install-18.15.1-win-x64-release.tar.xz
)
elseif (APPLE)
# TODO
vcpkg_download_distfile(
NODE_SOURCE_ARCHIVE
URLS "${EXTERNAL_BUILD_ASSETS}/dependencies/node/node-install-18.14.2-macOSXSDK10.14-macos-amd64-release.tar.xz"
SHA512 TODO
FILENAME node-install-18.14.2-macOSXSDK10.14-macos-amd64-release.tar.xz
)
else ()
# else Linux desktop
if (VCPKG_TARGET_ARCHITECTURE STREQUAL "x64")
vcpkg_download_distfile(
NODE_SOURCE_ARCHIVE
URLS "${EXTERNAL_BUILD_ASSETS}/dependencies/node/node-install-18.14.2-ubuntu-18.04-amd64-release.tar.xz"
SHA512 ff5ca5c27b811d20ac524346ee122bcd72e9e85c6de6f4799f620bb95dac959ce910cc5bb2162ed741a7f65043aa78173ecd2ce5b92f5a4d91ecb07ce71fa560
FILENAME node-install-18.14.2-ubuntu-18.04-amd64-release.tar.xz
)
elseif (VCPKG_TARGET_ARCHITECTURE STREQUAL "arm64")
vcpkg_download_distfile(
NODE_SOURCE_ARCHIVE
URLS "${EXTERNAL_BUILD_ASSETS}/dependencies/node/node-install-18.16.0-ubuntu-20.04-aarch64-release.tar.xz"
SHA512 aa4814c4ab1a922ec5afd4d7ef08479a32bfd23cb9a745102891bed5a2be13cc912e57e9bf80d856a15a5a9439b67c9a83963c605fdce349236795513090a426
FILENAME node-install-18.16.0-ubuntu-22.04-aarch64-release.tar.xz
)
endif ()
endif ()
vcpkg_extract_source_archive(MASTER_COPY_SOURCE_PATH ARCHIVE ${NODE_SOURCE_ARCHIVE} NO_REMOVE_ONE_LEVEL)
# move WIN dll to /bin and WIN .lib to /lib
if (WIN32)
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/include DESTINATION ${CURRENT_PACKAGES_DIR})
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/libnode.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib)
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/v8_libplatform.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib)
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/libnode.dll DESTINATION ${CURRENT_PACKAGES_DIR}/bin)
else ()
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/include DESTINATION ${CURRENT_PACKAGES_DIR})
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/lib DESTINATION ${CURRENT_PACKAGES_DIR})
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/share DESTINATION ${CURRENT_PACKAGES_DIR})
file(COPY ${MASTER_COPY_SOURCE_PATH}/node-install/bin DESTINATION ${CURRENT_PACKAGES_DIR})
endif ()

View file

@ -1,3 +1,7 @@
# Copyright 2014-2018 High Fidelity, Inc.
# Copyright 2021-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(TARGET_NAME domain-server)
if (UPPER_CMAKE_BUILD_TYPE MATCHES DEBUG AND NOT WIN32)
@ -25,6 +29,7 @@ symlink_or_copy_directory_beside_target(${_SHOULD_SYMLINK_RESOURCES} "${CMAKE_CU
# link the shared hifi libraries
include_hifi_library_headers(gpu)
include_hifi_library_headers(graphics)
include_hifi_library_headers(script-engine)
link_hifi_libraries(embedded-webserver networking shared avatars octree)
target_zlib()

View file

@ -169,7 +169,9 @@ endif()
if u_major == 18:
self.qtUrl = 'http://motofckr9k.ddns.net/vircadia_packages/qt5-install-5.15.2-ubuntu-18.04-aarch64_test.tar.xz'
elif u_major > 19:
elif u_major == 20:
self.qtUrl = self.assets_url + '/dependencies/qt5/qt5-install-5.15.9-2023.05.21-kde_fb3ec282151b1ee281a24f0545a40ac6438537c2-ubuntu-20.04-aarch64.tar.xz'
elif u_major > 20:
self.__no_qt_package_error()
else:
self.__unsupported_error()

View file

@ -1,3 +1,8 @@
# Copyright 2013-2019 High Fidelity, Inc.
# Copyright 2019-2021 Vircadia contributors
# Copyright 2021-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
if (APPLE)
# Make the OSX DMG app be Overte.app.
set(TARGET_NAME Overte)
@ -21,7 +26,7 @@ set(CUSTOM_INTERFACE_QRC_PATHS "")
find_package(
Qt5 COMPONENTS
Gui Widgets Multimedia Network Qml Quick Script Svg WebEngineCore WebEngineWidgets
Gui Widgets Multimedia Network Qml Quick Svg WebEngineCore WebEngineWidgets
${PLATFORM_QT_COMPONENTS}
WebChannel WebSockets
)
@ -217,7 +222,7 @@ link_hifi_libraries(
shared workload task octree ktx gpu gl procedural graphics graphics-scripting render
pointers recording hfm model-serializers networking material-networking
model-networking model-baker entities avatars
audio audio-client animation script-engine physics
audio audio-client animation physics
render-utils entities-renderer avatars-renderer ui qml auto-updater midi
controllers plugins image platform
ui-plugins display-plugins input-plugins
@ -227,6 +232,7 @@ link_hifi_libraries(
${PLATFORM_PLUGIN_LIBRARIES}
shaders
)
include_hifi_library_headers(script-engine)
# include the binary directory of render-utils for shader includes
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")
@ -291,7 +297,7 @@ endif ()
target_link_libraries(
${TARGET_NAME}
Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::Widgets
Qt5::Qml Qt5::Quick Qt5::Script Qt5::Svg
Qt5::Qml Qt5::Quick Qt5::Svg
Qt5::WebChannel Qt5::WebEngineCore Qt5::WebEngineWidgets
${PLATFORM_QT_LIBRARIES}
)

View file

@ -39,8 +39,9 @@ Rectangle {
}
Component.onCompleted: {
AudioScriptingInterface.noiseGateOpened.connect(function() { micBar.gated = false; });
AudioScriptingInterface.noiseGateClosed.connect(function() { micBar.gated = true; });
//TODO: this was causing type errors
//AudioScriptingInterface.noiseGateOpened.connect(function() { micBar.gated = false; });
//AudioScriptingInterface.noiseGateClosed.connect(function() { micBar.gated = true; });
HMD.displayModeChanged.connect(function() {
muted = AudioScriptingInterface.muted;
pushToTalk = AudioScriptingInterface.pushToTalk;

View file

@ -1,14 +1,15 @@
'use strict';
'no use strict';
//
// activator-doppleganger.js
//
// Created by Alezia Kurdis on February 20th, 2022.
// Copyright 2022 Overte e.V.
// Copyright 2022-2023 Overte e.V.
//
// This script is display a doppleganger of the user by entering an entity.
// This script displays a doppleganger of the user when entering an entity.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
(function() {
@ -23,6 +24,8 @@
autoUpdate: true
});
// V8TODO: does this need to be fixed? Right now it refers to global object in non-strict mode,
// and in strict mode it's undefined
this.preload = function(entityID) {
thisEntityID = entityID;
}

View file

@ -5,10 +5,11 @@
// Created by Andrzej Kapolka on 5/10/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2022 Overte e.V.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
@ -130,15 +131,19 @@
#include <plugins/SteamClientPlugin.h>
#include <plugins/OculusPlatformPlugin.h>
#include <plugins/InputConfiguration.h>
#include <RecordingScriptingInterface.h>
#include <Quat.h>
#include <recording/RecordingScriptingInterface.h>
#include <render/EngineStats.h>
#include <SecondaryCamera.h>
#include <ResourceCache.h>
#include <ResourceRequest.h>
#include <SandboxUtils.h>
#include <SceneScriptingInterface.h>
#include <ScriptEngines.h>
#include <ScriptCache.h>
#include <ScriptEngines.h>
#include <ScriptEngineCast.h>
#include <ScriptManager.h>
#include <ScriptUUID.h>
#include <ShapeEntityItem.h>
#include <SoundCacheScriptingInterface.h>
#include <ui/TabletScriptingInterface.h>
@ -166,6 +171,7 @@
#include <procedural/ProceduralMaterialCache.h>
#include <procedural/ReferenceMaterial.h>
#include "recording/ClipCache.h"
#include <Vec3.h>
#include "AudioClient.h"
#include "audio/AudioScope.h"
@ -236,7 +242,6 @@
#include <PickManager.h>
#include <PointerManager.h>
#include <raypick/RayPickScriptingInterface.h>
#include <raypick/LaserPointerScriptingInterface.h>
#include <raypick/PickScriptingInterface.h>
#include <raypick/PointerScriptingInterface.h>
#include <raypick/RayPick.h>
@ -443,38 +448,38 @@ public:
if (elapsedMovingAverage > _maxElapsedAverage * 1.1f) {
#if !defined(NDEBUG)
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
/* qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
<< "lastHeartbeatAge:" << lastHeartbeatAge
<< "elapsedMovingAverage:" << elapsedMovingAverage
<< "maxElapsed:" << _maxElapsed
<< "PREVIOUS maxElapsedAverage:" << _maxElapsedAverage
<< "NEW maxElapsedAverage:" << elapsedMovingAverage << "** NEW MAX ELAPSED AVERAGE **"
<< "samples:" << _movingAverage.getSamples();
<< "samples:" << _movingAverage.getSamples();*/
#endif
_maxElapsedAverage = elapsedMovingAverage;
}
if (lastHeartbeatAge > _maxElapsed) {
#if !defined(NDEBUG)
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
/* qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
<< "lastHeartbeatAge:" << lastHeartbeatAge
<< "elapsedMovingAverage:" << elapsedMovingAverage
<< "PREVIOUS maxElapsed:" << _maxElapsed
<< "NEW maxElapsed:" << lastHeartbeatAge << "** NEW MAX ELAPSED **"
<< "maxElapsedAverage:" << _maxElapsedAverage
<< "samples:" << _movingAverage.getSamples();
<< "samples:" << _movingAverage.getSamples();*/
#endif
_maxElapsed = lastHeartbeatAge;
}
#if !defined(NDEBUG)
if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) {
/* if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) {
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
<< "lastHeartbeatAge:" << lastHeartbeatAge
<< "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **"
<< "maxElapsed:" << _maxElapsed
<< "maxElapsedAverage:" << _maxElapsedAverage
<< "samples:" << _movingAverage.getSamples();
}
}*/
#endif
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
@ -800,7 +805,6 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
// Set dependencies
DependencyManager::set<PickManager>();
DependencyManager::set<PointerManager>();
DependencyManager::set<LaserPointerScriptingInterface>();
DependencyManager::set<RayPickScriptingInterface>();
DependencyManager::set<PointerScriptingInterface>();
DependencyManager::set<PickScriptingInterface>();
@ -814,7 +818,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
#endif
DependencyManager::set<DomainAccountManager>();
DependencyManager::set<StatTracker>();
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT, defaultScriptsOverrideOption);
DependencyManager::set<ScriptEngines>(ScriptManager::CLIENT_SCRIPT, defaultScriptsOverrideOption);
DependencyManager::set<Preferences>();
DependencyManager::set<recording::Deck>();
DependencyManager::set<recording::Recorder>();
@ -973,6 +977,12 @@ QSharedPointer<OffscreenUi> getOffscreenUI() {
#endif
}
bool Application::initMenu() {
_isMenuInitialized = false;
qApp->getWindow()->menuBar();
return true;
}
Application::Application(
int& argc, char** argv,
const QCommandLineParser& parser,
@ -981,6 +991,8 @@ Application::Application(
) :
QApplication(argc, argv),
_window(new MainWindow(desktop())),
// Menu needs to be initialized before other initializers. Otherwise deadlock happens on qApp->getWindow()->menuBar().
_isMenuInitialized(initMenu()),
_sessionRunTimer(startupTimer),
#ifndef Q_OS_ANDROID
_logger(new FileLogger(this)),
@ -1013,7 +1025,6 @@ Application::Application(
_snapshotSound(nullptr),
_sampleSound(nullptr)
{
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
@ -1399,8 +1410,8 @@ Application::Application(
{
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) {
registerScriptEngineWithApplicationServices(engine);
scriptEngines->registerScriptInitializer([this](ScriptManagerPointer manager) {
registerScriptEngineWithApplicationServices(manager);
});
connect(scriptEngines, &ScriptEngines::scriptCountChanged, this, [this] {
@ -2403,7 +2414,7 @@ Application::Application(
// Setup the mouse ray pick and related operators
{
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_LOCAL_ENTITIES()), 0.0f, true);
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::getPickEntities() | PickScriptingInterface::getPickLocalEntities()), 0.0f, true);
mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);
@ -4221,6 +4232,11 @@ bool Application::event(QEvent* event) {
return false;
}
// This helps avoid deadlock issue early during Application initialization
if (!_isMenuInitialized) {
return QApplication::event(event);
}
if (!Menu::getInstance()) {
return false;
}
@ -5835,7 +5851,7 @@ void Application::loadAvatarScripts(const QVector<QString>& urls) {
if (index < 0) {
auto scriptEnginePointer = scriptEngines->loadScript(url, false);
if (scriptEnginePointer) {
scriptEnginePointer->setType(ScriptEngine::Type::AVATAR);
scriptEnginePointer->setType(ScriptManager::Type::AVATAR);
}
}
}
@ -5846,7 +5862,7 @@ void Application::unloadAvatarScripts() {
auto urls = scriptEngines->getRunningScripts();
for (auto url : urls) {
auto scriptEngine = scriptEngines->getScriptEngine(url);
if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) {
if (scriptEngine->getType() == ScriptManager::Type::AVATAR) {
scriptEngines->stopScript(url, false);
}
}
@ -6034,7 +6050,8 @@ void Application::reloadResourceCaches() {
getEntities()->clear();
DependencyManager::get<AssetClient>()->clearCache();
DependencyManager::get<ScriptCache>()->clearCache();
//It's already cleared in reloadAllScripts so I'm not sure this is necessary.
//DependencyManager::get<ScriptCache>()->clearCache();
// Clear all the resource caches
DependencyManager::get<ResourceCacheSharedItems>()->clear();
@ -7436,9 +7453,10 @@ void Application::addingEntityWithCertificate(const QString& certificateID, cons
ledger->updateLocation(certificateID, placeName);
}
void Application::registerScriptEngineWithApplicationServices(const ScriptEnginePointer& scriptEngine) {
void Application::registerScriptEngineWithApplicationServices(ScriptManagerPointer& scriptManager) {
scriptEngine->setEmitScriptUpdatesFunction([this]() {
auto scriptEngine = scriptManager->engine();
scriptManager->setEmitScriptUpdatesFunction([this]() {
SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
return !entityServerNode || isPhysicsEnabled();
});
@ -7456,9 +7474,6 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("PlatformInfo", PlatformInfoScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("Rates", new RatesScriptingInterface(this));
// hook our avatar and avatar hash map object into this script engine
getMyAvatar()->registerMetaTypes(scriptEngine);
scriptEngine->registerGlobalObject("AvatarList", DependencyManager::get<AvatarManager>().data());
scriptEngine->registerGlobalObject("Camera", &_myCamera);
@ -7470,13 +7485,11 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface();
scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable);
connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
connect(scriptManager.get(), &ScriptManager::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater);
scriptEngine->registerGlobalObject("Overlays", &_overlays);
qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue,
RayToOverlayIntersectionResultFromScriptValue);
bool clientScript = scriptEngine->isClientScript();
bool clientScript = scriptManager->isClientScript();
#if !defined(DISABLE_QML)
scriptEngine->registerGlobalObject("OffscreenFlags", getOffscreenUI()->getFlags());
@ -7491,14 +7504,8 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
}
#endif
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<ToolbarProxy>, wrapperFromScriptValue<ToolbarProxy>);
qScriptRegisterMetaType(scriptEngine.data(),
wrapperToScriptValue<ToolbarButtonProxy>, wrapperFromScriptValue<ToolbarButtonProxy>);
scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data());
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
qScriptRegisterMetaType(scriptEngine.data(),
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
// FIXME remove these deprecated names for the tablet scripting interface
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
@ -7532,7 +7539,6 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get<LaserPointerScriptingInterface>().data());
scriptEngine->registerGlobalObject("Picks", DependencyManager::get<PickScriptingInterface>().data());
scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
@ -7548,12 +7554,10 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
scriptEngine->registerGlobalObject("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
scriptEngine->registerGlobalObject("AccountServices", AccountServicesScriptingInterface::getInstance());
qScriptRegisterMetaType(scriptEngine.data(), DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue);
scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data());
qScriptRegisterMetaType(scriptEngine.data(), worldDetailQualityToScriptValue, worldDetailQualityFromScriptValue);
scriptEngine->registerGlobalObject("Keyboard", DependencyManager::get<KeyboardScriptingInterface>().data());
scriptEngine->registerGlobalObject("Performance", new PerformanceScriptingInterface());
@ -7568,7 +7572,6 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("Render", RenderScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get());
GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data());
scriptEngine->registerGlobalObject("Graphics", DependencyManager::get<GraphicsScriptingInterface>().data());
scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
@ -7577,14 +7580,20 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().data());
scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get<GooglePolyScriptingInterface>().data());
//scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get<GooglePolyScriptingInterface>().data());
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine.data(), steamClient.get()));
scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptManager.get(), steamClient.get()));
}
auto scriptingInterface = DependencyManager::get<controller::ScriptingInterface>();
scriptEngine->registerGlobalObject("Controller", scriptingInterface.data());
UserInputMapper::registerControllerTypes(scriptEngine.data());
scriptManager->connect(scriptManager.get(), &ScriptManager::scriptEnding, [scriptManager]() {
// Request removal of controller routes with callbacks to a given script engine
auto userInputMapper = DependencyManager::get<UserInputMapper>();
userInputMapper->scheduleScriptEndpointCleanup(scriptManager->engine().get());
// V8TODO: Maybe we should wait until removal is finished if there are still crashes
});
UserInputMapper::registerControllerTypes(scriptEngine.get());
auto recordingInterface = DependencyManager::get<RecordingScriptingInterface>();
scriptEngine->registerGlobalObject("Recording", recordingInterface.data());
@ -7600,18 +7609,13 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); // Deprecated.
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
registerInteractiveWindowMetaType(scriptEngine.data());
auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
pickScriptingInterface->registerMetaTypes(scriptEngine.data());
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
connect(scriptEngine.data(), &ScriptEngine::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
connect(scriptEngine.data(), &ScriptEngine::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
connect(scriptEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
connect(scriptEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow, scriptEngines, &ScriptEngines::onClearDebugWindow);
connect(scriptManager.get(), &ScriptManager::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
connect(scriptManager.get(), &ScriptManager::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
connect(scriptManager.get(), &ScriptManager::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
connect(scriptManager.get(), &ScriptManager::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
connect(scriptManager.get(), &ScriptManager::clearDebugWindow, scriptEngines, &ScriptEngines::onClearDebugWindow);
}
@ -7998,6 +8002,7 @@ void Application::addAssetToWorldFromURL(QString url) {
void Application::addAssetToWorldFromURLRequestFinished() {
auto request = qobject_cast<ResourceRequest*>(sender());
Q_ASSERT(request != nullptr);
auto url = request->getUrl().toString();
auto result = request->getResult();
@ -8220,7 +8225,7 @@ void Application::addAssetToWorldCheckModelSize() {
propertyFlags += PROP_NAME;
propertyFlags += PROP_DIMENSIONS;
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
auto properties = entityScriptingInterface->getEntityProperties(entityID, propertyFlags);
auto properties = entityScriptingInterface->getEntityPropertiesInternal(entityID, propertyFlags);
auto name = properties.getName();
auto dimensions = properties.getDimensions();
@ -9210,7 +9215,7 @@ void Application::updateLoginDialogPosition() {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;
auto properties = entityScriptingInterface->getEntityProperties(_loginDialogID, desiredProperties);
auto properties = entityScriptingInterface->getEntityPropertiesInternal(_loginDialogID, desiredProperties);
auto positionVec = properties.getPosition();
auto cameraPositionVec = _myCamera.getPosition();
auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation());
@ -9366,6 +9371,7 @@ void Application::setActiveDisplayPlugin(const QString& pluginName) {
void Application::handleLocalServerConnection() const {
auto server = qobject_cast<QLocalServer*>(sender());
Q_ASSERT(server != nullptr);
qCDebug(interfaceapp) << "Got connection on local server from additional instance - waiting for parameters";
@ -9379,6 +9385,7 @@ void Application::handleLocalServerConnection() const {
void Application::readArgumentsFromLocalSocket() const {
auto socket = qobject_cast<QLocalSocket*>(sender());
Q_ASSERT(socket != nullptr);
auto message = socket->readAll();
socket->deleteLater();

View file

@ -5,16 +5,18 @@
// Created by Andrzej Kapolka on 5/10/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2022 Overte e.V.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_Application_h
#define hifi_Application_h
#include <functional>
#include <memory>
#include <QtCore/QCommandLineParser>
#include <QtCore/QHash>
@ -23,11 +25,13 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QStringList>
#include <QtQuick/QQuickItem>
#include <QtCore/QSharedPointer>
#include <QtGui/QImage>
#include <QtWidgets/QApplication>
#include <AvatarHashMap.h>
#include <ThreadHelpers.h>
#include <AbstractScriptingServicesInterface.h>
#include <AbstractViewStateInterface.h>
@ -42,7 +46,6 @@
#include <PhysicsEngine.h>
#include <plugins/Forward.h>
#include <ui-plugins/PluginContainer.h>
#include <ScriptEngine.h>
#include <ShapeManager.h>
#include <SimpleMovingAverage.h>
#include <StDev.h>
@ -91,6 +94,8 @@ class MainWindow;
class AssetUpload;
class CompositorHelper;
class AudioInjector;
class ScriptEngine;
using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
namespace controller {
class StateController;
@ -249,7 +254,7 @@ public:
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
virtual void registerScriptEngineWithApplicationServices(const ScriptEnginePointer& scriptEngine) override;
virtual void registerScriptEngineWithApplicationServices(ScriptManagerPointer& scriptManager) override;
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); }
virtual QThread* getMainThread() override { return thread(); }
@ -557,6 +562,7 @@ private slots:
private:
void init();
bool initMenu();
void pauseUntilLoginDetermined();
void resumeAfterLoginDialogActionTaken();
bool handleKeyEventForFocusedEntity(QEvent* event);
@ -621,6 +627,10 @@ private:
void userKickConfirmation(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags());
MainWindow* _window;
// _isMenuInitialized: used to initialize menu early enough before it's needed by other
// initializers. Fixes a deadlock issue with recent Qt versions.
bool _isMenuInitialized;
QElapsedTimer& _sessionRunTimer;
bool _aboutToQuit { false };

View file

@ -5,9 +5,11 @@
// Created by Triplelexx on 23/03/17.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AvatarBookmarks.h"
@ -50,12 +52,13 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
EntitySimulationPointer entitySimulation = entityTree->getSimulation();
PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast<PhysicalEntitySimulation>(entitySimulation);
EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender();
QScriptEngine scriptEngine;
// V8TODO: Creating new script engine each time is very inefficient
ScriptEnginePointer scriptEngine = newScriptEngine();
for (int index = 0; index < avatarEntities.count(); index++) {
const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap();
QVariant variantProperties = avatarEntityProperties["properties"];
QVariantMap asMap = variantProperties.toMap();
QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine);
ScriptValue scriptProperties = variantMapToScriptValue(asMap, *scriptEngine);
EntityItemProperties entityProperties;
EntityItemPropertiesFromScriptValueIgnoreReadOnly(scriptProperties, entityProperties);
@ -302,7 +305,8 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
if (entityTree) {
QScriptEngine scriptEngine;
// V8TODO: Creating new script engine each time is very inefficient
ScriptEnginePointer scriptEngine = newScriptEngine();
auto avatarEntities = myAvatar->getAvatarEntityDataNonDefault();
for (auto entityID : avatarEntities.keys()) {
auto entity = entityTree->findEntityByID(entityID);
@ -322,7 +326,7 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
desiredProperties -= PROP_JOINT_TRANSLATIONS;
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties);
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(scriptEngine.get(), entityProperties);
avatarEntityData["properties"] = scriptProperties.toVariant();
wearableEntities.append(QVariant(avatarEntityData));
}

View file

@ -5,9 +5,11 @@
// Created by Clement on 1/16/15.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2021 Vircadia contributors.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "LODManager.h"
@ -15,11 +17,18 @@
#include <SettingHandle.h>
#include <Util.h>
#include <shared/GlobalAppProperties.h>
#include <ScriptEngineCast.h>
#include "Application.h"
#include "ui/DialogsManager.h"
#include "InterfaceLogging.h"
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<WorldDetailQuality, worldDetailQualityToScriptValue, worldDetailQualityFromScriptValue>(scriptEngine);
}));
const QString LOD_SETTINGS_PREFIX { "lodManager/" };
Setting::Handle<bool> automaticLODAdjust(LOD_SETTINGS_PREFIX + "automaticLODAdjust", (bool)DEFAULT_LOD_AUTO_ADJUST);
@ -426,13 +435,14 @@ WorldDetailQuality LODManager::getWorldDetailQuality() const {
return qApp->isHMDMode() ? _hmdWorldDetailQuality : _desktopWorldDetailQuality;
}
QScriptValue worldDetailQualityToScriptValue(QScriptEngine* engine, const WorldDetailQuality& worldDetailQuality) {
return worldDetailQuality;
ScriptValue worldDetailQualityToScriptValue(ScriptEngine* engine, const WorldDetailQuality& worldDetailQuality) {
return engine->newValue(worldDetailQuality);
}
void worldDetailQualityFromScriptValue(const QScriptValue& 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) {

View file

@ -5,9 +5,11 @@
// Created by Clement on 1/16/15.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2021 Vircadia contributors.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_LODManager_h
@ -22,7 +24,9 @@
#include <PIDController.h>
#include <SimpleMovingAverage.h>
#include <render/Args.h>
#include <ScriptValue.h>
class ScriptEngine;
/*@jsdoc
* <p>The world detail quality rendered.</p>
@ -380,7 +384,7 @@ private:
glm::vec4 _pidOutputs{ 0.0f };
};
QScriptValue worldDetailQualityToScriptValue(QScriptEngine* engine, const WorldDetailQuality& worldDetailQuality);
void worldDetailQualityFromScriptValue(const QScriptValue& object, WorldDetailQuality& worldDetailQuality);
ScriptValue worldDetailQualityToScriptValue(ScriptEngine* engine, const WorldDetailQuality& worldDetailQuality);
bool worldDetailQualityFromScriptValue(const ScriptValue& object, WorldDetailQuality& worldDetailQuality);
#endif // hifi_LODManager_h

View file

@ -4,9 +4,11 @@
//
// Created by Triplelexx on 23/03/17.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "LocationBookmarks.h"
@ -73,6 +75,7 @@ QString LocationBookmarks::getAddress(const QString& bookmarkName) {
void LocationBookmarks::teleportToBookmark() {
QAction* action = qobject_cast<QAction*>(sender());
Q_ASSERT(action != nullptr);
QString address = action->data().toString();
DependencyManager::get<AddressManager>()->handleLookupString(address);
}

View file

@ -25,25 +25,16 @@
#include "scripting/ControllerScriptingInterface.h"
static const float SEARCH_SPHERE_SIZE = 0.0132f;
static const QVariantMap SEARCH_SPHERE = {{"x", SEARCH_SPHERE_SIZE},
{"y", SEARCH_SPHERE_SIZE},
{"z", SEARCH_SPHERE_SIZE}};
static const glm::vec3 SEARCH_SPHERE(SEARCH_SPHERE_SIZE, SEARCH_SPHERE_SIZE, SEARCH_SPHERE_SIZE);
static const int DEFAULT_SEARCH_SPHERE_DISTANCE = 1000; // how far from camera to search intersection?
static const QVariantMap COLORS_GRAB_SEARCHING_HALF_SQUEEZE = {{"red", 10},
{"green", 10},
{"blue", 255}};
static const QVariantMap COLORS_GRAB_SEARCHING_FULL_SQUEEZE = {{"red", 250},
{"green", 10},
{"blue", 10}};
static const QVariantMap COLORS_GRAB_DISTANCE_HOLD = {{"red", 238},
{"green", 75},
{"blue", 214}};
static const glm::u8vec3 COLORS_GRAB_SEARCHING_HALF_SQUEEZE(10, 10, 255);
static const glm::u8vec3 COLORS_GRAB_SEARCHING_FULL_SQUEEZE(250, 10, 10);
static const glm::u8vec3 COLORS_GRAB_DISTANCE_HOLD(238, 75, 215);
void LoginStateManager::tearDown() {
auto pointers = DependencyManager::get<PointerManager>().data();
@ -60,90 +51,88 @@ void LoginStateManager::tearDown() {
}
void LoginStateManager::setUp() {
QVariantMap fullPathRenderState {
{"type", "line3d"},
{"color", COLORS_GRAB_SEARCHING_FULL_SQUEEZE},
{"visible", true},
{"alpha", 1.0f},
{"solid", true},
{"glow", 1.0f},
{"ignoreRayIntersection", true}, // always ignore this
{"drawInFront", true}, // Even when burried inside of something, show it.
{"drawHUDLayer", false}
};
QVariantMap fullEndRenderState {
{"type", "sphere"},
{"dimensions", SEARCH_SPHERE},
{"solid", true},
{"color", COLORS_GRAB_SEARCHING_FULL_SQUEEZE},
{"alpha", 0.9f},
{"ignoreRayIntersection", true},
{"drawInFront", true}, // Even when burried inside of something, show it.
{"drawHUDLayer", false},
{"visible", true}
};
QVariantMap halfPathRenderState {
{"type", "line3d"},
{"color", COLORS_GRAB_SEARCHING_HALF_SQUEEZE},
{"visible", true},
{"alpha", 1.0f},
{"solid", true},
{"glow", 1.0f},
{"ignoreRayIntersection", true}, // always ignore this
{"drawInFront", true}, // Even when burried inside of something, show it.
{"drawHUDLayer", false}
};
QVariantMap halfEndRenderState {
{"type", "sphere"},
{"dimensions", SEARCH_SPHERE},
{"solid", true},
{"color", COLORS_GRAB_SEARCHING_HALF_SQUEEZE},
{"alpha", 0.9f},
{"ignoreRayIntersection", true},
{"drawInFront", true}, // Even when burried inside of something, show it.
{"drawHUDLayer", false},
{"visible", true}
};
QVariantMap holdPathRenderState {
{"type", "line3d"},
{"color", COLORS_GRAB_DISTANCE_HOLD},
{"visible", true},
{"alpha", 1.0f},
{"solid", true},
{"glow", 1.0f},
{"ignoreRayIntersection", true}, // always ignore this
{"drawInFront", true}, // Even when burried inside of something, show it.
{"drawHUDLayer", false},
};
QList<EntityItemProperties> entityProperties;
//V8TODO: are points and normals needed here
EntityItemProperties fullPathRenderState;
fullPathRenderState.setType(EntityTypes::PolyLine);
fullPathRenderState.setColor(COLORS_GRAB_SEARCHING_FULL_SQUEEZE);
fullPathRenderState.setGlow(true);
fullPathRenderState.setIgnorePickIntersection(true); // always ignore this
fullPathRenderState.setRenderLayer(RenderLayer::FRONT); // Even when buried inside of something, show it.
fullPathRenderState.setFaceCamera(true);
int fullPathRenderStateIndex = entityProperties.length();
entityProperties.append(fullPathRenderState);
EntityItemProperties fullEndRenderState;
fullEndRenderState.setType(EntityTypes::Sphere);
fullEndRenderState.setDimensions(SEARCH_SPHERE);
fullEndRenderState.setColor(COLORS_GRAB_SEARCHING_FULL_SQUEEZE);
fullEndRenderState.setAlpha(0.9f);
fullEndRenderState.setIgnorePickIntersection(true); // always ignore this
fullEndRenderState.setRenderLayer(RenderLayer::FRONT); // Even when buried inside of something, show it.
int fullEndRenderStateIndex = entityProperties.length();
entityProperties.append(fullEndRenderState);
EntityItemProperties halfPathRenderState;
halfPathRenderState.setType(EntityTypes::PolyLine);
halfPathRenderState.setColor(COLORS_GRAB_SEARCHING_HALF_SQUEEZE);
halfPathRenderState.setGlow(true);
halfPathRenderState.setIgnorePickIntersection(true); // always ignore this
halfPathRenderState.setRenderLayer(RenderLayer::FRONT); // Even when buried inside of something, show it.
halfPathRenderState.setFaceCamera(true);
int halfPathRenderStateIndex = entityProperties.length();
entityProperties.append(halfPathRenderState);
EntityItemProperties halfEndRenderState;
halfEndRenderState.setType(EntityTypes::Sphere);
halfEndRenderState.setDimensions(SEARCH_SPHERE);
halfEndRenderState.setColor(COLORS_GRAB_SEARCHING_HALF_SQUEEZE);
halfEndRenderState.setAlpha(0.9f);
halfEndRenderState.setIgnorePickIntersection(true); // always ignore this
halfEndRenderState.setRenderLayer(RenderLayer::FRONT); // Even when buried inside of something, show it.
int halfEndRenderStateIndex = entityProperties.length();
entityProperties.append(halfEndRenderState);
EntityItemProperties holdPathRenderState;
holdPathRenderState.setType(EntityTypes::PolyLine);
holdPathRenderState.setColor(COLORS_GRAB_DISTANCE_HOLD);
holdPathRenderState.setGlow(true);
holdPathRenderState.setIgnorePickIntersection(true); // always ignore this
holdPathRenderState.setRenderLayer(RenderLayer::FRONT); // Even when buried inside of something, show it.
holdPathRenderState.setFaceCamera(true);
int holdPathRenderStateIndex = entityProperties.length();
entityProperties.append(holdPathRenderState);
QVariantMap halfRenderStateIdentifier {
{"name", "half"},
{"path", halfPathRenderState},
{"end", halfEndRenderState}
{"pathPropertyIndex", halfPathRenderStateIndex},
{"endPropertyIndex", halfEndRenderStateIndex}
};
QVariantMap fullRenderStateIdentifier {
{"name", "full"},
{"path", fullPathRenderState},
{"end", fullEndRenderState}
{"pathPropertyIndex", fullPathRenderStateIndex},
{"endPropertyIndex", fullEndRenderStateIndex}
};
QVariantMap holdRenderStateIdentifier {
{"name", "hold"},
{"path", holdPathRenderState},
{"pathPropertyIndex", holdPathRenderStateIndex},
};
QVariantMap halfDefaultRenderStateIdentifier {
{"name", "half"},
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
{"path", halfPathRenderState}
{"pathPropertyIndex", halfPathRenderStateIndex}
};
QVariantMap fullDefaultRenderStateIdentifier {
{"name", "full"},
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
{"path", fullPathRenderState}
{"pathPropertyIndex", fullPathRenderStateIndex}
};
QVariantMap holdDefaultRenderStateIdentifier {
{"name", "hold"},
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
{"path", holdPathRenderState}
{"pathPropertyIndex", holdPathRenderStateIndex}
};
_renderStates = QList<QVariant>({halfRenderStateIdentifier, fullRenderStateIdentifier, holdRenderStateIdentifier});
@ -168,9 +157,9 @@ void LoginStateManager::setUp() {
leftPointerTriggerProperties = QList<QVariant>({ltClick1, ltClick2});
const unsigned int leftHand = 0;
QVariantMap leftPointerProperties {
QVariantMap leftPointerPropertiesMap {
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND" },
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
{ "filter", PickScriptingInterface::getPickLocalEntities() },
{ "triggers", leftPointerTriggerProperties },
{ "posOffset", vec3toVariant(grabPointSphereOffsetLeft + malletOffset) },
{ "hover", true },
@ -178,9 +167,12 @@ void LoginStateManager::setUp() {
{ "distanceScaleEnd", true },
{ "hand", leftHand }
};
leftPointerProperties["renderStates"] = _renderStates;
leftPointerProperties["defaultRenderStates"] = _defaultRenderStates;
_leftLoginPointerID = pointers->createPointer(PickQuery::PickType::Ray, leftPointerProperties);
leftPointerPropertiesMap["renderStates"] = _renderStates;
leftPointerPropertiesMap["defaultRenderStates"] = _defaultRenderStates;
RayPointerProperties leftPointerProperties;
leftPointerProperties.properties = leftPointerPropertiesMap;
leftPointerProperties.entityProperties = entityProperties;
_leftLoginPointerID = pointers->createRayPointer(leftPointerProperties);
pointers->setRenderState(_leftLoginPointerID, "");
pointers->enablePointer(_leftLoginPointerID);
const unsigned int rightHand = 1;
@ -195,9 +187,9 @@ void LoginStateManager::setUp() {
{ "button", "Primary" }
};
rightPointerTriggerProperties = QList<QVariant>({rtClick1, rtClick2});
QVariantMap rightPointerProperties{
QVariantMap rightPointerPropertiesMap{
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" },
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
{ "filter", PickScriptingInterface::getPickLocalEntities() },
{ "triggers", rightPointerTriggerProperties },
{ "posOffset", vec3toVariant(grabPointSphereOffsetRight + malletOffset) },
{ "hover", true },
@ -205,9 +197,12 @@ void LoginStateManager::setUp() {
{ "distanceScaleEnd", true },
{ "hand", rightHand }
};
rightPointerProperties["renderStates"] = _renderStates;
rightPointerProperties["defaultRenderStates"] = _defaultRenderStates;
_rightLoginPointerID = pointers->createPointer(PickQuery::PickType::Ray, rightPointerProperties);
rightPointerPropertiesMap["renderStates"] = _renderStates;
rightPointerPropertiesMap["defaultRenderStates"] = _defaultRenderStates;
RayPointerProperties rightPointerProperties;
rightPointerProperties.properties = rightPointerPropertiesMap;
rightPointerProperties.entityProperties = entityProperties;
_rightLoginPointerID = pointers->createRayPointer(rightPointerProperties);
pointers->setRenderState(_rightLoginPointerID, "");
pointers->enablePointer(_rightLoginPointerID);
}

View file

@ -5,9 +5,11 @@
// Created by Stephen Birarda on 8/12/13.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
// For happ(ier) development of QML, use these two things:
// This forces QML files to be pulled from the source as you edit it: set environment variable HIFI_USE_SOURCE_TREE_RESOURCES=1
@ -22,6 +24,7 @@
#include <thread>
#include <AddressManager.h>
#include <AssetClient.h>
#include <AudioClient.h>
#include <CrashHelpers.h>
#include <DependencyManager.h>

View file

@ -4,9 +4,11 @@
//
// Created by Sam Gateau on 2019-05-29.
// Copyright 2019 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PerformanceManager.h"
@ -19,7 +21,11 @@
PerformanceManager::PerformanceManager()
{
setPerformancePreset((PerformancePreset) _performancePresetSetting.get());
static std::once_flag registry_flag;
std::call_once(registry_flag, [] {
qRegisterMetaType<PerformanceManager::PerformancePreset>("PerformanceManager::PerformancePreset");
});
setPerformancePreset((PerformancePreset)_performancePresetSetting.get());
}
void PerformanceManager::setupPerformancePresetSettings(bool evaluatePlatformTier) {

View file

@ -4,16 +4,35 @@
//
// Created by Dante Ruiz on 2019-04-15.
// Copyright 2019 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "RefreshRateManager.h"
#include <array>
#include <ScriptEngineCast.h>
#include <ScriptManager.h>
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<RefreshRateManager::RefreshRateRegime, scriptValueFromEnumClass<RefreshRateManager::RefreshRateRegime>, scriptValueToEnumClass<RefreshRateManager::RefreshRateRegime> >(scriptEngine, "RefreshRateRegime");
scriptRegisterMetaType<RefreshRateManager::UXMode, scriptValueFromEnumClass<RefreshRateManager::UXMode>, scriptValueToEnumClass<RefreshRateManager::UXMode> >(scriptEngine, "UXMode");
}));
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptEngine->registerEnum("RefreshRateRegime",QMetaEnum::fromType<RefreshRateManager::RefreshRateRegime>());
scriptEngine->registerEnum("UXMode",QMetaEnum::fromType<RefreshRateManager::UXMode>());
});
static const int VR_TARGET_RATE = 90;

View file

@ -4,9 +4,11 @@
//
// Created by Dante Ruiz on 2019-04-15.
// Copyright 2019 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_RefreshRateManager_h
@ -19,9 +21,12 @@
#include <QTimer>
#include <SettingHandle.h>
#include <ScriptEngineCast.h>
#include <ScriptManager.h>
#include <shared/ReadWriteLockable.h>
class RefreshRateManager {
class RefreshRateManager : QObject {
Q_OBJECT
public:
enum RefreshRateProfile {
ECO = 0,
@ -29,6 +34,7 @@ public:
REALTIME,
PROFILE_NUM
};
Q_ENUM(RefreshRateProfile)
static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= RefreshRateProfile::ECO && value <= RefreshRateProfile::REALTIME); }
/*@jsdoc
@ -57,6 +63,7 @@ public:
SHUTDOWN,
REGIME_NUM
};
Q_ENUM(RefreshRateRegime)
static bool isValidRefreshRateRegime(RefreshRateRegime value) { return (value >= RefreshRateRegime::FOCUS_ACTIVE && value <= RefreshRateRegime::SHUTDOWN); }
/*@jsdoc
@ -77,6 +84,7 @@ public:
VR,
UX_NUM
};
Q_ENUM(UXMode)
static bool isValidUXMode(UXMode value) { return (value >= UXMode::DESKTOP && value <= UXMode::VR); }
RefreshRateManager();
@ -110,7 +118,7 @@ private:
mutable int _activeRefreshRate { 20 };
RefreshRateProfile _refreshRateProfile { RefreshRateProfile::INTERACTIVE};
RefreshRateRegime _refreshRateRegime { RefreshRateRegime::STARTUP };
UXMode _uxMode;
UXMode _uxMode { UXMode::DESKTOP };
mutable ReadWriteLockable _refreshRateProfileSettingLock;
Setting::Handle<int> _refreshRateProfileSetting { "refreshRateProfile", RefreshRateProfile::INTERACTIVE };

View file

@ -4,16 +4,19 @@
//
// Created by Stephen Birarda on 1/23/2014.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AvatarManager.h"
#include <string>
#include <QScriptEngine>
#include <ScriptEngine.h>
#include <ScriptValue.h>
#include "AvatarLogging.h"
@ -735,8 +738,8 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID)
}
RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray,
const QScriptValue& avatarIdsToInclude,
const QScriptValue& avatarIdsToDiscard,
const ScriptValue& avatarIdsToInclude,
const ScriptValue& avatarIdsToDiscard,
bool pickAgainstMesh) {
QVector<EntityItemID> avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude);
QVector<EntityItemID> avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard);
@ -860,6 +863,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
result.avatarID = rayAvatarResult._intersectWithAvatar;
result.distance = rayAvatarResult._distance;
result.face = face;
Q_ASSERT(face < 7);
result.intersection = ray.origin + rayAvatarResult._distance * rayDirection;
result.surfaceNormal = rayAvatarResult._intersectionNormal;
result.jointIndex = rayAvatarResult._intersectWithJoint;
@ -953,6 +957,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector
result.avatarID = sortedAvatar.second->getID();
result.parabolicDistance = parabolicDistance;
result.face = face;
Q_ASSERT(face < 7);
result.surfaceNormal = surfaceNormal;
result.extraInfo = extraInfo;
}
@ -980,7 +985,7 @@ float AvatarManager::getAvatarSortCoefficient(const QString& name) {
}
// HACK
void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptValue& value) {
void AvatarManager::setAvatarSortCoefficient(const QString& name, const ScriptValue& value) {
bool somethingChanged = false;
if (value.isNumber()) {
float numericalValue = (float)value.toNumber();

View file

@ -4,9 +4,11 @@
//
// Created by Stephen Birarda on 1/23/2014.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AvatarManager_h
@ -26,13 +28,14 @@
#include <AudioInjectorManager.h>
#include <workload/Space.h>
#include <EntitySimulation.h> // for SetOfEntities
#include <ScriptValue.h>
#include "AvatarMotionState.h"
#include "DetailedMotionState.h"
#include "MyAvatar.h"
#include "OtherAvatar.h"
class ScriptEngine;
using SortedAvatar = std::pair<float, std::shared_ptr<Avatar>>;
/*@jsdoc
@ -94,7 +97,7 @@ public:
*/
/// Registers the script types associated with the avatar manager.
static void registerMetaTypes(QScriptEngine* engine);
static void registerMetaTypes(ScriptEngine* engine);
virtual ~AvatarManager();
@ -185,8 +188,8 @@ public:
* }
*/
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
const QScriptValue& avatarIdsToInclude = QScriptValue(),
const QScriptValue& avatarIdsToDiscard = QScriptValue(),
const ScriptValue& avatarIdsToInclude = ScriptValue(),
const ScriptValue& avatarIdsToDiscard = ScriptValue(),
bool pickAgainstMesh = true);
/*@jsdoc
* @function AvatarManager.findRayIntersectionVector
@ -229,7 +232,7 @@ public:
* @param {number} value - Value.
* @deprecated This function is deprecated and will be removed.
*/
Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value);
Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const ScriptValue& value);
/*@jsdoc
* Gets PAL (People Access List) data for one or more avatars. Using this method is faster than iterating over each avatar

View file

@ -5,9 +5,11 @@
// Created by Mark Peng on 8/16/13.
// Copyright 2012 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "MyAvatar.h"
@ -43,13 +45,16 @@
#include <udt/PacketHeaders.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include <ScriptEngineLogging.h>
#include <SharedUtil.h>
#include <SoundCache.h>
#include <ModelEntityItem.h>
#include <TextRenderer3D.h>
#include <UserActivityLogger.h>
#include <recording/Recorder.h>
#include <RecordingScriptingInterface.h>
#include <recording/RecordingScriptingInterface.h>
#include <RenderableModelEntityItem.h>
#include <VariantMapToScriptValue.h>
#include <NetworkingConstants.h>
@ -110,6 +115,23 @@ const QString POINT_BLEND_LINEAR_ALPHA_NAME = "pointBlendAlpha";
const QString POINT_REF_JOINT_NAME = "RightShoulder";
const float POINT_ALPHA_BLENDING = 1.0f;
STATIC_SCRIPT_TYPES_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine();
MyAvatar::registerMetaTypes(scriptEngine);
});
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine();
auto avatarManager = DependencyManager::get<AvatarManager>();
if (avatarManager) {
avatarManager->getMyAvatar()->registerProperties(scriptEngine);
} else {
qWarning(scriptengine) << "Cannot register MyAvatar with script engine, AvatarManager instance not available";
}
});
const std::array<QString, static_cast<uint>(MyAvatar::AllowAvatarStandingPreference::Count)>
MyAvatar::allowAvatarStandingPreferenceStrings = {
QStringLiteral("WhenUserIsStanding"),
@ -378,8 +400,6 @@ MyAvatar::MyAvatar(QThread* thread) :
MyAvatar::~MyAvatar() {
_lookAtTargetAvatar.reset();
delete _scriptEngine;
_scriptEngine = nullptr;
if (_addAvatarEntitiesToTreeTimer.isActive()) {
_addAvatarEntitiesToTreeTimer.stop();
}
@ -439,20 +459,24 @@ void MyAvatar::enableHandTouchForID(const QUuid& entityID) {
}
void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) {
QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
scriptRegisterMetaType<AudioListenerMode, audioListenModeToScriptValue, audioListenModeFromScriptValue>(engine.get());
scriptRegisterMetaType<MyAvatar::DriveKeys, driveKeysToScriptValue, driveKeysFromScriptValue>(engine.get(), "DriveKeys");
qDebug() << "MyAvatar::registerMetaTypes";
}
void MyAvatar::registerProperties(ScriptEnginePointer engine) {
ScriptValue value = engine->newQObject(this, ScriptEngine::QtOwnership);
engine->globalObject().setProperty("MyAvatar", value);
QScriptValue driveKeys = engine->newObject();
ScriptValue driveKeys = engine->newObject();
auto metaEnum = QMetaEnum::fromType<DriveKeys>();
for (int i = 0; i < MAX_DRIVE_KEYS; ++i) {
driveKeys.setProperty(metaEnum.key(i), metaEnum.value(i));
}
engine->globalObject().setProperty("DriveKeys", driveKeys);
qScriptRegisterMetaType(engine.data(), audioListenModeToScriptValue, audioListenModeFromScriptValue);
qScriptRegisterMetaType(engine.data(), driveKeysToScriptValue, driveKeysFromScriptValue);
}
void MyAvatar::setOrientationVar(const QVariant& newOrientationVar) {
Avatar::setWorldOrientation(quatFromVariant(newOrientationVar));
}
@ -2065,7 +2089,7 @@ void MyAvatar::avatarEntityDataToJson(QJsonObject& root) const {
void MyAvatar::loadData() {
if (!_scriptEngine) {
_scriptEngine = new QScriptEngine();
_scriptEngine = newScriptEngine();
}
getHead()->setBasePitch(_headPitchSetting.get());
@ -2673,8 +2697,7 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() {
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
{
std::lock_guard<std::mutex> guard(_scriptEngineLock);
QScriptValue scriptProperties;
scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine, entityProperties);
ScriptValue scriptProperties = EntityItemPropertiesToScriptValue(_scriptEngine.get(), entityProperties);
avatarEntityData["properties"] = scriptProperties.toVariant();
}
avatarEntitiesData.append(QVariant(avatarEntityData));
@ -5704,20 +5727,22 @@ void MyAvatar::setAudioListenerMode(AudioListenerMode audioListenerMode) {
}
}
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode) {
return audioListenerMode;
ScriptValue audioListenModeToScriptValue(ScriptEngine* engine, const AudioListenerMode& audioListenerMode) {
return engine->newValue(audioListenerMode);
}
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) {
bool audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode) {
audioListenerMode = static_cast<AudioListenerMode>(object.toUInt16());
return true;
}
QScriptValue driveKeysToScriptValue(QScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys) {
return driveKeys;
ScriptValue driveKeysToScriptValue(ScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys) {
return engine->newValue(driveKeys);
}
void driveKeysFromScriptValue(const QScriptValue& object, MyAvatar::DriveKeys& driveKeys) {
bool driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys) {
driveKeys = static_cast<MyAvatar::DriveKeys>(object.toUInt16());
return true;
}

View file

@ -5,16 +5,18 @@
// Created by Mark Peng on 8/16/13.
// Copyright 2012 High Fidelity, Inc.
// Copyright 2021 Vircadia contributors.
// Copyright 2022 Overte e.V.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_MyAvatar_h
#define hifi_MyAvatar_h
#include <bitset>
#include <memory>
#include <glm/glm.hpp>
@ -28,10 +30,10 @@
#include <EntityItem.h>
#include <ThreadSafeValueCache.h>
#include <Rig.h>
#include <ScriptEngine.h>
#include <SettingHandle.h>
#include <Sound.h>
#include <shared/Camera.h>
#include <ScriptValue.h>
#include "AtRestDetector.h"
#include "MyCharacterController.h"
@ -41,6 +43,8 @@ class AvatarActionHold;
class ModelItemID;
class MyHead;
class DetailedMotionState;
class ScriptEngine;
using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
/*@jsdoc
* <p>Locomotion control types.</p>
@ -581,7 +585,8 @@ public:
virtual ~MyAvatar();
void instantiableAvatar() override {};
void registerMetaTypes(ScriptEnginePointer engine);
static void registerMetaTypes(ScriptEnginePointer engine);
void registerProperties(ScriptEnginePointer engine);
virtual void simulateAttachments(float deltaTime) override;
@ -870,7 +875,7 @@ public:
* MyAvatar.removeAnimationStateHandler(handler);
* }, 100);
*/
Q_INVOKABLE QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { return _skeletonModel->getRig().addAnimationStateHandler(handler, propertiesList); }
Q_INVOKABLE ScriptValue addAnimationStateHandler(const ScriptValue& handler, const ScriptValue& propertiesList) { return _skeletonModel->getRig().addAnimationStateHandler(handler, propertiesList); }
/*@jsdoc
* Removes an animation state handler function.
@ -878,7 +883,7 @@ public:
* @param {number} handler - The ID of the animation state handler function to remove.
*/
// Removes a handler previously added by addAnimationStateHandler.
Q_INVOKABLE void removeAnimationStateHandler(QScriptValue handler) { _skeletonModel->getRig().removeAnimationStateHandler(handler); }
Q_INVOKABLE void removeAnimationStateHandler(const ScriptValue& handler) { _skeletonModel->getRig().removeAnimationStateHandler(handler); }
/*@jsdoc
@ -1213,8 +1218,6 @@ public:
* @function MyAvatar.getTargetAvatar
* @returns {ScriptAvatar} Information on the avatar being looked at, <code>null</code> if no avatar is being looked at.
*/
// FIXME: The return type doesn't have a conversion to a script value so the function always returns undefined in
// JavaScript. Note: When fixed, JSDoc is needed for the return type.
Q_INVOKABLE ScriptAvatarData* getTargetAvatar() const;
@ -2288,13 +2291,6 @@ public slots:
*/
void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true) override;
/*@jsdoc
* @function MyAvatar.sanitizeAvatarEntityProperties
* @param {EntityItemProperties} properties - Properties.
* @deprecated This function is deprecated and will be removed.
*/
void sanitizeAvatarEntityProperties(EntityItemProperties& properties) const;
/*@jsdoc
* Sets whether your avatar mesh is visible to you.
* @function MyAvatar.setEnableMeshVisible
@ -2686,6 +2682,7 @@ private:
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
virtual glm::vec3 getSkeletonPosition() const override;
int _skeletonModelChangeCount { 0 };
void sanitizeAvatarEntityProperties(EntityItemProperties& properties) const;
void saveAvatarScale();
@ -3099,7 +3096,7 @@ private:
//
// keep a ScriptEngine around so we don't have to instantiate on the fly (these are very slow to create/delete)
mutable std::mutex _scriptEngineLock;
QScriptEngine* _scriptEngine { nullptr };
ScriptEnginePointer _scriptEngine { nullptr };
bool _needToSaveAvatarEntitySettings { false };
bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false };
@ -3116,11 +3113,13 @@ private:
QTimer _addAvatarEntitiesToTreeTimer;
};
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode);
Q_DECLARE_METATYPE(MyAvatar::DriveKeys)
QScriptValue driveKeysToScriptValue(QScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys);
void driveKeysFromScriptValue(const QScriptValue& object, MyAvatar::DriveKeys& driveKeys);
ScriptValue audioListenModeToScriptValue(ScriptEngine* engine, const AudioListenerMode& audioListenerMode);
bool audioListenModeFromScriptValue(const ScriptValue& object, AudioListenerMode& audioListenerMode);
ScriptValue driveKeysToScriptValue(ScriptEngine* engine, const MyAvatar::DriveKeys& driveKeys);
bool driveKeysFromScriptValue(const ScriptValue& object, MyAvatar::DriveKeys& driveKeys);
bool isWearableEntity(const EntityItemPointer& entity);

View file

@ -4,9 +4,11 @@
//
// Created by Howard Stearns on 8/4/17.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "QmlCommerce.h"
@ -374,7 +376,7 @@ bool QmlCommerce::installApp(const QString& itemHref, const bool& alsoOpenImmedi
// Don't try to re-load (install) a script if it's already running
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
if (!runningScripts.contains(scriptUrl)) {
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
if (!(DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed()))) {
qCDebug(commerce) << "Couldn't load script.";
return false;
}

View file

@ -3,9 +3,11 @@
//
// Created by Sam Gateau on 29/6/2018.
// Copyright 2018 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "GraphicsEngine.h"
@ -187,7 +189,7 @@ void GraphicsEngine::render_performFrame() {
{
PROFILE_RANGE(render, "/pluginBeginFrameRender");
// If a display plugin loses it's underlying support, it
// If a display plugin loses its underlying support, it
// needs to be able to signal us to not use it
if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
QMetaObject::invokeMethod(qApp, "updateDisplayMode");
@ -267,7 +269,7 @@ void GraphicsEngine::render_performFrame() {
PROFILE_RANGE(render, "/renderOverlay");
PerformanceTimer perfTimer("renderOverlay");
// NOTE: There is no batch associated with this renderArgs
// the ApplicationOverlay class assumes it's viewport is setup to be the device size
// the ApplicationOverlay class assumes it's viewport is set up to be the device size
renderArgs._viewport = glm::ivec4(0, 0, qApp->getDeviceSize());
qApp->getApplicationOverlay().renderOverlay(&renderArgs);
}

View file

@ -4,9 +4,11 @@
//
// Created by Stephen Birarda on 5/31/17.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "CloseEventSender.h"
@ -74,6 +76,7 @@ void CloseEventSender::handleQuitEventFinished() {
_hasFinishedQuitEvent = true;
auto reply = qobject_cast<QNetworkReply*>(sender());
Q_ASSERT(reply != nullptr);
if (reply->error() == QNetworkReply::NoError) {
qCDebug(networking) << "Quit event sent successfully";
} else {

View file

@ -4,6 +4,7 @@
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -32,6 +33,7 @@ PickQuery::PickType LaserPointer::getType() const {
}
void LaserPointer::editRenderStatePath(const std::string& state, const QVariant& pathProps) {
//V8TODO pathProps are not a thing anymore
auto renderState = std::static_pointer_cast<RenderState>(_renderStates[state]);
if (renderState) {
updateRenderState(renderState->getPathID(), pathProps);
@ -135,12 +137,12 @@ LaserPointer::RenderState::RenderState(const QUuid& startID, const QUuid& pathID
{
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
_pathIgnorePicks = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getIgnorePickIntersection();
_pathIgnorePicks = entityScriptingInterface->getEntityPropertiesInternal(getPathID(), desiredProperties).getIgnorePickIntersection();
}
{
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_STROKE_WIDTHS;
auto widths = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getStrokeWidths();
auto widths = entityScriptingInterface->getEntityPropertiesInternal(getPathID(), desiredProperties).getStrokeWidths();
_lineWidth = widths.length() == 0 ? PolyLineEntityItem::DEFAULT_LINE_WIDTH : widths[0];
}
}
@ -172,9 +174,14 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
points.append(glm::vec3(0.0f));
points.append(end - origin);
properties.setPosition(origin);
properties.setRotation(glm::quat(1.0f, 0.0f ,0.0f ,0.0f));
properties.setLinePoints(points);
properties.setVisible(true);
properties.setIgnorePickIntersection(doesPathIgnorePicks());
QVector<glm::vec3> normals;
normals.append(glm::vec3(0.0f, 0.0f, 1.0f));
normals.append(glm::vec3(0.0f, 0.0f, 1.0f));
properties.setNormals(normals);
QVector<float> widths;
float width = getLineWidth() * parentScale;
widths.append(width);
@ -184,33 +191,34 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
}
}
std::shared_ptr<StartEndRenderState> LaserPointer::buildRenderState(const QVariantMap& propMap) {
std::shared_ptr<StartEndRenderState> LaserPointer::buildRenderState(const QVariantMap& propMap, const QList<EntityItemProperties> &entityProperties) {
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
QUuid startID;
if (propMap["start"].isValid()) {
QVariantMap startMap = propMap["start"].toMap();
if (startMap["type"].isValid()) {
startMap.remove("visible");
startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap);
if (propMap["startPropertyIndex"].isValid()) {
int startPropertyIndex = propMap["startPropertyIndex"].toInt();
if (startPropertyIndex >= 0 && startPropertyIndex < entityProperties.length()) {
//startMap.remove("visible");
startID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[startPropertyIndex], entity::HostType::LOCAL);
}
}
QUuid pathID;
if (propMap["path"].isValid()) {
QVariantMap pathMap = propMap["path"].toMap();
// laser paths must be line3ds
if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") {
pathMap.remove("visible");
pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap);
if (propMap["pathPropertyIndex"].isValid()) {
// laser paths must be PolyLine
int pathPropertyIndex = propMap["pathPropertyIndex"].toInt();
if (pathPropertyIndex >= 0 && pathPropertyIndex < entityProperties.length()) {
//startMap.remove("visible");
//pathMap["type"].toString() == "PolyLine"
pathID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[pathPropertyIndex], entity::HostType::LOCAL);
}
}
QUuid endID;
if (propMap["end"].isValid()) {
QVariantMap endMap = propMap["end"].toMap();
if (endMap["type"].isValid()) {
endMap.remove("visible");
endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap);
if (propMap["endPropertyIndex"].isValid()) {
int endPropertyIndex = propMap["endPropertyIndex"].toInt();
if (endPropertyIndex >= 0 && endPropertyIndex < entityProperties.length()) {
//startMap.remove("visible");
endID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[endPropertyIndex], entity::HostType::LOCAL);
}
}

View file

@ -13,6 +13,8 @@
#include "PathPointer.h"
#include<EntityItemProperties.h>
class LaserPointer : public PathPointer {
using Parent = PathPointer;
public:
@ -46,7 +48,7 @@ public:
QVariantMap toVariantMap() const override;
static std::shared_ptr<StartEndRenderState> buildRenderState(const QVariantMap& propMap);
static std::shared_ptr<StartEndRenderState> buildRenderState(const QVariantMap& propMap, const QList<EntityItemProperties> &entityProperties);
protected:
PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override;

View file

@ -1,35 +0,0 @@
//
// LaserPointerScriptingInterface.cpp
// interface/src/raypick
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "LaserPointerScriptingInterface.h"
#include "RegisteredMetaTypes.h"
#include "PointerScriptingInterface.h"
void LaserPointerScriptingInterface::setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems) const {
DependencyManager::get<PointerManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
}
void LaserPointerScriptingInterface::setIncludeItems(unsigned int uid, const QScriptValue& includeItems) const {
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
}
unsigned int LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const {
return DependencyManager::get<PointerScriptingInterface>()->createPointer(PickQuery::PickType::Ray, properties);
}
void LaserPointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
DependencyManager::get<PointerScriptingInterface>()->editRenderState(uid, renderState, properties);
}
QVariantMap LaserPointerScriptingInterface::getPrevRayPickResult(unsigned int uid) const {
return DependencyManager::get<PointerScriptingInterface>()->getPrevPickResult(uid);
}

View file

@ -1,168 +0,0 @@
//
// LaserPointerScriptingInterface.h
// interface/src/raypick
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_LaserPointerScriptingInterface_h
#define hifi_LaserPointerScriptingInterface_h
#include <QtCore/QObject>
#include "DependencyManager.h"
#include <PointerManager.h>
class LaserPointerScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
/*@jsdoc
* The <code>LaserPointers</code> API is a subset of the {@link Pointers} API. It lets you create, manage, and visually
* represent objects for repeatedly calculating ray intersections with avatars, entities, and overlays. Ray pointers can also
* be configured to generate events on entities and overlays intersected.
*
* @namespace LaserPointers
*
* @deprecated This API is deprecated and will be removed. Use {@link Pointers} instead.
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @borrows Pointers.enablePointer as enableLaserPointer
* @borrows Pointers.disablePointer as disableLaserPointer
* @borrows Pointers.removePointer as removeLaserPointer
* @borrows Pointers.setPrecisionPicking as setPrecisionPicking
*/
public:
/*@jsdoc
* Creates a new ray pointer. The pointer can have a wide range of behaviors depending on the properties specified. For
* example, it may be a static ray pointer, a mouse ray pointer, or joint ray pointer.
* <p><strong>Warning:</strong> Pointers created using this method currently always intersect at least visible and
* collidable things but this may not always be the case.</p>
* @function LaserPointers.createLaserPointer
* @param {Pointers.RayPointerProperties} properties - The properties of the pointer, including the properties of the
* underlying pick that the pointer uses to do its picking.
* @returns {number} The ID of the pointer if successfully created, otherwise <code>0</code>.
*/
Q_INVOKABLE unsigned int createLaserPointer(const QVariant& properties) const;
// jsdoc @borrows from Pointers
Q_INVOKABLE void enableLaserPointer(unsigned int uid) const { DependencyManager::get<PointerManager>()->enablePointer(uid); }
// jsdoc @borrows from Pointers
Q_INVOKABLE void disableLaserPointer(unsigned int uid) const { DependencyManager::get<PointerManager>()->disablePointer(uid); }
// jsdoc @borrows from Pointers
Q_INVOKABLE void removeLaserPointer(unsigned int uid) const { DependencyManager::get<PointerManager>()->removePointer(uid); }
/*@jsdoc
* Edits a render state of a pointer, to change its visual appearance for the state when the pointer is intersecting
* something.
* <p><strong>Note:</strong> You can only edit the properties of the existing parts of the pointer; you cannot change the
* type of any part.</p>
* <p><strong>Note:</strong> You cannot use this method to change the appearance of a default render state.</p>
* @function LaserPointers.editRenderState
* @param {number} id - The ID of the pointer.
* @param {string} renderState - The name of the render state to edit.
* @param {Pointers.RayPointerRenderState} properties - The new properties for the render state. Only the overlay
* properties to change need be specified.
*/
Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const;
/*@jsdoc
* Sets the render state of a pointer, to change its visual appearance and possibly disable or enable it.
* @function LaserPointers.setRenderState
* @param {string} renderState - <p>The name of the render state to set the pointer to. This may be:</p>
* <ul>
* <li>The name of one of the render states set in the pointer's properties.</li>
* <li><code>""</code>, to hide the pointer and disable emitting of events.</li>
* </ul>
* @param {number} id - The ID of the pointer.
*/
Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get<PointerManager>()->setRenderState(uid, renderState.toStdString()); }
/*@jsdoc
* Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as
* it is enabled, regardless of the render state.
* @function LaserPointers.getPrevRayPickResult
* @param {number} id - The ID of the pointer.
* @returns {RayPickResult} The most recent intersection of the pointer.
*/
Q_INVOKABLE QVariantMap getPrevRayPickResult(unsigned int uid) const;
// jsdoc @borrows from Pointers
Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get<PointerManager>()->setPrecisionPicking(uid, precisionPicking); }
/*@jsdoc
* Sets the length of a pointer.
* @function LaserPointers.setLaserLength
* @param {number} id - The ID of the pointer.
* @param {number} laserLength - The desired length of the pointer.
*/
Q_INVOKABLE void setLaserLength(unsigned int uid, float laserLength) const { DependencyManager::get<PointerManager>()->setLength(uid, laserLength); }
/*@jsdoc
* Sets a list of entity and avatar IDs that a pointer should ignore during intersection.
* @function LaserPointers.setIgnoreItems
* @param {number} id - The ID of the pointer.
* @param {Uuid[]} ignoreItems - A list of IDs to ignore.
*/
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const;
/*@jsdoc
* Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with
* everything.
* @function LaserPointers.setIncludeItems
* @param {number} id - The ID of the pointer.
* @param {Uuid[]} includeItems - A list of IDs to include.
*/
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const;
/*@jsdoc
* Locks a pointer onto a specific entity or avatar.
* @function LaserPointers.setLockEndUUID
* @param {number} id - The ID of the pointer.
* @param {Uuid} targetID - The ID of the entity or avatar to lock the pointer on to.
* @param {boolean} isAvatar - <code>true</code> if the target is an avatar, <code>false</code> if it is an entity.
* @param {Mat4} [offset] - The offset of the target point from the center of the target item. If not specified, the
* pointer locks on to the center of the target item.
*/
Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); }
/*@jsdoc
* Checks if a pointer is associated with the left hand: a pointer with <code>joint</code> property set to
* <code>"_CONTROLLER_LEFTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"</code>.
* @function LaserPointers.isLeftHand
* @param {number} id - The ID of the pointer.
* @returns {boolean} <code>true</code> if the pointer is associated with the left hand, <code>false</code> if it isn't.
*/
Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->isLeftHand(uid); }
/*@jsdoc
* Checks if a pointer is associated with the right hand: a pointer with <code>joint</code> property set to
* <code>"_CONTROLLER_RIGHTHAND"</code> or <code>"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"</code>.
* @function LaserPointers.isRightHand
* @param {number} id - The ID of the pointer.
* @returns {boolean} <code>true</code> if the pointer is associated with the right hand, <code>false</code> if it isn't.
*/
Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get<PointerManager>()->isRightHand(uid); }
/*@jsdoc
* Checks if a pointer is associated with the system mouse: a pointer with <code>joint</code> property set to
* <code>"Mouse"</code>.
* @function LaserPointers.isMouse
* @param {number} id - The ID of the pointer.
* @returns {boolean} <code>true</code> if the pointer is associated with the system mouse, <code>false</code> if it isn't.
*/
Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get<PointerManager>()->isMouse(uid); }
};
#endif // hifi_LaserPointerScriptingInterface_h

View file

@ -71,7 +71,7 @@ PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick)
if (getFilter().doesPickLocalEntities()) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_ENTITY_HOST_TYPE;
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
if (DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
type = IntersectionType::LOCAL_ENTITY;
}
}

View file

@ -1,6 +1,7 @@
//
// Created by Sam Gondelman 7/17/2018
// Copyright 2018 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -232,14 +233,13 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
}
}
std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVariantMap& propMap) {
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVariantMap& propMap, const QList<EntityItemProperties> &entityProperties) {
QUuid startID;
if (propMap["start"].isValid()) {
QVariantMap startMap = propMap["start"].toMap();
if (startMap["type"].isValid()) {
startMap.remove("visible");
startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap);
if (propMap["startPropertyIndex"].isValid()) {
int startPropertyIndex = propMap["startPropertyIndex"].toInt();
if (startPropertyIndex >= 0 && startPropertyIndex < entityProperties.length()) {
//startMap.remove("visible");
startID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[startPropertyIndex], entity::HostType::LOCAL);
}
}
@ -249,6 +249,7 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
bool isVisibleInSecondaryCamera = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA;
bool drawInFront = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT;
bool enabled = false;
if (propMap["path"].isValid()) {
enabled = true;
QVariantMap pathMap = propMap["path"].toMap();
@ -274,11 +275,11 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
}
QUuid endID;
if (propMap["end"].isValid()) {
QVariantMap endMap = propMap["end"].toMap();
if (endMap["type"].isValid()) {
endMap.remove("visible");
endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap);
if (propMap["endPropertyIndex"].isValid()) {
int endPropertyIndex = propMap["endPropertyIndex"].toInt();
if (endPropertyIndex >= 0 && endPropertyIndex < entityProperties.length()) {
//endMap.remove("visible");
endID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[endPropertyIndex], entity::HostType::LOCAL);
}
}

View file

@ -10,6 +10,8 @@
#include "PathPointer.h"
#include<EntityItemProperties.h>
#include <render/Item.h>
class ParabolaPointer : public PathPointer {
@ -105,7 +107,7 @@ public:
QVariantMap toVariantMap() const override;
static std::shared_ptr<StartEndRenderState> buildRenderState(const QVariantMap& propMap);
static std::shared_ptr<StartEndRenderState> buildRenderState(const QVariantMap& propMap, const QList<EntityItemProperties> &entityProperties);
protected:
virtual PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override;

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman 7/17/2018
// Copyright 2018 High Fidelity, Inc.
// copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PathPointer.h"
@ -12,6 +14,7 @@
#include <DependencyManager.h>
#include <PickManager.h>
#include <Quat.h>
#include "PickScriptingInterface.h"
#include "RayPick.h"
@ -141,11 +144,13 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
auto renderState = _renderStates.find(_currentRenderState);
auto defaultRenderState = _defaultRenderStates.find(_currentRenderState);
float parentScale = 1.0f;
//if (_scaleWithParent) {
if (_enabled && _scaleWithParent) {
glm::vec3 dimensions = DependencyManager::get<PickManager>()->getParentTransform(_pickUID).getScale();
parentScale = glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z);
}
//if (!_currentRenderState.empty() && renderState != _renderStates.end() &&
if (_enabled && !_currentRenderState.empty() && renderState != _renderStates.end() &&
(type != IntersectionType::NONE || _pathLength > 0.0f)) {
glm::vec3 origin = getPickOrigin(pickResult);
@ -157,6 +162,7 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
defaultRenderState->second.second->disable();
}
} else if (_enabled && !_currentRenderState.empty() && defaultRenderState != _defaultRenderStates.end()) {
//} else if (!_currentRenderState.empty() && defaultRenderState != _defaultRenderStates.end()) {
if (renderState != _renderStates.end() && renderState->second->isEnabled()) {
renderState->second->disable();
}
@ -251,7 +257,7 @@ StartEndRenderState::StartEndRenderState(const QUuid& startID, const QUuid& endI
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_DIMENSIONS;
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
auto properties = entityScriptingInterface->getEntityProperties(_startID, desiredProperties);
auto properties = entityScriptingInterface->getEntityPropertiesInternal(_startID, desiredProperties);
_startDim = properties.getDimensions();
_startIgnorePicks = properties.getIgnorePickIntersection();
}
@ -260,7 +266,7 @@ StartEndRenderState::StartEndRenderState(const QUuid& startID, const QUuid& endI
desiredProperties += PROP_DIMENSIONS;
desiredProperties += PROP_ROTATION;
desiredProperties += PROP_IGNORE_PICK_INTERSECTION;
auto properties = entityScriptingInterface->getEntityProperties(_endID, desiredProperties);
auto properties = entityScriptingInterface->getEntityPropertiesInternal(_endID, desiredProperties);
_endDim = properties.getDimensions();
_endRot = properties.getRotation();
_endIgnorePicks = properties.getIgnorePickIntersection();

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman 10/20/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PickScriptingInterface.h"
@ -29,6 +31,26 @@
#include "EntityTransformNode.h"
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include <ScriptEngineLogging.h>
#include <ScriptValueUtils.h>
STATIC_SCRIPT_TYPES_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
PickScriptingInterface::registerMetaTypes(scriptEngine);
});
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
if (pickScriptingInterface) {
pickScriptingInterface->registerProperties(scriptEngine);
} else {
qWarning(scriptengine) << "Cannot register PickScriptingInterface properties with script engine, PickScriptingInterface instance not available";
}
});
static const float WEB_TOUCH_Y_OFFSET = 0.105f; // how far forward (or back with a negative number) to slide stylus in hand
static const glm::vec3 TIP_OFFSET = glm::vec3(0.0f, StylusPick::WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, 0.0f);
@ -67,7 +89,7 @@ unsigned int PickScriptingInterface::createPick(const PickQuery::PickType type,
PickFilter getPickFilter(unsigned int filter) {
// FIXME: Picks always intersect visible and collidable things right now
filter = filter | (PickScriptingInterface::PICK_INCLUDE_VISIBLE() | PickScriptingInterface::PICK_INCLUDE_COLLIDABLE());
filter = filter | (PickScriptingInterface::getPickIncludeVisible() | PickScriptingInterface::getPickIncludeCollidable());
return PickFilter(filter);
}
@ -425,11 +447,11 @@ void PickScriptingInterface::setPrecisionPicking(unsigned int uid, bool precisio
DependencyManager::get<PickManager>()->setPrecisionPicking(uid, precisionPicking);
}
void PickScriptingInterface::setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems) {
void PickScriptingInterface::setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems) {
DependencyManager::get<PickManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
}
void PickScriptingInterface::setIncludeItems(unsigned int uid, const QScriptValue& includeItems) {
void PickScriptingInterface::setIncludeItems(unsigned int uid, const ScriptValue& includeItems) {
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
}
@ -445,23 +467,26 @@ bool PickScriptingInterface::isMouse(unsigned int uid) {
return DependencyManager::get<PickManager>()->isMouse(uid);
}
QScriptValue pickTypesToScriptValue(QScriptEngine* engine, const PickQuery::PickType& pickType) {
return pickType;
ScriptValue pickTypesToScriptValue(ScriptEngine* engine, const PickQuery::PickType& pickType) {
return engine->newValue(pickType);
}
void pickTypesFromScriptValue(const QScriptValue& object, PickQuery::PickType& pickType) {
bool pickTypesFromScriptValue(const ScriptValue& object, PickQuery::PickType& pickType) {
pickType = static_cast<PickQuery::PickType>(object.toUInt16());
return true;
}
void PickScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
QScriptValue pickTypes = engine->newObject();
void PickScriptingInterface::registerMetaTypes(ScriptEngine* engine) {
scriptRegisterMetaType<PickQuery::PickType, pickTypesToScriptValue, pickTypesFromScriptValue>(engine);
}
void PickScriptingInterface::registerProperties(ScriptEngine* engine) {
ScriptValue pickTypes = engine->newObject();
auto metaEnum = QMetaEnum::fromType<PickQuery::PickType>();
for (int i = 0; i < PickQuery::PickType::NUM_PICK_TYPES; ++i) {
pickTypes.setProperty(metaEnum.key(i), metaEnum.value(i));
}
engine->globalObject().setProperty("PickType", pickTypes);
qScriptRegisterMetaType(engine, pickTypesToScriptValue, pickTypesFromScriptValue);
}
unsigned int PickScriptingInterface::getPerFrameTimeBudget() const {

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman 10/20/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_PickScriptingInterface_h
#define hifi_PickScriptingInterface_h
@ -15,6 +17,9 @@
#include <Pick.h>
#include <PickFilter.h>
class ScriptEngine;
class ScriptValue;
/*@jsdoc
* The <code>Picks</code> API lets you create and manage objects for repeatedly calculating intersections.
*
@ -71,39 +76,40 @@
class PickScriptingInterface : public QObject, public Dependency {
Q_OBJECT
Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT)
Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT)
Q_PROPERTY(unsigned int PICK_ENTITIES READ getPickEntities CONSTANT)
Q_PROPERTY(unsigned int PICK_OVERLAYS READ getPickOverlays CONSTANT)
Q_PROPERTY(unsigned int PICK_DOMAIN_ENTITIES READ PICK_DOMAIN_ENTITIES CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATAR_ENTITIES READ PICK_AVATAR_ENTITIES CONSTANT)
Q_PROPERTY(unsigned int PICK_LOCAL_ENTITIES READ PICK_LOCAL_ENTITIES CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT)
Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT)
Q_PROPERTY(unsigned int PICK_DOMAIN_ENTITIES READ getPickDomainEntities CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATAR_ENTITIES READ getPickAvatarEntities CONSTANT)
Q_PROPERTY(unsigned int PICK_LOCAL_ENTITIES READ getPickLocalEntities CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATARS READ getPickAvatars CONSTANT)
Q_PROPERTY(unsigned int PICK_HUD READ getPickHud CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_VISIBLE READ PICK_INCLUDE_VISIBLE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_VISIBLE READ getPickIncludeVisible CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ getPickIncludeInvisible CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_COLLIDABLE READ PICK_INCLUDE_COLLIDABLE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_COLLIDABLE READ getPickIncludeCollidable CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ getPickIncludeNoncollidable CONSTANT)
Q_PROPERTY(unsigned int PICK_PRECISE READ PICK_PRECISE CONSTANT)
Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT)
Q_PROPERTY(unsigned int PICK_PRECISE READ getPickPrecise CONSTANT)
Q_PROPERTY(unsigned int PICK_COARSE READ getPickCoarse CONSTANT)
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ getPickAllIntersections CONSTANT)
Q_PROPERTY(unsigned int PICK_BYPASS_IGNORE READ PICK_BYPASS_IGNORE CONSTANT)
Q_PROPERTY(unsigned int PICK_BYPASS_IGNORE READ getPickBypassIgnore CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_NONE READ getIntersectedNone CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ getIntersectedEntity CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ getIntersectedLocalEntity CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ getIntersectedOverlay CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ getIntersectedAvatar CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_HUD READ getIntersectedHud CONSTANT)
Q_PROPERTY(unsigned int perFrameTimeBudget READ getPerFrameTimeBudget WRITE setPerFrameTimeBudget)
SINGLETON_DEPENDENCY
public:
void registerMetaTypes(QScriptEngine* engine);
static void registerMetaTypes(ScriptEngine* engine);
void registerProperties(ScriptEngine* engine);
/*@jsdoc
* Creates a new pick. Different {@link PickType}s use different properties, and within one PickType the properties you
@ -245,7 +251,7 @@ public:
* @param {number} id - The ID of the pick.
* @param {Uuid[]} ignoreItems - The list of IDs to ignore.
*/
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems);
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems);
/*@jsdoc
* Sets a list of entity and avatar IDs that a pick should include during intersection, instead of intersecting with
@ -255,7 +261,7 @@ public:
* @param {number} id - The ID of the pick.
* @param {Uuid[]} includeItems - The list of IDs to include.
*/
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeItems);
Q_INVOKABLE void setIncludeItems(unsigned int uid, const ScriptValue& includeItems);
/*@jsdoc
* Checks if a pick is associated with the left hand: a ray or parabola pick with <code>joint</code> property set to
@ -289,17 +295,17 @@ public:
unsigned int getPerFrameTimeBudget() const;
void setPerFrameTimeBudget(unsigned int numUsecs);
static constexpr unsigned int PICK_BYPASS_IGNORE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_BYPASS_IGNORE); }
public slots:
static constexpr unsigned int getPickBypassIgnore() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_BYPASS_IGNORE); }
/*@jsdoc
* @function Picks.PICK_ENTITIES
* @deprecated This function is deprecated and will be removed. Use the <code>Picks.PICK_DOMAIN_ENTITIES |
* Picks.PICK_AVATAR_ENTITIES</code> properties expression instead.
* @returns {number}
*/
static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); }
static constexpr unsigned int getPickEntities() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); }
/*@jsdoc
* @function Picks.PICK_OVERLAYS
@ -307,7 +313,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); }
static constexpr unsigned int getPickOverlays() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); }
/*@jsdoc
@ -316,7 +322,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_DOMAIN_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES); }
static constexpr unsigned int getPickDomainEntities() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES); }
/*@jsdoc
* @function Picks.PICK_AVATAR_ENTITIES
@ -324,7 +330,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_AVATAR_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); }
static constexpr unsigned int getPickAvatarEntities() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); }
/*@jsdoc
* @function Picks.PICK_LOCAL_ENTITIES
@ -332,7 +338,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_LOCAL_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); }
static constexpr unsigned int getPickLocalEntities() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); }
/*@jsdoc
* @function Picks.PICK_AVATARS
@ -340,14 +346,14 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATARS); }
static constexpr unsigned int getPickAvatars() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATARS); }
/*@jsdoc
* @function Picks.PICK_HUD
* @deprecated This function is deprecated and will be removed. Use the <code>Picks.PICK_HUD</code> property instead.
* @returns {number}
*/
static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::HUD); }
static constexpr unsigned int getPickHud() { return PickFilter::getBitMask(PickFilter::FlagBit::HUD); }
/*@jsdoc
@ -356,7 +362,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_INCLUDE_VISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); }
static constexpr unsigned int getPickIncludeVisible() { return PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); }
/*@jsdoc
* @function Picks.PICK_INCLUDE_INVISIBLE
@ -364,7 +370,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::INVISIBLE); }
static constexpr unsigned int getPickIncludeInvisible() { return PickFilter::getBitMask(PickFilter::FlagBit::INVISIBLE); }
/*@jsdoc
@ -373,7 +379,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_INCLUDE_COLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); }
static constexpr unsigned int getPickIncludeCollidable() { return PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); }
/*@jsdoc
* @function Picks.PICK_INCLUDE_NONCOLLIDABLE
@ -381,7 +387,7 @@ public slots:
* property instead.
* @returns {number}
*/
static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::NONCOLLIDABLE); }
static constexpr unsigned int getPickIncludeNoncollidable() { return PickFilter::getBitMask(PickFilter::FlagBit::NONCOLLIDABLE); }
/*@jsdoc
@ -389,14 +395,14 @@ public slots:
* @deprecated This function is deprecated and will be removed. Use the <code>Picks.PICK_PRECISE</code> property instead.
* @returns {number}
*/
static constexpr unsigned int PICK_PRECISE() { return PickFilter::getBitMask(PickFilter::FlagBit::PRECISE); }
static constexpr unsigned int getPickPrecise() { return PickFilter::getBitMask(PickFilter::FlagBit::PRECISE); }
/*@jsdoc
* @function Picks.PICK_COARSE
* @deprecated This function is deprecated and will be removed. Use the <code>Picks.PICK_COARSE</code> property instead.
* @returns {number}
*/
static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::COARSE); }
static constexpr unsigned int getPickCoarse() { return PickFilter::getBitMask(PickFilter::FlagBit::COARSE); }
/*@jsdoc
@ -405,7 +411,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
static constexpr unsigned int getPickAllIntersections() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
/*@jsdoc
* @function Picks.INTERSECTED_NONE
@ -413,7 +419,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; }
static constexpr unsigned int getIntersectedNone() { return IntersectionType::NONE; }
/*@jsdoc
* @function Picks.INTERSECTED_ENTITY
@ -421,7 +427,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; }
static constexpr unsigned int getIntersectedEntity() { return IntersectionType::ENTITY; }
/*@jsdoc
* @function Picks.INTERSECTED_LOCAL_ENTITY
@ -429,7 +435,7 @@ public slots:
* property instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_LOCAL_ENTITY() { return IntersectionType::LOCAL_ENTITY; }
static constexpr unsigned int getIntersectedLocalEntity() { return IntersectionType::LOCAL_ENTITY; }
/*@jsdoc
* @function Picks.INTERSECTED_OVERLAY
@ -437,7 +443,7 @@ public slots:
* property instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_OVERLAY() { return INTERSECTED_LOCAL_ENTITY(); }
static constexpr unsigned int getIntersectedOverlay() { return getIntersectedLocalEntity(); }
/*@jsdoc
* @function Picks.INTERSECTED_AVATAR
@ -445,7 +451,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; }
static constexpr unsigned int getIntersectedAvatar() { return IntersectionType::AVATAR; }
/*@jsdoc
* @function Picks.INTERSECTED_HUD
@ -453,7 +459,7 @@ public slots:
* instead.
* @returns {number}
*/
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
static constexpr unsigned int getIntersectedHud() { return IntersectionType::HUD; }
protected:
static std::shared_ptr<PickQuery> buildRayPick(const QVariantMap& properties);

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman 10/20/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PointerScriptingInterface.h"
@ -12,45 +14,56 @@
#include <GLMHelpers.h>
#include <shared/QtHelpers.h>
#include <ScriptValueUtils.h>
#include "Application.h"
#include "PickManager.h"
#include "LaserPointer.h"
#include "StylusPointer.h"
#include "ParabolaPointer.h"
#include "StylusPick.h"
#include <ScriptManager.h>
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
qDebug() << "STATIC_SCRIPT_TYPES_INITIALIZER PointerScriptingInterface";
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<RayPointerProperties, rayPointerPropertiesToScriptValue, rayPointerPropertiesFromScriptValue>(scriptEngine);
scriptRegisterMetaType<StylusPointerProperties, stylusPointerPropertiesToScriptValue, stylusPointerPropertiesFromScriptValue>(scriptEngine);
scriptRegisterMetaType<ParabolaPointerProperties, parabolaPointerPropertiesToScriptValue, parabolaPointerPropertiesFromScriptValue>(scriptEngine);
}));
static const glm::quat X_ROT_NEG_90{ 0.70710678f, -0.70710678f, 0.0f, 0.0f };
static const glm::vec3 DEFAULT_POSITION_OFFSET{0.0f, 0.0f, -StylusPick::WEB_STYLUS_LENGTH / 2.0f};
static const glm::vec3 DEFAULT_MODEL_DIMENSIONS{0.01f, 0.01f, StylusPick::WEB_STYLUS_LENGTH};
void PointerScriptingInterface::setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems) const {
void PointerScriptingInterface::setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems) const {
DependencyManager::get<PointerManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
}
void PointerScriptingInterface::setIncludeItems(unsigned int uid, const QScriptValue& includeItems) const {
void PointerScriptingInterface::setIncludeItems(unsigned int uid, const ScriptValue& includeItems) const {
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
}
unsigned int PointerScriptingInterface::createPointer(const PickQuery::PickType& type, const QVariant& properties) {
unsigned int PointerScriptingInterface::createPointerInternal(const PickQuery::PickType& type, const PointerProperties& properties) {
// Interaction with managers should always happen on the main thread
if (QThread::currentThread() != qApp->thread()) {
unsigned int result;
BLOCKING_INVOKE_METHOD(this, "createPointer", Q_RETURN_ARG(unsigned int, result), Q_ARG(PickQuery::PickType, type), Q_ARG(QVariant, properties));
BLOCKING_INVOKE_METHOD(this, "createPointerInternal", Q_RETURN_ARG(unsigned int, result), Q_ARG(PickQuery::PickType, type), Q_ARG(PointerProperties, properties));
return result;
}
QVariantMap propertyMap = properties.toMap();
QVariantMap propertyMap = properties.properties;
std::shared_ptr<Pointer> pointer;
switch (type) {
case PickQuery::PickType::Ray:
pointer = buildLaserPointer(propertyMap);
pointer = buildLaserPointer(properties);
break;
case PickQuery::PickType::Stylus:
pointer = buildStylus(propertyMap);
pointer = buildStylus(properties);
break;
case PickQuery::PickType::Parabola:
pointer = buildParabolaPointer(propertyMap);
pointer = buildParabolaPointer(properties);
break;
default:
break;
@ -67,6 +80,19 @@ unsigned int PointerScriptingInterface::createPointer(const PickQuery::PickType&
return DependencyManager::get<PointerManager>()->addPointer(pointer);
}
unsigned int PointerScriptingInterface::createRayPointer(RayPointerProperties properties) {
return createPointerInternal(PickQuery::PickType::Ray, properties);
}
unsigned int PointerScriptingInterface::createStylusPointer(StylusPointerProperties properties) {
return createPointerInternal(PickQuery::PickType::Stylus, properties);
}
unsigned int PointerScriptingInterface::createParabolaPointer(ParabolaPointerProperties properties) {
return createPointerInternal(PickQuery::PickType::Parabola, properties);
}
bool PointerScriptingInterface::isPointerEnabled(unsigned int uid) const {
return DependencyManager::get<PointerManager>()->isPointerEnabled(uid);
}
@ -105,8 +131,8 @@ QVariantMap PointerScriptingInterface::getPointerScriptParameters(unsigned int u
* offset.
* @property {Quat} [rotationOffset] - The rotation offset of the model from the hand, to override the default rotation offset.
*/
std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const QVariant& properties) {
QVariantMap propertyMap = properties.toMap();
std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const PointerProperties& properties) {
QVariantMap propertyMap = properties.properties;
bool hover = false;
if (propertyMap["hover"].isValid()) {
@ -138,7 +164,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const QVariant&
}
}
return std::make_shared<StylusPointer>(properties, StylusPointer::buildStylus(propertyMap), hover, enabled, modelPositionOffset, modelRotationOffset, modelDimensions);
return std::make_shared<StylusPointer>(properties.properties, StylusPointer::buildStylus(propertyMap), hover, enabled, modelPositionOffset, modelRotationOffset, modelDimensions);
}
/*@jsdoc
@ -217,8 +243,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const QVariant&
* {@link Pointers.getPointerProperties}.
* @see {@link Picks.RayPickProperties} for additional properties from the underlying ray pick.
*/
std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVariant& properties) {
QVariantMap propertyMap = properties.toMap();
std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const PointerProperties& properties) {
QVariantMap propertyMap = properties.properties;
#if defined (Q_OS_ANDROID)
QString jointName { "" };
@ -280,7 +306,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString();
renderStates[name] = LaserPointer::buildRenderState(renderStateMap);
renderStates[name] = LaserPointer::buildRenderState(renderStateMap, properties.entityProperties);
}
}
}
@ -295,7 +321,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString();
float distance = renderStateMap["distance"].toFloat();
defaultRenderStates[name] = std::pair<float, std::shared_ptr<StartEndRenderState>>(distance, LaserPointer::buildRenderState(renderStateMap));
defaultRenderStates[name] = std::pair<float, std::shared_ptr<StartEndRenderState>>(distance,
LaserPointer::buildRenderState(renderStateMap, properties.entityProperties));
}
}
}
@ -324,7 +351,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
}
}
return std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
return std::make_shared<LaserPointer>(properties.properties, renderStates, defaultRenderStates, hover, triggers,
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
distanceScaleEnd, scaleWithParent, enabled);
}
@ -412,8 +439,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
* {@link Pointers.getPointerProperties}.
* @see {@link Picks.ParabolaPickProperties} for additional properties from the underlying parabola pick.
*/
std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const QVariant& properties) {
QVariantMap propertyMap = properties.toMap();
std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const PointerProperties& properties) {
QVariantMap propertyMap = properties.properties;
bool faceAvatar = false;
if (propertyMap["faceAvatar"].isValid()) {
@ -464,7 +491,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const Q
QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString();
renderStates[name] = ParabolaPointer::buildRenderState(renderStateMap);
renderStates[name] = ParabolaPointer::buildRenderState(renderStateMap, properties.entityProperties);
}
}
}
@ -479,7 +506,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const Q
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString();
float distance = renderStateMap["distance"].toFloat();
defaultRenderStates[name] = std::pair<float, std::shared_ptr<StartEndRenderState>>(distance, ParabolaPointer::buildRenderState(renderStateMap));
defaultRenderStates[name] = std::pair<float, std::shared_ptr<StartEndRenderState>>(distance,
ParabolaPointer::buildRenderState(renderStateMap, properties.entityProperties));
}
}
}
@ -508,12 +536,13 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const Q
}
}
return std::make_shared<ParabolaPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
return std::make_shared<ParabolaPointer>(properties.properties, renderStates, defaultRenderStates, hover, triggers,
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
scaleWithParent, enabled);
}
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
//V8TODO: this needs testing
QVariantMap propMap = properties.toMap();
QVariant startProps;
@ -542,3 +571,166 @@ QVariantMap PointerScriptingInterface::getPrevPickResult(unsigned int uid) const
}
return result;
}
ScriptValue rayPointerPropertiesToScriptValue(ScriptEngine* engine, const RayPointerProperties& in) {
return engine->newVariant(QVariant(in.properties));
}
bool rayPointerPropertiesFromScriptValue(const ScriptValue& value, RayPointerProperties& out) {
// This copies properties from script value, but also converts entity properties of entities used in render states
// from JS objects into EntityItemProperties
out.properties = value.engine()->fromScriptValue<QVariantMap>(value);
QList<QString> renderStatesNames;
renderStatesNames.append("renderStates");
renderStatesNames.append("defaultRenderStates");
for (auto renderStatesName = renderStatesNames.cbegin(); renderStatesName!=renderStatesNames.cend(); renderStatesName++) {
if (out.properties[*renderStatesName].canConvert<QVariantList>()) {
QVariantList renderStates = out.properties[*renderStatesName].value<QVariantList>();
for (int i = 0; i < renderStates.length(); i++) {
if (renderStates[i].canConvert<QVariantMap>()) {
QVariantMap stateMap = renderStates[i].value<QVariantMap>();
if (stateMap["name"].canConvert<QString>()) {
stateMap["name"].value<QString>();
}
if (stateMap["start"].isValid()) {
ScriptValue start = value.property(*renderStatesName).property(i).property("start");
EntityItemProperties startProperties;
startProperties.copyFromScriptValue(start, false);
stateMap.insert("startPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(startProperties);
}
if (stateMap["path"].isValid()) {
ScriptValue path = value.property(*renderStatesName).property(i).property("path");
EntityItemProperties pathProperties;
pathProperties.copyFromScriptValue(path, false);
stateMap.insert("pathPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(pathProperties);
}
if (stateMap["end"].isValid()) {
ScriptValue end = value.property(*renderStatesName).property(i).property("end");
EntityItemProperties endProperties;
endProperties.copyFromScriptValue(end, false);
stateMap.insert("endPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(endProperties);
}
// V8TODO: Check if path is a polyline and if values are valid
renderStates[i].setValue(stateMap);
}
}
out.properties[*renderStatesName].setValue(renderStates);
}
}
qDebug() << "rayPointerPropertiesFromScriptValue" << out.properties;
return true;
}
ScriptValue stylusPointerPropertiesToScriptValue(ScriptEngine* engine, const StylusPointerProperties& in) {
return engine->newVariant(QVariant(in.properties));
}
bool stylusPointerPropertiesFromScriptValue(const ScriptValue& value, StylusPointerProperties& out) {
// This copies properties from script value, but also converts entity properties of entities used in render states
// from JS objects into EntityItemProperties
out.properties = value.engine()->fromScriptValue<QVariantMap>(value);
QList<QString> renderStatesNames;
renderStatesNames.append("renderStates");
renderStatesNames.append("defaultRenderStates");
for (auto renderStatesName = renderStatesNames.cbegin(); renderStatesName!=renderStatesNames.cend(); renderStatesName++) {
if (out.properties[*renderStatesName].canConvert<QVariantList>()) {
QVariantList renderStates = out.properties[*renderStatesName].value<QVariantList>();
for (int i = 0; i < renderStates.length(); i++) {
if (renderStates[i].canConvert<QVariantMap>()) {
QVariantMap stateMap = renderStates[i].value<QVariantMap>();
if (stateMap["name"].canConvert<QString>()) {
stateMap["name"].value<QString>();
}
if (stateMap["start"].isValid()) {
ScriptValue start = value.property(*renderStatesName).property(i).property("start");
EntityItemProperties startProperties;
startProperties.copyFromScriptValue(start, false);
stateMap.insert("startPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(startProperties);
}
if (stateMap["path"].isValid()) {
ScriptValue path = value.property(*renderStatesName).property(i).property("path");
EntityItemProperties pathProperties;
pathProperties.copyFromScriptValue(path, false);
stateMap.insert("pathPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(pathProperties);
}
if (stateMap["end"].isValid()) {
ScriptValue end = value.property(*renderStatesName).property(i).property("end");
EntityItemProperties endProperties;
endProperties.copyFromScriptValue(end, false);
stateMap.insert("endPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(endProperties);
}
renderStates[i].setValue(stateMap);
}
}
out.properties[*renderStatesName].setValue(renderStates);
}
}
qDebug() << "stylusPointerPropertiesFromScriptValue" << out.properties;
return true;
}
ScriptValue parabolaPointerPropertiesToScriptValue(ScriptEngine* engine, const ParabolaPointerProperties& in) {
return engine->newVariant(QVariant(in.properties));
}
//V8TODO: adapt render states to what parabola expects
bool parabolaPointerPropertiesFromScriptValue(const ScriptValue& value, ParabolaPointerProperties& out) {
// This copies properties from script value, but also converts entity properties of entities used in render states
// from JS objects into EntityItemProperties
out.properties = value.engine()->fromScriptValue<QVariantMap>(value);
QList<QString> renderStatesNames;
renderStatesNames.append("renderStates");
renderStatesNames.append("defaultRenderStates");
for (auto renderStatesName = renderStatesNames.cbegin(); renderStatesName!=renderStatesNames.cend(); renderStatesName++) {
if (out.properties[*renderStatesName].canConvert<QVariantList>()) {
QVariantList renderStates = out.properties[*renderStatesName].value<QVariantList>();
for (int i = 0; i < renderStates.length(); i++) {
if (renderStates[i].canConvert<QVariantMap>()) {
QVariantMap stateMap = renderStates[i].value<QVariantMap>();
if (stateMap["name"].canConvert<QString>()) {
stateMap["name"].value<QString>();
}
if (stateMap["start"].isValid()) {
ScriptValue start = value.property(*renderStatesName).property(i).property("start");
EntityItemProperties startProperties;
startProperties.copyFromScriptValue(start, false);
stateMap.insert("startPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(startProperties);
}
if (stateMap["path"].isValid()) {
ScriptValue path = value.property(*renderStatesName).property(i).property("path");
EntityItemProperties pathProperties;
pathProperties.copyFromScriptValue(path, false);
stateMap.insert("pathPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(pathProperties);
qDebug() << "parabolaPointerPropertiesFromScriptValue : added path entity";
}
if (stateMap["end"].isValid()) {
ScriptValue end = value.property(*renderStatesName).property(i).property("end");
EntityItemProperties endProperties;
endProperties.copyFromScriptValue(end, false);
stateMap.insert("endPropertyIndex", QVariant(out.entityProperties.length()));
out.entityProperties.append(endProperties);
qDebug() << "parabolaPointerPropertiesFromScriptValue : added end entity";
}
renderStates[i].setValue(stateMap);
}
}
out.properties[*renderStatesName].setValue(renderStates);
}
}
qDebug() << "parabolaPointerPropertiesFromScriptValue" << out.properties;
return true;
}

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman 10/20/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_PointerScriptingInterface_h
#define hifi_PointerScriptingInterface_h
@ -12,12 +14,15 @@
#include "DependencyManager.h"
#include "RegisteredMetaTypes.h"
#include <EntityItemProperties.h>
#include <PointerManager.h>
#include <Pick.h>
class ScriptValue;
/*@jsdoc
* The <code>Pointers</code> API lets you create, manage, and visually represent objects for repeatedly calculating
* intersections with avatars, entities, and overlays. Pointers can also be configured to generate events on entities and
* The <code>Pointers</code> API lets you create, manage, and visually represent objects for repeatedly calculating
* intersections with avatars, entities, and overlays. Pointers can also be configured to generate events on entities and
* overlays intersected.
*
* @namespace Pointers
@ -27,12 +32,36 @@
* @hifi-avatar
*/
class PointerProperties {
public:
QVariantMap properties;
QList<EntityItemProperties> entityProperties;
};
class RayPointerProperties : public PointerProperties {
};
class ParabolaPointerProperties : public PointerProperties {
};
class StylusPointerProperties : public PointerProperties {
};
Q_DECLARE_METATYPE(RayPointerProperties);
Q_DECLARE_METATYPE(StylusPointerProperties);
Q_DECLARE_METATYPE(ParabolaPointerProperties);
Q_DECLARE_METATYPE(PointerProperties);
class PointerScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
// The purpose of registering different classes is to let the script engine know what data structure it has to
// expect in JS object that will be converted to PointerProperties
/*@jsdoc
* Specifies that a {@link Controller} action or function should trigger events on the entity or overlay currently
* intersected by a {@link Pointers.RayPointerProperties|Ray} or {@link Pointers.ParabolaPointerProperties|Parabola}
@ -129,7 +158,11 @@ public:
* });
*/
// TODO: expand Pointers to be able to be fully configurable with PickFilters
Q_INVOKABLE unsigned int createPointer(const PickQuery::PickType& type, const QVariant& properties);
// V8TODO: add documentation
Q_INVOKABLE unsigned int createRayPointer(RayPointerProperties properties);
Q_INVOKABLE unsigned int createStylusPointer(StylusPointerProperties properties);
Q_INVOKABLE unsigned int createParabolaPointer(ParabolaPointerProperties properties);
/*@jsdoc
* Enables and shows a pointer. Enabled pointers update their pick results and generate events.
@ -365,7 +398,7 @@ public:
* @param {number} id - The ID of the pointer.
* @param {Uuid[]} ignoreItems - A list of IDs to ignore.
*/
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const;
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const ScriptValue& ignoreEntities) const;
/*@jsdoc
* Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with
@ -375,7 +408,7 @@ public:
* @param {number} id - The ID of the pointer.
* @param {Uuid[]} includeItems - A list of IDs to include.
*/
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const;
Q_INVOKABLE void setIncludeItems(unsigned int uid, const ScriptValue& includeEntities) const;
/*@jsdoc
@ -475,9 +508,19 @@ public:
Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const;
protected:
static std::shared_ptr<Pointer> buildLaserPointer(const QVariant& properties);
static std::shared_ptr<Pointer> buildStylus(const QVariant& properties);
static std::shared_ptr<Pointer> buildParabolaPointer(const QVariant& properties);
static std::shared_ptr<Pointer> buildLaserPointer(const PointerProperties& properties);
static std::shared_ptr<Pointer> buildStylus(const PointerProperties& properties);
static std::shared_ptr<Pointer> buildParabolaPointer(const PointerProperties& properties);
private:
Q_INVOKABLE unsigned int createPointerInternal(const PickQuery::PickType& type, const PointerProperties& properties);
};
ScriptValue rayPointerPropertiesToScriptValue(ScriptEngine* engine, const RayPointerProperties& in);
ScriptValue stylusPointerPropertiesToScriptValue(ScriptEngine* engine, const StylusPointerProperties& in);
ScriptValue parabolaPointerPropertiesToScriptValue(ScriptEngine* engine, const ParabolaPointerProperties& in);
bool rayPointerPropertiesFromScriptValue(const ScriptValue& value, RayPointerProperties& out);
bool stylusPointerPropertiesFromScriptValue(const ScriptValue& value, StylusPointerProperties& out);
bool parabolaPointerPropertiesFromScriptValue(const ScriptValue& value, ParabolaPointerProperties& out);
#endif // hifi_PointerScriptingInterface_h

View file

@ -40,7 +40,7 @@ PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
if (getFilter().doesPickLocalEntities()) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_ENTITY_HOST_TYPE;
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
if (DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) {
type = IntersectionType::LOCAL_ENTITY;
}
}
@ -123,6 +123,6 @@ glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::ve
desiredProperties += PROP_ROTATION;
desiredProperties += PROP_DIMENSIONS;
desiredProperties += PROP_REGISTRATION_POINT;
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID, desiredProperties);
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(entityID, desiredProperties);
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized);
}

View file

@ -4,9 +4,11 @@
//
// Created by Sam Gondelman 8/15/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "RayPickScriptingInterface.h"
@ -15,6 +17,7 @@
#include "GLMHelpers.h"
#include <PickManager.h>
#include <ScriptValueUtils.h>
unsigned int RayPickScriptingInterface::createRayPick(const QVariant& properties) {
return DependencyManager::get<PickScriptingInterface>()->createPick(PickQuery::PickType::Ray, properties);
@ -45,11 +48,11 @@ void RayPickScriptingInterface::setPrecisionPicking(unsigned int uid, bool preci
DependencyManager::get<PickManager>()->setPrecisionPicking(uid, precisionPicking);
}
void RayPickScriptingInterface::setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems) {
void RayPickScriptingInterface::setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems) {
DependencyManager::get<PickManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
}
void RayPickScriptingInterface::setIncludeItems(unsigned int uid, const QScriptValue& includeItems) {
void RayPickScriptingInterface::setIncludeItems(unsigned int uid, const ScriptValue& includeItems) {
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
}

View file

@ -4,9 +4,11 @@
//
// Created by Sam Gondelman 8/15/2017
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_RayPickScriptingInterface_h
#define hifi_RayPickScriptingInterface_h
@ -18,6 +20,8 @@
#include "PickScriptingInterface.h"
class ScriptValue;
/*@jsdoc
* The <code>RayPick</code> API is a subset of the {@link Picks} API, as used for ray picks.
*
@ -47,20 +51,20 @@
*/
class RayPickScriptingInterface : public QObject, public Dependency {
Q_OBJECT
Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT)
Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT)
Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT)
Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT)
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT)
Q_PROPERTY(unsigned int PICK_ENTITIES READ getPickEntities CONSTANT)
Q_PROPERTY(unsigned int PICK_OVERLAYS READ getPickOverlays CONSTANT)
Q_PROPERTY(unsigned int PICK_AVATARS READ getPickAvatars CONSTANT)
Q_PROPERTY(unsigned int PICK_HUD READ getPickHud CONSTANT)
Q_PROPERTY(unsigned int PICK_COARSE READ getPickCoarse CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ getPickIncludeInvisible CONSTANT)
Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ getPickIncludeNoncollidable CONSTANT)
Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ getPickAllIntersections CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_NONE READ getIntersectedNone CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ getIntersectedEntity CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ getIntersectedLocalEntity CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ getIntersectedOverlay CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ getIntersectedAvatar CONSTANT)
Q_PROPERTY(unsigned int INTERSECTED_HUD READ getIntersectedHud CONSTANT)
SINGLETON_DEPENDENCY
public:
@ -121,7 +125,7 @@ public:
* @param {number} id - The ID of the ray pick.
* @param {Uuid[]} ignoreItems - The list of IDs to ignore.
*/
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities);
Q_INVOKABLE void setIgnoreItems(unsigned int uid, const ScriptValue& ignoreEntities);
/*@jsdoc
* Sets a list of entity and avatar IDs that a ray pick should include during intersection, instead of intersecting with
@ -130,7 +134,7 @@ public:
* @param {number} id - The ID of the ray pick.
* @param {Uuid[]} includeItems - The list of IDs to include.
*/
Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities);
Q_INVOKABLE void setIncludeItems(unsigned int uid, const ScriptValue& includeEntities);
/*@jsdoc
@ -169,35 +173,35 @@ public slots:
* @deprecated This function is deprecated and will be removed. Use the <code>Raypick.PICK_ENTITIES</code> property instead.
* @returns {number}
*/
static unsigned int PICK_ENTITIES() { return PickScriptingInterface::PICK_ENTITIES(); }
static unsigned int getPickEntities() { return PickScriptingInterface::getPickEntities(); }
/*@jsdoc
* @function RayPick.PICK_OVERLAYS
* @deprecated This function is deprecated and will be removed. Use the <code>RayPick.PICK_OVERLAYS</code> property instead.
* @returns {number}
*/
static unsigned int PICK_OVERLAYS() { return PickScriptingInterface::PICK_OVERLAYS(); }
static unsigned int getPickOverlays() { return PickScriptingInterface::getPickOverlays(); }
/*@jsdoc
* @function RayPick.PICK_AVATARS
* @deprecated This function is deprecated and will be removed. Use the <code>RayPick.PICK_AVATARS</code> property instead.
* @returns {number}
*/
static unsigned int PICK_AVATARS() { return PickScriptingInterface::PICK_AVATARS(); }
static unsigned int getPickAvatars() { return PickScriptingInterface::getPickAvatars(); }
/*@jsdoc
* @function RayPick.PICK_HUD
* @deprecated This function is deprecated and will be removed. Use the <code>RayPick.PICK_HUD</code> property instead.
* @returns {number}
*/
static unsigned int PICK_HUD() { return PickScriptingInterface::PICK_HUD(); }
static unsigned int getPickHud() { return PickScriptingInterface::getPickHud(); }
/*@jsdoc
* @function RayPick.PICK_COARSE
* @deprecated This function is deprecated and will be removed. Use the <code>RayPick.PICK_COARSE</code> property instead.
* @returns {number}
*/
static unsigned int PICK_COARSE() { return PickScriptingInterface::PICK_COARSE(); }
static unsigned int getPickCoarse() { return PickScriptingInterface::getPickCoarse(); }
/*@jsdoc
* @function RayPick.PICK_INCLUDE_INVISIBLE
@ -205,7 +209,7 @@ public slots:
* property instead.
* @returns {number}
*/
static unsigned int PICK_INCLUDE_INVISIBLE() { return PickScriptingInterface::PICK_INCLUDE_INVISIBLE(); }
static unsigned int getPickIncludeInvisible() { return PickScriptingInterface::getPickIncludeInvisible(); }
/*@jsdoc
* @function RayPick.PICK_INCLUDE_NONCOLLIDABLE
@ -213,7 +217,7 @@ public slots:
* property instead.
* @returns {number}
*/
static unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE(); }
static unsigned int getPickIncludeNoncollidable() { return PickScriptingInterface::getPickIncludeNoncollidable(); }
/*@jsdoc
* @function RayPick.PICK_ALL_INTERSECTIONS
@ -221,7 +225,7 @@ public slots:
* property instead.
* @returns {number}
*/
static unsigned int PICK_ALL_INTERSECTIONS() { return PickScriptingInterface::PICK_ALL_INTERSECTIONS(); }
static unsigned int getPickAllIntersections() { return PickScriptingInterface::getPickAllIntersections(); }
/*@jsdoc
* @function RayPick.INTERSECTED_NONE
@ -229,7 +233,7 @@ public slots:
* instead.
* @returns {number}
*/
static unsigned int INTERSECTED_NONE() { return PickScriptingInterface::INTERSECTED_NONE(); }
static unsigned int getIntersectedNone() { return PickScriptingInterface::getIntersectedNone(); }
/*@jsdoc
* @function RayPick.INTERSECTED_ENTITY
@ -237,7 +241,7 @@ public slots:
* instead.
* @returns {number}
*/
static unsigned int INTERSECTED_ENTITY() { return PickScriptingInterface::INTERSECTED_ENTITY(); }
static unsigned int getIntersectedEntity() { return PickScriptingInterface::getIntersectedEntity(); }
/*@jsdoc
* @function RayPick.INTERSECTED_OVERLAY
@ -245,7 +249,7 @@ public slots:
* property instead.
* @returns {number}
*/
static unsigned int INTERSECTED_LOCAL_ENTITY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); }
static unsigned int getIntersectedLocalEntity() { return PickScriptingInterface::getIntersectedLocalEntity(); }
/*@jsdoc
* @function RayPick.INTERSECTED_OVERLAY
@ -253,7 +257,7 @@ public slots:
* instead.
* @returns {number}
*/
static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); }
static unsigned int getIntersectedOverlay() { return PickScriptingInterface::getIntersectedOverlay(); }
/*@jsdoc
* @function RayPick.INTERSECTED_AVATAR
@ -261,7 +265,7 @@ public slots:
* instead.
* @returns {number}
*/
static unsigned int INTERSECTED_AVATAR() { return PickScriptingInterface::INTERSECTED_AVATAR(); }
static unsigned int getIntersectedAvatar() { return PickScriptingInterface::getIntersectedAvatar(); }
/*@jsdoc
* @function RayPick.INTERSECTED_HUD
@ -269,7 +273,7 @@ public slots:
* instead.
* @returns {number}
*/
static unsigned int INTERSECTED_HUD() { return PickScriptingInterface::INTERSECTED_HUD(); }
static unsigned int getIntersectedHud() { return PickScriptingInterface::getIntersectedHud(); }
};
#endif // hifi_RayPickScriptingInterface_h

View file

@ -49,7 +49,7 @@ PickQuery::PickType StylusPointer::getType() const {
QUuid StylusPointer::buildStylus(const QVariantMap& properties) {
// FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
QVariantMap propertiesMap;
/*QVariantMap propertiesMap;
QString modelUrl = DEFAULT_STYLUS_MODEL_URL;
@ -69,7 +69,26 @@ QUuid StylusPointer::buildStylus(const QVariantMap& properties) {
propertiesMap["ignorePickIntersection"] = true;
propertiesMap["drawInFront"] = false;
return qApp->getOverlays().addOverlay("model", propertiesMap);
return qApp->getOverlays().addOverlay("model", propertiesMap);*/
EntityItemProperties entityProperties;
QString modelURL = DEFAULT_STYLUS_MODEL_URL;
if (properties["model"].isValid()) {
QVariantMap modelData = properties["model"].toMap();
if (modelData["url"].isValid()) {
modelURL = modelData["url"].toString();
}
}
// TODO: make these configurable per pointer
entityProperties.setType(EntityTypes::Model);
entityProperties.setName("stylus");
entityProperties.setModelURL(modelURL);
entityProperties.setPrimitiveMode(PrimitiveMode::SOLID);
entityProperties.setVisible(true);
entityProperties.setIgnorePickIntersection(true);
return DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties, entity::HostType::LOCAL);
}
void StylusPointer::updateVisuals(const PickResultPointer& pickResult) {

View file

@ -4,18 +4,28 @@
//
// Created by Thijs Wenker on 9/10/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AccountServicesScriptingInterface.h"
#include <ScriptEngineCast.h>
#include "AccountManager.h"
#include "Application.h"
#include "DiscoverabilityManager.h"
#include "ResourceCache.h"
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<DownloadInfoResult, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue>(scriptEngine);
}));
AccountServicesScriptingInterface::AccountServicesScriptingInterface() {
auto accountManager = DependencyManager::get<AccountManager>();
connect(accountManager.data(), &AccountManager::usernameChanged, this, &AccountServicesScriptingInterface::onUsernameChanged);
@ -123,10 +133,10 @@ DownloadInfoResult::DownloadInfoResult() :
* @property {number[]} downloading - The download percentage remaining of each asset currently downloading.
* @property {number} pending - The number of assets pending download.
*/
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result) {
QScriptValue object = engine->newObject();
ScriptValue DownloadInfoResultToScriptValue(ScriptEngine* engine, const DownloadInfoResult& result) {
ScriptValue object = engine->newObject();
QScriptValue array = engine->newArray(result.downloading.count());
ScriptValue array = engine->newArray(result.downloading.count());
for (int i = 0; i < result.downloading.count(); i += 1) {
array.setProperty(i, result.downloading[i]);
}
@ -136,7 +146,7 @@ QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const Downlo
return object;
}
void DownloadInfoResultFromScriptValue(const QScriptValue& 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 +154,7 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR
}
result.pending = object.property("pending").toVariant().toFloat();
return true;
}
DownloadInfoResult AccountServicesScriptingInterface::getDownloadInfo() {

View file

@ -4,23 +4,25 @@
//
// Created by Thijs Wenker on 9/10/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AccountServicesScriptingInterface_h
#define hifi_AccountServicesScriptingInterface_h
#include <QObject>
#include <QScriptContext>
#include <QScriptEngine>
#include <QScriptValue>
#include <QString>
#include <QStringList>
#include <AccountManager.h>
#include <DiscoverabilityManager.h>
#include <ScriptValue.h>
class ScriptEngine;
class DownloadInfoResult {
public:
@ -31,8 +33,8 @@ public:
Q_DECLARE_METATYPE(DownloadInfoResult)
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result);
void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoResult& result);
ScriptValue DownloadInfoResultToScriptValue(ScriptEngine* engine, const DownloadInfoResult& result);
bool DownloadInfoResultFromScriptValue(const ScriptValue& object, DownloadInfoResult& result);
class AccountServicesScriptingInterface : public QObject {
Q_OBJECT

View file

@ -4,14 +4,15 @@
//
// Created by Ryan Huffman on 2016-03-09.
// Copyright 2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AssetMappingsScriptingInterface.h"
#include <QtScript/QScriptEngine>
#include <QtCore/QFile>
#include <QtCore/QThread>

View file

@ -4,9 +4,11 @@
//
// Created by Ryan Huffman on 2016-03-09.
// Copyright 2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
@ -15,14 +17,12 @@
#define hifi_AssetMappingsScriptingInterface_h
#include <QtCore/QObject>
#include <QtScript/QScriptValue>
#include <AssetClient.h>
#include <QSortFilterProxyModel>
#include "DependencyManager.h"
class AssetMappingModel : public QStandardItemModel {
Q_OBJECT
Q_PROPERTY(bool autoRefreshEnabled READ isAutoRefreshEnabled WRITE setAutoRefreshEnabled)

View file

@ -508,9 +508,9 @@ void Audio::setReverb(bool enable) {
});
}
void Audio::setReverbOptions(const AudioEffectOptions* options) {
void Audio::setReverbOptions(const AudioEffectOptions options) {
withWriteLock([&] {
DependencyManager::get<AudioClient>()->setReverbOptions(options);
DependencyManager::get<AudioClient>()->setReverbOptions(&options);
});
}

View file

@ -215,7 +215,7 @@ public:
* @function Audio.setReverbOptions
* @param {AudioEffectOptions} options - The reverberation options.
*/
Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options);
Q_INVOKABLE void setReverbOptions(const AudioEffectOptions options);
/*@jsdoc
* Sets the gain (relative volume) that avatars' voices are played at. This gain is used at the server.

View file

@ -7,6 +7,7 @@
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "DesktopScriptingInterface.h"

View file

@ -4,16 +4,17 @@
//
// Created by David Rowe on 25 Aug 2015.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_DesktopScriptingInterface_h
#define hifi_DesktopScriptingInterface_h
#include <QObject>
#include <QtScript/QScriptValue>
#include <DependencyManager.h>
@ -46,6 +47,7 @@
* {@link InteractiveWindow}: none, top left, top right, bottom right, or bottom left of the Interface window.
* <em>Read-only.</em>
*/
class DesktopScriptingInterface : public QObject, public Dependency {
Q_OBJECT
Q_PROPERTY(int width READ getWidth) // Physical width of screen(s) including task bars and system menus

View file

@ -4,21 +4,24 @@
//
// Created by Thijs Wenker on 1/12/15.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "HMDScriptingInterface.h"
#include <QtScript/QScriptContext>
#include <shared/QtHelpers.h>
#include <avatar/AvatarManager.h>
#include <display-plugins/DisplayPlugin.h>
#include <display-plugins/CompositorHelper.h>
#include <OffscreenUi.h>
#include <plugins/PluginUtils.h>
#include <ScriptContext.h>
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include <QUuid>
#include "Application.h"
@ -151,23 +154,23 @@ bool HMDScriptingInterface::getAwayStateWhenFocusLostInVREnabled() {
}
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
ScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(ScriptContext* context, ScriptEngine* engine) {
glm::vec3 hudIntersection;
auto instance = DependencyManager::get<HMDScriptingInterface>();
if (instance->getHUDLookAtPosition3D(hudIntersection)) {
glm::vec2 overlayPos = qApp->getApplicationCompositor().overlayFromSphereSurface(hudIntersection);
return qScriptValueFromValue<glm::vec2>(engine, overlayPos);
return scriptValueFromValue<glm::vec2>(engine, overlayPos);
}
return QScriptValue::NullValue;
return engine->nullValue();
}
QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) {
ScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(ScriptContext* context, ScriptEngine* engine) {
glm::vec3 result;
auto instance = DependencyManager::get<HMDScriptingInterface>();
if (instance->getHUDLookAtPosition3D(result)) {
return qScriptValueFromValue<glm::vec3>(engine, result);
return scriptValueFromValue<glm::vec3>(engine, result);
}
return QScriptValue::NullValue;
return engine->nullValue();
}
bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {

View file

@ -4,9 +4,11 @@
//
// Created by Thijs Wenker on 1/12/15.
// Copyright 2015 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_HMDScriptingInterface_h
@ -14,15 +16,15 @@
#include <atomic>
#include <QtScript/QScriptValue>
class QScriptContext;
class QScriptEngine;
#include <GLMHelpers.h>
#include <DependencyManager.h>
#include <display-plugins/AbstractHMDScriptingInterface.h>
#include <QReadWriteLock>
#include <ScriptValue.h>
class ScriptContext;
class ScriptEngine;
/*@jsdoc
* The <code>HMD</code> API provides access to the HMD used in VR display mode.
@ -442,14 +444,14 @@ public:
* @function HMD.getHUDLookAtPosition2D
* @returns {Vec2} The position on the HUD overlay that your HMD is looking at, in pixels.
*/
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
static ScriptValue getHUDLookAtPosition2D(ScriptContext* context, ScriptEngine* engine);
/*@jsdoc
* Gets the position on the HUD overlay that your HMD is looking at, in world coordinates.
* @function HMD.getHUDLookAtPosition3D
* @returns {Vec3} The position on the HUD overlay the your HMD is looking at, in world coordinates.
*/
static QScriptValue getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine);
static ScriptValue getHUDLookAtPosition3D(ScriptContext* context, ScriptEngine* engine);
bool isMounted() const override;

View file

@ -1,16 +1,34 @@
//
// Created by Bradley Austin Davis on 2019/05/14
// Copyright 2013-2019 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PerformanceScriptingInterface.h"
#include <ScriptEngineCast.h>
#include "../Application.h"
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<PerformanceScriptingInterface::PerformancePreset, scriptValueFromEnumClass<PerformanceScriptingInterface::PerformancePreset>, scriptValueToEnumClass<PerformanceScriptingInterface::PerformancePreset> >(scriptEngine, "PerformancePreset");
scriptRegisterMetaType<PerformanceScriptingInterface::RefreshRateProfile, scriptValueFromEnumClass<PerformanceScriptingInterface::RefreshRateProfile>, scriptValueToEnumClass<PerformanceScriptingInterface::RefreshRateProfile> >(scriptEngine, "RefreshRateProfile");
}));
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptEngine->registerEnum("Performance.PerformancePreset",QMetaEnum::fromType<PerformanceScriptingInterface::PerformancePreset>());
scriptEngine->registerEnum("Performance.RefreshRateProfile",QMetaEnum::fromType<PerformanceScriptingInterface::RefreshRateProfile>());
});
std::once_flag PerformanceScriptingInterface::registry_flag;
PerformanceScriptingInterface::PerformanceScriptingInterface() {

View file

@ -1,9 +1,11 @@
//
// Created by Bradley Austin Davis on 2019/05/14
// Copyright 2013-2019 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
@ -55,7 +57,7 @@ public:
* @typedef {number} Performance.PerformancePreset
*/
// PerformanceManager PerformancePreset tri state level enums
enum PerformancePreset {
enum class PerformancePreset {
UNKNOWN = PerformanceManager::PerformancePreset::UNKNOWN,
LOW_POWER = PerformanceManager::PerformancePreset::LOW_POWER,
LOW = PerformanceManager::PerformancePreset::LOW,
@ -82,7 +84,7 @@ public:
* @typedef {number} Performance.RefreshRateProfile
*/
// Must match RefreshRateManager enums
enum RefreshRateProfile {
enum class RefreshRateProfile {
ECO = RefreshRateManager::RefreshRateProfile::ECO,
INTERACTIVE = RefreshRateManager::RefreshRateProfile::INTERACTIVE,
REALTIME = RefreshRateManager::RefreshRateProfile::REALTIME,

View file

@ -1,9 +1,11 @@
//
// Created by Nissim Hadar on 2018/12/28
// Copyright 2013-2016 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "PlatformInfoScriptingInterface.h"
#include "Application.h"
@ -12,6 +14,7 @@
#include <platform/Platform.h>
#include <platform/Profiler.h>
#include <ScriptEngineCast.h>
#ifdef Q_OS_WIN
#include <Windows.h>
@ -19,6 +22,18 @@
#include <sstream>
#endif
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<PlatformInfoScriptingInterface::PlatformTier, scriptValueFromEnumClass<PlatformInfoScriptingInterface::PlatformTier>, scriptValueToEnumClass<PlatformInfoScriptingInterface::PlatformTier> >(scriptEngine, "PlatformTier");
}));
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptEngine->registerEnum("PlatformInfo.PlatformTier",QMetaEnum::fromType<PlatformInfoScriptingInterface::PlatformTier>());
});
PlatformInfoScriptingInterface* PlatformInfoScriptingInterface::getInstance() {
static PlatformInfoScriptingInterface sharedInstance;
return &sharedInstance;

View file

@ -1,9 +1,11 @@
//
// Created by Nissim Hadar on 2018/12/28
// Copyright 2013-2016 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_PlatformInfoScriptingInterface_h
@ -12,8 +14,6 @@
#include <platform/Profiler.h>
#include <QtCore/QObject>
class QScriptValue;
/*@jsdoc
* The <code>PlatformInfo</code> API provides information about the hardware platform being used.
*
@ -26,8 +26,12 @@ class QScriptValue;
class PlatformInfoScriptingInterface : public QObject {
Q_OBJECT
private:
static PlatformInfoScriptingInterface* getInstance();
friend class Application;
public:
PlatformInfoScriptingInterface();
virtual ~PlatformInfoScriptingInterface();
@ -47,7 +51,7 @@ public:
* @typedef {number} PlatformInfo.PlatformTier
*/
// Platform tier enum type
enum PlatformTier {
enum class PlatformTier {
UNKNOWN = platform::Profiler::Tier::UNKNOWN,
LOW = platform::Profiler::Tier::LOW,
MID = platform::Profiler::Tier::MID,
@ -56,11 +60,10 @@ public:
Q_ENUM(PlatformTier);
public slots:
/*@jsdoc
/*
* @function PlatformInfo.getInstance
* @deprecated This function is deprecated and will be removed.
*/
static PlatformInfoScriptingInterface* getInstance();
/*@jsdoc
* Gets the operating system type.

View file

@ -1,16 +1,33 @@
//
// Created by Sam Gondelman on 5/16/19
// Copyright 2013-2019 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "RenderScriptingInterface.h"
#include <ScriptEngineCast.h>
#include "LightingModel.h"
#include <QScreen>
#include "ScreenName.h"
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<RenderScriptingInterface::RenderMethod, scriptValueFromEnumClass<RenderScriptingInterface::RenderMethod>, scriptValueToEnumClass<RenderScriptingInterface::RenderMethod> >(scriptEngine, "RenderMethod");
scriptRegisterMetaType<AntialiasingConfig::Mode, scriptValueFromEnumClass<AntialiasingConfig::Mode>, scriptValueToEnumClass<AntialiasingConfig::Mode> >(scriptEngine, "Mode");
}));
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
scriptEngine->registerEnum("Render.RenderMethod",QMetaEnum::fromType<RenderScriptingInterface::RenderMethod>());
scriptEngine->registerEnum("AntialiasingMode",QMetaEnum::fromType<AntialiasingConfig::Mode>());
});
RenderScriptingInterface* RenderScriptingInterface::getInstance() {
static RenderScriptingInterface sharedInstance;

View file

@ -1,9 +1,11 @@
//
// Created by Sam Gondelman on 5/16/19
// Copyright 2013-2019 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_RenderScriptingInterface_h
@ -148,14 +150,14 @@ public slots:
/*@jsdoc
* Gets the active anti-aliasing mode.
* @function Render.getAntialiasingMode
* @returns {integer} the active anti-aliasing mode.
* @returns {AntialiasingMode} The active anti-aliasing mode.
*/
AntialiasingConfig::Mode getAntialiasingMode() const;
/*@jsdoc
* Sets the active anti-aliasing mode.
* @function Render.setAntialiasingMode
* @param {integer} the active anti-aliasing mode.
* @param {AntialiasingMode} The active anti-aliasing mode.
*/
void setAntialiasingMode(AntialiasingConfig::Mode mode);

View file

@ -4,10 +4,11 @@
//
// Created by Brad Hefta-Gaub on 2/25/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2022 Overte e.V.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "SettingsScriptingInterface.h"
@ -48,7 +49,7 @@ void SettingsScriptingInterface::setValue(const QString& setting, const QVariant
}
}
// Make a deep-copy of the string.
// Dangling pointers can occur with QStrings that are implicitly shared from a QScriptEngine.
// Dangling pointers can occur with QStrings that are implicitly shared from a ScriptEngine.
QString deepCopy = QString::fromUtf16(setting.utf16());
Setting::Handle<QVariant>(deepCopy).set(value);
emit valueChanged(setting, value);

View file

@ -1,9 +1,11 @@
//
// Created by Bradley Austin Davis on 2016/12/12
// Copyright 2013-2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "TestScriptingInterface.h"
@ -16,6 +18,7 @@
#include <DependencyManager.h>
#include <MainWindow.h>
#include <OffscreenUi.h>
#include <ScriptValue.h>
#include <StatTracker.h>
#include <Trace.h>
@ -153,7 +156,7 @@ void TestScriptingInterface::savePhysicsSimulationStats(QString originalPath) {
qApp->saveNextPhysicsStats(path);
}
void TestScriptingInterface::profileRange(const QString& name, QScriptValue fn) {
void TestScriptingInterface::profileRange(const QString& name, const ScriptValue& fn) {
PROFILE_RANGE(script, name);
fn.call();
}

View file

@ -1,9 +1,11 @@
//
// Created by Bradley Austin Davis on 2016/12/12
// Copyright 2013-2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
@ -12,8 +14,7 @@
#include <functional>
#include <QtCore/QObject>
class QScriptValue;
#include <ScriptValue.h>
class TestScriptingInterface : public QObject {
Q_OBJECT
@ -127,7 +128,7 @@ public slots:
* @param {string} name - Name used to reference the function
* @param {function} function - Function to profile
*/
Q_INVOKABLE void profileRange(const QString& name, QScriptValue function);
Q_INVOKABLE void profileRange(const QString& name, const ScriptValue& function);
/*@jsdoc
* Clear all caches (menu command Reload Content)

View file

@ -34,7 +34,7 @@ void WalletScriptingInterface::setWalletStatus(const uint& status) {
void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUuid& entityID) {
QSharedPointer<ContextOverlayInterface> contextOverlayInterface = DependencyManager::get<ContextOverlayInterface>();
EntityItemProperties entityProperties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID,
EntityItemProperties entityProperties = DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(entityID,
contextOverlayInterface->getEntityPropertyFlags());
if (entityProperties.getEntityHostType() == entity::HostType::AVATAR) {
if (!entityID.isNull() && entityProperties.getCertificateID().length() > 0) {

View file

@ -4,9 +4,11 @@
//
// Created by Ryan Huffman on 4/29/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "WindowScriptingInterface.h"
@ -14,7 +16,7 @@
#include <QClipboard>
#include <QtCore/QDir>
#include <QMessageBox>
#include <QScriptValue>
#include <ScriptValue.h>
#include <QtGui/QDesktopServices>
#include <shared/QtHelpers.h>
#include <SettingHandle.h>
@ -76,8 +78,9 @@ WindowScriptingInterface::~WindowScriptingInterface() {
_messageBoxes.clear();
}
QScriptValue WindowScriptingInterface::hasFocus() {
return qApp->hasFocus();
ScriptValue WindowScriptingInterface::hasFocus() {
Q_ASSERT(engine);
return engine()->newValue(qApp->hasFocus());
}
void WindowScriptingInterface::setFocus() {
@ -96,28 +99,31 @@ void WindowScriptingInterface::raise() {
/// Display an alert box
/// \param const QString& message message to display
/// \return QScriptValue::UndefinedValue
/// \return ScriptValue::UndefinedValue
void WindowScriptingInterface::alert(const QString& message) {
OffscreenUi::asyncWarning("", message, QMessageBox::Ok, QMessageBox::Ok);
}
/// Display a confirmation box with the options 'Yes' and 'No'
/// \param const QString& message message to display
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
QScriptValue WindowScriptingInterface::confirm(const QString& message) {
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)));
/// \return ScriptValue `true` if 'Yes' was clicked, `false` otherwise
ScriptValue WindowScriptingInterface::confirm(const QString& message) {
Q_ASSERT(engine);
return engine()->newValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)));
}
/// Display a prompt with a text box
/// \param const QString& message message to display
/// \param const QString& defaultText default text in the text box
/// \return QScriptValue string text value in text box if the dialog was accepted, `null` otherwise.
QScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) {
/// \return ScriptValue string text value in text box if the dialog was accepted, `null` otherwise.
ScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) {
QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText);
if (QScriptValue(result).equals("")) {
return QScriptValue::NullValue;
Q_ASSERT(engine);
auto sResult = engine()->newValue(result);
if (sResult.equals(engine()->newValue(""))) {
return engine()->nullValue();
}
return QScriptValue(result);
return sResult;
}
/// Display a prompt with a text box
@ -217,8 +223,8 @@ void WindowScriptingInterface::ensureReticleVisible() const {
/// working directory.
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the directory browser at
/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue`
QScriptValue WindowScriptingInterface::browseDir(const QString& title, const QString& directory) {
/// \return ScriptValue file path as a string if one was selected, otherwise `ScriptValue::NullValue`
ScriptValue WindowScriptingInterface::browseDir(const QString& title, const QString& directory) {
ensureReticleVisible();
QString path = directory;
if (path.isEmpty()) {
@ -231,7 +237,8 @@ QScriptValue WindowScriptingInterface::browseDir(const QString& title, const QSt
if (!result.isEmpty()) {
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
}
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
Q_ASSERT(engine);
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
}
/// Display a "browse to directory" dialog. If `directory` is an invalid file or directory the browser will start at the current
@ -261,8 +268,8 @@ void WindowScriptingInterface::browseDirAsync(const QString& title, const QStrin
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the file browser at
/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue`
QScriptValue WindowScriptingInterface::browse(const QString& title, const QString& directory, const QString& nameFilter) {
/// \return ScriptValue file path as a string if one was selected, otherwise `ScriptValue::NullValue`
ScriptValue WindowScriptingInterface::browse(const QString& title, const QString& directory, const QString& nameFilter) {
ensureReticleVisible();
QString path = directory;
if (path.isEmpty()) {
@ -275,7 +282,8 @@ QScriptValue WindowScriptingInterface::browse(const QString& title, const QStrin
if (!result.isEmpty()) {
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
}
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
Q_ASSERT(engine);
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
}
/// Display an open file dialog. If `directory` is an invalid file or directory the browser will start at the current
@ -308,8 +316,8 @@ void WindowScriptingInterface::browseAsync(const QString& title, const QString&
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the file browser at
/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
/// \return QScriptValue file path as a string if one was selected, otherwise `QScriptValue::NullValue`
QScriptValue WindowScriptingInterface::save(const QString& title, const QString& directory, const QString& nameFilter) {
/// \return ScriptValue file path as a string if one was selected, otherwise `ScriptValue::NullValue`
ScriptValue WindowScriptingInterface::save(const QString& title, const QString& directory, const QString& nameFilter) {
ensureReticleVisible();
QString path = directory;
if (path.isEmpty()) {
@ -322,7 +330,8 @@ QScriptValue WindowScriptingInterface::save(const QString& title, const QString&
if (!result.isEmpty()) {
setPreviousBrowseLocation(QFileInfo(result).absolutePath());
}
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
Q_ASSERT(engine);
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
}
/// Display a save file dialog. If `directory` is an invalid file or directory the browser will start at the current
@ -355,8 +364,8 @@ void WindowScriptingInterface::saveAsync(const QString& title, const QString& di
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the asset browser at
/// \param const QString& nameFilter filter to filter asset names by - see `QFileDialog`
/// \return QScriptValue asset path as a string if one was selected, otherwise `QScriptValue::NullValue`
QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const QString& directory, const QString& nameFilter) {
/// \return ScriptValue asset path as a string if one was selected, otherwise `ScriptValue::NullValue`
ScriptValue WindowScriptingInterface::browseAssets(const QString& title, const QString& directory, const QString& nameFilter) {
ensureReticleVisible();
QString path = directory;
if (path.isEmpty()) {
@ -372,7 +381,8 @@ QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const
if (!result.isEmpty()) {
setPreviousBrowseAssetLocation(QFileInfo(result).absolutePath());
}
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
Q_ASSERT(engine);
return result.isEmpty() ? engine()->nullValue() : engine()->newValue(result);
}
/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
@ -603,6 +613,7 @@ void WindowScriptingInterface::closeMessageBox(int id) {
void WindowScriptingInterface::onMessageBoxSelected(int button) {
auto messageBox = qobject_cast<QQuickItem*>(sender());
Q_ASSERT(messageBox != nullptr);
auto keys = _messageBoxes.keys(messageBox);
if (keys.length() > 0) {
auto id = keys[0]; // Should be just one message box.

View file

@ -4,9 +4,11 @@
//
// Created by Ryan Huffman on 4/29/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_WindowScriptingInterface_h
@ -17,10 +19,12 @@
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtQuick/QQuickItem>
#include <QtScript/QScriptValue>
#include <QtWidgets/QMessageBox>
#include <DependencyManager.h>
#include <Scriptable.h>
#include <ScriptValue.h>
/*@jsdoc
* The <code>Window</code> API provides various facilities not covered elsewhere, including: window dimensions, window focus,
@ -46,7 +50,7 @@
* @property {location} location - Provides facilities for working with your current directory services location.
*/
class WindowScriptingInterface : public QObject, public Dependency {
class WindowScriptingInterface : public QObject, protected Scriptable, public Dependency {
Q_OBJECT
Q_PROPERTY(int innerWidth READ getInnerWidth)
Q_PROPERTY(int innerHeight READ getInnerHeight)
@ -69,7 +73,7 @@ public slots:
* @function Window.hasFocus
* @returns {boolean} <code>true</code> if the Interface window has focus, <code>false</code> if it doesn't.
*/
QScriptValue hasFocus();
ScriptValue hasFocus();
/*@jsdoc
* Makes the Interface window have focus. On Windows, if Interface doesn't already have focus, the task bar icon flashes to
@ -104,7 +108,7 @@ public slots:
* var answer = Window.confirm("Are you sure?");
* print(answer); // true or false
*/
QScriptValue confirm(const QString& message = "");
ScriptValue confirm(const QString& message = "");
/*@jsdoc
* Prompts the user to enter some text. Displays a modal dialog with a message and a text box, plus "OK" and "Cancel"
@ -121,7 +125,7 @@ public slots:
* print("User answer: " + answer);
* }
*/
QScriptValue prompt(const QString& message, const QString& defaultText);
ScriptValue prompt(const QString& message, const QString& defaultText);
/*@jsdoc
* Prompts the user to enter some text. Displays a non-modal dialog with a message and a text box, plus "OK" and "Cancel"
@ -151,7 +155,7 @@ public slots:
* var directory = Window.browseDir("Select Directory", Paths.resources);
* print("Directory: " + directory);
*/
QScriptValue browseDir(const QString& title = "", const QString& directory = "");
ScriptValue browseDir(const QString& title = "", const QString& directory = "");
/*@jsdoc
* Prompts the user to choose a directory. Displays a non-modal dialog that navigates the directory tree. A
@ -183,7 +187,7 @@ public slots:
* var filename = Window.browse("Select Image File", Paths.resources, "Images (*.png *.jpg *.svg)");
* print("File: " + filename);
*/
QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
ScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
/*@jsdoc
* Prompts the user to choose a file. Displays a non-modal dialog that navigates the directory tree. A
@ -219,7 +223,7 @@ public slots:
* var filename = Window.save("Save to JSON file", Paths.resources, "*.json");
* print("File: " + filename);
*/
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
ScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
/*@jsdoc
* Prompts the user to specify the path and name of a file to save to. Displays a non-modal dialog that navigates the
@ -254,7 +258,7 @@ public slots:
* var asset = Window.browseAssets("Select FBX File", "/", "*.fbx");
* print("FBX file: " + asset);
*/
QScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
ScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
/*@jsdoc
* Prompts the user to choose an Asset Server item. Displays a non-modal dialog that navigates the tree of assets on the

View file

@ -4,9 +4,11 @@
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "InteractiveWindow.h"
@ -24,6 +26,8 @@
#include <DependencyManager.h>
#include <DockWidget.h>
#include <RegisteredMetaTypes.h>
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include "OffscreenUi.h"
#include "shared/QtHelpers.h"
@ -33,6 +37,12 @@
#include <WinUser.h>
#endif
STATIC_SCRIPT_TYPES_INITIALIZER(+[](ScriptManager* manager){
auto scriptEngine = manager->engine().get();
registerInteractiveWindowMetaType(scriptEngine);
});
static auto CONTENT_WINDOW_QML = QUrl("InteractiveWindow.qml");
static const char* const ADDITIONAL_FLAGS_PROPERTY = "additionalFlags";
@ -91,18 +101,20 @@ static void dockWidgetDeleter(DockWidget* dockWidget) {
dockWidget->deleteLater();
}
void registerInteractiveWindowMetaType(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, interactiveWindowPointerToScriptValue, interactiveWindowPointerFromScriptValue);
void registerInteractiveWindowMetaType(ScriptEngine* engine) {
scriptRegisterMetaType<InteractiveWindowPointer, interactiveWindowPointerToScriptValue, interactiveWindowPointerFromScriptValue>(engine);
}
QScriptValue interactiveWindowPointerToScriptValue(QScriptEngine* engine, const InteractiveWindowPointer& in) {
return engine->newQObject(in, QScriptEngine::ScriptOwnership);
ScriptValue interactiveWindowPointerToScriptValue(ScriptEngine* engine, const InteractiveWindowPointer& in) {
// V8TODO: is ScriptOwnership safe here?
return engine->newQObject(in, ScriptEngine::ScriptOwnership);
}
void interactiveWindowPointerFromScriptValue(const QScriptValue& 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) {

View file

@ -4,9 +4,11 @@
//
// Created by Thijs Wenker on 2018-06-25
// Copyright 2018 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
@ -16,12 +18,14 @@
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtScript/QScriptValue>
#include <QQmlEngine>
#include <ui/QmlWrapper.h>
#include <glm/glm.hpp>
#include <GLMHelpers.h>
#include <ScriptValue.h>
class ScriptEngine;
class QmlWindowProxy : public QmlWrapper {
Q_OBJECT
@ -408,10 +412,10 @@ private:
typedef InteractiveWindow* InteractiveWindowPointer;
QScriptValue interactiveWindowPointerToScriptValue(QScriptEngine* engine, const InteractiveWindowPointer& in);
void interactiveWindowPointerFromScriptValue(const QScriptValue& object, InteractiveWindowPointer& out);
ScriptValue interactiveWindowPointerToScriptValue(ScriptEngine* engine, const InteractiveWindowPointer& in);
bool interactiveWindowPointerFromScriptValue(const ScriptValue& object, InteractiveWindowPointer& out);
void registerInteractiveWindowMetaType(QScriptEngine* engine);
void registerInteractiveWindowMetaType(ScriptEngine* engine);
Q_DECLARE_METATYPE(InteractiveWindowPointer)

View file

@ -4,9 +4,11 @@
//
// Created by Ryan Huffman on 05/12/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "JSConsole.h"
@ -18,6 +20,8 @@
#include <QStringListModel>
#include <QListView>
#include <QToolTip>
#include <QtGui/QStandardItem>
#include <QtGui/QStandardItemModel>
#include <shared/QtHelpers.h>
#include <ScriptEngines.h>
@ -133,7 +137,7 @@ QStandardItemModel* JSConsole::getAutoCompleteModel(const QString& memberOf) {
return model;
}
JSConsole::JSConsole(QWidget* parent, const ScriptEnginePointer& scriptEngine) :
JSConsole::JSConsole(QWidget* parent, const ScriptManagerPointer& scriptManager) :
QWidget(parent),
_ui(new Ui::Console),
_currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND),
@ -181,11 +185,11 @@ JSConsole::JSConsole(QWidget* parent, const ScriptEnginePointer& scriptEngine) :
QObject::connect(_completer, static_cast<void(QCompleter::*)(const QModelIndex&)>(&QCompleter::highlighted), this,
&JSConsole::highlightedCompletion);
setScriptEngine(scriptEngine);
setScriptManager(scriptManager);
resizeTextInput();
connect(&_executeWatcher, &QFutureWatcher<QScriptValue>::finished, this, &JSConsole::commandFinished);
connect(&_executeWatcher, &QFutureWatcher<ScriptValue>::finished, this, &JSConsole::commandFinished);
}
void JSConsole::insertCompletion(const QModelIndex& completion) {
@ -305,33 +309,33 @@ void JSConsole::highlightedCompletion(const QModelIndex& completion) {
}
JSConsole::~JSConsole() {
if (_scriptEngine) {
disconnect(_scriptEngine.data(), nullptr, this, nullptr);
_scriptEngine.reset();
if (_scriptManager) {
disconnect(_scriptManager.get(), nullptr, this, nullptr);
_scriptManager.reset();
}
delete _ui;
}
void JSConsole::setScriptEngine(const ScriptEnginePointer& scriptEngine) {
if (_scriptEngine == scriptEngine && scriptEngine != nullptr) {
void JSConsole::setScriptManager(const ScriptManagerPointer& scriptManager) {
if (_scriptManager == scriptManager && scriptManager != nullptr) {
return;
}
if (_scriptEngine != nullptr) {
disconnect(_scriptEngine.data(), nullptr, this, nullptr);
_scriptEngine.reset();
if (_scriptManager != nullptr) {
disconnect(_scriptManager.get(), nullptr, this, nullptr);
_scriptManager.reset();
}
// if scriptEngine is nullptr then create one and keep track of it using _ownScriptEngine
if (scriptEngine.isNull()) {
_scriptEngine = DependencyManager::get<ScriptEngines>()->loadScript(_consoleFileName, false);
if (!scriptManager) {
_scriptManager = DependencyManager::get<ScriptEngines>()->loadScript(_consoleFileName, false);
} else {
_scriptEngine = scriptEngine;
_scriptManager = scriptManager;
}
connect(_scriptEngine.data(), &ScriptEngine::printedMessage, this, &JSConsole::handlePrint);
connect(_scriptEngine.data(), &ScriptEngine::infoMessage, this, &JSConsole::handleInfo);
connect(_scriptEngine.data(), &ScriptEngine::warningMessage, this, &JSConsole::handleWarning);
connect(_scriptEngine.data(), &ScriptEngine::errorMessage, this, &JSConsole::handleError);
connect(_scriptManager.get(), &ScriptManager::printedMessage, this, &JSConsole::handlePrint);
connect(_scriptManager.get(), &ScriptManager::infoMessage, this, &JSConsole::handleInfo);
connect(_scriptManager.get(), &ScriptManager::warningMessage, this, &JSConsole::handleWarning);
connect(_scriptManager.get(), &ScriptManager::errorMessage, this, &JSConsole::handleError);
}
void JSConsole::executeCommand(const QString& command) {
@ -347,16 +351,15 @@ void JSConsole::executeCommand(const QString& command) {
appendMessage(">", "<span style='" + COMMAND_STYLE + "'>" + command.toHtmlEscaped() + "</span>");
QWeakPointer<ScriptEngine> weakScriptEngine = _scriptEngine;
std::weak_ptr<ScriptManager> weakScriptManager = _scriptManager;
auto consoleFileName = _consoleFileName;
QFuture<QScriptValue> future = QtConcurrent::run([weakScriptEngine, consoleFileName, command]()->QScriptValue{
QScriptValue result;
auto scriptEngine = weakScriptEngine.lock();
if (scriptEngine) {
BLOCKING_INVOKE_METHOD(scriptEngine.data(), "evaluate",
Q_RETURN_ARG(QScriptValue, result),
Q_ARG(const QString&, command),
Q_ARG(const QString&, consoleFileName));
QFuture<QVariant> future = QtConcurrent::run([weakScriptManager, consoleFileName, command]() -> QVariant {
QVariant result;
auto scriptManager = weakScriptManager.lock();
if (scriptManager) {
BLOCKING_INVOKE_METHOD(scriptManager.get(), [&scriptManager, &consoleFileName, &command, &result]() -> void {
result = scriptManager->evaluate(command, consoleFileName).toVariant();
});
}
return result;
});
@ -364,7 +367,7 @@ void JSConsole::executeCommand(const QString& command) {
}
void JSConsole::commandFinished() {
QScriptValue result = _executeWatcher.result();
QVariant result = _executeWatcher.result();
_ui->promptTextEdit->setDisabled(false);
@ -373,9 +376,12 @@ void JSConsole::commandFinished() {
_ui->promptTextEdit->setFocus();
}
bool error = (_scriptEngine->hasUncaughtException() || result.isError());
QString gutter = error ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND;
QString resultColor = error ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE;
// V8TODO:
//bool error = (_scriptManager->engine()->hasUncaughtException() || result.isError());
//QString gutter = error ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND;
//QString resultColor = error ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE;
QString gutter = GUTTER_PREVIOUS_COMMAND;
QString resultColor = RESULT_SUCCESS_STYLE;
QString resultStr = "<span style='" + resultColor + "'>" + result.toString().toHtmlEscaped() + "</span>";
appendMessage(gutter, resultStr);

View file

@ -4,21 +4,29 @@
//
// Created by Ryan Huffman on 05/12/14.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_JSConsole_h
#define hifi_JSConsole_h
#include <memory>
#include <QFutureWatcher>
#include <QObject>
#include <QCompleter>
#include <QtCore/QJsonArray>
#include <ScriptValue.h>
#include "ui_console.h"
#include "ScriptEngine.h"
class QStandardItemModel;
class ScriptManager;
using ScriptManagerPointer = std::shared_ptr<ScriptManager>;
const QString CONSOLE_TITLE = "Scripting Console";
const float CONSOLE_WINDOW_OPACITY = 0.95f;
@ -28,10 +36,10 @@ const int CONSOLE_HEIGHT = 200;
class JSConsole : public QWidget {
Q_OBJECT
public:
JSConsole(QWidget* parent, const ScriptEnginePointer& scriptEngine = ScriptEnginePointer());
JSConsole(QWidget* parent, const ScriptManagerPointer& scriptManager = ScriptManagerPointer());
~JSConsole();
void setScriptEngine(const ScriptEnginePointer& scriptEngine = ScriptEnginePointer());
void setScriptManager(const ScriptManagerPointer& scriptManager = ScriptManagerPointer());
void clear();
public slots:
@ -66,13 +74,13 @@ private:
QStandardItemModel* getAutoCompleteModel(const QString& memberOf = nullptr);
QFutureWatcher<QScriptValue> _executeWatcher;
QFutureWatcher<QVariant> _executeWatcher;
Ui::Console* _ui;
int _currentCommandInHistory;
QString _savedHistoryFilename;
QList<QString> _commandHistory;
QString _rootCommand;
ScriptEnginePointer _scriptEngine;
ScriptManagerPointer _scriptManager;
static const QString _consoleFileName;
QJsonArray _apiDocs;
QCompleter* _completer;

View file

@ -118,7 +118,7 @@ std::pair<glm::vec3, glm::quat> calculateKeyboardPositionAndOrientation() {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;
desiredProperties += PROP_ROTATION;
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(tabletID, desiredProperties);
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(tabletID, desiredProperties);
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
bool landscapeMode = tablet->getLandscape();
@ -146,7 +146,7 @@ void Key::saveDimensionsAndLocalPosition() {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_LOCAL_POSITION;
desiredProperties += PROP_DIMENSIONS;
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(_keyID, desiredProperties);
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(_keyID, desiredProperties);
_originalLocalPosition = properties.getLocalPosition();
_originalDimensions = properties.getDimensions();
@ -271,14 +271,14 @@ void Keyboard::createKeyboard() {
QVariantMap leftStylusProperties {
{ "hand", LEFT_HAND_CONTROLLER_INDEX },
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
{ "filter", PickScriptingInterface::getPickLocalEntities() },
{ "model", modelProperties },
{ "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) }
};
QVariantMap rightStylusProperties {
{ "hand", RIGHT_HAND_CONTROLLER_INDEX },
{ "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() },
{ "filter", PickScriptingInterface::getPickLocalEntities() },
{ "model", modelProperties },
{ "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) }
};
@ -469,7 +469,7 @@ void Keyboard::switchToLayer(int layerIndex) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;
desiredProperties += PROP_ROTATION;
auto oldProperties = entityScriptingInterface->getEntityProperties(_anchor.entityID, desiredProperties);
auto oldProperties = entityScriptingInterface->getEntityPropertiesInternal(_anchor.entityID, desiredProperties);
glm::vec3 currentPosition = oldProperties.getPosition();
glm::quat currentOrientation = oldProperties.getRotation();
@ -530,7 +530,7 @@ void Keyboard::handleTriggerBegin(const QUuid& id, const PointerEvent& event) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;
glm::vec3 keyWorldPosition = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getPosition();
glm::vec3 keyWorldPosition = DependencyManager::get<EntityScriptingInterface>()->getEntityPropertiesInternal(id, desiredProperties).getPosition();
AudioInjectorOptions audioOptions;
audioOptions.localOnly = true;
@ -662,7 +662,7 @@ void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event)
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_ROTATION;
glm::quat orientation = entityScriptingInterface->getEntityProperties(id, desiredProperties).getRotation();
glm::quat orientation = entityScriptingInterface->getEntityPropertiesInternal(id, desiredProperties).getRotation();
glm::vec3 yAxis = orientation * Z_AXIS;
glm::vec3 yOffset = yAxis * Z_OFFSET;
glm::vec3 localPosition = key.getCurrentLocalPosition() - yOffset;

View file

@ -4,15 +4,18 @@
//
// Created by Ryan Jones on 12/3/2016.
// Copyright 2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "TestingDialog.h"
#include "Application.h"
#include "ScriptEngines.h"
#include <ScriptManager.h>
TestingDialog::TestingDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint),
@ -23,12 +26,12 @@ TestingDialog::TestingDialog(QWidget* parent) :
_console->setFixedHeight(TESTING_CONSOLE_HEIGHT);
_engine = DependencyManager::get<ScriptEngines>()->loadScript(qApp->applicationDirPath() + testRunnerRelativePath);
_console->setScriptEngine(_engine);
connect(_engine.data(), &ScriptEngine::finished, this, &TestingDialog::onTestingFinished);
_scriptManager = DependencyManager::get<ScriptEngines>()->loadScript(qApp->applicationDirPath() + testRunnerRelativePath);
_console->setScriptManager(_scriptManager);
connect(_scriptManager.get(), &ScriptManager::finished, this, &TestingDialog::onTestingFinished);
}
void TestingDialog::onTestingFinished(const QString& scriptPath) {
_engine.reset();
_console->setScriptEngine();
_scriptManager.reset();
_console->setScriptManager();
}

View file

@ -4,18 +4,24 @@
//
// Created by Ryan Jones on 12/3/2016.
// Copyright 2016 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_TestingDialog_h
#define hifi_TestingDialog_h
#include <memory>
#include <QDialog>
#include "ScriptEngine.h"
#include "JSConsole.h"
class ScriptManager;
using ScriptManagerPointer = std::shared_ptr<ScriptManager>;
const QString windowLabel = "Client Script Tests";
const QString testRunnerRelativePath = "/scripts/developer/tests/unit_tests/testRunner.js";
const unsigned int TESTING_CONSOLE_HEIGHT = 400;
@ -29,7 +35,7 @@ public:
private:
std::unique_ptr<JSConsole> _console;
ScriptEnginePointer _engine;
ScriptManagerPointer _scriptManager;
};
#endif

View file

@ -141,7 +141,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
qCDebug(context_overlay) << "Creating Context Overlay on top of entity with ID: " << entityItemID;
// Add all necessary variables to the stack
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(entityItemID, _entityPropertyFlags);
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityPropertiesInternal(entityItemID, _entityPropertyFlags);
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
glm::vec3 entityDimensions = entityProperties.getDimensions();
glm::vec3 entityPosition = entityProperties.getPosition();
@ -231,7 +231,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
}
bool ContextOverlayInterface::contextOverlayFilterPassed(const EntityItemID& entityItemID) {
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(entityItemID, _entityPropertyFlags);
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityPropertiesInternal(entityItemID, _entityPropertyFlags);
return (entityProperties.getCertificateID().length() != 0);
}
@ -294,7 +294,7 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID
setLastInspectedEntity(entityID);
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(entityID, _entityPropertyFlags);
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityPropertiesInternal(entityID, _entityPropertyFlags);
auto nodeList = DependencyManager::get<NodeList>();
@ -399,7 +399,7 @@ void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) {
void ContextOverlayInterface::startChallengeOwnershipTimer(const EntityItemID& entityItemID) {
auto ledger = DependencyManager::get<Ledger>();
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(entityItemID, _entityPropertyFlags);
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityPropertiesInternal(entityItemID, _entityPropertyFlags);
connect(&_challengeOwnershipTimeoutTimer, &QTimer::timeout, this, [=]() {
qCDebug(entities) << "Ownership challenge timed out for" << entityItemID;

File diff suppressed because it is too large Load diff

View file

@ -4,9 +4,11 @@
//
// Modified by Zander Otavka on 7/15/15
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
// Exposes methods to scripts for managing `Overlay`s and `OverlayPanel`s.
//
@ -20,15 +22,16 @@
#include <QMouseEvent>
#include <QReadWriteLock>
#include <QScriptValue>
#include <PointerEvent.h>
#include <ScriptValue.h>
#include "Overlay.h"
#include <EntityScriptingInterface.h>
class PickRay;
class ScriptEngine;
/*@jsdoc
* The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}.
@ -52,8 +55,8 @@ public:
QVariantMap extraInfo;
};
Q_DECLARE_METATYPE(RayToOverlayIntersectionResult);
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value);
void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, RayToOverlayIntersectionResult& value);
ScriptValue RayToOverlayIntersectionResultToScriptValue(ScriptEngine* engine, const RayToOverlayIntersectionResult& value);
bool RayToOverlayIntersectionResultFromScriptValue(const ScriptValue& object, RayToOverlayIntersectionResult& value);
class ParabolaToOverlayIntersectionResult {
public:
@ -74,8 +77,6 @@ public:
* <p><strong>Note:</strong> 3D overlays are local {@link Entities}, internally, so many of the methods also work with
* entities.</p>
*
* <p class="important">3D overlays are deprecated: Use local {@link Entities} for these instead.</p>
*
* @namespace Overlays
*
* @hifi-interface
@ -120,8 +121,6 @@ public:
void cleanupAllOverlays();
mutable QScriptEngine _scriptEngine;
public slots:
/*@jsdoc
* Adds an overlay to the scene.
@ -311,74 +310,6 @@ public slots:
*/
QUuid getOverlayAtPoint(const glm::vec2& point);
/*@jsdoc
* Gets a specified property value of a 3D overlay (or entity).
* <p><strong>Note:</strong> 2D overlays' property values cannot be retrieved.</p>
* @function Overlays.getProperty
* @param {Uuid} id - The ID of the 3D overlay (or entity).
* @param {string} property - The name of the property to get the value of.
* @returns {object} The value of the property if the 3D overlay and property can be found, otherwise
* <code>undefined</code>.
* @example <caption>Create an overlay in front of your avatar then report its alpha property value.</caption>
* var overlay = Overlays.addOverlay("cube", {
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })),
* rotation: MyAvatar.orientation,
* dimensions: { x: 0.3, y: 0.3, z: 0.3 },
* solid: true
* });
* var alpha = Overlays.getProperty(overlay, "alpha");
* print("Overlay alpha: " + alpha);
*/
QVariant getProperty(const QUuid& id, const QString& property);
/*@jsdoc
* Gets specified property values of a 3D overlay (or entity).
* <p><strong>Note:</strong> 2D overlays' property values cannot be retrieved.</p>
* @function Overlays.getProperties
* @param {Uuid} id - The ID of the overlay (or entity).
* @param {Array.<string>} properties - The names of the properties to get the values of.
* @returns {Overlays.OverlayProperties} The values of valid properties if the overlay can be found, otherwise an empty
* object.
* @example <caption>Create an overlay in front of your avatar then report some of its properties.</caption>
* var overlay = Overlays.addOverlay("cube", {
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })),
* rotation: MyAvatar.orientation,
* dimensions: { x: 0.3, y: 0.3, z: 0.3 },
* solid: true
* });
* var properties = Overlays.getProperties(overlay, ["color", "alpha", "grabbable"]);
* print("Overlay properties: " + JSON.stringify(properties));
*/
QVariantMap getProperties(const QUuid& id, const QStringList& properties);
/*@jsdoc
* Gets the values of multiple overlays' (or entities') properties.
* @function Overlays.getOverlaysProperties
* @param propertiesById {object.<Uuid, Array.<string>>} - An object with overlay (or entity) IDs as keys and arrays of the
* names of properties to get for each as values.
* @returns {object.<Uuid, Overlays.OverlayProperties>} An object with overlay (or entity) IDs as keys and
* {@link Overlays.OverlayProperties|OverlayProperties} as values.
* @example <caption>Create two cube overlays in front of your avatar then get some of their properties.</caption>
* var overlayA = Overlays.addOverlay("cube", {
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.3, y: 0, z: -3 })),
* rotation: MyAvatar.orientation,
* dimensions: { x: 0.3, y: 0.3, z: 0.3 },
* solid: true
* });
* var overlayB = Overlays.addOverlay("cube", {
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0.3, y: 0, z: -3 })),
* rotation: MyAvatar.orientation,
* dimensions: { x: 0.3, y: 0.3, z: 0.3 },
* solid: true
* });
* var propertiesToGet = {};
* propertiesToGet[overlayA] = ["color", "alpha"];
* propertiesToGet[overlayB] = ["dimensions"];
* var properties = Overlays.getOverlaysProperties(propertiesToGet);
* print("Overlays properties: " + JSON.stringify(properties));
*/
QVariantMap getOverlaysProperties(const QVariant& overlaysProperties);
/*@jsdoc
* Finds the closest 3D overlay (or local entity) intersected by a {@link PickRay}.
* @function Overlays.findRayIntersection
@ -411,8 +342,8 @@ public slots:
*/
RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray,
bool precisionPicking = false,
const QScriptValue& include = QScriptValue(),
const QScriptValue& discard = QScriptValue(),
const ScriptValue& include = ScriptValue(),
const ScriptValue& discard = ScriptValue(),
bool visibleOnly = false,
bool collidableOnly = false);
@ -759,14 +690,9 @@ private:
QMouseEvent* event, PointerEvent::EventType eventType);
static QString entityToOverlayType(const QString& type);
static QString overlayToEntityType(const QString& type);
static std::unordered_map<QString, QString> _entityToOverlayTypes;
static std::unordered_map<QString, QString> _overlayToEntityTypes;
QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps);
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id);
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
private slots:
void mousePressOnPointerEvent(const QUuid& id, const PointerEvent& event);
void mousePressOffPointerEvent();

View file

@ -1,6 +1,10 @@
# Copyright 2014-2019, High Fidelity, Inc.
# Copyright 2021-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(TARGET_NAME animation)
setup_hifi_library(Network Script)
link_hifi_libraries(shared graphics model-serializers)
setup_hifi_library(Network)
link_hifi_libraries(shared graphics model-serializers script-engine)
include_hifi_library_headers(networking)
include_hifi_library_headers(gpu)
include_hifi_library_headers(hfm)

View file

@ -4,27 +4,29 @@
//
// Created by Howard Stearns on 10/15/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AnimVariant.h" // which has AnimVariant/AnimVariantMap
#include <QScriptEngine>
#include <QScriptValueIterator>
#include <ScriptEngine.h>
#include <QThread>
#include <RegisteredMetaTypes.h>
#include <ScriptValueIterator.h>
#include <ScriptValueUtils.h>
const AnimVariant AnimVariant::False = AnimVariant();
QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine, const QStringList& names, bool useNames) const {
ScriptValue AnimVariantMap::animVariantMapToScriptValue(ScriptEngine* engine, const QStringList& names, bool useNames) const {
if (QThread::currentThread() != engine->thread()) {
qCWarning(animation) << "Cannot create Javacript object from non-script thread" << QThread::currentThread();
Q_ASSERT(false);
return QScriptValue();
return ScriptValue();
}
QScriptValue target = engine->newObject();
ScriptValue target = engine->newObject();
auto setOne = [&] (const QString& name, const AnimVariant& value) {
switch (value.getType()) {
case AnimVariant::Type::Bool:
@ -74,54 +76,55 @@ void AnimVariantMap::copyVariantsFrom(const AnimVariantMap& other) {
}
}
void AnimVariantMap::animVariantMapFromScriptValue(const QScriptValue& source) {
void AnimVariantMap::animVariantMapFromScriptValue(const ScriptValue& source) {
if (QThread::currentThread() != source.engine()->thread()) {
qCWarning(animation) << "Cannot examine Javacript object from non-script thread" << QThread::currentThread();
Q_ASSERT(false);
return;
}
// This was here before, but marking as V8TODO
// POTENTIAL OPTIMIZATION: cache the types we've seen. I.e, keep a dictionary mapping property names to an enumeration of types.
// Whenever we identify a new outbound type in animVariantMapToScriptValue above, or a new inbound type in the code that follows here,
// we would enter it into the dictionary. Then switch on that type here, with the code that follow being executed only if
// the type is not known. One problem with that is that there is no checking that two different script use the same name differently.
QScriptValueIterator property(source);
// Note: QScriptValueIterator iterates only over source's own properties. It does not follow the prototype chain.
while (property.hasNext()) {
property.next();
QScriptValue value = property.value();
ScriptValueIteratorPointer property(source.newIterator());
// Note: ScriptValueIterator iterates only over source's own properties. It does not follow the prototype chain.
while (property->hasNext()) {
property->next();
ScriptValue value = property->value();
if (value.isBool()) {
set(property.name(), value.toBool());
set(property->name(), value.toBool());
} else if (value.isString()) {
set(property.name(), value.toString());
set(property->name(), value.toString());
} else if (value.isNumber()) {
int asInteger = value.toInt32();
float asFloat = value.toNumber();
if (asInteger == asFloat) {
set(property.name(), asInteger);
set(property->name(), asInteger);
} else {
set(property.name(), asFloat);
set(property->name(), asFloat);
}
} else { // Try to get x,y,z and possibly w
if (value.isObject()) {
QScriptValue x = value.property("x");
ScriptValue x = value.property("x");
if (x.isNumber()) {
QScriptValue y = value.property("y");
ScriptValue y = value.property("y");
if (y.isNumber()) {
QScriptValue z = value.property("z");
ScriptValue z = value.property("z");
if (z.isNumber()) {
QScriptValue w = value.property("w");
ScriptValue w = value.property("w");
if (w.isNumber()) {
set(property.name(), glm::quat(w.toNumber(), x.toNumber(), y.toNumber(), z.toNumber()));
set(property->name(), glm::quat(w.toNumber(), x.toNumber(), y.toNumber(), z.toNumber()));
} else {
set(property.name(), glm::vec3(x.toNumber(), y.toNumber(), z.toNumber()));
set(property->name(), glm::vec3(x.toNumber(), y.toNumber(), z.toNumber()));
}
continue; // we got either a vector or quaternion object, so don't fall through to warning
}
}
}
}
qCWarning(animation) << "Ignoring unrecognized data" << value.toString() << "for animation property" << property.name();
Q_ASSERT(false);
qCWarning(animation) << "Ignoring unrecognized data " << value.toString() << " for animation property " << property->name();
//Q_ASSERT(false);
}
}
}

View file

@ -3,9 +3,11 @@
//
// Created by Anthony J. Thibault on 9/2/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AnimVariant_h
@ -17,10 +19,12 @@
#include <glm/gtx/quaternion.hpp>
#include <map>
#include <set>
#include <QScriptValue>
#include <StreamUtils.h>
#include <GLMHelpers.h>
#include "AnimationLogging.h"
#include <ScriptValue.h>
class ScriptEngine;
class AnimVariant {
public:
@ -229,9 +233,9 @@ public:
}
// Answer a Plain Old Javascript Object (for the given engine) all of our values set as properties.
QScriptValue animVariantMapToScriptValue(QScriptEngine* engine, const QStringList& names, bool useNames) const;
ScriptValue animVariantMapToScriptValue(ScriptEngine* engine, const QStringList& names, bool useNames) const;
// Side-effect us with the value of object's own properties. (No inherited properties.)
void animVariantMapFromScriptValue(const QScriptValue& object);
void animVariantMapFromScriptValue(const ScriptValue& object);
void copyVariantsFrom(const AnimVariantMap& other);
// For stat debugging.
@ -274,7 +278,7 @@ protected:
glm::quat _rigToGeometryRot;
};
typedef std::function<void(QScriptValue)> AnimVariantResultHandler;
typedef std::function<void(ScriptValue)> AnimVariantResultHandler;
Q_DECLARE_METATYPE(AnimVariantResultHandler);
Q_DECLARE_METATYPE(AnimVariantMap)

View file

@ -4,9 +4,11 @@
//
// Created by Andrzej Kapolka on 4/14/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
// Copyright Overte e.V. 2023
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AnimationCache_h
@ -14,8 +16,6 @@
#include <QtCore/QRunnable>
#include <QtCore/QSharedPointer>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
#include <DependencyManager.h>
#include <hfm/HFM.h>

View file

@ -4,34 +4,49 @@
//
// Created by Andrzej Kapolka on 4/17/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AnimationObject.h"
#include <QScriptEngine>
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include <ScriptManager.h>
#include <ScriptValue.h>
#include "AnimationCache.h"
STATIC_SCRIPT_TYPES_INITIALIZER(+[](ScriptManager* manager) {
registerAnimationTypes(manager->engine().get());
});
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
registerAnimationPrototypes(manager->engine().get());
});
QStringList AnimationObject::getJointNames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getJointNames();
return scriptvalue_cast<AnimationPointer>(thisObject())->getJointNames();
}
QVector<HFMAnimationFrame> AnimationObject::getFrames() const {
return qscriptvalue_cast<AnimationPointer>(thisObject())->getFrames();
return scriptvalue_cast<AnimationPointer>(thisObject())->getFrames();
}
QVector<glm::quat> AnimationFrameObject::getRotations() const {
return qscriptvalue_cast<HFMAnimationFrame>(thisObject()).rotations;
return scriptvalue_cast<HFMAnimationFrame>(thisObject()).rotations;
}
void registerAnimationTypes(QScriptEngine* engine) {
qScriptRegisterSequenceMetaType<QVector<HFMAnimationFrame> >(engine);
void registerAnimationTypes(ScriptEngine* engine) {
scriptRegisterSequenceMetaType<QVector<HFMAnimationFrame> >(engine);
}
void registerAnimationPrototypes(ScriptEngine* engine) {
engine->setDefaultPrototype(qMetaTypeId<HFMAnimationFrame>(), engine->newQObject(
new AnimationFrameObject(), QScriptEngine::ScriptOwnership));
new AnimationFrameObject(), ScriptEngine::ScriptOwnership));
engine->setDefaultPrototype(qMetaTypeId<AnimationPointer>(), engine->newQObject(
new AnimationObject(), QScriptEngine::ScriptOwnership));
new AnimationObject(), ScriptEngine::ScriptOwnership));
}

View file

@ -4,20 +4,22 @@
//
// Created by Andrzej Kapolka on 4/17/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AnimationObject_h
#define hifi_AnimationObject_h
#include <QObject>
#include <QScriptable>
#include <FBXSerializer.h>
#include "Scriptable.h"
class QScriptEngine;
class ScriptEngine;
/*@jsdoc
* Information about an animation resource, created by {@link AnimationCache.getAnimation}.
@ -35,7 +37,7 @@ class QScriptEngine;
* @property {AnimationFrameObject[]} frames - The frames in the animation. <em>Read-only.</em>
*/
/// Scriptable wrapper for animation pointers.
class AnimationObject : public QObject, protected QScriptable {
class AnimationObject : public QObject, protected Scriptable {
Q_OBJECT
Q_PROPERTY(QStringList jointNames READ getJointNames)
Q_PROPERTY(QVector<HFMAnimationFrame> frames READ getFrames)
@ -72,7 +74,7 @@ public:
* @property {Quat[]} rotations - Joint rotations. <em>Read-only.</em>
*/
/// Scriptable wrapper for animation frames.
class AnimationFrameObject : public QObject, protected QScriptable {
class AnimationFrameObject : public QObject, protected Scriptable {
Q_OBJECT
Q_PROPERTY(QVector<glm::quat> rotations READ getRotations)
@ -86,6 +88,7 @@ public:
Q_INVOKABLE QVector<glm::quat> getRotations() const;
};
void registerAnimationTypes(QScriptEngine* engine);
void registerAnimationTypes(ScriptEngine* engine);
void registerAnimationPrototypes(ScriptEngine* engine);
#endif // hifi_AnimationObject_h

View file

@ -4,16 +4,17 @@
//
// Created by Howard Stearns, Seth Alves, Anthony Thibault, Andrew Meadows on 7/15/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "Rig.h"
#include <glm/gtx/vector_angle.hpp>
#include <queue>
#include <QScriptValueIterator>
#include <QWriteLocker>
#include <QReadLocker>
@ -21,7 +22,10 @@
#include <NumericalConstants.h>
#include <DebugDraw.h>
#include <PerfStat.h>
#include <ScriptEngine.h>
#include <ScriptManager.h>
#include <ScriptValueUtils.h>
#include <ScriptValue.h>
#include <shared/NsightHelpers.h>
#include "AnimationLogging.h"
@ -1584,7 +1588,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
}
// Allow script to add/remove handlers and report results, from within their thread.
QScriptValue Rig::addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { // called in script thread
ScriptValue Rig::addAnimationStateHandler(const ScriptValue& handler, const ScriptValue& propertiesList) { // called in script thread
// validate argument types
if (handler.isFunction() && (isListOfStrings(propertiesList) || propertiesList.isUndefined() || propertiesList.isNull())) {
@ -1594,19 +1598,19 @@ QScriptValue Rig::addAnimationStateHandler(QScriptValue handler, QScriptValue pr
_nextStateHandlerId++;
}
StateHandler& data = _stateHandlers[_nextStateHandlerId];
data.function = handler;
data.function = std::make_shared<ScriptValue>(handler);
data.useNames = propertiesList.isArray();
if (data.useNames) {
data.propertyNames = propertiesList.toVariant().toStringList();
}
return QScriptValue(_nextStateHandlerId); // suitable for giving to removeAnimationStateHandler
return handler.engine()->newValue(_nextStateHandlerId); // suitable for giving to removeAnimationStateHandler
} else {
qCWarning(animation) << "Rig::addAnimationStateHandler invalid arguments, expected (function, string[])";
return QScriptValue(QScriptValue::UndefinedValue);
return handler.engine() ? handler.engine()->undefinedValue() : ScriptValue();
}
}
void Rig::removeAnimationStateHandler(QScriptValue identifier) { // called in script thread
void Rig::removeAnimationStateHandler(const ScriptValue& identifier) { // called in script thread
// validate arguments
if (identifier.isNumber()) {
QMutexLocker locker(&_stateMutex);
@ -1616,7 +1620,7 @@ void Rig::removeAnimationStateHandler(QScriptValue identifier) { // called in sc
}
}
void Rig::animationStateHandlerResult(int identifier, QScriptValue result) { // called synchronously from script
void Rig::animationStateHandlerResult(int identifier, const ScriptValue& result) { // called synchronously from script
QMutexLocker locker(&_stateMutex);
auto found = _stateHandlers.find(identifier);
if (found == _stateHandlers.end()) {
@ -1635,9 +1639,9 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
// call out:
int identifier = data.key();
StateHandler& value = data.value();
QScriptValue& function = value.function;
std::shared_ptr<ScriptValue> function = value.function;
int rigId = _rigId;
auto handleResult = [rigId, identifier](QScriptValue result) { // called in script thread to get the result back to us.
auto handleResult = [rigId, identifier](const ScriptValue& result) { // called in script thread to get the result back to us.
// Hold the rigRegistryMutex to ensure thread-safe access to the rigRegistry, but
// also to prevent the rig from being deleted while this lambda is being executed.
std::lock_guard<std::mutex> guard(rigRegistryMutex);
@ -1650,14 +1654,35 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
rig->animationStateHandlerResult(identifier, result);
}
};
// invokeMethod makes a copy of the args, and copies of AnimVariantMap do copy the underlying map, so this will correctly capture
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
QMetaObject::invokeMethod(function.engine(), "callAnimationStateHandler", Qt::QueuedConnection,
Q_ARG(QScriptValue, function),
Q_ARG(AnimVariantMap, _animVars),
Q_ARG(QStringList, value.propertyNames),
Q_ARG(bool, value.useNames),
Q_ARG(AnimVariantResultHandler, handleResult));
{
// make references to the parameters for the lambda here, but let the lambda be the one to take the copies
// Copies of AnimVariantMap do copy the underlying map, so this will correctly capture
// the state of _animVars and allow continued changes to _animVars in this thread without conflict.
const AnimVariantMap& animVars = _animVars;
ScriptEnginePointer engine = function->engine();
const QStringList& names = value.propertyNames;
bool useNames = value.useNames;
QMetaObject::invokeMethod(
engine->manager(),
[function, animVars, names, useNames, handleResult, engine] {
ScriptValue javascriptParameters = animVars.animVariantMapToScriptValue(engine.get(), names, useNames);
ScriptValueList callingArguments;
callingArguments << javascriptParameters;
ScriptValue result = function->call(ScriptValue(), callingArguments);
// validate result from callback function.
if (result.isValid() && result.isObject()) {
handleResult(result);
} else {
qCWarning(animation) << "Rig::updateAnimationStateHandlers invalid return argument from "
"callback, expected an object";
} //V8TODO: std::shared_ptr<ScriptValue> function should probably be reset here if it's a local copy?
},
Qt::QueuedConnection);
}
// It turns out that, for thread-safety reasons, ScriptEngine::callAnimationStateHandler will invoke itself if called from other
// than the script thread. Thus the above _could_ be replaced with an ordinary call, which will then trigger the same
// invokeMethod as is done explicitly above. However, the script-engine library depends on this animation library, not vice versa.
@ -1670,7 +1695,9 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
// Gather results in (likely from an earlier update).
// Note: the behavior is undefined if a handler (re-)sets a trigger. Scripts should not be doing that.
_animVars.copyVariantsFrom(value.results); // If multiple handlers write the same anim var, the last registgered wins. (_map preserves order).
// V8TODO: This causes a deadlock right now, and in any case will cause stutters. Probably should be done on script thread instead
_animVars.copyVariantsFrom(value.results); // If multiple handlers write the same anim var, the last registered wins. (_map preserves order).
}
}
@ -1685,6 +1712,7 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons
++_evaluationCount;
// V8TODO: this causes a deadlock right now
updateAnimationStateHandlers();
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
if (_networkNode) {

View file

@ -6,9 +6,11 @@
//
// Created by Howard Stearns, Seth Alves, Anthony Thibault, Andrew Meadows on 7/15/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef __hifi__Rig__
@ -16,10 +18,10 @@
#include <QObject>
#include <QMutex>
#include <QScriptValue>
#include <vector>
#include <JointData.h>
#include <QReadWriteLock>
#include <ScriptValue.h>
#include "AnimNode.h"
#include "AnimNodeLoader.h"
@ -40,7 +42,7 @@ public:
struct StateHandler {
AnimVariantMap results;
QStringList propertyNames;
QScriptValue function;
std::shared_ptr<ScriptValue> function;
bool useNames;
};
@ -205,9 +207,9 @@ public:
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
AnimNode::ConstPointer findAnimNodeByName(const QString& name) const;
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
void removeAnimationStateHandler(QScriptValue handler);
void animationStateHandlerResult(int identifier, QScriptValue result);
ScriptValue addAnimationStateHandler(const ScriptValue& handler, const ScriptValue& propertiesList);
void removeAnimationStateHandler(const ScriptValue& handler);
void animationStateHandlerResult(int identifier, const ScriptValue& result);
// rig space
bool getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const;

View file

@ -1,3 +1,7 @@
# Copyright 2013-2019, High Fidelity, Inc.
# Copyright 2022-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(TARGET_NAME audio-client)
if (ANDROID)
set(PLATFORM_QT_COMPONENTS AndroidExtras)
@ -6,6 +10,7 @@ setup_hifi_library(Network Multimedia ${PLATFORM_QT_COMPONENTS})
link_hifi_libraries(audio plugins)
include_hifi_library_headers(shared)
include_hifi_library_headers(networking)
include_hifi_library_headers(script-engine)
if (ANDROID)
else ()

View file

@ -1,3 +1,7 @@
# Copyright 2013-2016, High Fidelity, Inc.
# Copyright 2022-2023 Overte e.V.
# SPDX-License-Identifier: Apache-2.0
set(TARGET_NAME audio)
setup_hifi_library(Network)
@ -5,4 +9,4 @@ if (ANDROID)
add_definitions("-D__STDC_CONSTANT_MACROS")
endif ()
link_hifi_libraries(networking shared plugins)
link_hifi_libraries(networking shared plugins script-engine)

View file

@ -3,13 +3,44 @@
// libraries/audio/src
//
// Copyright 2013 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AudioEffectOptions.h"
#include <ScriptContext.h>
#include <ScriptEngine.h>
#include <ScriptManager.h>
#include <ScriptValue.h>
#include <ScriptEngineCast.h>
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager) {
auto scriptEngine = manager->engine().get();
scriptRegisterMetaType<AudioEffectOptions, audioEffectOptionsToScriptValue, audioEffectOptionsFromScriptValue>(scriptEngine);
}));
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
auto scriptEngine = manager->engine().get();
ScriptValue audioEffectOptionsConstructorValue = scriptEngine->newFunction(AudioEffectOptions::constructor);
scriptEngine->globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue);
});
ScriptValue audioEffectOptionsToScriptValue(ScriptEngine* scriptEngine, const AudioEffectOptions& audioEffectOptions) {
qCritical() << "Conversion of AudioEffectOptions to ScriptValue should never happen.";
return ScriptValue();
}
bool audioEffectOptionsFromScriptValue(const ScriptValue& scriptValue, AudioEffectOptions& audioEffectOptions) {
audioEffectOptions = AudioEffectOptions(scriptValue);
return true;
}
static const QString BANDWIDTH_HANDLE = "bandwidth";
static const QString PRE_DELAY_HANDLE = "preDelay";
static const QString LATE_DELAY_HANDLE = "lateDelay";
@ -54,7 +85,7 @@ static const float LATE_MIX_LEFT_DEFAULT = 90.0f;
static const float LATE_MIX_RIGHT_DEFAULT = 90.0f;
static const float WET_DRY_MIX_DEFAULT = 50.0f;
static void setOption(QScriptValue arguments, const QString name, float defaultValue, float& variable) {
static void setOption(const ScriptValue& arguments, const QString name, float defaultValue, float& variable) {
variable = arguments.property(name).isNumber() ? (float)arguments.property(name).toNumber() : defaultValue;
}
@ -83,7 +114,7 @@ static void setOption(QScriptValue arguments, const QString name, float defaultV
* @property {number} lateMixRight=90 - The apparent distance of the source (percent) in the reverb tail.
* @property {number} wetDryMix=50 - Adjusts the wet/dry ratio, from completely dry (0%) to completely wet (100%).
*/
AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) {
AudioEffectOptions::AudioEffectOptions(const ScriptValue& arguments) {
setOption(arguments, BANDWIDTH_HANDLE, BANDWIDTH_DEFAULT, _bandwidth);
setOption(arguments, PRE_DELAY_HANDLE, PRE_DELAY_DEFAULT, _preDelay);
setOption(arguments, LATE_DELAY_HANDLE, LATE_DELAY_DEFAULT, _lateDelay);
@ -137,6 +168,6 @@ AudioEffectOptions& AudioEffectOptions::operator=(const AudioEffectOptions &othe
return *this;
}
QScriptValue AudioEffectOptions::constructor(QScriptContext* context, QScriptEngine* engine) {
return engine->newQObject(new AudioEffectOptions(context->argument(0)));
ScriptValue AudioEffectOptions::constructor(ScriptContext* context, ScriptEngine* engine) {
return engine->newQObject(new AudioEffectOptions(context->argument(0)), ScriptEngine::ScriptOwnership);
}

View file

@ -3,17 +3,21 @@
// libraries/audio/src
//
// Copyright 2013 High Fidelity, Inc.
// Copyright 2022-2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AudioEffectOptions_h
#define hifi_AudioEffectOptions_h
#include <QObject>
#include <QtScript/QScriptContext>
#include <QtScript/QScriptEngine>
#include <ScriptValue.h>
class ScriptContext;
class ScriptEngine;
/*@jsdoc
* Audio effect options used by the {@link Audio} API.
@ -78,11 +82,11 @@ class AudioEffectOptions : public QObject {
Q_PROPERTY(float wetDryMix READ getWetDryMix WRITE setWetDryMix)
public:
AudioEffectOptions(QScriptValue arguments = QScriptValue());
AudioEffectOptions(const ScriptValue& arguments = ScriptValue());
AudioEffectOptions(const AudioEffectOptions &other);
AudioEffectOptions& operator=(const AudioEffectOptions &other);
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
static ScriptValue constructor(ScriptContext* context, ScriptEngine* engine);
float getBandwidth() const { return _bandwidth; }
void setBandwidth(float bandwidth) { _bandwidth = bandwidth; }
@ -180,4 +184,10 @@ private:
float _wetDryMix; // [0, 100] percent
};
Q_DECLARE_METATYPE(AudioEffectOptions);
ScriptValue audioEffectOptionsToScriptValue(ScriptEngine* scriptEngine, const AudioEffectOptions& audioEffectOptions);
bool audioEffectOptionsFromScriptValue(const ScriptValue& scriptValue, AudioEffectOptions& audioEffectOptions);
#endif // hifi_AudioEffectOptions_h

View file

@ -4,16 +4,18 @@
//
// Created by Stephen Birarda on 1/2/2014.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AudioInjectorOptions.h"
#include <QScriptValueIterator>
#include <RegisteredMetaTypes.h>
#include <ScriptValueIterator.h>
#include <ScriptValueUtils.h>
#include <ScriptEngine.h>
#include "AudioLogging.h"
@ -32,8 +34,8 @@ AudioInjectorOptions::AudioInjectorOptions() :
{
}
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
QScriptValue obj = engine->newObject();
ScriptValue injectorOptionsToScriptValue(ScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
ScriptValue obj = engine->newObject();
if (injectorOptions.positionSet) {
obj.setProperty("position", vec3ToScriptValue(engine, injectorOptions.position));
}
@ -66,10 +68,10 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje
* @property {boolean} ignorePenumbra=false - <p class="important">Deprecated: This property is deprecated and will be
* removed.</p>
*/
void injectorOptionsFromScriptValue(const QScriptValue& 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) {
@ -77,53 +79,54 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
}
injectorOptions.positionSet = false;
QScriptValueIterator it(object);
while (it.hasNext()) {
it.next();
ScriptValueIteratorPointer it(object.newIterator());
while (it->hasNext()) {
it->next();
if (it.name() == "position") {
if (it->name() == "position") {
vec3FromScriptValue(object.property("position"), injectorOptions.position);
injectorOptions.positionSet = true;
} else if (it.name() == "orientation") {
} else if (it->name() == "orientation") {
quatFromScriptValue(object.property("orientation"), injectorOptions.orientation);
} else if (it.name() == "volume") {
if (it.value().isNumber()) {
injectorOptions.volume = it.value().toNumber();
} else if (it->name() == "volume") {
if (it->value().isNumber()) {
injectorOptions.volume = it->value().toNumber();
} else {
qCWarning(audio) << "Audio injector options: volume is not a number";
}
} else if (it.name() == "loop") {
if (it.value().isBool()) {
injectorOptions.loop = it.value().toBool();
} else if (it->name() == "loop") {
if (it->value().isBool()) {
injectorOptions.loop = it->value().toBool();
} else {
qCWarning(audio) << "Audio injector options: loop is not a boolean";
}
} else if (it.name() == "ignorePenumbra") {
if (it.value().isBool()) {
injectorOptions.ignorePenumbra = it.value().toBool();
} else if (it->name() == "ignorePenumbra") {
if (it->value().isBool()) {
injectorOptions.ignorePenumbra = it->value().toBool();
} else {
qCWarning(audio) << "Audio injector options: ignorePenumbra is not a boolean";
}
} else if (it.name() == "localOnly") {
if (it.value().isBool()) {
injectorOptions.localOnly = it.value().toBool();
} else if (it->name() == "localOnly") {
if (it->value().isBool()) {
injectorOptions.localOnly = it->value().toBool();
} else {
qCWarning(audio) << "Audio injector options: localOnly is not a boolean";
}
} else if (it.name() == "secondOffset") {
if (it.value().isNumber()) {
injectorOptions.secondOffset = it.value().toNumber();
} else if (it->name() == "secondOffset") {
if (it->value().isNumber()) {
injectorOptions.secondOffset = it->value().toNumber();
} else {
qCWarning(audio) << "Audio injector options: secondOffset is not a number";
}
} else if (it.name() == "pitch") {
if (it.value().isNumber()) {
injectorOptions.pitch = it.value().toNumber();
} else if (it->name() == "pitch") {
if (it->value().isNumber()) {
injectorOptions.pitch = it->value().toNumber();
} else {
qCWarning(audio) << "Audio injector options: pitch is not a number";
}
} else {
qCWarning(audio) << "Unknown audio injector option:" << it.name();
qCWarning(audio) << "Unknown audio injector option:" << it->name();
}
}
return true;
}

View file

@ -4,18 +4,21 @@
//
// Created by Stephen Birarda on 1/2/2014.
// Copyright 2014 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AudioInjectorOptions_h
#define hifi_AudioInjectorOptions_h
#include <QtScript/qscriptengine.h>
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <ScriptValue.h>
class ScriptEngine;
class AudioInjectorOptions {
public:
@ -35,7 +38,7 @@ public:
Q_DECLARE_METATYPE(AudioInjectorOptions);
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions);
void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOptions& injectorOptions);
ScriptValue injectorOptionsToScriptValue(ScriptEngine* engine, const AudioInjectorOptions& injectorOptions);
bool injectorOptionsFromScriptValue(const ScriptValue& object, AudioInjectorOptions& injectorOptions);
#endif // hifi_AudioInjectorOptions_h

Some files were not shown because too many files have changed in this diff Show more