Work on porting laser pointers to local entities, removal of LaserPointer JS API

This commit is contained in:
ksuprynowicz 2023-03-26 21:09:46 +02:00
parent 4d03033c9e
commit 2a2cf3898b
13 changed files with 311 additions and 385 deletions

View file

@ -242,7 +242,6 @@
#include <PickManager.h> #include <PickManager.h>
#include <PointerManager.h> #include <PointerManager.h>
#include <raypick/RayPickScriptingInterface.h> #include <raypick/RayPickScriptingInterface.h>
#include <raypick/LaserPointerScriptingInterface.h>
#include <raypick/PickScriptingInterface.h> #include <raypick/PickScriptingInterface.h>
#include <raypick/PointerScriptingInterface.h> #include <raypick/PointerScriptingInterface.h>
#include <raypick/RayPick.h> #include <raypick/RayPick.h>
@ -806,7 +805,6 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
// Set dependencies // Set dependencies
DependencyManager::set<PickManager>(); DependencyManager::set<PickManager>();
DependencyManager::set<PointerManager>(); DependencyManager::set<PointerManager>();
DependencyManager::set<LaserPointerScriptingInterface>();
DependencyManager::set<RayPickScriptingInterface>(); DependencyManager::set<RayPickScriptingInterface>();
DependencyManager::set<PointerScriptingInterface>(); DependencyManager::set<PointerScriptingInterface>();
DependencyManager::set<PickScriptingInterface>(); DependencyManager::set<PickScriptingInterface>();
@ -7529,7 +7527,6 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptManage
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data()); scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get<LaserPointerScriptingInterface>().data());
scriptEngine->registerGlobalObject("Picks", DependencyManager::get<PickScriptingInterface>().data()); scriptEngine->registerGlobalObject("Picks", DependencyManager::get<PickScriptingInterface>().data());
scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data()); scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data());

View file

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

View file

@ -4,6 +4,7 @@
// //
// Created by Sam Gondelman 7/11/2017 // Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc. // Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -32,6 +33,7 @@ PickQuery::PickType LaserPointer::getType() const {
} }
void LaserPointer::editRenderStatePath(const std::string& state, const QVariant& pathProps) { 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]); auto renderState = std::static_pointer_cast<RenderState>(_renderStates[state]);
if (renderState) { if (renderState) {
updateRenderState(renderState->getPathID(), pathProps); updateRenderState(renderState->getPathID(), pathProps);
@ -51,6 +53,7 @@ PickResultPointer LaserPointer::getPickResultCopy(const PickResultPointer& pickR
} }
QVariantMap LaserPointer::toVariantMap() const { QVariantMap LaserPointer::toVariantMap() const {
//V8TODO: this cannot be done anymore without script engine
QVariantMap qVariantMap = Parent::toVariantMap(); QVariantMap qVariantMap = Parent::toVariantMap();
QVariantMap qRenderStates; QVariantMap qRenderStates;
@ -175,6 +178,10 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
properties.setLinePoints(points); properties.setLinePoints(points);
properties.setVisible(true); properties.setVisible(true);
properties.setIgnorePickIntersection(doesPathIgnorePicks()); 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; QVector<float> widths;
float width = getLineWidth() * parentScale; float width = getLineWidth() * parentScale;
widths.append(width); 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 // FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers
QUuid startID; QUuid startID;
if (propMap["start"].isValid()) { if (propMap["startPropertyIndex"].isValid()) {
QVariantMap startMap = propMap["start"].toMap(); int startPropertyIndex = propMap["startPropertyIndex"].toInt();
if (startMap["type"].isValid()) { if (startPropertyIndex >= 0 && startPropertyIndex < entityProperties.length()) {
startMap.remove("visible"); //startMap.remove("visible");
startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); startID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[startPropertyIndex], entity::HostType::LOCAL);
} }
} }
QUuid pathID; QUuid pathID;
if (propMap["path"].isValid()) { if (propMap["pathPropertyIndex"].isValid()) {
QVariantMap pathMap = propMap["path"].toMap(); // laser paths must be PolyLine
// laser paths must be line3ds int pathPropertyIndex = propMap["pathPropertyIndex"].toInt();
if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { if (pathPropertyIndex >= 0 && pathPropertyIndex < entityProperties.length()) {
pathMap.remove("visible"); //startMap.remove("visible");
pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); //pathMap["type"].toString() == "PolyLine"
pathID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[pathPropertyIndex], entity::HostType::LOCAL);
} }
} }
QUuid endID; QUuid endID;
if (propMap["end"].isValid()) { if (propMap["endPropertyIndex"].isValid()) {
QVariantMap endMap = propMap["end"].toMap(); int endPropertyIndex = propMap["endPropertyIndex"].toInt();
if (endMap["type"].isValid()) { if (endPropertyIndex >= 0 && endPropertyIndex < entityProperties.length()) {
endMap.remove("visible"); //startMap.remove("visible");
endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); endID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[endPropertyIndex], entity::HostType::LOCAL);
} }
} }

View file

@ -13,6 +13,8 @@
#include "PathPointer.h" #include "PathPointer.h"
#include<EntityItemProperties.h>
class LaserPointer : public PathPointer { class LaserPointer : public PathPointer {
using Parent = PathPointer; using Parent = PathPointer;
public: public:
@ -46,7 +48,7 @@ public:
QVariantMap toVariantMap() const override; 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: protected:
PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override; PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override;

View file

@ -1,37 +0,0 @@
//
// LaserPointerScriptingInterface.cpp
// interface/src/raypick
//
// 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
// SPDX-License-Identifier: Apache-2.0
//
#include "LaserPointerScriptingInterface.h"
#include "PointerScriptingInterface.h"
#include <ScriptValueUtils.h>
void LaserPointerScriptingInterface::setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems) const {
DependencyManager::get<PointerManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
}
void LaserPointerScriptingInterface::setIncludeItems(unsigned int uid, const ScriptValue& 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,172 +0,0 @@
//
// LaserPointerScriptingInterface.h
// interface/src/raypick
//
// 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
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_LaserPointerScriptingInterface_h
#define hifi_LaserPointerScriptingInterface_h
#include <QtCore/QObject>
#include "DependencyManager.h"
#include <PointerManager.h>
class ScriptValue;
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 ScriptValue& 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 ScriptValue& 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

@ -1,6 +1,7 @@
// //
// Created by Sam Gondelman 7/17/2018 // Created by Sam Gondelman 7/17/2018
// Copyright 2018 High Fidelity, Inc. // Copyright 2018 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -232,14 +233,13 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
} }
} }
std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVariantMap& propMap) { std::shared_ptr<StartEndRenderState> ParabolaPointer::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; QUuid startID;
if (propMap["start"].isValid()) { if (propMap["startPropertyIndex"].isValid()) {
QVariantMap startMap = propMap["start"].toMap(); int startPropertyIndex = propMap["startPropertyIndex"].toInt();
if (startMap["type"].isValid()) { if (startPropertyIndex >= 0 && startPropertyIndex < entityProperties.length()) {
startMap.remove("visible"); //startMap.remove("visible");
startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); startID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[startPropertyIndex], entity::HostType::LOCAL);
} }
} }
@ -249,36 +249,25 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
bool isVisibleInSecondaryCamera = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA; bool isVisibleInSecondaryCamera = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA;
bool drawInFront = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT; bool drawInFront = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT;
bool enabled = false; bool enabled = false;
if (propMap["path"].isValid()) { if (propMap["pathPropertyIndex"].isValid()) {
enabled = true; int pathPropertyIndex = propMap["pathPropertyIndex"].toInt();
QVariantMap pathMap = propMap["path"].toMap(); if (pathPropertyIndex >= 0 && pathPropertyIndex < entityProperties.length()) {
if (pathMap["color"].isValid()) { const EntityItemProperties &pathProperties(entityProperties[pathPropertyIndex]);
color = toGlm(u8vec3FromVariant(pathMap["color"])); enabled = true;
} color = pathProperties.getColor();
alpha = pathProperties.getAlpha();
if (pathMap["alpha"].isValid()) { //V8TODO I'm not sure how to do this one
alpha = pathMap["alpha"].toFloat(); //width = pathProperties.getWidth;
} drawInFront = (pathProperties.getRenderLayer() == RenderLayer::FRONT);
if (pathMap["width"].isValid()) {
width = pathMap["width"].toFloat();
}
if (pathMap["isVisibleInSecondaryCamera"].isValid()) {
isVisibleInSecondaryCamera = pathMap["isVisibleInSecondaryCamera"].toBool();
}
if (pathMap["drawInFront"].isValid()) {
drawInFront = pathMap["drawInFront"].toBool();
} }
} }
QUuid endID; QUuid endID;
if (propMap["end"].isValid()) { if (propMap["endPropertyIndex"].isValid()) {
QVariantMap endMap = propMap["end"].toMap(); int endPropertyIndex = propMap["endPropertyIndex"].toInt();
if (endMap["type"].isValid()) { if (endPropertyIndex >= 0 && endPropertyIndex < entityProperties.length()) {
endMap.remove("visible"); //endMap.remove("visible");
endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); endID = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties[endPropertyIndex], entity::HostType::LOCAL);
} }
} }

View file

@ -10,6 +10,8 @@
#include "PathPointer.h" #include "PathPointer.h"
#include<EntityItemProperties.h>
#include <render/Item.h> #include <render/Item.h>
class ParabolaPointer : public PathPointer { class ParabolaPointer : public PathPointer {
@ -105,7 +107,7 @@ public:
QVariantMap toVariantMap() const override; 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: protected:
virtual PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override; virtual PickResultPointer getPickResultCopy(const PickResultPointer& pickResult) const override;

View file

@ -22,6 +22,13 @@
#include "StylusPointer.h" #include "StylusPointer.h"
#include "ParabolaPointer.h" #include "ParabolaPointer.h"
#include "StylusPick.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);
}));
static const glm::quat X_ROT_NEG_90{ 0.70710678f, -0.70710678f, 0.0f, 0.0f }; 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_POSITION_OFFSET{0.0f, 0.0f, -StylusPick::WEB_STYLUS_LENGTH / 2.0f};
@ -35,26 +42,26 @@ void PointerScriptingInterface::setIncludeItems(unsigned int uid, const ScriptVa
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); 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 // Interaction with managers should always happen on the main thread
if (QThread::currentThread() != qApp->thread()) { if (QThread::currentThread() != qApp->thread()) {
unsigned int result; 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; return result;
} }
QVariantMap propertyMap = properties.toMap(); QVariantMap propertyMap = properties.properties;
std::shared_ptr<Pointer> pointer; std::shared_ptr<Pointer> pointer;
switch (type) { switch (type) {
case PickQuery::PickType::Ray: case PickQuery::PickType::Ray:
pointer = buildLaserPointer(propertyMap); pointer = buildLaserPointer(properties);
break; break;
case PickQuery::PickType::Stylus: case PickQuery::PickType::Stylus:
pointer = buildStylus(propertyMap); pointer = buildStylus(properties);
break; break;
case PickQuery::PickType::Parabola: case PickQuery::PickType::Parabola:
pointer = buildParabolaPointer(propertyMap); pointer = buildParabolaPointer(properties);
break; break;
default: default:
break; break;
@ -71,6 +78,10 @@ unsigned int PointerScriptingInterface::createPointer(const PickQuery::PickType&
return DependencyManager::get<PointerManager>()->addPointer(pointer); return DependencyManager::get<PointerManager>()->addPointer(pointer);
} }
unsigned int PointerScriptingInterface::createRayPointer(RayPointerProperties properties) {
return createPointerInternal(PickQuery::PickType::Ray, properties);
}
bool PointerScriptingInterface::isPointerEnabled(unsigned int uid) const { bool PointerScriptingInterface::isPointerEnabled(unsigned int uid) const {
return DependencyManager::get<PointerManager>()->isPointerEnabled(uid); return DependencyManager::get<PointerManager>()->isPointerEnabled(uid);
} }
@ -109,8 +120,8 @@ QVariantMap PointerScriptingInterface::getPointerScriptParameters(unsigned int u
* offset. * offset.
* @property {Quat} [rotationOffset] - The rotation offset of the model from the hand, to override the default rotation 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) { std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const PointerProperties& properties) {
QVariantMap propertyMap = properties.toMap(); QVariantMap propertyMap = properties.properties;
bool hover = false; bool hover = false;
if (propertyMap["hover"].isValid()) { if (propertyMap["hover"].isValid()) {
@ -142,7 +153,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 /*@jsdoc
@ -221,8 +232,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildStylus(const QVariant&
* {@link Pointers.getPointerProperties}. * {@link Pointers.getPointerProperties}.
* @see {@link Picks.RayPickProperties} for additional properties from the underlying ray pick. * @see {@link Picks.RayPickProperties} for additional properties from the underlying ray pick.
*/ */
std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVariant& properties) { std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const PointerProperties& properties) {
QVariantMap propertyMap = properties.toMap(); QVariantMap propertyMap = properties.properties;
#if defined (Q_OS_ANDROID) #if defined (Q_OS_ANDROID)
QString jointName { "" }; QString jointName { "" };
@ -284,7 +295,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
QVariantMap renderStateMap = renderStateVariant.toMap(); QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid()) { if (renderStateMap["name"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString(); std::string name = renderStateMap["name"].toString().toStdString();
renderStates[name] = LaserPointer::buildRenderState(renderStateMap); renderStates[name] = LaserPointer::buildRenderState(renderStateMap, properties.entityProperties);
} }
} }
} }
@ -299,7 +310,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString(); std::string name = renderStateMap["name"].toString().toStdString();
float distance = renderStateMap["distance"].toFloat(); 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));
} }
} }
} }
@ -328,7 +340,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, faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
distanceScaleEnd, scaleWithParent, enabled); distanceScaleEnd, scaleWithParent, enabled);
} }
@ -416,8 +428,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildLaserPointer(const QVar
* {@link Pointers.getPointerProperties}. * {@link Pointers.getPointerProperties}.
* @see {@link Picks.ParabolaPickProperties} for additional properties from the underlying parabola pick. * @see {@link Picks.ParabolaPickProperties} for additional properties from the underlying parabola pick.
*/ */
std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const QVariant& properties) { std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const PointerProperties& properties) {
QVariantMap propertyMap = properties.toMap(); QVariantMap propertyMap = properties.properties;
bool faceAvatar = false; bool faceAvatar = false;
if (propertyMap["faceAvatar"].isValid()) { if (propertyMap["faceAvatar"].isValid()) {
@ -468,7 +480,7 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const Q
QVariantMap renderStateMap = renderStateVariant.toMap(); QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid()) { if (renderStateMap["name"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString(); std::string name = renderStateMap["name"].toString().toStdString();
renderStates[name] = ParabolaPointer::buildRenderState(renderStateMap); renderStates[name] = ParabolaPointer::buildRenderState(renderStateMap, properties.entityProperties);
} }
} }
} }
@ -483,7 +495,8 @@ std::shared_ptr<Pointer> PointerScriptingInterface::buildParabolaPointer(const Q
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
std::string name = renderStateMap["name"].toString().toStdString(); std::string name = renderStateMap["name"].toString().toStdString();
float distance = renderStateMap["distance"].toFloat(); 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));
} }
} }
} }
@ -512,12 +525,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, faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
scaleWithParent, enabled); scaleWithParent, enabled);
} }
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const { void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
//V8TODO: this won't work for now
QVariantMap propMap = properties.toMap(); QVariantMap propMap = properties.toMap();
QVariant startProps; QVariant startProps;
@ -546,3 +560,52 @@ QVariantMap PointerScriptingInterface::getPrevPickResult(unsigned int uid) const
} }
return result; 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);
if (out.properties["renderStates"].canConvert<QVariantList>()) {
QVariantList renderStates = out.properties["renderStates"].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("renderStates").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("renderStates").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("renderStates").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["renderStates"].setValue(renderStates);
}
qDebug() << "rayPointerPropertiesFromScriptValue" << out.properties;
return true;
}

View file

@ -14,14 +14,15 @@
#include "DependencyManager.h" #include "DependencyManager.h"
#include "RegisteredMetaTypes.h" #include "RegisteredMetaTypes.h"
#include <EntityItemProperties.h>
#include <PointerManager.h> #include <PointerManager.h>
#include <Pick.h> #include <Pick.h>
class ScriptValue; class ScriptValue;
/*@jsdoc /*@jsdoc
* The <code>Pointers</code> API lets you create, manage, and visually represent objects for repeatedly calculating * 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 * intersections with avatars, entities, and overlays. Pointers can also be configured to generate events on entities and
* overlays intersected. * overlays intersected.
* *
* @namespace Pointers * @namespace Pointers
@ -31,12 +32,34 @@ class ScriptValue;
* @hifi-avatar * @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(PointerProperties);
class PointerScriptingInterface : public QObject, public Dependency { class PointerScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
public: 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 /*@jsdoc
* Specifies that a {@link Controller} action or function should trigger events on the entity or overlay currently * 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} * intersected by a {@link Pointers.RayPointerProperties|Ray} or {@link Pointers.ParabolaPointerProperties|Parabola}
@ -133,7 +156,9 @@ public:
* }); * });
*/ */
// TODO: expand Pointers to be able to be fully configurable with PickFilters // 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);
/*@jsdoc /*@jsdoc
* Enables and shows a pointer. Enabled pointers update their pick results and generate events. * Enables and shows a pointer. Enabled pointers update their pick results and generate events.
@ -479,9 +504,15 @@ public:
Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const; Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const;
protected: protected:
static std::shared_ptr<Pointer> buildLaserPointer(const QVariant& properties); static std::shared_ptr<Pointer> buildLaserPointer(const PointerProperties& properties);
static std::shared_ptr<Pointer> buildStylus(const QVariant& properties); static std::shared_ptr<Pointer> buildStylus(const PointerProperties& properties);
static std::shared_ptr<Pointer> buildParabolaPointer(const QVariant& 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);
bool rayPointerPropertiesFromScriptValue(const ScriptValue& value, RayPointerProperties& out);
#endif // hifi_PointerScriptingInterface_h #endif // hifi_PointerScriptingInterface_h

View file

@ -49,7 +49,7 @@ PickQuery::PickType StylusPointer::getType() const {
QUuid StylusPointer::buildStylus(const QVariantMap& properties) { 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 // 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; QString modelUrl = DEFAULT_STYLUS_MODEL_URL;
@ -69,7 +69,30 @@ QUuid StylusPointer::buildStylus(const QVariantMap& properties) {
propertiesMap["ignorePickIntersection"] = true; propertiesMap["ignorePickIntersection"] = true;
propertiesMap["drawInFront"] = false; 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);
// V8TODO: I can't find equivalent for entities
//propertiesMap["loadPriority"] = 10.0f;
entityProperties.setPrimitiveMode(PrimitiveMode::SOLID);
entityProperties.setVisible(true);
entityProperties.setIgnorePickIntersection(true);
// V8TODO: I can't find equivalent for entities but shouldn't be necessary
//propertiesMap["drawInFront"] = false;
return DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(entityProperties, entity::HostType::LOCAL);
} }
void StylusPointer::updateVisuals(const PickResultPointer& pickResult) { void StylusPointer::updateVisuals(const PickResultPointer& pickResult) {

View file

@ -1051,7 +1051,11 @@ void ScriptMethodV8Proxy::call(const v8::FunctionCallbackInfo<v8::Value>& argume
for (int arg = 0; arg < numArgs; ++arg) { for (int arg = 0; arg < numArgs; ++arg) {
int methodArgTypeId = meta.parameterType(arg); int methodArgTypeId = meta.parameterType(arg);
Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); if (methodArgTypeId == QMetaType::UnknownType) {
QString methodName = fullName();
qCDebug(scriptengine_v8) << "One of the arguments is QMetaType::UnknownType for method " << methodName;
Q_ASSERT(false);
}
v8::Local<v8::Value> argVal = arguments[arg]; v8::Local<v8::Value> argVal = arguments[arg];
if (methodArgTypeId == scriptValueTypeId) { if (methodArgTypeId == scriptValueTypeId) {
qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, argVal)))); qScriptArgLists[i].append(ScriptValue(new ScriptValueV8Wrapper(_engine, V8ScriptValue(_engine, argVal))));

View file

@ -23,58 +23,62 @@ var Pointer = function(hudLayer, pickType, pointerData) {
this.SEARCH_SPHERE_SIZE = 0.0132; this.SEARCH_SPHERE_SIZE = 0.0132;
this.dim = {x: this.SEARCH_SPHERE_SIZE, y: this.SEARCH_SPHERE_SIZE, z: this.SEARCH_SPHERE_SIZE}; this.dim = {x: this.SEARCH_SPHERE_SIZE, y: this.SEARCH_SPHERE_SIZE, z: this.SEARCH_SPHERE_SIZE};
this.halfPath = { this.halfPath = {
type: "line3d", type: "PolyLine",
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
visible: true, visible: true,
alpha: 1, alpha: 1,
solid: true, solid: true,
glow: 1.0, glow: true,
ignoreRayIntersection: true, // always ignore this billboardMode: "yaw",
drawInFront: !hudLayer, // Even when burried inside of something, show it. ignorePickIntersection: true, // always ignore this
//V8TODO
drawInFront: !hudLayer, // Even when buried inside of something, show it.
drawHUDLayer: hudLayer, drawHUDLayer: hudLayer,
}; };
this.halfEnd = { this.halfEnd = {
type: "sphere", type: "Sphere",
dimensions: this.dim, dimensions: this.dim,
solid: true, solid: true,
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
alpha: 0.9, alpha: 0.9,
ignoreRayIntersection: true, ignorePickIntersection: true,
drawInFront: !hudLayer, // Even when burried inside of something, show it. drawInFront: !hudLayer, // Even when buried inside of something, show it.
drawHUDLayer: hudLayer, drawHUDLayer: hudLayer,
visible: true visible: true
}; };
this.fullPath = { this.fullPath = {
type: "line3d", type: "PolyLine",
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
visible: true, visible: true,
alpha: 1, alpha: 1,
solid: true, solid: true,
glow: 1.0, glow: true,
ignoreRayIntersection: true, // always ignore this billboardMode: "yaw",
drawInFront: !hudLayer, // Even when burried inside of something, show it. ignorePickIntersection: true, // always ignore this
drawInFront: !hudLayer, // Even when buried inside of something, show it.
drawHUDLayer: hudLayer, drawHUDLayer: hudLayer,
}; };
this.fullEnd = { this.fullEnd = {
type: "sphere", type: "Sphere",
dimensions: this.dim, dimensions: this.dim,
solid: true, solid: true,
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
alpha: 0.9, alpha: 0.9,
ignoreRayIntersection: true, ignorePickIntersection: true,
drawInFront: !hudLayer, // Even when burried inside of something, show it. drawInFront: !hudLayer, // Even when buried inside of something, show it.
drawHUDLayer: hudLayer, drawHUDLayer: hudLayer,
visible: true visible: true
}; };
this.holdPath = { this.holdPath = {
type: "line3d", type: "PolyLine",
color: COLORS_GRAB_DISTANCE_HOLD, color: COLORS_GRAB_DISTANCE_HOLD,
visible: true, visible: true,
alpha: 1, alpha: 1,
solid: true, solid: true,
glow: 1.0, glow: true,
ignoreRayIntersection: true, // always ignore this billboardMode: "yaw",
drawInFront: !hudLayer, // Even when burried inside of something, show it. ignorePickIntersection: true, // always ignore this
drawInFront: !hudLayer, // Even when buried inside of something, show it.
drawHUDLayer: hudLayer, drawHUDLayer: hudLayer,
}; };
@ -99,6 +103,7 @@ var Pointer = function(hudLayer, pickType, pointerData) {
delete pointerData.hand; delete pointerData.hand;
function createPointer(pickType, pointerData) { function createPointer(pickType, pointerData) {
//V8TODO
var pointerID = Pointers.createPointer(pickType, pointerData); var pointerID = Pointers.createPointer(pickType, pointerData);
Pointers.setRenderState(pointerID, ""); Pointers.setRenderState(pointerID, "");
Pointers.enablePointer(pointerID); Pointers.enablePointer(pointerID);