mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-08 13:34:01 +02:00
Merge pull request #14075 from ctrlaltdavid/M18586
Teleport with play area
This commit is contained in:
commit
4805d3564a
29 changed files with 758 additions and 77 deletions
|
@ -34,7 +34,7 @@ Preference {
|
|||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: isFirstCheckBox ? hifi.dimensions.controlInterlineHeight : 0
|
||||
height: isFirstCheckBox && !preference.indented ? 16 : 2
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
|
@ -54,6 +54,7 @@ Preference {
|
|||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
leftMargin: preference.indented ? 20 : 0
|
||||
}
|
||||
text: root.label
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
|
|
@ -11,14 +11,27 @@
|
|||
import QtQuick 2.5
|
||||
|
||||
import "../../controls-uit"
|
||||
import "../../styles-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
|
||||
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
property int value: 0
|
||||
|
||||
Component.onCompleted: {
|
||||
repeater.itemAt(preference.value).checked = true
|
||||
value = preference.value;
|
||||
repeater.itemAt(preference.value).checked = true;
|
||||
}
|
||||
|
||||
function updateValue() {
|
||||
for (var i = 0; i < repeater.count; i++) {
|
||||
if (repeater.itemAt(i).checked) {
|
||||
value = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
@ -33,24 +46,36 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Row {
|
||||
Column {
|
||||
id: control
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
spacing: 5
|
||||
spacing: 3
|
||||
|
||||
RalewaySemiBold {
|
||||
id: heading
|
||||
size: hifi.fontSizes.inputLabel
|
||||
text: preference.heading
|
||||
color: hifi.colors.lightGrayText
|
||||
visible: text !== ""
|
||||
bottomPadding: 3
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: preference.items.length
|
||||
delegate: RadioButton {
|
||||
text: preference.items[index]
|
||||
letterSpacing: 0
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
}
|
||||
leftPadding: 0
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
onClicked: updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,11 +138,12 @@ Preference {
|
|||
break;
|
||||
|
||||
case Preference.PrimaryHand:
|
||||
checkBoxCount++;
|
||||
checkBoxCount = 0;
|
||||
builder = primaryHandBuilder;
|
||||
break;
|
||||
|
||||
case Preference.RadioButtons:
|
||||
checkBoxCount++;
|
||||
checkBoxCount = 0;
|
||||
builder = radioButtonsBuilder;
|
||||
break;
|
||||
};
|
||||
|
|
|
@ -122,6 +122,22 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
// Runtime customization of preferences.
|
||||
var locomotionPreference = findPreference("VR Movement", "Teleporting only / Walking and teleporting");
|
||||
var flyingPreference = findPreference("VR Movement", "Jumping and flying");
|
||||
if (locomotionPreference && flyingPreference) {
|
||||
flyingPreference.visible = (locomotionPreference.value === 1);
|
||||
locomotionPreference.valueChanged.connect(function () {
|
||||
flyingPreference.visible = (locomotionPreference.value === 1);
|
||||
});
|
||||
}
|
||||
if (HMD.isHeadControllerAvailable("Oculus")) {
|
||||
var boundariesPreference = findPreference("VR Movement", "Show room boundaries while teleporting");
|
||||
if (boundariesPreference) {
|
||||
boundariesPreference.label = "Show room boundaries and sensors while teleporting";
|
||||
}
|
||||
}
|
||||
|
||||
if (sections.length) {
|
||||
// Default sections to expanded/collapsed as appropriate for dialog.
|
||||
if (sections.length === 1) {
|
||||
|
@ -234,4 +250,32 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findPreference(category, name) {
|
||||
var section = null;
|
||||
var preference = null;
|
||||
var i;
|
||||
|
||||
// Find category section.
|
||||
i = 0;
|
||||
while (!section && i < sections.length) {
|
||||
if (sections[i].name === category) {
|
||||
section = sections[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Find named preference.
|
||||
if (section) {
|
||||
i = 0;
|
||||
while (!preference && i < section.preferences.length) {
|
||||
if (section.preferences[i].preference && section.preferences[i].preference.name === name) {
|
||||
preference = section.preferences[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return preference;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,11 +153,12 @@ Preference {
|
|||
break;
|
||||
|
||||
case Preference.PrimaryHand:
|
||||
checkBoxCount++;
|
||||
checkBoxCount = 0;
|
||||
builder = primaryHandBuilder;
|
||||
break;
|
||||
|
||||
case Preference.RadioButtons:
|
||||
checkBoxCount++;
|
||||
checkBoxCount = 0;
|
||||
builder = radioButtonsBuilder;
|
||||
break;
|
||||
};
|
||||
|
|
|
@ -106,6 +106,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
_useAdvancedMovementControls("advancedMovementForHandControllersIsChecked", true),
|
||||
_showPlayArea("showPlayArea", true),
|
||||
_smoothOrientationTimer(std::numeric_limits<float>::max()),
|
||||
_smoothOrientationInitial(),
|
||||
_smoothOrientationTarget(),
|
||||
|
@ -3307,7 +3308,7 @@ float MyAvatar::getRawDriveKey(DriveKeys key) const {
|
|||
}
|
||||
|
||||
void MyAvatar::relayDriveKeysToCharacterController() {
|
||||
if (getDriveKey(TRANSLATE_Y) > 0.0f) {
|
||||
if (getDriveKey(TRANSLATE_Y) > 0.0f && (!qApp->isHMDMode() || (useAdvancedMovementControls() && getFlyingHMDPref()))) {
|
||||
_characterController.jump();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,8 +122,10 @@ class MyAvatar : public Avatar {
|
|||
* zone may disallow collisionless avatars.
|
||||
* @property {boolean} characterControllerEnabled - Synonym of <code>collisionsEnabled</code>.
|
||||
* <strong>Deprecated:</strong> Use <code>collisionsEnabled</code> instead.
|
||||
* @property {boolean} useAdvancedMovementControls - Returns the value of the Interface setting, Settings > Advanced
|
||||
* Movement for Hand Controller. Note: Setting the value has no effect unless Interface is restarted.
|
||||
* @property {boolean} useAdvancedMovementControls - Returns and sets the value of the Interface setting, Settings >
|
||||
* Walking and teleporting. Note: Setting the value has no effect unless Interface is restarted.
|
||||
* @property {boolean} showPlayArea - Returns and sets the value of the Interface setting, Settings > Show room boundaries
|
||||
* while teleporting. Note: Setting the value has no effect unless Interface is restarted.
|
||||
* @property {number} yawSpeed=75
|
||||
* @property {number} pitchSpeed=50
|
||||
* @property {boolean} hmdRollControlEnabled=true - If <code>true</code>, the roll angle of your HMD turns your avatar
|
||||
|
@ -223,6 +225,7 @@ class MyAvatar : public Avatar {
|
|||
Q_PROPERTY(bool collisionsEnabled READ getCollisionsEnabled WRITE setCollisionsEnabled)
|
||||
Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled)
|
||||
Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls)
|
||||
Q_PROPERTY(bool showPlayArea READ getShowPlayArea WRITE setShowPlayArea)
|
||||
|
||||
Q_PROPERTY(float yawSpeed MEMBER _yawSpeed)
|
||||
Q_PROPERTY(float pitchSpeed MEMBER _pitchSpeed)
|
||||
|
@ -542,6 +545,9 @@ public:
|
|||
void setUseAdvancedMovementControls(bool useAdvancedMovementControls)
|
||||
{ _useAdvancedMovementControls.set(useAdvancedMovementControls); }
|
||||
|
||||
bool getShowPlayArea() const { return _showPlayArea.get(); }
|
||||
void setShowPlayArea(bool showPlayArea) { _showPlayArea.set(showPlayArea); }
|
||||
|
||||
void setHMDRollControlEnabled(bool value) { _hmdRollControlEnabled = value; }
|
||||
bool getHMDRollControlEnabled() const { return _hmdRollControlEnabled; }
|
||||
void setHMDRollControlDeadZone(float value) { _hmdRollControlDeadZone = value; }
|
||||
|
@ -1631,6 +1637,7 @@ private:
|
|||
|
||||
Setting::Handle<float> _realWorldFieldOfView;
|
||||
Setting::Handle<bool> _useAdvancedMovementControls;
|
||||
Setting::Handle<bool> _showPlayArea;
|
||||
|
||||
// Smoothing.
|
||||
const float SMOOTH_TIME_ORIENTATION = 0.5f;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
const glm::vec4 ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_COLOR { 1.0f };
|
||||
const float ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_WIDTH { 0.01f };
|
||||
const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA { false };
|
||||
const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT { false };
|
||||
|
||||
gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_parabolaPipeline { nullptr };
|
||||
gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::_transparentParabolaPipeline { nullptr };
|
||||
|
@ -46,6 +47,7 @@ void ParabolaPointer::editRenderStatePath(const std::string& state, const QVaria
|
|||
float alpha = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_COLOR.a;
|
||||
float width = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_WIDTH;
|
||||
bool isVisibleInSecondaryCamera = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA;
|
||||
bool drawInFront = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT;
|
||||
bool enabled = false;
|
||||
if (!pathMap.isEmpty()) {
|
||||
enabled = true;
|
||||
|
@ -63,8 +65,11 @@ void ParabolaPointer::editRenderStatePath(const std::string& state, const QVaria
|
|||
if (pathMap["isVisibleInSecondaryCamera"].isValid()) {
|
||||
isVisibleInSecondaryCamera = pathMap["isVisibleInSecondaryCamera"].toBool();
|
||||
}
|
||||
if (pathMap["drawInFront"].isValid()) {
|
||||
drawInFront = pathMap["drawInFront"].toBool();
|
||||
}
|
||||
}
|
||||
renderState->editParabola(color, alpha, width, isVisibleInSecondaryCamera, enabled);
|
||||
renderState->editParabola(color, alpha, width, isVisibleInSecondaryCamera, drawInFront, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +151,7 @@ void ParabolaPointer::setVisualPickResultInternal(PickResultPointer pickResult,
|
|||
}
|
||||
|
||||
ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
|
||||
bool isVisibleInSecondaryCamera, bool pathEnabled) :
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled) :
|
||||
StartEndRenderState(startID, endID)
|
||||
{
|
||||
render::Transaction transaction;
|
||||
|
@ -154,7 +159,7 @@ ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const Overla
|
|||
_pathID = scene->allocateID();
|
||||
_pathWidth = pathWidth;
|
||||
if (render::Item::isValidID(_pathID)) {
|
||||
auto renderItem = std::make_shared<ParabolaRenderItem>(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, pathEnabled);
|
||||
auto renderItem = std::make_shared<ParabolaRenderItem>(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, drawInFront, pathEnabled);
|
||||
transaction.resetItem(_pathID, std::make_shared<ParabolaRenderItem::Payload>(renderItem));
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
@ -182,15 +187,16 @@ void ParabolaPointer::RenderState::disable() {
|
|||
}
|
||||
}
|
||||
|
||||
void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool enabled) {
|
||||
void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled) {
|
||||
if (render::Item::isValidID(_pathID)) {
|
||||
render::Transaction transaction;
|
||||
auto scene = qApp->getMain3DScene();
|
||||
transaction.updateItem<ParabolaRenderItem>(_pathID, [color, alpha, width, isVisibleInSecondaryCamera, enabled](ParabolaRenderItem& item) {
|
||||
transaction.updateItem<ParabolaRenderItem>(_pathID, [color, alpha, width, isVisibleInSecondaryCamera, drawInFront, enabled](ParabolaRenderItem& item) {
|
||||
item.setColor(color);
|
||||
item.setAlpha(alpha);
|
||||
item.setWidth(width);
|
||||
item.setIsVisibleInSecondaryCamera(isVisibleInSecondaryCamera);
|
||||
item.setDrawInFront(drawInFront);
|
||||
item.setEnabled(enabled);
|
||||
item.updateKey();
|
||||
});
|
||||
|
@ -238,6 +244,7 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
|
|||
float alpha = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_COLOR.a;
|
||||
float width = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_WIDTH;
|
||||
bool isVisibleInSecondaryCamera = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA;
|
||||
bool drawInFront = RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_DRAWINFRONT;
|
||||
bool enabled = false;
|
||||
if (propMap["path"].isValid()) {
|
||||
enabled = true;
|
||||
|
@ -258,6 +265,10 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
|
|||
if (pathMap["isVisibleInSecondaryCamera"].isValid()) {
|
||||
isVisibleInSecondaryCamera = pathMap["isVisibleInSecondaryCamera"].toBool();
|
||||
}
|
||||
|
||||
if (pathMap["drawInFront"].isValid()) {
|
||||
drawInFront = pathMap["drawInFront"].toBool();
|
||||
}
|
||||
}
|
||||
|
||||
QUuid endID;
|
||||
|
@ -269,7 +280,7 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
|
|||
}
|
||||
}
|
||||
|
||||
return std::make_shared<RenderState>(startID, endID, color, alpha, width, isVisibleInSecondaryCamera, enabled);
|
||||
return std::make_shared<RenderState>(startID, endID, color, alpha, width, isVisibleInSecondaryCamera, drawInFront, enabled);
|
||||
}
|
||||
|
||||
PointerEvent ParabolaPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button, bool hover) {
|
||||
|
@ -321,8 +332,8 @@ glm::vec3 ParabolaPointer::findIntersection(const PickedObject& pickedObject, co
|
|||
}
|
||||
|
||||
ParabolaPointer::RenderState::ParabolaRenderItem::ParabolaRenderItem(const glm::vec3& color, float alpha, float width,
|
||||
bool isVisibleInSecondaryCamera, bool enabled) :
|
||||
_isVisibleInSecondaryCamera(isVisibleInSecondaryCamera), _enabled(enabled)
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled) :
|
||||
_isVisibleInSecondaryCamera(isVisibleInSecondaryCamera), _drawInFront(drawInFront), _enabled(enabled)
|
||||
{
|
||||
_uniformBuffer->resize(sizeof(ParabolaData));
|
||||
setColor(color);
|
||||
|
@ -358,6 +369,10 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() {
|
|||
builder.withTagBits(render::hifi::TAG_MAIN_VIEW);
|
||||
}
|
||||
|
||||
if (_drawInFront) {
|
||||
builder.withLayer(render::hifi::LAYER_3D_FRONT);
|
||||
}
|
||||
|
||||
_key = builder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
using Pointer = Payload::DataPointer;
|
||||
|
||||
ParabolaRenderItem(const glm::vec3& color, float alpha, float width,
|
||||
bool isVisibleInSecondaryCamera, bool enabled);
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
|
||||
~ParabolaRenderItem() {}
|
||||
|
||||
static gpu::PipelinePointer _parabolaPipeline;
|
||||
|
@ -46,11 +46,13 @@ public:
|
|||
void setAcceleration(const glm::vec3& acceleration) { _parabolaData.acceleration = acceleration; }
|
||||
void setOrigin(const glm::vec3& origin) { _origin = origin; }
|
||||
void setIsVisibleInSecondaryCamera(const bool& isVisibleInSecondaryCamera) { _isVisibleInSecondaryCamera = isVisibleInSecondaryCamera; }
|
||||
void setDrawInFront(const bool& drawInFront) { _drawInFront = drawInFront; }
|
||||
void setEnabled(const bool& enabled) { _enabled = enabled; }
|
||||
|
||||
static const glm::vec4 DEFAULT_PARABOLA_COLOR;
|
||||
static const float DEFAULT_PARABOLA_WIDTH;
|
||||
static const bool DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA;
|
||||
static const bool DEFAULT_PARABOLA_DRAWINFRONT;
|
||||
|
||||
private:
|
||||
render::Item::Bound _bound;
|
||||
|
@ -58,6 +60,7 @@ public:
|
|||
|
||||
glm::vec3 _origin { 0.0f };
|
||||
bool _isVisibleInSecondaryCamera { DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA };
|
||||
bool _drawInFront { DEFAULT_PARABOLA_DRAWINFRONT };
|
||||
bool _visible { false };
|
||||
bool _enabled { false };
|
||||
|
||||
|
@ -77,7 +80,7 @@ public:
|
|||
|
||||
RenderState() {}
|
||||
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
|
||||
bool isVisibleInSecondaryCamera, bool pathEnabled);
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled);
|
||||
|
||||
void setPathWidth(float width) { _pathWidth = width; }
|
||||
float getPathWidth() const { return _pathWidth; }
|
||||
|
@ -87,7 +90,7 @@ public:
|
|||
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
|
||||
|
||||
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool enabled);
|
||||
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
|
||||
|
||||
private:
|
||||
int _pathID;
|
||||
|
|
|
@ -218,6 +218,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
|||
* @property {number} alpha=1.0 The alpha of the parabola.
|
||||
* @property {number} width=0.01 The width of the parabola, in meters.
|
||||
* @property {boolean} isVisibleInSecondaryCamera=false The width of the parabola, in meters.
|
||||
* @property {boolean} drawInFront=false If <code>true</code>, the parabola is rendered in front of other items in the scene.
|
||||
*/
|
||||
/**jsdoc
|
||||
* A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.ParabolaPointerRenderState},
|
||||
|
@ -393,4 +394,4 @@ QVariantMap PointerScriptingInterface::getPrevPickResult(unsigned int uid) const
|
|||
|
||||
QVariantMap PointerScriptingInterface::getPointerProperties(unsigned int uid) const {
|
||||
return DependencyManager::get<PointerManager>()->getPointerProperties(uid);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* Returns information about an existing Pointer
|
||||
* @function Pointers.getPointerState
|
||||
* @function Pointers.getPointerProperties
|
||||
* @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}.
|
||||
* @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer.
|
||||
* Currently only includes renderStates and defaultRenderStates with associated overlay IDs.
|
||||
|
|
|
@ -241,4 +241,4 @@ glm::vec2 StylusPointer::findPos2D(const PickedObject& pickedObject, const glm::
|
|||
default:
|
||||
return glm::vec2(NAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,3 +201,12 @@ bool HMDScriptingInterface::isKeyboardVisible() {
|
|||
void HMDScriptingInterface::centerUI() {
|
||||
QMetaObject::invokeMethod(qApp, "centerUI", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QVariant HMDScriptingInterface::getPlayAreaRect() {
|
||||
auto rect = qApp->getActiveDisplayPlugin()->getPlayAreaRect();
|
||||
return qRectFToVariant(rect);
|
||||
}
|
||||
|
||||
QVector<glm::vec3> HMDScriptingInterface::getSensorPositions() {
|
||||
return qApp->getActiveDisplayPlugin()->getSensorPositions();
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ class QScriptEngine;
|
|||
* @property {Uuid} miniTabletScreenID - The UUID of the mini tablet's screen overlay. <code>null</code> if not in HMD mode.
|
||||
* @property {number} miniTabletHand - The hand that the mini tablet is displayed on: <code>0</code> for left hand,
|
||||
* <code>1</code> for right hand, <code>-1</code> if not in HMD mode.
|
||||
* @property {Rect} playArea=0,0,0,0 - The size and position of the HMD play area in sensor coordinates. <em>Read-only.</em>
|
||||
* @property {Vec3[]} sensorPositions=[]] - The positions of the VR system sensors in sensor coordinates. <em>Read-only.</em>
|
||||
*/
|
||||
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -75,6 +77,8 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(QUuid miniTabletID READ getCurrentMiniTabletID WRITE setCurrentMiniTabletID)
|
||||
Q_PROPERTY(QUuid miniTabletScreenID READ getCurrentMiniTabletScreenID WRITE setCurrentMiniTabletScreenID)
|
||||
Q_PROPERTY(int miniTabletHand READ getCurrentMiniTabletHand WRITE setCurrentMiniTabletHand)
|
||||
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
|
||||
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -384,6 +388,9 @@ public:
|
|||
void setCurrentMiniTabletHand(int miniTabletHand) { _miniTabletHand = miniTabletHand; }
|
||||
int getCurrentMiniTabletHand() const { return _miniTabletHand; }
|
||||
|
||||
QVariant getPlayAreaRect();
|
||||
QVector<glm::vec3> getSensorPositions();
|
||||
|
||||
private:
|
||||
bool _showTablet { false };
|
||||
bool _tabletContextualMode { false };
|
||||
|
|
|
@ -226,18 +226,22 @@ void setupPreferences() {
|
|||
|
||||
static const QString VR_MOVEMENT{ "VR Movement" };
|
||||
{
|
||||
|
||||
static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler");
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->useAdvancedMovementControls(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
|
||||
preferences->addPreference(new CheckPreference(VR_MOVEMENT,
|
||||
QStringLiteral("Advanced movement in VR (Teleport movement when unchecked)"),
|
||||
getter, setter));
|
||||
auto getter = [myAvatar]()->int { return myAvatar->useAdvancedMovementControls() ? 1 : 0; };
|
||||
auto setter = [myAvatar](int value) { myAvatar->setUseAdvancedMovementControls(value == 1); };
|
||||
auto preference =
|
||||
new RadioButtonsPreference(VR_MOVEMENT, "Teleporting only / Walking and teleporting", getter, setter);
|
||||
QStringList items;
|
||||
items << "Teleporting only" << "Walking and teleporting";
|
||||
preference->setHeading("Movement mode");
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->getFlyingHMDPref(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setFlyingHMDPref(value); };
|
||||
preferences->addPreference(new CheckPreference(VR_MOVEMENT, "Flying & jumping (HMD)", getter, setter));
|
||||
auto preference = new CheckPreference(VR_MOVEMENT, "Jumping and flying", getter, setter);
|
||||
preference->setIndented(true);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
|
||||
|
@ -245,9 +249,16 @@ void setupPreferences() {
|
|||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Snap turn / Smooth turn", getter, setter);
|
||||
QStringList items;
|
||||
items << "Snap turn" << "Smooth turn";
|
||||
preference->setHeading("Rotation mode");
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); };
|
||||
auto preference = new CheckPreference(VR_MOVEMENT, "Show room boundaries while teleporting", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->float { return myAvatar->getUserHeight(); };
|
||||
auto setter = [=](float value) { myAvatar->setUserHeight(value); };
|
||||
|
@ -258,12 +269,6 @@ void setupPreferences() {
|
|||
preference->setStep(0.001f);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto preference = new ButtonPreference(VR_MOVEMENT, "RESET SENSORS", [] {
|
||||
qApp->resetSensors();
|
||||
});
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
static const QString AVATAR_CAMERA{ "Mouse Sensitivity" };
|
||||
{
|
||||
|
|
|
@ -112,6 +112,9 @@ public:
|
|||
virtual bool suppressKeyboard() { return false; }
|
||||
virtual void unsuppressKeyboard() {};
|
||||
virtual bool isKeyboardVisible() { return false; }
|
||||
|
||||
virtual QRectF getPlayAreaRect() { return QRectF(); }
|
||||
virtual QVector<glm::vec3> getSensorPositions() { return QVector<glm::vec3>(); }
|
||||
};
|
||||
|
||||
class DisplayPlugin : public Plugin, public HmdDisplay {
|
||||
|
|
|
@ -153,4 +153,4 @@ bool PointerManager::isMouse(unsigned int uid) {
|
|||
return pointer->isMouse();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ layout(location=0) in vec2 varTexCoord0;
|
|||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
const float FAR_Z = 1.0;
|
||||
const float LINEAR_DEPTH_BIAS = 5e-3;
|
||||
const float OPACITY_EPSILON = 5e-3;
|
||||
|
||||
<@func main(IS_FILLED)@>
|
||||
|
@ -46,7 +45,7 @@ void main(void) {
|
|||
highlightedDepth = -evalZeyeFromZdb(highlightedDepth);
|
||||
sceneDepth = -evalZeyeFromZdb(sceneDepth);
|
||||
|
||||
if (sceneDepth < (highlightedDepth-LINEAR_DEPTH_BIAS)) {
|
||||
if (sceneDepth < highlightedDepth) {
|
||||
outFragColor = vec4(params._fillOccludedColor, params._fillOccludedAlpha);
|
||||
} else {
|
||||
outFragColor = vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha);
|
||||
|
@ -107,7 +106,7 @@ void main(void) {
|
|||
sceneDepth = -evalZeyeFromZdb(sceneDepth);
|
||||
|
||||
// Are we occluded?
|
||||
if (sceneDepth < (outlinedDepth/*-LINEAR_DEPTH_BIAS*/)) {
|
||||
if (sceneDepth < outlinedDepth) {
|
||||
outFragColor = vec4(params._outlineOccludedColor, intensity * params._outlineOccludedAlpha);
|
||||
} else {
|
||||
outFragColor = vec4(params._outlineUnoccludedColor, intensity * params._outlineUnoccludedAlpha);
|
||||
|
|
|
@ -340,10 +340,16 @@ public:
|
|||
|
||||
class CheckPreference : public BoolPreference {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool indented READ getIndented CONSTANT)
|
||||
public:
|
||||
CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||
: BoolPreference(category, name, getter, setter) { }
|
||||
Type getType() override { return Checkbox; }
|
||||
|
||||
bool getIndented() { return _isIndented; }
|
||||
void setIndented(const bool indented) { _isIndented = indented; }
|
||||
protected:
|
||||
bool _isIndented { false };
|
||||
};
|
||||
|
||||
class PrimaryHandPreference : public StringPreference {
|
||||
|
@ -356,16 +362,20 @@ public:
|
|||
|
||||
class RadioButtonsPreference : public IntPreference {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString heading READ getHeading CONSTANT)
|
||||
Q_PROPERTY(QStringList items READ getItems CONSTANT)
|
||||
public:
|
||||
RadioButtonsPreference(const QString& category, const QString& name, Getter getter, Setter setter)
|
||||
: IntPreference(category, name, getter, setter) { }
|
||||
Type getType() override { return RadioButtons; }
|
||||
|
||||
const QString& getHeading() { return _heading; }
|
||||
const QStringList& getItems() { return _items; }
|
||||
void setHeading(const QString& heading) { _heading = heading; }
|
||||
void setItems(const QStringList& items) { _items = items; }
|
||||
|
||||
protected:
|
||||
QString _heading;
|
||||
QStringList _items;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -552,6 +552,14 @@ glm::vec2 vec2FromVariant(const QVariant &object) {
|
|||
return vec2FromVariant(object, valid);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* Defines a rectangular portion of an image or screen, or similar.
|
||||
* @typedef {object} Rect
|
||||
* @property {number} x - Left, x-coordinate value.
|
||||
* @property {number} y - Top, y-coordinate value.
|
||||
* @property {number} width - Width of the rectangle.
|
||||
* @property {number} height - Height of the rectangle.
|
||||
*/
|
||||
QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", rect.x());
|
||||
|
@ -568,22 +576,6 @@ void qRectFromScriptValue(const QScriptValue &object, QRect& rect) {
|
|||
rect.setHeight(object.property("height").toVariant().toInt());
|
||||
}
|
||||
|
||||
QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("red", color.red);
|
||||
obj.setProperty("green", color.green);
|
||||
obj.setProperty("blue", color.blue);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* Defines a rectangular portion of an image or screen.
|
||||
* @typedef {object} Rect
|
||||
* @property {number} x - Integer left, x-coordinate value.
|
||||
* @property {number} y - Integer top, y-coordinate value.
|
||||
* @property {number} width - Integer width of the rectangle.
|
||||
* @property {number} height - Integer height of the rectangle.
|
||||
*/
|
||||
QVariant qRectToVariant(const QRect& rect) {
|
||||
QVariantMap obj;
|
||||
obj["x"] = rect.x();
|
||||
|
@ -615,6 +607,61 @@ QRect qRectFromVariant(const QVariant& object) {
|
|||
return qRectFromVariant(object, valid);
|
||||
}
|
||||
|
||||
QScriptValue qRectFToScriptValue(QScriptEngine* engine, const QRectF& rect) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", rect.x());
|
||||
obj.setProperty("y", rect.y());
|
||||
obj.setProperty("width", rect.width());
|
||||
obj.setProperty("height", rect.height());
|
||||
return obj;
|
||||
}
|
||||
|
||||
void qRectFFromScriptValue(const QScriptValue &object, QRectF& rect) {
|
||||
rect.setX(object.property("x").toVariant().toFloat());
|
||||
rect.setY(object.property("y").toVariant().toFloat());
|
||||
rect.setWidth(object.property("width").toVariant().toFloat());
|
||||
rect.setHeight(object.property("height").toVariant().toFloat());
|
||||
}
|
||||
|
||||
QVariant qRectFToVariant(const QRectF& rect) {
|
||||
QVariantMap obj;
|
||||
obj["x"] = rect.x();
|
||||
obj["y"] = rect.y();
|
||||
obj["width"] = rect.width();
|
||||
obj["height"] = rect.height();
|
||||
return obj;
|
||||
}
|
||||
|
||||
QRectF qRectFFromVariant(const QVariant& objectVar, bool& valid) {
|
||||
QVariantMap object = objectVar.toMap();
|
||||
QRectF rect;
|
||||
valid = false;
|
||||
rect.setX(object["x"].toFloat(&valid));
|
||||
if (valid) {
|
||||
rect.setY(object["y"].toFloat(&valid));
|
||||
}
|
||||
if (valid) {
|
||||
rect.setWidth(object["width"].toFloat(&valid));
|
||||
}
|
||||
if (valid) {
|
||||
rect.setHeight(object["height"].toFloat(&valid));
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
QRectF qRectFFromVariant(const QVariant& object) {
|
||||
bool valid;
|
||||
return qRectFFromVariant(object, valid);
|
||||
}
|
||||
|
||||
|
||||
QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("red", color.red);
|
||||
obj.setProperty("green", color.green);
|
||||
obj.setProperty("blue", color.blue);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void xColorFromScriptValue(const QScriptValue &object, xColor& color) {
|
||||
if (!object.isValid()) {
|
||||
|
|
|
@ -100,7 +100,11 @@ void qRectFromScriptValue(const QScriptValue& object, QRect& rect);
|
|||
QRect qRectFromVariant(const QVariant& object, bool& isValid);
|
||||
QRect qRectFromVariant(const QVariant& object);
|
||||
QVariant qRectToVariant(const QRect& rect);
|
||||
|
||||
QScriptValue qRectFToScriptValue(QScriptEngine* engine, const QRectF& rect);
|
||||
void qRectFFromScriptValue(const QScriptValue& object, QRectF& rect);
|
||||
QRectF qRectFFromVariant(const QVariant& object, bool& isValid);
|
||||
QRectF qRectFFromVariant(const QVariant& object);
|
||||
QVariant qRectFToVariant(const QRectF& rect);
|
||||
|
||||
// xColor
|
||||
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
||||
|
|
|
@ -171,3 +171,53 @@ void OculusBaseDisplayPlugin::updatePresentPose() {
|
|||
_currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
||||
_currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
|
||||
}
|
||||
|
||||
QRectF OculusBaseDisplayPlugin::getPlayAreaRect() {
|
||||
if (!_session) {
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
int floorPointsCount = 0;
|
||||
auto result = ovr_GetBoundaryGeometry(_session, ovrBoundary_PlayArea, nullptr, &floorPointsCount);
|
||||
if (!OVR_SUCCESS(result) || floorPointsCount != 4) {
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
auto floorPoints = new ovrVector3f[floorPointsCount];
|
||||
result = ovr_GetBoundaryGeometry(_session, ovrBoundary_PlayArea, floorPoints, nullptr);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
auto minXZ = ovr::toGlm(floorPoints[0]);
|
||||
auto maxXZ = minXZ;
|
||||
for (int i = 1; i < floorPointsCount; i++) {
|
||||
auto point = ovr::toGlm(floorPoints[i]);
|
||||
minXZ.x = std::min(minXZ.x, point.x);
|
||||
minXZ.z = std::min(minXZ.z, point.z);
|
||||
maxXZ.x = std::max(maxXZ.x, point.x);
|
||||
maxXZ.z = std::max(maxXZ.z, point.z);
|
||||
}
|
||||
|
||||
glm::vec2 center = glm::vec2((minXZ.x + maxXZ.x) / 2, (minXZ.z + maxXZ.z) / 2);
|
||||
glm::vec2 dimensions = glm::vec2(maxXZ.x - minXZ.x, maxXZ.z - minXZ.z);
|
||||
|
||||
return QRectF(center.x, center.y, dimensions.x, dimensions.y);
|
||||
}
|
||||
|
||||
QVector<glm::vec3> OculusBaseDisplayPlugin::getSensorPositions() {
|
||||
if (!_session) {
|
||||
return QVector<glm::vec3>();
|
||||
}
|
||||
|
||||
QVector<glm::vec3> result;
|
||||
auto numTrackers = ovr_GetTrackerCount(_session);
|
||||
for (uint i = 0; i < numTrackers; i++) {
|
||||
auto trackerPose = ovr_GetTrackerPose(_session, i);
|
||||
if (trackerPose.TrackerFlags & ovrTracker_PoseTracked) {
|
||||
result.append(ovr::toGlm(trackerPose.Pose.Position));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ public:
|
|||
void resetSensors() override final;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||
|
||||
QRectF getPlayAreaRect() override;
|
||||
QVector<glm::vec3> getSensorPositions() override;
|
||||
|
||||
protected:
|
||||
void customizeContext() override;
|
||||
|
|
|
@ -750,3 +750,37 @@ QString OpenVrDisplayPlugin::getPreferredAudioOutDevice() const {
|
|||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
QRectF OpenVrDisplayPlugin::getPlayAreaRect() {
|
||||
auto chaperone = vr::VRChaperone();
|
||||
if (!chaperone) {
|
||||
qWarning() << "No chaperone";
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
if (chaperone->GetCalibrationState() >= vr::ChaperoneCalibrationState_Error) {
|
||||
qWarning() << "Chaperone status =" << chaperone->GetCalibrationState();
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
vr::HmdQuad_t rect;
|
||||
if (!chaperone->GetPlayAreaRect(&rect)) {
|
||||
qWarning() << "Chaperone rect not obtained";
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
auto minXZ = transformPoint(_sensorResetMat, toGlm(rect.vCorners[0]));
|
||||
auto maxXZ = minXZ;
|
||||
for (int i = 1; i < 4; i++) {
|
||||
auto point = transformPoint(_sensorResetMat, toGlm(rect.vCorners[i]));
|
||||
minXZ.x = std::min(minXZ.x, point.x);
|
||||
minXZ.z = std::min(minXZ.z, point.z);
|
||||
maxXZ.x = std::max(maxXZ.x, point.x);
|
||||
maxXZ.z = std::max(maxXZ.z, point.z);
|
||||
}
|
||||
|
||||
glm::vec2 center = glm::vec2((minXZ.x + maxXZ.x) / 2, (minXZ.z + maxXZ.z) / 2);
|
||||
glm::vec2 dimensions = glm::vec2(maxXZ.x - minXZ.x, maxXZ.z - minXZ.z);
|
||||
|
||||
return QRectF(center.x, center.y, dimensions.x, dimensions.y);
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ public:
|
|||
QString getPreferredAudioInDevice() const override;
|
||||
QString getPreferredAudioOutDevice() const override;
|
||||
|
||||
QRectF getPlayAreaRect() override;
|
||||
|
||||
protected:
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
|
|
BIN
scripts/system/assets/models/oculusSensorv11.fbx
Normal file
BIN
scripts/system/assets/models/oculusSensorv11.fbx
Normal file
Binary file not shown.
BIN
scripts/system/assets/models/teleportationSpotBasev8.fbx
Normal file
BIN
scripts/system/assets/models/teleportationSpotBasev8.fbx
Normal file
Binary file not shown.
BIN
scripts/system/assets/models/trackingSpacev18.fbx
Normal file
BIN
scripts/system/assets/models/trackingSpacev18.fbx
Normal file
Binary file not shown.
|
@ -21,14 +21,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleport-destination.fbx");
|
||||
var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleportationSpotBasev8.fbx");
|
||||
var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx");
|
||||
|
||||
var TARGET_MODEL_DIMENSIONS = {
|
||||
x: 1.15,
|
||||
y: 0.5,
|
||||
z: 1.15
|
||||
};
|
||||
var TARGET_MODEL_DIMENSIONS = { x: 0.6552, y: 0.3063, z: 0.6552 };
|
||||
|
||||
var COLORS_TELEPORT_SEAT = {
|
||||
red: 255,
|
||||
|
@ -59,20 +55,23 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
var cancelPath = {
|
||||
color: COLORS_TELEPORT_CANCEL,
|
||||
alpha: 1,
|
||||
width: 0.025
|
||||
alpha: 0.3,
|
||||
width: 0.025,
|
||||
drawInFront: true
|
||||
};
|
||||
|
||||
var teleportPath = {
|
||||
color: COLORS_TELEPORT_CAN_TELEPORT,
|
||||
alpha: 1,
|
||||
width: 0.025
|
||||
alpha: 0.7,
|
||||
width: 0.025,
|
||||
drawInFront: true
|
||||
};
|
||||
|
||||
var seatPath = {
|
||||
color: COLORS_TELEPORT_SEAT,
|
||||
alpha: 1,
|
||||
width: 0.025
|
||||
alpha: 0.7,
|
||||
width: 0.025,
|
||||
drawInFront: true
|
||||
};
|
||||
|
||||
var teleportEnd = {
|
||||
|
@ -150,19 +149,149 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.teleportParabolaHeadVisuals;
|
||||
this.teleportParabolaHeadCollisions;
|
||||
|
||||
|
||||
this.PLAY_AREA_OVERLAY_MODEL = Script.resolvePath("../../assets/models/trackingSpacev18.fbx");
|
||||
this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS = { x: 1.969, y: 0.001, z: 1.969 };
|
||||
this.PLAY_AREA_FLOAT_ABOVE_FLOOR = 0.005;
|
||||
this.PLAY_AREA_OVERLAY_OFFSET = // Offset from floor.
|
||||
{ x: 0, y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2 + this.PLAY_AREA_FLOAT_ABOVE_FLOOR, z: 0 };
|
||||
this.PLAY_AREA_SENSOR_OVERLAY_MODEL = Script.resolvePath("../../assets/models/oculusSensorv11.fbx");
|
||||
this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS = { x: 0.1198, y: 0.2981, z: 0.1198 };
|
||||
this.PLAY_AREA_SENSOR_OVERLAY_ROTATION = Quat.fromVec3Degrees({ x: 0, y: -90, z: 0 });
|
||||
this.PLAY_AREA_BOX_ALPHA = 1.0;
|
||||
this.PLAY_AREA_SENSOR_ALPHA = 0.8;
|
||||
this.playAreaSensorPositions = [];
|
||||
this.playArea = { x: 0, y: 0 };
|
||||
this.playAreaCenterOffset = this.PLAY_AREA_OVERLAY_OFFSET;
|
||||
this.isPlayAreaVisible = false;
|
||||
this.wasPlayAreaVisible = false;
|
||||
this.isPlayAreaAvailable = false;
|
||||
this.targetOverlayID = null;
|
||||
this.playAreaOverlay = null;
|
||||
this.playAreaSensorPositionOverlays = [];
|
||||
|
||||
this.TELEPORT_SCALE_DURATION = 130;
|
||||
this.TELEPORT_SCALE_TIMEOUT = 25;
|
||||
this.isTeleportVisible = false;
|
||||
this.teleportScaleTimer = null;
|
||||
this.teleportScaleStart = 0;
|
||||
this.teleportScaleFactor = 0;
|
||||
this.teleportScaleMode = "head";
|
||||
|
||||
this.TELEPORTED_FADE_DELAY_DURATION = 900;
|
||||
this.TELEPORTED_FADE_DURATION = 200;
|
||||
this.TELEPORTED_FADE_INTERVAL = 25;
|
||||
this.TELEPORTED_FADE_DELAY_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DELAY_DURATION;
|
||||
this.TELEPORTED_FADE_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DURATION;
|
||||
this.teleportedFadeTimer = null;
|
||||
this.teleportedFadeDelayFactor = 0;
|
||||
this.teleportedFadeFactor = 0;
|
||||
this.teleportedPosition = Vec3.ZERO;
|
||||
this.TELEPORTED_TARGET_ALPHA = 1.0;
|
||||
this.TELEPORTED_TARGET_ROTATION = Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 });
|
||||
this.teleportedTargetOverlay = null;
|
||||
|
||||
this.setPlayAreaDimensions = function () {
|
||||
var avatarScale = MyAvatar.sensorToWorldScale;
|
||||
|
||||
var playAreaOverlayProperties = {
|
||||
dimensions:
|
||||
Vec3.multiply(this.teleportScaleFactor * avatarScale, {
|
||||
x: this.playArea.width,
|
||||
y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y,
|
||||
z: this.playArea.height
|
||||
})
|
||||
};
|
||||
|
||||
if (this.teleportScaleFactor < 1) {
|
||||
// Adjust position of playAreOverlay so that its base is at correct height.
|
||||
// Always parenting to teleport target is good enough for this.
|
||||
var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix;
|
||||
var sensorToWorldRotation = Mat4.extractRotation(MyAvatar.sensorToWorldMatrix);
|
||||
var worldToSensorMatrix = Mat4.inverse(sensorToWorldMatrix);
|
||||
var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position);
|
||||
avatarSensorPosition.y = 0;
|
||||
|
||||
var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation");
|
||||
var relativePlayAreaCenterOffset =
|
||||
Vec3.sum(this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 });
|
||||
var localPosition = Vec3.multiplyQbyV(Quat.inverse(targetRotation),
|
||||
Vec3.multiplyQbyV(sensorToWorldRotation,
|
||||
Vec3.multiply(avatarScale, Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition))));
|
||||
localPosition.y = this.teleportScaleFactor * localPosition.y;
|
||||
|
||||
playAreaOverlayProperties.parentID = this.targetOverlayID;
|
||||
playAreaOverlayProperties.localPosition = localPosition;
|
||||
}
|
||||
|
||||
Overlays.editOverlay(this.playAreaOverlay, playAreaOverlayProperties);
|
||||
|
||||
for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) {
|
||||
localPosition = this.playAreaSensorPositions[i];
|
||||
localPosition = Vec3.multiply(avatarScale, localPosition);
|
||||
// Position relative to the play area.
|
||||
localPosition.y = avatarScale * (this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2
|
||||
- this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2);
|
||||
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], {
|
||||
dimensions: Vec3.multiply(this.teleportScaleFactor * avatarScale, this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS),
|
||||
parentID: this.playAreaOverlay,
|
||||
localPosition: localPosition
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.updatePlayAreaScale = function () {
|
||||
if (this.isPlayAreaAvailable) {
|
||||
this.setPlayAreaDimensions();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.teleporterSelectionName = "teleporterSelection" + hand.toString();
|
||||
this.TELEPORTER_SELECTION_STYLE = {
|
||||
outlineUnoccludedColor: { red: 0, green: 0, blue: 0 },
|
||||
outlineUnoccludedAlpha: 0,
|
||||
outlineOccludedColor: { red: 0, green: 0, blue: 0 },
|
||||
outlineOccludedAlpha: 0,
|
||||
fillUnoccludedColor: { red: 0, green: 0, blue: 0 },
|
||||
fillUnoccludedAlpha: 0,
|
||||
fillOccludedColor: { red: 0, green: 0, blue: 255 },
|
||||
fillOccludedAlpha: 0.84,
|
||||
outlineWidth: 0,
|
||||
isOutlineSmooth: false
|
||||
};
|
||||
|
||||
this.addToSelectedItemsList = function (properties) {
|
||||
for (var i = 0, length = teleportRenderStates.length; i < length; i++) {
|
||||
var state = properties.renderStates[teleportRenderStates[i].name];
|
||||
if (state && state.end) {
|
||||
Selection.addToSelectedItemsList(this.teleporterSelectionName, "overlay", state.end);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.cleanup = function() {
|
||||
Selection.removeListFromMap(_this.teleporterSelectionName);
|
||||
Pointers.removePointer(_this.teleportParabolaHandVisuals);
|
||||
Pointers.removePointer(_this.teleportParabolaHandCollisions);
|
||||
Pointers.removePointer(_this.teleportParabolaHeadVisuals);
|
||||
Pointers.removePointer(_this.teleportParabolaHeadCollisions);
|
||||
Picks.removePick(_this.teleportHandCollisionPick);
|
||||
Picks.removePick(_this.teleportHeadCollisionPick);
|
||||
Overlays.deleteOverlay(_this.teleportedTargetOverlay);
|
||||
Overlays.deleteOverlay(_this.playAreaOverlay);
|
||||
for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {
|
||||
Overlays.deleteOverlay(_this.playAreaSensorPositionOverlays[i]);
|
||||
}
|
||||
_this.playAreaSensorPositionOverlays = [];
|
||||
};
|
||||
|
||||
this.initPointers = function () {
|
||||
this.initPointers = function() {
|
||||
if (_this.init) {
|
||||
_this.cleanup();
|
||||
}
|
||||
|
||||
_this.teleportParabolaHandVisuals = Pointers.createPointer(PickType.Parabola, {
|
||||
joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
dirOffset: { x: 0, y: 1, z: 0.1 },
|
||||
|
@ -221,6 +350,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
maxDistance: 8.0
|
||||
});
|
||||
|
||||
_this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHandVisuals));
|
||||
_this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHeadVisuals));
|
||||
|
||||
|
||||
var capsuleData = MyAvatar.getCollisionCapsule();
|
||||
|
||||
|
@ -262,11 +394,264 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
position: { x: 0, y: offset + height * 0.5, z: 0 },
|
||||
threshold: _this.capsuleThreshold
|
||||
});
|
||||
|
||||
|
||||
_this.playAreaOverlay = Overlays.addOverlay("model", {
|
||||
url: _this.PLAY_AREA_OVERLAY_MODEL,
|
||||
drawInFront: false,
|
||||
visible: false
|
||||
});
|
||||
|
||||
_this.teleportedTargetOverlay = Overlays.addOverlay("model", {
|
||||
url: TARGET_MODEL_URL,
|
||||
alpha: _this.TELEPORTED_TARGET_ALPHA,
|
||||
visible: false
|
||||
});
|
||||
|
||||
Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", _this.playAreaOverlay);
|
||||
Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", _this.teleportedTargetOverlay);
|
||||
|
||||
|
||||
_this.playArea = HMD.playArea;
|
||||
_this.isPlayAreaAvailable = HMD.active && _this.playArea.width !== 0 && _this.playArea.height !== 0;
|
||||
if (_this.isPlayAreaAvailable) {
|
||||
_this.playAreaCenterOffset = Vec3.sum({ x: _this.playArea.x, y: 0, z: _this.playArea.y },
|
||||
_this.PLAY_AREA_OVERLAY_OFFSET);
|
||||
_this.playAreaSensorPositions = HMD.sensorPositions;
|
||||
|
||||
for (var i = 0; i < _this.playAreaSensorPositions.length; i++) {
|
||||
if (i > _this.playAreaSensorPositionOverlays.length - 1) {
|
||||
var overlay = Overlays.addOverlay("model", {
|
||||
url: _this.PLAY_AREA_SENSOR_OVERLAY_MODEL,
|
||||
dimensions: _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS,
|
||||
parentID: _this.playAreaOverlay,
|
||||
localRotation: _this.PLAY_AREA_SENSOR_OVERLAY_ROTATION,
|
||||
drawInFront: false,
|
||||
visible: false
|
||||
});
|
||||
_this.playAreaSensorPositionOverlays.push(overlay);
|
||||
Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", overlay);
|
||||
}
|
||||
}
|
||||
|
||||
_this.setPlayAreaDimensions();
|
||||
}
|
||||
|
||||
_this.init = true;
|
||||
}
|
||||
};
|
||||
|
||||
_this.initPointers();
|
||||
|
||||
|
||||
this.translateXAction = Controller.findAction("TranslateX");
|
||||
this.translateYAction = Controller.findAction("TranslateY");
|
||||
this.translateZAction = Controller.findAction("TranslateZ");
|
||||
|
||||
this.setPlayAreaVisible = function (visible, targetOverlayID, fade) {
|
||||
if (!this.isPlayAreaAvailable || this.isPlayAreaVisible === visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.wasPlayAreaVisible = this.isPlayAreaVisible;
|
||||
this.isPlayAreaVisible = visible;
|
||||
this.targetOverlayID = targetOverlayID;
|
||||
|
||||
if (this.teleportedFadeTimer !== null) {
|
||||
Script.clearTimeout(this.teleportedFadeTimer);
|
||||
this.teleportedFadeTimer = null;
|
||||
}
|
||||
if (visible || !fade) {
|
||||
// Immediately make visible or invisible.
|
||||
this.isPlayAreaVisible = visible;
|
||||
Overlays.editOverlay(this.playAreaOverlay, {
|
||||
dimensions: Vec3.ZERO,
|
||||
alpha: this.PLAY_AREA_BOX_ALPHA,
|
||||
visible: visible
|
||||
});
|
||||
for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) {
|
||||
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], {
|
||||
dimensions: Vec3.ZERO,
|
||||
alpha: this.PLAY_AREA_SENSOR_ALPHA,
|
||||
visible: visible
|
||||
});
|
||||
}
|
||||
Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false });
|
||||
} else {
|
||||
// Fading out of overlays is initiated in setTeleportVisible().
|
||||
}
|
||||
};
|
||||
|
||||
this.updatePlayArea = function (position) {
|
||||
var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix;
|
||||
var sensorToWorldRotation = Mat4.extractRotation(MyAvatar.sensorToWorldMatrix);
|
||||
var worldToSensorMatrix = Mat4.inverse(sensorToWorldMatrix);
|
||||
var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position);
|
||||
avatarSensorPosition.y = 0;
|
||||
|
||||
var targetXZPosition = { x: position.x, y: 0, z: position.z };
|
||||
var avatarXZPosition = MyAvatar.position;
|
||||
avatarXZPosition.y = 0;
|
||||
var MIN_PARENTING_DISTANCE = 0.2; // Parenting under this distance results in the play area's rotation jittering.
|
||||
if (Vec3.distance(targetXZPosition, avatarXZPosition) < MIN_PARENTING_DISTANCE) {
|
||||
// Set play area position and rotation in world coordinates with no parenting.
|
||||
Overlays.editOverlay(this.playAreaOverlay, {
|
||||
parentID: Uuid.NULL,
|
||||
position: Vec3.sum(position,
|
||||
Vec3.multiplyQbyV(sensorToWorldRotation,
|
||||
Vec3.multiply(MyAvatar.sensorToWorldScale,
|
||||
Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))),
|
||||
rotation: sensorToWorldRotation
|
||||
});
|
||||
} else {
|
||||
// Set play area position and rotation in local coordinates with parenting.
|
||||
var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation");
|
||||
var sensorToTargetRotation = Quat.multiply(Quat.inverse(targetRotation), sensorToWorldRotation);
|
||||
var relativePlayAreaCenterOffset =
|
||||
Vec3.sum(this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 });
|
||||
Overlays.editOverlay(this.playAreaOverlay, {
|
||||
parentID: this.targetOverlayID,
|
||||
localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation),
|
||||
Vec3.multiplyQbyV(sensorToWorldRotation,
|
||||
Vec3.multiply(MyAvatar.sensorToWorldScale,
|
||||
Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition)))),
|
||||
localRotation: sensorToTargetRotation
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.scaleInTeleport = function () {
|
||||
_this.teleportScaleFactor = Math.min((Date.now() - _this.teleportScaleStart) / _this.TELEPORT_SCALE_DURATION, 1);
|
||||
Pointers.editRenderState(
|
||||
_this.teleportScaleMode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals,
|
||||
"teleport",
|
||||
{
|
||||
path: teleportPath, // Teleport beam disappears if not included.
|
||||
end: { dimensions: Vec3.multiply(_this.teleportScaleFactor, TARGET_MODEL_DIMENSIONS) }
|
||||
}
|
||||
);
|
||||
if (_this.isPlayAreaVisible) {
|
||||
_this.setPlayAreaDimensions();
|
||||
}
|
||||
if (_this.teleportScaleFactor < 1) {
|
||||
_this.teleportScaleTimer = Script.setTimeout(_this.scaleInTeleport, _this.TELEPORT_SCALE_TIMEOUT);
|
||||
} else {
|
||||
_this.teleportScaleTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.fadeOutTeleport = function () {
|
||||
var isAvatarMoving,
|
||||
i, length;
|
||||
|
||||
isAvatarMoving = Controller.getActionValue(_this.translateXAction) !== 0
|
||||
|| Controller.getActionValue(_this.translateYAction) !== 0
|
||||
|| Controller.getActionValue(_this.translateZAction) !== 0;
|
||||
|
||||
if (_this.teleportedFadeDelayFactor > 0 && !_this.isTeleportVisible && !isAvatarMoving) {
|
||||
// Delay fade.
|
||||
_this.teleportedFadeDelayFactor = _this.teleportedFadeDelayFactor - _this.TELEPORTED_FADE_DELAY_DELTA;
|
||||
_this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_INTERVAL);
|
||||
} else if (_this.teleportedFadeFactor > 0 && !_this.isTeleportVisible && !isAvatarMoving) {
|
||||
// Fade.
|
||||
_this.teleportedFadeFactor = _this.teleportedFadeFactor - _this.TELEPORTED_FADE_DELTA;
|
||||
Overlays.editOverlay(_this.teleportedTargetOverlay, {
|
||||
alpha: _this.teleportedFadeFactor * _this.TELEPORTED_TARGET_ALPHA
|
||||
});
|
||||
if (_this.wasPlayAreaVisible) {
|
||||
Overlays.editOverlay(_this.playAreaOverlay, {
|
||||
alpha: _this.teleportedFadeFactor * _this.PLAY_AREA_BOX_ALPHA
|
||||
});
|
||||
var sensorAlpha = _this.teleportedFadeFactor * _this.PLAY_AREA_SENSOR_ALPHA;
|
||||
for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) {
|
||||
Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { alpha: sensorAlpha });
|
||||
}
|
||||
}
|
||||
_this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_INTERVAL);
|
||||
} else {
|
||||
// Make invisible.
|
||||
Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false });
|
||||
if (_this.wasPlayAreaVisible) {
|
||||
Overlays.editOverlay(_this.playAreaOverlay, { visible: false });
|
||||
for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) {
|
||||
Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { visible: false });
|
||||
}
|
||||
}
|
||||
_this.teleportedFadeTimer = null;
|
||||
Selection.disableListHighlight(this.teleporterSelectionName);
|
||||
}
|
||||
};
|
||||
|
||||
this.cancelFade = function () {
|
||||
// Other hand may call this to immediately hide fading overlays.
|
||||
var i, length;
|
||||
if (this.teleportedFadeTimer) {
|
||||
Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false });
|
||||
if (this.wasPlayAreaVisible) {
|
||||
Overlays.editOverlay(this.playAreaOverlay, { visible: false });
|
||||
for (i = 0, length = this.playAreaSensorPositionOverlays.length; i < length; i++) {
|
||||
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { visible: false });
|
||||
}
|
||||
}
|
||||
this.teleportedFadeTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.setTeleportVisible = function (visible, mode, fade) {
|
||||
// Scales in teleport target and play area when start displaying them.
|
||||
if (visible === this.isTeleportVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
this.teleportScaleMode = mode;
|
||||
Pointers.editRenderState(
|
||||
mode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals,
|
||||
"teleport",
|
||||
{
|
||||
path: teleportPath, // Teleport beam disappears if not included.
|
||||
end: { dimensions: Vec3.ZERO }
|
||||
}
|
||||
);
|
||||
this.getOtherModule().cancelFade();
|
||||
this.teleportScaleStart = Date.now();
|
||||
this.teleportScaleFactor = 0;
|
||||
this.scaleInTeleport();
|
||||
Selection.enableListHighlight(this.teleporterSelectionName, this.TELEPORTER_SELECTION_STYLE);
|
||||
} else {
|
||||
if (this.teleportScaleTimer !== null) {
|
||||
Script.clearTimeout(this.teleportScaleTimer);
|
||||
this.teleportScaleTimer = null;
|
||||
}
|
||||
|
||||
if (fade) {
|
||||
// Copy of target at teleported position for fading.
|
||||
var avatarScale = MyAvatar.sensorToWorldScale;
|
||||
Overlays.editOverlay(this.teleportedTargetOverlay, {
|
||||
position: Vec3.sum(this.teleportedPosition, {
|
||||
x: 0,
|
||||
y: -getAvatarFootOffset() + avatarScale * TARGET_MODEL_DIMENSIONS.y / 2,
|
||||
z: 0
|
||||
}),
|
||||
rotation: Quat.multiply(this.TELEPORTED_TARGET_ROTATION, MyAvatar.orientation),
|
||||
dimensions: Vec3.multiply(avatarScale, TARGET_MODEL_DIMENSIONS),
|
||||
alpha: this.TELEPORTED_TARGET_ALPHA,
|
||||
visible: true
|
||||
});
|
||||
|
||||
// Fade out over time.
|
||||
this.teleportedFadeDelayFactor = 1.0;
|
||||
this.teleportedFadeFactor = 1.0;
|
||||
this.teleportedFadeTimer = Script.setTimeout(this.fadeOutTeleport, this.TELEPORTED_FADE_DELAY);
|
||||
} else {
|
||||
Selection.disableListHighlight(this.teleporterSelectionName);
|
||||
}
|
||||
}
|
||||
|
||||
this.isTeleportVisible = visible;
|
||||
};
|
||||
|
||||
|
||||
this.axisButtonStateX = 0; // Left/right axis button pressed.
|
||||
this.axisButtonStateY = 0; // Up/down axis button pressed.
|
||||
this.BUTTON_TRANSITION_DELAY = 100; // Allow time for transition from direction buttons to touch-pad.
|
||||
|
@ -379,6 +764,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.setTeleportState(mode, "cancel", "collision");
|
||||
} else if (teleportLocationType === TARGET.SURFACE || teleportLocationType === TARGET.DISCREPANCY) {
|
||||
this.setTeleportState(mode, "teleport", "collision");
|
||||
this.updatePlayArea(result.intersection);
|
||||
} else if (teleportLocationType === TARGET.SEAT) {
|
||||
this.setTeleportState(mode, "collision", "seat");
|
||||
}
|
||||
|
@ -387,6 +773,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
this.teleport = function(newResult, target) {
|
||||
var result = newResult;
|
||||
this.teleportedPosition = newResult.intersection;
|
||||
if (_this.buttonValue !== 0) {
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
|
@ -410,6 +797,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.disableLasers = function() {
|
||||
this.setPlayAreaVisible(false, null, true);
|
||||
this.setTeleportVisible(false, null, true);
|
||||
Pointers.disablePointer(_this.teleportParabolaHandVisuals);
|
||||
Pointers.disablePointer(_this.teleportParabolaHandCollisions);
|
||||
Pointers.disablePointer(_this.teleportParabolaHeadVisuals);
|
||||
|
@ -418,14 +807,29 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
Picks.disablePick(_this.teleportHandCollisionPick);
|
||||
};
|
||||
|
||||
this.setTeleportState = function(mode, visibleState, invisibleState) {
|
||||
this.teleportState = "";
|
||||
|
||||
this.setTeleportState = function (mode, visibleState, invisibleState) {
|
||||
var teleportState = mode + visibleState + invisibleState;
|
||||
if (teleportState === this.teleportState) {
|
||||
return;
|
||||
}
|
||||
this.teleportState = teleportState;
|
||||
|
||||
var pointerID;
|
||||
if (mode === 'head') {
|
||||
Pointers.setRenderState(_this.teleportParabolaHeadVisuals, visibleState);
|
||||
Pointers.setRenderState(_this.teleportParabolaHeadCollisions, invisibleState);
|
||||
pointerID = _this.teleportParabolaHeadVisuals;
|
||||
} else {
|
||||
Pointers.setRenderState(_this.teleportParabolaHandVisuals, visibleState);
|
||||
Pointers.setRenderState(_this.teleportParabolaHandCollisions, invisibleState);
|
||||
pointerID = _this.teleportParabolaHandVisuals;
|
||||
}
|
||||
var visible = visibleState === "teleport";
|
||||
this.setPlayAreaVisible(visible && MyAvatar.showPlayArea,
|
||||
Pointers.getPointerProperties(pointerID).renderStates.teleport.end, false);
|
||||
this.setTeleportVisible(visible, mode, false);
|
||||
};
|
||||
|
||||
this.setIgnoreEntities = function(entitiesToIgnore) {
|
||||
|
@ -642,4 +1046,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
Messages.subscribe('Hifi-Teleport-Ignore-Remove');
|
||||
Messages.messageReceived.connect(handleTeleportMessages);
|
||||
|
||||
MyAvatar.sensorToWorldScaleChanged.connect(function () {
|
||||
leftTeleporter.updatePlayAreaScale();
|
||||
rightTeleporter.updatePlayAreaScale();
|
||||
});
|
||||
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
Loading…
Reference in a new issue