mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 13:30:33 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into groups
This commit is contained in:
commit
9a69361391
31 changed files with 1636 additions and 806 deletions
|
@ -28,6 +28,7 @@ module.exports = {
|
|||
"ModelCache": false,
|
||||
"MyAvatar": false,
|
||||
"Overlays": false,
|
||||
"OverlayWebWindow": false,
|
||||
"Paths": false,
|
||||
"Quat": false,
|
||||
"Rates": false,
|
||||
|
@ -40,8 +41,10 @@ module.exports = {
|
|||
"SoundCache": false,
|
||||
"Stats": false,
|
||||
"TextureCache": false,
|
||||
"Toolbars": false,
|
||||
"Uuid": false,
|
||||
"UndoStack": false,
|
||||
"UserActivityLogger": false,
|
||||
"Vec3": false,
|
||||
"WebSocket": false,
|
||||
"WebWindow": false,
|
||||
|
@ -55,6 +58,7 @@ module.exports = {
|
|||
"comma-dangle": ["error", "never"],
|
||||
"camelcase": ["error"],
|
||||
"curly": ["error", "all"],
|
||||
"eqeqeq": ["error", "always"],
|
||||
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }],
|
||||
"max-len": ["error", 128, 4],
|
||||
|
|
|
@ -65,6 +65,7 @@ Original.CheckBox {
|
|||
colorScheme: checkBox.colorScheme
|
||||
x: checkBox.boxSize / 2
|
||||
wrapMode: Text.Wrap
|
||||
enabled: checkBox.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,19 +117,22 @@ FocusScope {
|
|||
|
||||
function showList() {
|
||||
var r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
|
||||
listView.currentIndex = root.currentIndex
|
||||
scrollView.x = r.x;
|
||||
scrollView.y = r.y + r.height;
|
||||
var bottom = scrollView.y + scrollView.height;
|
||||
var y = r.y + r.height;
|
||||
var bottom = y + scrollView.height;
|
||||
if (bottom > desktop.height) {
|
||||
scrollView.y -= bottom - desktop.height + 8;
|
||||
y -= bottom - desktop.height + 8;
|
||||
}
|
||||
scrollView.x = r.x;
|
||||
scrollView.y = y;
|
||||
popup.visible = true;
|
||||
popup.forceActiveFocus();
|
||||
listView.currentIndex = root.currentIndex;
|
||||
scrollView.hoverEnabled = true;
|
||||
}
|
||||
|
||||
function hideList() {
|
||||
popup.visible = false;
|
||||
scrollView.hoverEnabled = false;
|
||||
}
|
||||
|
||||
FocusScope {
|
||||
|
@ -161,6 +164,7 @@ FocusScope {
|
|||
id: scrollView
|
||||
height: 480
|
||||
width: root.width + 4
|
||||
property bool hoverEnabled: false;
|
||||
|
||||
style: ScrollViewStyle {
|
||||
decrementControl: Item {
|
||||
|
@ -193,7 +197,8 @@ FocusScope {
|
|||
delegate: Rectangle {
|
||||
width: root.width + 4
|
||||
height: popupText.implicitHeight * 1.4
|
||||
color: popupHover.containsMouse ? hifi.colors.primaryHighlight : (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
color: (listView.currentIndex === index) ? hifi.colors.primaryHighlight :
|
||||
(isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
FiraSansSemiBold {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.textPadding
|
||||
|
@ -206,9 +211,9 @@ FocusScope {
|
|||
MouseArea {
|
||||
id: popupHover
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true
|
||||
hoverEnabled: scrollView.hoverEnabled;
|
||||
onEntered: listView.currentIndex = index;
|
||||
onClicked: popup.selectSpecificItem(index)
|
||||
onClicked: popup.selectSpecificItem(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,5 +16,6 @@ RalewaySemiBold {
|
|||
property int colorScheme: hifi.colorSchemes.light
|
||||
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText
|
||||
color: enabled ? (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText)
|
||||
: (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight);
|
||||
}
|
||||
|
|
|
@ -456,6 +456,11 @@ FocusScope {
|
|||
return inputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: customInputDialogBuilder; CustomQueryDialog { } }
|
||||
function customInputDialog(properties) {
|
||||
return customInputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: fileDialogBuilder; FileDialog { } }
|
||||
function fileDialog(properties) {
|
||||
return fileDialogBuilder.createObject(desktop, properties);
|
||||
|
|
300
interface/resources/qml/dialogs/CustomQueryDialog.qml
Normal file
300
interface/resources/qml/dialogs/CustomQueryDialog.qml
Normal file
|
@ -0,0 +1,300 @@
|
|||
//
|
||||
// CustomQueryDialog.qml
|
||||
//
|
||||
// Created by Zander Otavka on 7/14/16
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5;
|
||||
import QtQuick.Controls 1.4;
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs;
|
||||
|
||||
import "../controls-uit";
|
||||
import "../styles-uit";
|
||||
import "../windows";
|
||||
|
||||
ModalWindow {
|
||||
id: root;
|
||||
HifiConstants { id: hifi; }
|
||||
implicitWidth: 640;
|
||||
implicitHeight: 320;
|
||||
visible: true;
|
||||
|
||||
signal selected(var result);
|
||||
signal canceled();
|
||||
|
||||
property int icon: hifi.icons.none;
|
||||
property string iconText: "";
|
||||
property int iconSize: 35;
|
||||
onIconChanged: updateIcon();
|
||||
|
||||
property var textInput;
|
||||
property var comboBox;
|
||||
property var checkBox;
|
||||
onTextInputChanged: {
|
||||
if (textInput && textInput.text !== undefined) {
|
||||
textField.text = textInput.text;
|
||||
}
|
||||
}
|
||||
onComboBoxChanged: {
|
||||
if (comboBox && comboBox.index !== undefined) {
|
||||
comboBoxField.currentIndex = comboBox.index;
|
||||
}
|
||||
}
|
||||
onCheckBoxChanged: {
|
||||
if (checkBox && checkBox.checked !== undefined) {
|
||||
checkBoxField.checked = checkBox.checked;
|
||||
}
|
||||
}
|
||||
|
||||
property var warning: "";
|
||||
property var result;
|
||||
|
||||
property var implicitCheckState: null;
|
||||
|
||||
property int titleWidth: 0;
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
function updateCheckbox() {
|
||||
if (checkBox.disableForItems) {
|
||||
var currentItemInDisableList = false;
|
||||
for (var i in checkBox.disableForItems) {
|
||||
if (comboBoxField.currentIndex === checkBox.disableForItems[i]) {
|
||||
currentItemInDisableList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentItemInDisableList) {
|
||||
checkBoxField.enabled = false;
|
||||
if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) {
|
||||
root.implicitCheckState = checkBoxField.checked;
|
||||
checkBoxField.checked = checkBox.checkStateOnDisable;
|
||||
}
|
||||
root.warning = checkBox.warningOnDisable;
|
||||
} else {
|
||||
checkBoxField.enabled = true;
|
||||
if (root.implicitCheckState !== null) {
|
||||
checkBoxField.checked = root.implicitCheckState;
|
||||
root.implicitCheckState = null;
|
||||
}
|
||||
root.warning = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
clip: true;
|
||||
width: pane.width;
|
||||
height: pane.height;
|
||||
anchors.margins: 0;
|
||||
|
||||
QtObject {
|
||||
id: d;
|
||||
readonly property int minWidth: 480;
|
||||
readonly property int maxWdith: 1280;
|
||||
readonly property int minHeight: 120;
|
||||
readonly property int maxHeight: 720;
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, pane.width);
|
||||
var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(buttons.height + 3 * hifi.dimensions.contentSpacing.y);
|
||||
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||
root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ?
|
||||
d.maxHeight : targetHeight);
|
||||
if (checkBoxField.visible && comboBoxField.visible) {
|
||||
checkBoxField.width = extraInputs.width / 2;
|
||||
comboBoxField.width = extraInputs.width / 2;
|
||||
} else if (!checkBoxField.visible && comboBoxField.visible) {
|
||||
comboBoxField.width = extraInputs.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
top: parent.top;
|
||||
bottom: extraInputs.visible ? extraInputs.top : buttons.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
TextField {
|
||||
id: textField;
|
||||
label: root.textInput.label;
|
||||
focus: root.textInput ? true : false;
|
||||
visible: root.textInput ? true : false;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: extraInputs;
|
||||
visible: Boolean(root.checkBox || root.comboBox);
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: buttons.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
height: comboBoxField.controlHeight;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: d.resize();
|
||||
|
||||
CheckBox {
|
||||
id: checkBoxField;
|
||||
text: root.checkBox.label;
|
||||
focus: Boolean(root.checkBox);
|
||||
visible: Boolean(root.checkBox);
|
||||
anchors {
|
||||
left: parent.left;
|
||||
bottom: parent.bottom;
|
||||
leftMargin: 6; // Magic number to align with warning icon
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBoxField;
|
||||
label: root.comboBox.label;
|
||||
focus: Boolean(root.comboBox);
|
||||
visible: Boolean(root.comboBox);
|
||||
anchors {
|
||||
right: parent.right;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
model: root.comboBox ? root.comboBox.items : [];
|
||||
onCurrentTextChanged: updateCheckbox();
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons;
|
||||
focus: true;
|
||||
spacing: hifi.dimensions.contentSpacing.x;
|
||||
layoutDirection: Qt.RightToLeft;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: {
|
||||
d.resize();
|
||||
resizeWarningText();
|
||||
}
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
|
||||
function resizeWarningText() {
|
||||
var rowWidth = buttons.width;
|
||||
var buttonsWidth = acceptButton.width + cancelButton.width + hifi.dimensions.contentSpacing.x * 2;
|
||||
var warningIconWidth = warningIcon.width + hifi.dimensions.contentSpacing.x;
|
||||
warningText.width = rowWidth - buttonsWidth - warningIconWidth;
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cancelButton;
|
||||
action: cancelAction;
|
||||
}
|
||||
|
||||
Button {
|
||||
id: acceptButton;
|
||||
action: acceptAction;
|
||||
}
|
||||
|
||||
Text {
|
||||
id: warningText;
|
||||
visible: Boolean(root.warning);
|
||||
text: root.warning;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.italic: true;
|
||||
maximumLineCount: 2;
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: warningIcon;
|
||||
visible: Boolean(root.warning);
|
||||
text: hifi.glyphs.alert;
|
||||
size: hifi.dimensions.controlLineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: cancelAction;
|
||||
text: qsTr("Cancel");
|
||||
shortcut: Qt.Key_Escape;
|
||||
onTriggered: {
|
||||
root.result = null;
|
||||
root.canceled();
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: acceptAction;
|
||||
text: qsTr("Add");
|
||||
shortcut: Qt.Key_Return;
|
||||
onTriggered: {
|
||||
var result = {};
|
||||
if (textInput) {
|
||||
result.textInput = textField.text;
|
||||
}
|
||||
if (comboBox) {
|
||||
result.comboBox = comboBoxField.currentIndex;
|
||||
result.comboBoxText = comboBoxField.currentText;
|
||||
}
|
||||
if (checkBox) {
|
||||
result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null;
|
||||
}
|
||||
root.result = JSON.stringify(result);
|
||||
root.selected(root.result);
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
cancelAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateIcon();
|
||||
d.resize();
|
||||
textField.forceActiveFocus();
|
||||
}
|
||||
}
|
|
@ -4715,6 +4715,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
qScriptRegisterMetaType(scriptEngine, CustomPromptResultToScriptValue, CustomPromptResultFromScriptValue);
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter, "Window");
|
||||
// register `location` on the global object.
|
||||
|
|
|
@ -29,6 +29,20 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
|
|||
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
|
||||
|
||||
|
||||
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) {
|
||||
if (!result.value.isValid()) {
|
||||
return QScriptValue::UndefinedValue;
|
||||
}
|
||||
|
||||
Q_ASSERT(result.value.userType() == qMetaTypeId<QVariantMap>());
|
||||
return engine->toScriptValue(result.value.toMap());
|
||||
}
|
||||
|
||||
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result) {
|
||||
result.value = object.toVariant();
|
||||
}
|
||||
|
||||
|
||||
WindowScriptingInterface::WindowScriptingInterface() {
|
||||
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);
|
||||
|
@ -95,6 +109,14 @@ QScriptValue WindowScriptingInterface::prompt(const QString& message, const QStr
|
|||
return ok ? QScriptValue(result) : QScriptValue::NullValue;
|
||||
}
|
||||
|
||||
CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) {
|
||||
CustomPromptResult result;
|
||||
bool ok = false;
|
||||
auto configMap = config.toMap();
|
||||
result.value = OffscreenUi::getCustomInfo(OffscreenUi::ICON_NONE, "", configMap, &ok);
|
||||
return ok ? result : CustomPromptResult();
|
||||
}
|
||||
|
||||
QString fixupPathForMac(const QString& directory) {
|
||||
// On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus
|
||||
// filename if the directory is valid.
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
|
||||
class WebWindowClass;
|
||||
|
||||
|
||||
class CustomPromptResult {
|
||||
public:
|
||||
QVariant value;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CustomPromptResult);
|
||||
|
||||
QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result);
|
||||
void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result);
|
||||
|
||||
|
||||
class WindowScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int innerWidth READ getInnerWidth)
|
||||
|
@ -38,6 +50,7 @@ public slots:
|
|||
void alert(const QString& message = "");
|
||||
QScriptValue confirm(const QString& message = "");
|
||||
QScriptValue prompt(const QString& message = "", const QString& defaultText = "");
|
||||
CustomPromptResult customPrompt(const QVariant& config);
|
||||
QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
|
||||
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
|
||||
void copyToClipboard(const QString& text);
|
||||
|
|
|
@ -700,11 +700,12 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
}
|
||||
info.setParams(type, dimensions, _compoundShapeURL);
|
||||
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
updateModelBounds();
|
||||
|
||||
// should never fall in here when model not fully loaded
|
||||
assert(_model && _model->isLoaded());
|
||||
|
||||
updateModelBounds();
|
||||
_model->updateGeometry();
|
||||
|
||||
// compute meshPart local transforms
|
||||
QVector<glm::mat4> localTransforms;
|
||||
const FBXGeometry& fbxGeometry = _model->getFBXGeometry();
|
||||
|
|
|
@ -1211,11 +1211,21 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
|||
|
||||
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const {
|
||||
// a TerseUpdate includes the transform and its derivatives
|
||||
if (!properties._positionChanged) {
|
||||
properties._position = getLocalPosition();
|
||||
}
|
||||
if (!properties._velocityChanged) {
|
||||
properties._velocity = getLocalVelocity();
|
||||
}
|
||||
if (!properties._rotationChanged) {
|
||||
properties._rotation = getLocalOrientation();
|
||||
}
|
||||
if (!properties._angularVelocityChanged) {
|
||||
properties._angularVelocity = getLocalAngularVelocity();
|
||||
}
|
||||
if (!properties._accelerationChanged) {
|
||||
properties._acceleration = _acceleration;
|
||||
}
|
||||
|
||||
properties._positionChanged = true;
|
||||
properties._velocityChanged = true;
|
||||
|
|
|
@ -723,13 +723,10 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
|||
int index = changedProperties.indexOf("velocity");
|
||||
if (index >= 0) {
|
||||
glm::vec3 value = properties.getVelocity();
|
||||
QString changeHint = "0";
|
||||
if (value.x + value.y + value.z > 0) {
|
||||
changeHint = "+";
|
||||
} else if (value.x + value.y + value.z < 0) {
|
||||
changeHint = "-";
|
||||
}
|
||||
changedProperties[index] = QString("velocity:") + changeHint;
|
||||
changedProperties[index] = QString("velocity:") +
|
||||
QString::number((int)value.x) + "," +
|
||||
QString::number((int)value.y) + "," +
|
||||
QString::number((int)value.z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) {
|
|||
motionState->updateBodyVelocities();
|
||||
motionState->updateLastKinematicStep();
|
||||
body->setSleepingThresholds(KINEMATIC_LINEAR_SPEED_THRESHOLD, KINEMATIC_ANGULAR_SPEED_THRESHOLD);
|
||||
motionState->clearInternalKinematicChanges();
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_DYNAMIC: {
|
||||
|
|
|
@ -69,7 +69,6 @@ static const btVector3 _unitSphereDirections[NUM_UNIT_SPHERE_DIRECTIONS] = {
|
|||
|
||||
// util method
|
||||
btConvexHullShape* createConvexHull(const ShapeInfo::PointList& points) {
|
||||
//std::cout << "adebug createConvexHull() points.size() = " << points.size() << std::endl; // adebug
|
||||
assert(points.size() > 0);
|
||||
|
||||
btConvexHullShape* hull = new btConvexHullShape();
|
||||
|
@ -241,7 +240,6 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) {
|
|||
btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
|
||||
btCollisionShape* shape = NULL;
|
||||
int type = info.getType();
|
||||
//std::cout << "adebug createShapeFromInfo() type = " << type << std::endl; // adebug
|
||||
switch(type) {
|
||||
case SHAPE_TYPE_BOX: {
|
||||
shape = new btBoxShape(glmToBullet(info.getHalfExtents()));
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) const {
|
||||
return !_needsReload && isRenderable() && isActive();
|
||||
}
|
||||
bool needsReload() const { return _needsReload; }
|
||||
bool initWhenReady(render::ScenePointer scene);
|
||||
bool addToScene(std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges,
|
||||
|
@ -232,6 +233,9 @@ public:
|
|||
|
||||
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; }
|
||||
|
||||
// returns 'true' if needs fullUpdate after geometry change
|
||||
bool updateGeometry();
|
||||
|
||||
protected:
|
||||
|
||||
void setPupilDilation(float dilation) { _pupilDilation = dilation; }
|
||||
|
@ -297,9 +301,6 @@ protected:
|
|||
std::unordered_set<int> _cauterizeBoneSet;
|
||||
bool _cauterizeBones;
|
||||
|
||||
// returns 'true' if needs fullUpdate after geometry change
|
||||
bool updateGeometry();
|
||||
|
||||
virtual void initJointStates();
|
||||
|
||||
void setScaleInternal(const glm::vec3& scale);
|
||||
|
|
|
@ -343,6 +343,23 @@ QString OffscreenUi::getItem(const Icon icon, const QString& title, const QStrin
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok) {
|
||||
if (ok) {
|
||||
*ok = false;
|
||||
}
|
||||
|
||||
QVariant result = DependencyManager::get<OffscreenUi>()->customInputDialog(icon, title, config);
|
||||
if (result.isValid()) {
|
||||
// We get a JSON encoded result, so we unpack it into a QVariant wrapping a QVariantMap
|
||||
result = QVariant(QJsonDocument::fromJson(result.toString().toUtf8()).object().toVariantMap());
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
|
@ -358,6 +375,20 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q
|
|||
return waitForInputDialogResult(createInputDialog(icon, title, label, current));
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(this, "customInputDialog", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(Icon, icon),
|
||||
Q_ARG(QString, title),
|
||||
Q_ARG(QVariantMap, config));
|
||||
return result;
|
||||
}
|
||||
|
||||
return waitForInputDialogResult(createCustomInputDialog(icon, title, config));
|
||||
}
|
||||
|
||||
void OffscreenUi::togglePinned() {
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned");
|
||||
if (!invokeResult) {
|
||||
|
@ -401,6 +432,23 @@ QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title
|
|||
return qvariant_cast<QQuickItem*>(result);
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config) {
|
||||
QVariantMap map = config;
|
||||
map.insert("title", title);
|
||||
map.insert("icon", icon);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "customInputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create custom message box";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return qvariant_cast<QQuickItem*>(result);
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) {
|
||||
if (!inputDialog) {
|
||||
return QVariant();
|
||||
|
|
|
@ -122,7 +122,9 @@ public:
|
|||
static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
|
||||
|
||||
Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
|
||||
Q_INVOKABLE QVariant customInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
|
||||
QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current);
|
||||
QQuickItem* createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config);
|
||||
QVariant waitForInputDialogResult(QQuickItem* inputDialog);
|
||||
|
||||
// Compatibility with QInputDialog::getText
|
||||
|
@ -140,6 +142,7 @@ public:
|
|||
|
||||
static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0);
|
||||
static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0);
|
||||
static QVariant getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok = 0);
|
||||
|
||||
unsigned int getMenuUserDataId() const;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ Script.load("system/users.js");
|
|||
Script.load("system/mute.js");
|
||||
Script.load("system/goto.js");
|
||||
Script.load("system/hmd.js");
|
||||
Script.load("system/examples.js");
|
||||
Script.load("system/marketplace.js");
|
||||
Script.load("system/edit.js");
|
||||
Script.load("system/ignore.js");
|
||||
Script.load("system/selectAudioDevice.js");
|
||||
|
|
|
@ -1915,7 +1915,9 @@ function MyController(hand) {
|
|||
var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||
var reparentProps = {
|
||||
parentID: MyAvatar.sessionUUID,
|
||||
parentJointIndex: handJointIndex
|
||||
parentJointIndex: handJointIndex,
|
||||
velocity: {x: 0, y: 0, z: 0},
|
||||
angularVelocity: {x: 0, y: 0, z: 0}
|
||||
};
|
||||
if (hasPresetPosition) {
|
||||
reparentProps["localPosition"] = this.offsetPosition;
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton";
|
||||
var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
|
||||
var EDIT_TOOLBAR = "com.highfidelity.interface.toolbar.edit";
|
||||
|
||||
/* globals SelectionDisplay, SelectionManager, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Toolbars,
|
||||
progressDialog, tooltip, ParticleExplorerTool */
|
||||
Script.include([
|
||||
"libraries/stringHelpers.js",
|
||||
"libraries/dataViewHelpers.js",
|
||||
|
@ -29,7 +31,7 @@ Script.include([
|
|||
"libraries/gridTool.js",
|
||||
"libraries/entityList.js",
|
||||
"particle_explorer/particleExplorerTool.js",
|
||||
"libraries/lightOverlayManager.js",
|
||||
"libraries/lightOverlayManager.js"
|
||||
]);
|
||||
|
||||
var selectionDisplay = SelectionDisplay;
|
||||
|
@ -39,13 +41,13 @@ var lightOverlayManager = new LightOverlayManager();
|
|||
|
||||
var cameraManager = new CameraManager();
|
||||
|
||||
var grid = Grid();
|
||||
gridTool = GridTool({
|
||||
var grid = new Grid();
|
||||
var gridTool = new GridTool({
|
||||
horizontalGrid: grid
|
||||
});
|
||||
gridTool.setVisible(false);
|
||||
|
||||
var entityListTool = EntityListTool();
|
||||
var entityListTool = new EntityListTool();
|
||||
|
||||
selectionManager.addEventListener(function () {
|
||||
selectionDisplay.updateHandles();
|
||||
|
@ -89,17 +91,16 @@ var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode";
|
|||
|
||||
// marketplace info, etc. not quite ready yet.
|
||||
var SHOULD_SHOW_PROPERTY_MENU = false;
|
||||
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."
|
||||
var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain."
|
||||
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain.";
|
||||
var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain.";
|
||||
|
||||
var mode = 0;
|
||||
var isActive = false;
|
||||
|
||||
IMPORTING_SVO_OVERLAY_WIDTH = 144;
|
||||
IMPORTING_SVO_OVERLAY_HEIGHT = 30;
|
||||
IMPORTING_SVO_OVERLAY_MARGIN = 5;
|
||||
IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34;
|
||||
|
||||
var IMPORTING_SVO_OVERLAY_WIDTH = 144;
|
||||
var IMPORTING_SVO_OVERLAY_HEIGHT = 30;
|
||||
var IMPORTING_SVO_OVERLAY_MARGIN = 5;
|
||||
var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34;
|
||||
var importingSVOImageOverlay = Overlays.addOverlay("image", {
|
||||
imageURL: Script.resolvePath("assets") + "/images/hourglass.svg",
|
||||
width: 20,
|
||||
|
@ -107,7 +108,7 @@ var importingSVOImageOverlay = Overlays.addOverlay("image", {
|
|||
alpha: 1.0,
|
||||
x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH,
|
||||
y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT,
|
||||
visible: false,
|
||||
visible: false
|
||||
});
|
||||
var importingSVOTextOverlay = Overlays.addOverlay("text", {
|
||||
font: {
|
||||
|
@ -125,7 +126,7 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", {
|
|||
blue: 80
|
||||
},
|
||||
backgroundAlpha: 0.7,
|
||||
visible: false,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
|
||||
|
@ -177,7 +178,7 @@ var toolBar = (function() {
|
|||
var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS;
|
||||
var position = getPositionToCreateEntity();
|
||||
var entityID = null;
|
||||
if (position != null) {
|
||||
if (position !== null && position !== undefined) {
|
||||
position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions),
|
||||
properties.position = position;
|
||||
entityID = Entities.addEntity(properties);
|
||||
|
@ -204,7 +205,7 @@ var toolBar = (function() {
|
|||
imageURL: imageUrl,
|
||||
buttonState: 1,
|
||||
alpha: 0.9,
|
||||
visible: true,
|
||||
visible: true
|
||||
});
|
||||
if (handler) {
|
||||
button.clicked.connect(function () {
|
||||
|
@ -237,7 +238,7 @@ var toolBar = (function() {
|
|||
alpha: 0.9,
|
||||
buttonState: 1,
|
||||
hoverState: 3,
|
||||
defaultState: 1,
|
||||
defaultState: 1
|
||||
});
|
||||
activeButton.clicked.connect(function () {
|
||||
that.setActive(!isActive);
|
||||
|
@ -250,13 +251,70 @@ var toolBar = (function() {
|
|||
toolBar.writeProperty("shown", false);
|
||||
|
||||
addButton("newModelButton", "model-01.svg", function () {
|
||||
var url = Window.prompt("Model URL");
|
||||
if (url !== null && url !== "") {
|
||||
var SHAPE_TYPE_NONE = 0;
|
||||
var SHAPE_TYPE_SIMPLE_HULL = 1;
|
||||
var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
|
||||
var SHAPE_TYPE_STATIC_MESH = 3;
|
||||
|
||||
var SHAPE_TYPES = [];
|
||||
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
||||
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
|
||||
|
||||
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH;
|
||||
var DYNAMIC_DEFAULT = false;
|
||||
var result = Window.customPrompt({
|
||||
textInput: {
|
||||
label: "Model URL"
|
||||
},
|
||||
comboBox: {
|
||||
label: "Automatic Collisions",
|
||||
index: SHAPE_TYPE_DEFAULT,
|
||||
items: SHAPE_TYPES
|
||||
},
|
||||
checkBox: {
|
||||
label: "Dynamic",
|
||||
checked: DYNAMIC_DEFAULT,
|
||||
disableForItems: [
|
||||
SHAPE_TYPE_STATIC_MESH
|
||||
],
|
||||
checkStateOnDisable: false,
|
||||
warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic"
|
||||
}
|
||||
});
|
||||
|
||||
if (result) {
|
||||
var url = result.textInput;
|
||||
var shapeType;
|
||||
switch (result.comboBox) {
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
shapeType = "simple-hull";
|
||||
break;
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
shapeType = "simple-compound";
|
||||
break;
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
shapeType = "static-mesh";
|
||||
break;
|
||||
default:
|
||||
shapeType = "none";
|
||||
}
|
||||
|
||||
var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT;
|
||||
if (shapeType === "static-mesh" && dynamic) {
|
||||
// The prompt should prevent this case
|
||||
print("Error: model cannot be both static mesh and dynamic. This should never happen.");
|
||||
} else if (url) {
|
||||
createNewEntity({
|
||||
type: "Model",
|
||||
modelURL: url
|
||||
modelURL: url,
|
||||
shapeType: shapeType,
|
||||
dynamic: dynamic,
|
||||
gravity: dynamic ? { x: 0, y: -10, z: 0 } : { x: 0, y: 0, z: 0 }
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addButton("newCubeButton", "cube-01.svg", function () {
|
||||
|
@ -298,7 +356,7 @@ var toolBar = (function() {
|
|||
linearAttenuation: 0,
|
||||
quadraticAttenuation: 0,
|
||||
exponent: 0,
|
||||
cutoff: 180, // in degrees
|
||||
cutoff: 180 // in degrees
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -333,7 +391,7 @@ var toolBar = (function() {
|
|||
y: 0.9,
|
||||
z: 0.01
|
||||
},
|
||||
sourceUrl: "https://highfidelity.com/",
|
||||
sourceUrl: "https://highfidelity.com/"
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -344,7 +402,7 @@ var toolBar = (function() {
|
|||
x: 10,
|
||||
y: 10,
|
||||
z: 10
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -352,7 +410,6 @@ var toolBar = (function() {
|
|||
createNewEntity({
|
||||
type: "ParticleEffect",
|
||||
isEmitting: true,
|
||||
particleRadius: 0.1,
|
||||
emitAcceleration: {
|
||||
x: 0,
|
||||
y: -1,
|
||||
|
@ -368,7 +425,7 @@ var toolBar = (function() {
|
|||
particleRadius: 0.025,
|
||||
alphaFinish: 0,
|
||||
emitRate: 100,
|
||||
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
|
||||
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png"
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -380,7 +437,7 @@ var toolBar = (function() {
|
|||
};
|
||||
|
||||
that.setActive = function (active) {
|
||||
if (active == isActive) {
|
||||
if (active === isActive) {
|
||||
return;
|
||||
}
|
||||
if (active && !Entities.canRez() && !Entities.canRezTmp()) {
|
||||
|
@ -402,7 +459,6 @@ var toolBar = (function() {
|
|||
selectionDisplay.triggerMapping.disable();
|
||||
} else {
|
||||
UserActivityLogger.enabledEdit();
|
||||
hasShownPropertiesTool = false;
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
|
@ -431,8 +487,8 @@ var toolBar = (function() {
|
|||
|
||||
function isLocked(properties) {
|
||||
// special case to lock the ground plane model in hq.
|
||||
if (location.hostname == "hq.highfidelity.io" &&
|
||||
properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") {
|
||||
if (location.hostname === "hq.highfidelity.io" &&
|
||||
properties.modelURL === HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -629,9 +685,10 @@ function mouseReleaseEvent(event) {
|
|||
|
||||
function mouseClickEvent(event) {
|
||||
var wantDebug = false;
|
||||
var result, properties;
|
||||
if (isActive && event.isLeftButton) {
|
||||
var result = findClickedEntity(event);
|
||||
if (result === null) {
|
||||
result = findClickedEntity(event);
|
||||
if (result === null || result === undefined) {
|
||||
if (!event.isShifted) {
|
||||
selectionManager.clearSelections();
|
||||
}
|
||||
|
@ -641,7 +698,7 @@ function mouseClickEvent(event) {
|
|||
var pickRay = result.pickRay;
|
||||
var foundEntity = result.entityID;
|
||||
|
||||
var properties = Entities.getEntityProperties(foundEntity);
|
||||
properties = Entities.getEntityProperties(foundEntity);
|
||||
if (isLocked(properties)) {
|
||||
if (wantDebug) {
|
||||
print("Model locked " + properties.id);
|
||||
|
@ -660,7 +717,7 @@ function mouseClickEvent(event) {
|
|||
// x x - distance from A
|
||||
//
|
||||
// |X-A| = (P-A).B
|
||||
// X == A + ((P-A).B)B
|
||||
// X === A + ((P-A).B)B
|
||||
// d = |P-X|
|
||||
|
||||
var A = pickRay.origin;
|
||||
|
@ -668,16 +725,14 @@ function mouseClickEvent(event) {
|
|||
var P = properties.position;
|
||||
|
||||
var x = Vec3.dot(Vec3.subtract(P, A), B);
|
||||
var X = Vec3.sum(A, Vec3.multiply(B, x));
|
||||
var d = Vec3.length(Vec3.subtract(P, X));
|
||||
var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
|
||||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) *
|
||||
180 / Math.PI;
|
||||
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) &&
|
||||
(allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
|
||||
if (0 < x && sizeOK) {
|
||||
entitySelected = true;
|
||||
selectedEntityID = foundEntity;
|
||||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
|
||||
|
@ -702,12 +757,12 @@ function mouseClickEvent(event) {
|
|||
}
|
||||
}
|
||||
} else if (event.isRightButton) {
|
||||
var result = findClickedEntity(event);
|
||||
result = findClickedEntity(event);
|
||||
if (result) {
|
||||
if (SHOULD_SHOW_PROPERTY_MENU !== true) {
|
||||
return;
|
||||
}
|
||||
var properties = Entities.getEntityProperties(result.entityID);
|
||||
properties = Entities.getEntityProperties(result.entityID);
|
||||
if (properties.marketplaceID) {
|
||||
propertyMenu.marketplaceID = properties.marketplaceID;
|
||||
propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace");
|
||||
|
@ -833,7 +888,7 @@ function setupModelMenus() {
|
|||
menuName: "Edit",
|
||||
menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true",
|
||||
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true",
|
||||
grouping: "Advanced"
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
|
@ -841,7 +896,7 @@ function setupModelMenus() {
|
|||
menuItemName: MENU_EASE_ON_FOCUS,
|
||||
afterItem: MENU_AUTO_FOCUS_ON_SELECT,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true",
|
||||
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true",
|
||||
grouping: "Advanced"
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
|
@ -849,7 +904,7 @@ function setupModelMenus() {
|
|||
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
|
||||
afterItem: MENU_EASE_ON_FOCUS,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true",
|
||||
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) === "true",
|
||||
grouping: "Advanced"
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
|
@ -857,7 +912,7 @@ function setupModelMenus() {
|
|||
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
|
||||
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true",
|
||||
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) === "true",
|
||||
grouping: "Advanced"
|
||||
});
|
||||
|
||||
|
@ -927,7 +982,9 @@ Script.update.connect(function(deltaTime) {
|
|||
});
|
||||
|
||||
function insideBox(center, dimensions, point) {
|
||||
return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && (Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
|
||||
return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) &&
|
||||
(Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) &&
|
||||
(Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
|
||||
}
|
||||
|
||||
function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
||||
|
@ -939,10 +996,10 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
|||
|
||||
if (!keepIfTouching) {
|
||||
var isValid;
|
||||
if (selectionManager.localPosition === null) {
|
||||
if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) {
|
||||
isValid = function (position) {
|
||||
return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
isValid = function (position) {
|
||||
var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
|
||||
|
@ -953,7 +1010,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
|
|||
y: 0,
|
||||
z: 0
|
||||
}, selectionManager.localDimensions, localPosition);
|
||||
}
|
||||
};
|
||||
}
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
var properties = Entities.getEntityProperties(entities[i]);
|
||||
|
@ -1019,19 +1076,19 @@ function toggleSelectedEntitiesVisible() {
|
|||
}
|
||||
|
||||
function handeMenuEvent(menuItem) {
|
||||
if (menuItem == "Allow Selecting of Small Models") {
|
||||
if (menuItem === "Allow Selecting of Small Models") {
|
||||
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
||||
} else if (menuItem == "Allow Selecting of Large Models") {
|
||||
} else if (menuItem === "Allow Selecting of Large Models") {
|
||||
allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
|
||||
} else if (menuItem == "Allow Selecting of Lights") {
|
||||
} else if (menuItem === "Allow Selecting of Lights") {
|
||||
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
|
||||
} else if (menuItem == "Delete") {
|
||||
} else if (menuItem === "Delete") {
|
||||
deleteSelectedEntities();
|
||||
} else if (menuItem == "Export Entities") {
|
||||
} else if (menuItem === "Export Entities") {
|
||||
if (!selectionManager.hasSelection()) {
|
||||
Window.alert("No entities have been selected.");
|
||||
} else {
|
||||
var filename = Window.save("Select Where to Save", "", "*.json")
|
||||
var filename = Window.save("Select Where to Save", "", "*.json");
|
||||
if (filename) {
|
||||
var success = Clipboard.exportEntities(filename, selectionManager.selections);
|
||||
if (!success) {
|
||||
|
@ -1039,10 +1096,10 @@ function handeMenuEvent(menuItem) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (menuItem == "Import Entities" || menuItem == "Import Entities from URL") {
|
||||
} else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") {
|
||||
|
||||
var importURL = null;
|
||||
if (menuItem == "Import Entities") {
|
||||
if (menuItem === "Import Entities") {
|
||||
var fullPath = Window.browse("Select Model to Import", "", "*.json");
|
||||
if (fullPath) {
|
||||
importURL = "file:///" + fullPath;
|
||||
|
@ -1054,15 +1111,15 @@ function handeMenuEvent(menuItem) {
|
|||
if (importURL) {
|
||||
importSVO(importURL);
|
||||
}
|
||||
} else if (menuItem == "Entity List...") {
|
||||
} else if (menuItem === "Entity List...") {
|
||||
entityListTool.toggleVisible();
|
||||
} else if (menuItem == "Select All Entities In Box") {
|
||||
} else if (menuItem === "Select All Entities In Box") {
|
||||
selectAllEtitiesInCurrentSelectionBox(false);
|
||||
} else if (menuItem == "Select All Entities Touching Box") {
|
||||
} else if (menuItem === "Select All Entities Touching Box") {
|
||||
selectAllEtitiesInCurrentSelectionBox(true);
|
||||
} else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
|
||||
} else if (menuItem === MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
|
||||
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
||||
} else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
||||
} else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
||||
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||
}
|
||||
tooltip.show(false);
|
||||
|
@ -1081,8 +1138,11 @@ function getPositionToCreateEntity() {
|
|||
|
||||
var HALF_TREE_SCALE = 16384;
|
||||
|
||||
var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE;
|
||||
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE;
|
||||
var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE ||
|
||||
Math.abs(cameraPosition.z) > HALF_TREE_SCALE;
|
||||
var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE ||
|
||||
Math.abs(placementPosition.y) > HALF_TREE_SCALE ||
|
||||
Math.abs(placementPosition.z) > HALF_TREE_SCALE;
|
||||
|
||||
if (cameraOutOfBounds && placementOutOfBounds) {
|
||||
return null;
|
||||
|
@ -1096,7 +1156,7 @@ function getPositionToCreateEntity() {
|
|||
}
|
||||
|
||||
function importSVO(importURL) {
|
||||
print("Import URL requested: " + importURL)
|
||||
print("Import URL requested: " + importURL);
|
||||
if (!Entities.canAdjustLocks()) {
|
||||
Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
|
||||
return;
|
||||
|
@ -1121,7 +1181,7 @@ function importSVO(importURL) {
|
|||
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
|
||||
position = getPositionToCreateEntity();
|
||||
}
|
||||
if (position != null) {
|
||||
if (position !== null && position !== undefined) {
|
||||
var pastedEntityIDs = Clipboard.pasteEntities(position);
|
||||
|
||||
if (isActive) {
|
||||
|
@ -1158,13 +1218,13 @@ Controller.keyReleaseEvent.connect(function(event) {
|
|||
cameraManager.keyReleaseEvent(event);
|
||||
}
|
||||
// since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items
|
||||
if (event.text == "BACKSPACE" || event.text == "DELETE") {
|
||||
if (event.text === "BACKSPACE" || event.text === "DELETE") {
|
||||
deleteSelectedEntities();
|
||||
} else if (event.text == "ESC") {
|
||||
} else if (event.text === "ESC") {
|
||||
selectionManager.clearSelections();
|
||||
} else if (event.text == "TAB") {
|
||||
} else if (event.text === "TAB") {
|
||||
selectionDisplay.toggleSpaceMode();
|
||||
} else if (event.text == "f") {
|
||||
} else if (event.text === "f") {
|
||||
if (isActive) {
|
||||
if (selectionManager.hasSelection()) {
|
||||
cameraManager.enable();
|
||||
|
@ -1173,11 +1233,11 @@ Controller.keyReleaseEvent.connect(function(event) {
|
|||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
}
|
||||
} else if (event.text == '[') {
|
||||
} else if (event.text === '[') {
|
||||
if (isActive) {
|
||||
cameraManager.enable();
|
||||
}
|
||||
} else if (event.text == 'g') {
|
||||
} else if (event.text === 'g') {
|
||||
if (isActive && selectionManager.hasSelection()) {
|
||||
var newPosition = selectionManager.worldPosition;
|
||||
newPosition = Vec3.subtract(newPosition, {
|
||||
|
@ -1193,30 +1253,31 @@ Controller.keyReleaseEvent.connect(function(event) {
|
|||
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
|
||||
// possible to create an entity with a specific id, earlier undo commands to the deleted entity
|
||||
// will fail if there isn't a way to find the new entity id.
|
||||
DELETED_ENTITY_MAP = {}
|
||||
var DELETED_ENTITY_MAP = {};
|
||||
|
||||
function applyEntityProperties(data) {
|
||||
var properties = data.setProperties;
|
||||
var selectedEntityIDs = [];
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
var entityID = properties[i].entityID;
|
||||
var i, entityID;
|
||||
for (i = 0; i < properties.length; i++) {
|
||||
entityID = properties[i].entityID;
|
||||
if (DELETED_ENTITY_MAP[entityID] !== undefined) {
|
||||
entityID = DELETED_ENTITY_MAP[entityID];
|
||||
}
|
||||
Entities.editEntity(entityID, properties[i].properties);
|
||||
selectedEntityIDs.push(entityID);
|
||||
}
|
||||
for (var i = 0; i < data.createEntities.length; i++) {
|
||||
var entityID = data.createEntities[i].entityID;
|
||||
var properties = data.createEntities[i].properties;
|
||||
var newEntityID = Entities.addEntity(properties);
|
||||
for (i = 0; i < data.createEntities.length; i++) {
|
||||
entityID = data.createEntities[i].entityID;
|
||||
var entityProperties = data.createEntities[i].properties;
|
||||
var newEntityID = Entities.addEntity(entityProperties);
|
||||
DELETED_ENTITY_MAP[entityID] = newEntityID;
|
||||
if (data.selectCreated) {
|
||||
selectedEntityIDs.push(newEntityID);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < data.deleteEntities.length; i++) {
|
||||
var entityID = data.deleteEntities[i].entityID;
|
||||
for (i = 0; i < data.deleteEntities.length; i++) {
|
||||
entityID = data.deleteEntities[i].entityID;
|
||||
if (DELETED_ENTITY_MAP[entityID] !== undefined) {
|
||||
entityID = DELETED_ENTITY_MAP[entityID];
|
||||
}
|
||||
|
@ -1224,7 +1285,7 @@ function applyEntityProperties(data) {
|
|||
}
|
||||
|
||||
selectionManager.setSelections(selectedEntityIDs);
|
||||
};
|
||||
}
|
||||
|
||||
// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the
|
||||
// redo command, and the saved properties for the undo command. Also, include create and delete entity data.
|
||||
|
@ -1233,13 +1294,13 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
|||
setProperties: [],
|
||||
createEntities: deletedEntityData || [],
|
||||
deleteEntities: createdEntityData || [],
|
||||
selectCreated: true,
|
||||
selectCreated: true
|
||||
};
|
||||
var redoData = {
|
||||
setProperties: [],
|
||||
createEntities: createdEntityData || [],
|
||||
deleteEntities: deletedEntityData || [],
|
||||
selectCreated: false,
|
||||
selectCreated: false
|
||||
};
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
|
@ -1253,22 +1314,22 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
|||
properties: {
|
||||
position: initialProperties.position,
|
||||
rotation: initialProperties.rotation,
|
||||
dimensions: initialProperties.dimensions,
|
||||
},
|
||||
dimensions: initialProperties.dimensions
|
||||
}
|
||||
});
|
||||
redoData.setProperties.push({
|
||||
entityID: entityID,
|
||||
properties: {
|
||||
position: currentProperties.position,
|
||||
rotation: currentProperties.rotation,
|
||||
dimensions: currentProperties.dimensions,
|
||||
},
|
||||
dimensions: currentProperties.dimensions
|
||||
}
|
||||
});
|
||||
}
|
||||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
||||
PropertiesTool = function(opts) {
|
||||
var PropertiesTool = function (opts) {
|
||||
var that = {};
|
||||
|
||||
var url = Script.resolvePath('html/entityProperties.html');
|
||||
|
@ -1288,8 +1349,8 @@ PropertiesTool = function(opts) {
|
|||
};
|
||||
|
||||
selectionManager.addEventListener(function () {
|
||||
data = {
|
||||
type: 'update',
|
||||
var data = {
|
||||
type: 'update'
|
||||
};
|
||||
var selections = [];
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
|
@ -1300,7 +1361,8 @@ PropertiesTool = function(opts) {
|
|||
entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation);
|
||||
}
|
||||
if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) {
|
||||
entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, Vec3.toPolar(entity.properties.keyLight.direction));
|
||||
entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES,
|
||||
Vec3.toPolar(entity.properties.keyLight.direction));
|
||||
entity.properties.keyLight.direction.z = 0.0;
|
||||
}
|
||||
selections.push(entity);
|
||||
|
@ -1311,18 +1373,19 @@ PropertiesTool = function(opts) {
|
|||
|
||||
webView.webEventReceived.connect(function (data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "print") {
|
||||
var i, properties, dY, diff, newPosition;
|
||||
if (data.type === "print") {
|
||||
if (data.message) {
|
||||
print(data.message);
|
||||
}
|
||||
} else if (data.type == "update") {
|
||||
} else if (data.type === "update") {
|
||||
selectionManager.saveProperties();
|
||||
if (selectionManager.selections.length > 1) {
|
||||
properties = {
|
||||
locked: data.properties.locked,
|
||||
visible: data.properties.visible,
|
||||
visible: data.properties.visible
|
||||
};
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.editEntity(selectionManager.selections[i], properties);
|
||||
}
|
||||
} else {
|
||||
|
@ -1345,100 +1408,105 @@ PropertiesTool = function(opts) {
|
|||
}
|
||||
if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) {
|
||||
data.properties.keyLight.direction = Vec3.fromPolar(
|
||||
data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, data.properties.keyLight.direction.y * DEGREES_TO_RADIANS);
|
||||
data.properties.keyLight.direction.x * DEGREES_TO_RADIANS,
|
||||
data.properties.keyLight.direction.y * DEGREES_TO_RADIANS
|
||||
);
|
||||
}
|
||||
Entities.editEntity(selectionManager.selections[0], data.properties);
|
||||
if (data.properties.name !== undefined || data.properties.modelURL !== undefined || data.properties.visible !== undefined || data.properties.locked !== undefined) {
|
||||
if (data.properties.name !== undefined || data.properties.modelURL !== undefined ||
|
||||
data.properties.visible !== undefined || data.properties.locked !== undefined) {
|
||||
entityListTool.sendUpdate();
|
||||
}
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
} else if (data.type == "showMarketplace") {
|
||||
} else if (data.type === "showMarketplace") {
|
||||
showMarketplace();
|
||||
} else if (data.type == "action") {
|
||||
if (data.action == "moveSelectionToGrid") {
|
||||
} else if (data.type === "action") {
|
||||
if (data.action === "moveSelectionToGrid") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
selectionManager.saveProperties();
|
||||
var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
|
||||
var diff = {
|
||||
dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
|
||||
diff = {
|
||||
x: 0,
|
||||
y: dY,
|
||||
z: 0
|
||||
};
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
var newPosition = Vec3.sum(properties.position, diff);
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
newPosition = Vec3.sum(properties.position, diff);
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
position: newPosition,
|
||||
position: newPosition
|
||||
});
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
}
|
||||
} else if (data.action == "moveAllToGrid") {
|
||||
} else if (data.action === "moveAllToGrid") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
selectionManager.saveProperties();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2;
|
||||
var dY = grid.getOrigin().y - bottomY;
|
||||
var diff = {
|
||||
dY = grid.getOrigin().y - bottomY;
|
||||
diff = {
|
||||
x: 0,
|
||||
y: dY,
|
||||
z: 0
|
||||
};
|
||||
var newPosition = Vec3.sum(properties.position, diff);
|
||||
newPosition = Vec3.sum(properties.position, diff);
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
position: newPosition,
|
||||
position: newPosition
|
||||
});
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
}
|
||||
} else if (data.action == "resetToNaturalDimensions") {
|
||||
} else if (data.action === "resetToNaturalDimensions") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
selectionManager.saveProperties();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
var naturalDimensions = properties.naturalDimensions;
|
||||
|
||||
// If any of the natural dimensions are not 0, resize
|
||||
if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) {
|
||||
Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded.");
|
||||
if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 &&
|
||||
naturalDimensions.z === 0) {
|
||||
Window.alert("Cannot reset entity to its natural dimensions: Model URL" +
|
||||
" is invalid or the model has not yet been loaded.");
|
||||
} else {
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
dimensions: properties.naturalDimensions,
|
||||
dimensions: properties.naturalDimensions
|
||||
});
|
||||
}
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
}
|
||||
} else if (data.action == "previewCamera") {
|
||||
} else if (data.action === "previewCamera") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
Camera.mode = "entity";
|
||||
Camera.cameraEntity = selectionManager.selections[0];
|
||||
}
|
||||
} else if (data.action == "rescaleDimensions") {
|
||||
} else if (data.action === "rescaleDimensions") {
|
||||
var multiplier = data.percentage / 100;
|
||||
if (selectionManager.hasSelection()) {
|
||||
selectionManager.saveProperties();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
properties = selectionManager.savedProperties[selectionManager.selections[i]];
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
dimensions: Vec3.multiply(multiplier, properties.dimensions),
|
||||
dimensions: Vec3.multiply(multiplier, properties.dimensions)
|
||||
});
|
||||
}
|
||||
pushCommandForSelections();
|
||||
selectionManager._update();
|
||||
}
|
||||
} else if (data.action == "reloadScript") {
|
||||
} else if (data.action === "reloadScript") {
|
||||
if (selectionManager.hasSelection()) {
|
||||
var timestamp = Date.now();
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.editEntity(selectionManager.selections[i], {
|
||||
scriptTimestamp: timestamp,
|
||||
scriptTimestamp: timestamp
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1449,7 +1517,7 @@ PropertiesTool = function(opts) {
|
|||
return that;
|
||||
};
|
||||
|
||||
PopupMenu = function() {
|
||||
var PopupMenu = function () {
|
||||
var self = this;
|
||||
|
||||
var MENU_ITEM_HEIGHT = 21;
|
||||
|
@ -1489,7 +1557,7 @@ PopupMenu = function() {
|
|||
font: {
|
||||
size: 12
|
||||
},
|
||||
visible: false,
|
||||
visible: false
|
||||
});
|
||||
overlays.push(id);
|
||||
overlayInfo[id] = {
|
||||
|
@ -1508,7 +1576,7 @@ PopupMenu = function() {
|
|||
for (var key in overlayInfo) {
|
||||
Overlays.editOverlay(key, {
|
||||
x: x,
|
||||
y: y,
|
||||
y: y
|
||||
});
|
||||
y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING;
|
||||
}
|
||||
|
@ -1543,13 +1611,13 @@ PopupMenu = function() {
|
|||
y: event.y
|
||||
});
|
||||
if (!pressingOverlay) {
|
||||
if (hoveringOverlay != null && overlay != hoveringOverlay) {
|
||||
if (hoveringOverlay !== null && hoveringOverlay !== null && overlay !== hoveringOverlay) {
|
||||
Overlays.editOverlay(hoveringOverlay, {
|
||||
backgroundColor: upColor
|
||||
});
|
||||
hoveringOverlay = null;
|
||||
}
|
||||
if (overlay != hoveringOverlay && overlay in overlayInfo) {
|
||||
if (overlay !== hoveringOverlay && overlay in overlayInfo) {
|
||||
Overlays.editOverlay(overlay, {
|
||||
backgroundColor: overColor
|
||||
});
|
||||
|
@ -1564,8 +1632,8 @@ PopupMenu = function() {
|
|||
x: event.x,
|
||||
y: event.y
|
||||
});
|
||||
if (pressingOverlay != null) {
|
||||
if (overlay == pressingOverlay) {
|
||||
if (pressingOverlay !== null && pressingOverlay !== undefined) {
|
||||
if (overlay === pressingOverlay) {
|
||||
self.onSelectMenuItem(overlayInfo[overlay].name);
|
||||
}
|
||||
Overlays.editOverlay(pressingOverlay, {
|
||||
|
@ -1579,7 +1647,7 @@ PopupMenu = function() {
|
|||
var visible = false;
|
||||
|
||||
self.setVisible = function (newVisible) {
|
||||
if (newVisible != visible) {
|
||||
if (newVisible !== visible) {
|
||||
visible = newVisible;
|
||||
for (var key in overlayInfo) {
|
||||
Overlays.editOverlay(key, {
|
||||
|
@ -1587,13 +1655,13 @@ PopupMenu = function() {
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
self.show = function () {
|
||||
self.setVisible(true);
|
||||
}
|
||||
};
|
||||
self.hide = function () {
|
||||
self.setVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
for (var i = 0; i < overlays.length; i++) {
|
||||
|
@ -1610,7 +1678,7 @@ PopupMenu = function() {
|
|||
};
|
||||
|
||||
|
||||
var propertyMenu = PopupMenu();
|
||||
var propertyMenu = new PopupMenu();
|
||||
|
||||
propertyMenu.onSelectMenuItem = function (name) {
|
||||
|
||||
|
@ -1621,12 +1689,12 @@ propertyMenu.onSelectMenuItem = function(name) {
|
|||
|
||||
var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
|
||||
|
||||
propertiesTool = PropertiesTool();
|
||||
var particleExplorerTool = ParticleExplorerTool();
|
||||
var propertiesTool = new PropertiesTool();
|
||||
var particleExplorerTool = new ParticleExplorerTool();
|
||||
var selectedParticleEntity = 0;
|
||||
entityListTool.webView.webEventReceived.connect(function (data) {
|
||||
var data = JSON.parse(data);
|
||||
if (data.type == "selectionUpdate") {
|
||||
data = JSON.parse(data);
|
||||
if (data.type === "selectionUpdate") {
|
||||
var ids = data.entityIds;
|
||||
if (ids.length === 1) {
|
||||
if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") {
|
||||
|
@ -1646,7 +1714,7 @@ entityListTool.webView.webEventReceived.connect(function(data) {
|
|||
particleExplorerTool.setActiveParticleEntity(ids[0]);
|
||||
|
||||
particleExplorerTool.webView.webEventReceived.connect(function (data) {
|
||||
var data = JSON.parse(data);
|
||||
data = JSON.parse(data);
|
||||
if (data.messageType === "page_loaded") {
|
||||
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
|
||||
}
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
//
|
||||
// examples.js
|
||||
// examples
|
||||
//
|
||||
// Created by Eric Levin on 8 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var toolIconUrl = Script.resolvePath("assets/images/tools/");
|
||||
|
||||
var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples";
|
||||
var examplesWindow = new OverlayWebWindow({
|
||||
title: 'Examples',
|
||||
source: "about:blank",
|
||||
width: 900,
|
||||
height: 700,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var toolHeight = 50;
|
||||
var toolWidth = 50;
|
||||
var TOOLBAR_MARGIN_Y = 0;
|
||||
|
||||
|
||||
function showExamples(marketplaceID) {
|
||||
var url = EXAMPLES_URL;
|
||||
if (marketplaceID) {
|
||||
url = url + "/items/" + marketplaceID;
|
||||
}
|
||||
print("setting examples URL to " + url);
|
||||
examplesWindow.setURL(url);
|
||||
examplesWindow.setVisible(true);
|
||||
|
||||
UserActivityLogger.openedMarketplace();
|
||||
}
|
||||
|
||||
function hideExamples() {
|
||||
examplesWindow.setVisible(false);
|
||||
examplesWindow.setURL("about:blank");
|
||||
}
|
||||
|
||||
function toggleExamples() {
|
||||
if (examplesWindow.visible) {
|
||||
hideExamples();
|
||||
} else {
|
||||
showExamples();
|
||||
}
|
||||
}
|
||||
|
||||
var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
|
||||
var browseExamplesButton = toolBar.addButton({
|
||||
imageURL: toolIconUrl + "market.svg",
|
||||
objectName: "examples",
|
||||
buttonState: 1,
|
||||
defaultState: 1,
|
||||
hoverState: 3,
|
||||
alpha: 0.9
|
||||
});
|
||||
|
||||
function onExamplesWindowVisibilityChanged() {
|
||||
browseExamplesButton.writeProperty('buttonState', examplesWindow.visible ? 0 : 1);
|
||||
browseExamplesButton.writeProperty('defaultState', examplesWindow.visible ? 0 : 1);
|
||||
browseExamplesButton.writeProperty('hoverState', examplesWindow.visible ? 2 : 3);
|
||||
}
|
||||
function onClick() {
|
||||
toggleExamples();
|
||||
}
|
||||
browseExamplesButton.clicked.connect(onClick);
|
||||
examplesWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
toolBar.removeButton("examples");
|
||||
browseExamplesButton.clicked.disconnect(onClick);
|
||||
examplesWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged);
|
||||
});
|
77
scripts/system/marketplace.js
Normal file
77
scripts/system/marketplace.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// marketplace.js
|
||||
//
|
||||
// Created by Eric Levin on 8 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var toolIconUrl = Script.resolvePath("assets/images/tools/");
|
||||
|
||||
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
|
||||
var marketplaceWindow = new OverlayWebWindow({
|
||||
title: "Marketplace",
|
||||
source: "about:blank",
|
||||
width: 900,
|
||||
height: 700,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var toolHeight = 50;
|
||||
var toolWidth = 50;
|
||||
var TOOLBAR_MARGIN_Y = 0;
|
||||
|
||||
|
||||
function showMarketplace(marketplaceID) {
|
||||
var url = MARKETPLACE_URL;
|
||||
if (marketplaceID) {
|
||||
url = url + "/items/" + marketplaceID;
|
||||
}
|
||||
marketplaceWindow.setURL(url);
|
||||
marketplaceWindow.setVisible(true);
|
||||
|
||||
UserActivityLogger.openedMarketplace();
|
||||
}
|
||||
|
||||
function hideMarketplace() {
|
||||
marketplaceWindow.setVisible(false);
|
||||
marketplaceWindow.setURL("about:blank");
|
||||
}
|
||||
|
||||
function toggleMarketplace() {
|
||||
if (marketplaceWindow.visible) {
|
||||
hideMarketplace();
|
||||
} else {
|
||||
showMarketplace();
|
||||
}
|
||||
}
|
||||
|
||||
var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
|
||||
var browseExamplesButton = toolBar.addButton({
|
||||
imageURL: toolIconUrl + "market.svg",
|
||||
objectName: "marketplace",
|
||||
buttonState: 1,
|
||||
defaultState: 1,
|
||||
hoverState: 3,
|
||||
alpha: 0.9
|
||||
});
|
||||
|
||||
function onExamplesWindowVisibilityChanged() {
|
||||
browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1);
|
||||
browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1);
|
||||
browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3);
|
||||
}
|
||||
function onClick() {
|
||||
toggleMarketplace();
|
||||
}
|
||||
browseExamplesButton.clicked.connect(onClick);
|
||||
marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
toolBar.removeButton("marketplace");
|
||||
browseExamplesButton.clicked.disconnect(onClick);
|
||||
marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged);
|
||||
});
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
var tiltMazePath = Script.resolvePath("atp:/tiltMaze/wrapper.js")
|
||||
|
||||
var whiteboardPath = Script.resolvePath("atp:/whiteboard/wrapper.js");
|
||||
|
||||
var cuckooClockPath = Script.resolvePath("atp:/cuckooClock/wrapper.js");
|
||||
|
||||
var pingPongGunPath = Script.resolvePath("atp:/pingPongGun/wrapper.js");
|
||||
|
@ -51,7 +49,6 @@
|
|||
|
||||
Script.include(fishTankPath);
|
||||
Script.include(tiltMazePath);
|
||||
Script.include(whiteboardPath);
|
||||
Script.include(cuckooClockPath);
|
||||
Script.include(pingPongGunPath);
|
||||
Script.include(transformerPath);
|
||||
|
@ -201,6 +198,7 @@
|
|||
Script.setTimeout(function() {
|
||||
_this.createKineticEntities();
|
||||
_this.createScriptedEntities();
|
||||
_this.createWhiteboard();
|
||||
_this.setupDressingRoom();
|
||||
_this.createMilkPailBalls();
|
||||
_this.createTarget();
|
||||
|
@ -296,6 +294,21 @@
|
|||
print('HOME after deleting home entities');
|
||||
},
|
||||
|
||||
createWhiteboard: function() {
|
||||
var WHITEBOARD_URL = "atp:/whiteboard/whiteboardWithSwiper.json"
|
||||
var success = Clipboard.importEntities(WHITEBOARD_URL);
|
||||
if (success === true) {
|
||||
created = Clipboard.pasteEntities({
|
||||
x: 1105.0955,
|
||||
y: 460.5000,
|
||||
z: -77.4409
|
||||
})
|
||||
print('created ' + created);
|
||||
} else {
|
||||
print('failed to import whiteboard');
|
||||
}
|
||||
},
|
||||
|
||||
createScriptedEntities: function() {
|
||||
var fishTank = new FishTank({
|
||||
x: 1099.2200,
|
||||
|
@ -313,16 +326,6 @@
|
|||
z: -80.4891
|
||||
});
|
||||
|
||||
var whiteboard = new Whiteboard({
|
||||
x: 1105.0955,
|
||||
y: 460.5000,
|
||||
z: -77.4409
|
||||
}, {
|
||||
x: -0.0013,
|
||||
y: -133.0056,
|
||||
z: -0.0013
|
||||
});
|
||||
|
||||
var pingPongGun = new HomePingPongGun({
|
||||
x: 1101.2123,
|
||||
y: 460.2328,
|
||||
|
|
|
@ -1,128 +1,59 @@
|
|||
//
|
||||
// eraserEntityScript.js
|
||||
// examples/homeContent/eraserEntityScript
|
||||
//
|
||||
// Created by Eric Levin on 2/17/15.
|
||||
// Additions by James B. Pollack @imgntn 6/9/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// This entity script provides logic for an object with attached script to erase nearby marker strokes
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
Script.include('../utils.js');
|
||||
var TRIGGER_CONTROLS = [
|
||||
Controller.Standard.LT,
|
||||
Controller.Standard.RT,
|
||||
];
|
||||
Script.include('atp:/whiteboard/utils.js');
|
||||
|
||||
var _this;
|
||||
|
||||
Eraser = function() {
|
||||
_this = this;
|
||||
|
||||
_this.ERASER_TRIGGER_THRESHOLD = 0.2;
|
||||
_this.STROKE_NAME = "home_polyline_markerStroke";
|
||||
_this.ERASER_TO_STROKE_SEARCH_RADIUS = 0.7;
|
||||
_this.ERASER_RESET_WAIT_TIME = 3000;
|
||||
_this.STROKE_NAME = "hifi_polyline_markerStroke";
|
||||
_this.ERASER_TO_STROKE_SEARCH_RADIUS = 0.1;
|
||||
};
|
||||
|
||||
Eraser.prototype = {
|
||||
|
||||
startEquip: function(id, params) {
|
||||
_this.equipped = true;
|
||||
_this.hand = params[0] == "left" ? 0 : 1;
|
||||
// We really only need to grab position of marker strokes once, and then just check to see if eraser comes near enough to those strokes
|
||||
Overlays.editOverlay(_this.searchSphere, {
|
||||
visible: true
|
||||
});
|
||||
},
|
||||
continueEquip: function() {
|
||||
continueNearGrab: function() {
|
||||
_this.eraserPosition = Entities.getEntityProperties(_this.entityID, "position").position;
|
||||
Overlays.editOverlay(_this.searchSphere, {
|
||||
position: _this.eraserPosition
|
||||
});
|
||||
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[_this.hand]);
|
||||
if (_this.triggerValue > _this.ERASER_TRIGGER_THRESHOLD) {
|
||||
_this.continueHolding();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
continueHolding: function() {
|
||||
var strokeIDs = Entities.findEntities(_this.eraserPosition, _this.ERASER_TO_STROKE_SEARCH_RADIUS);
|
||||
var results = Entities.findEntities(_this.eraserPosition, _this.ERASER_TO_STROKE_SEARCH_RADIUS);
|
||||
// Create a map of stroke entities and their positions
|
||||
|
||||
strokeIDs.forEach(function(strokeID) {
|
||||
var strokeProps = Entities.getEntityProperties(strokeID, ["position", "name"]);
|
||||
if (strokeProps.name === _this.STROKE_NAME && Vec3.distance(_this.eraserPosition, strokeProps.position) < _this.ERASER_TO_STROKE_SEARCH_RADIUS) {
|
||||
Entities.deleteEntity(strokeID);
|
||||
results.forEach(function(stroke) {
|
||||
var props = Entities.getEntityProperties(stroke, ["position", "name"]);
|
||||
if (props.name === _this.STROKE_NAME && Vec3.distance(_this.eraserPosition, props.position) < _this.ERASER_TO_STROKE_SEARCH_RADIUS) {
|
||||
Entities.deleteEntity(stroke);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
releaseEquip: function() {
|
||||
Overlays.editOverlay(_this.searchSphere, {
|
||||
visible: false
|
||||
});
|
||||
|
||||
// Once user releases eraser, wait a bit then put marker back to its original position and rotation
|
||||
// Script.setTimeout(function() {
|
||||
// var userData = getEntityUserData(_this.entityID);
|
||||
// Entities.editEntity(_this.entityID, {
|
||||
// position: userData.originalPosition,
|
||||
// rotation: userData.originalRotation,
|
||||
// velocity: {
|
||||
// x: 0,
|
||||
// y: -0.01,
|
||||
// z: 0
|
||||
// }
|
||||
// });
|
||||
// }, _this.ERASER_RESET_WAIT_TIME);
|
||||
},
|
||||
collisionWithEntity: function(myID, otherID, collision) {
|
||||
var otherProps = Entities.getEntityProperties(otherID);
|
||||
if (otherProps.name === 'home_model_homeset') {
|
||||
var userData = getEntityUserData(_this.entityID);
|
||||
Entities.editEntity(_this.entityID, {
|
||||
position: userData.originalPosition,
|
||||
rotation: userData.originalRotation,
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
angularVelocity: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
preload: function(entityID) {
|
||||
_this.entityID = entityID;
|
||||
_this.searchSphere = Overlays.addOverlay('sphere', {
|
||||
size: _this.ERASER_TO_STROKE_SEARCH_RADIUS,
|
||||
color: {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 10
|
||||
},
|
||||
alpha: 0.2,
|
||||
solid: true,
|
||||
visible: false
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
unload: function() {
|
||||
Overlays.deleteOverlay(_this.searchSphere);
|
||||
}
|
||||
startEquip: function() {
|
||||
_this.startNearGrab();
|
||||
},
|
||||
|
||||
continueEquip: function() {
|
||||
_this.continueNearGrab();
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Eraser();
|
||||
});
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// markerTipEntityScript.js
|
||||
// examples/homeContent/markerTipEntityScript
|
||||
//
|
||||
// Created by Eric Levin on 2/17/15.
|
||||
// Additions by James B. Pollack @imgntn 6/9/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// This script provides the logic for an object to draw marker strokes on its associated whiteboard
|
||||
|
@ -10,15 +10,9 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
Script.include('../utils.js');
|
||||
var TRIGGER_CONTROLS = [
|
||||
Controller.Standard.LT,
|
||||
Controller.Standard.RT,
|
||||
];
|
||||
Script.include('atp:/whiteboard/utils.js');
|
||||
|
||||
var MAX_POINTS_PER_STROKE = 40;
|
||||
var _this;
|
||||
|
@ -31,95 +25,74 @@
|
|||
min: 0.002,
|
||||
max: 0.01
|
||||
};
|
||||
_this.MAX_MARKER_TO_BOARD_DISTANCE = 1.4;
|
||||
_this.MIN_DISTANCE_BETWEEN_POINTS = 0.002;
|
||||
_this.MAX_DISTANCE_BETWEEN_POINTS = 0.1;
|
||||
_this.strokes = [];
|
||||
_this.PAINTING_TRIGGER_THRESHOLD = 0.2;
|
||||
_this.STROKE_NAME = "home_polyline_markerStroke";
|
||||
_this.WHITEBOARD_SURFACE_NAME = "home_box_whiteboardDrawingSurface"
|
||||
_this.MARKER_RESET_WAIT_TIME = 3000;
|
||||
_this.STROKE_NAME = "hifi_polyline_markerStroke";
|
||||
_this.WHITEBOARD_SURFACE_NAME = "hifi-whiteboardDrawingSurface"
|
||||
};
|
||||
|
||||
MarkerTip.prototype = {
|
||||
|
||||
startEquip: function(id, params) {
|
||||
print('start equip')
|
||||
startNearGrab: function() {
|
||||
_this.whiteboards = [];
|
||||
_this.equipped = true;
|
||||
_this.hand = params[0] == "left" ? 0 : 1;
|
||||
_this.markerColor = getEntityUserData(_this.entityID).markerColor;
|
||||
// search for whiteboards
|
||||
var markerPosition = Entities.getEntityProperties(_this.entityID, "position").position;
|
||||
var entities = Entities.findEntities(markerPosition, 10);
|
||||
entities.forEach(function(entity) {
|
||||
|
||||
var markerProps = Entities.getEntityProperties(_this.entityID);
|
||||
_this.DRAW_ON_BOARD_DISTANCE = markerProps.dimensions.z / 2;
|
||||
var markerPosition = markerProps.position;
|
||||
var results = Entities.findEntities(markerPosition, 5);
|
||||
results.forEach(function(entity) {
|
||||
var entityName = Entities.getEntityProperties(entity, "name").name;
|
||||
if (entityName === _this.WHITEBOARD_SURFACE_NAME) {
|
||||
_this.whiteboards.push(entity);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
releaseEquip: function() {
|
||||
releaseGrab: function() {
|
||||
_this.resetStroke();
|
||||
Overlays.editOverlay(_this.laserPointer, {
|
||||
visible: false
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
collisionWithEntity: function(myID, otherID, collision) {
|
||||
var otherProps = Entities.getEntityProperties(otherID);
|
||||
if (otherProps.name === 'home_model_homeset') {
|
||||
var userData = getEntityUserData(_this.entityID);
|
||||
Entities.editEntity(_this.entityID, {
|
||||
position: userData.originalPosition,
|
||||
rotation: userData.originalRotation,
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
angularVelocity: {x: 0, y: 0, z: 0}
|
||||
})
|
||||
}
|
||||
},
|
||||
continueEquip: function() {
|
||||
continueNearGrab: function() {
|
||||
// cast a ray from marker and see if it hits anything
|
||||
var markerProps = Entities.getEntityProperties(_this.entityID, ["position", "rotation"]);
|
||||
var markerProps = Entities.getEntityProperties(_this.entityID);
|
||||
|
||||
//need to back up the ray to the back of the marker
|
||||
|
||||
var markerFront = Quat.getFront(markerProps.rotation);
|
||||
var howFarBack = markerProps.dimensions.z / 2;
|
||||
var pulledBack = Vec3.multiply(markerFront, -howFarBack);
|
||||
var backedOrigin = Vec3.sum(markerProps.position, pulledBack);
|
||||
|
||||
var pickRay = {
|
||||
origin: markerProps.position,
|
||||
origin: backedOrigin,
|
||||
direction: Quat.getFront(markerProps.rotation)
|
||||
}
|
||||
var intersection = Entities.findRayIntersectionBlocking(pickRay, true, _this.whiteboards);
|
||||
var intersection = Entities.findRayIntersection(pickRay, true, _this.whiteboards);
|
||||
|
||||
if (intersection.intersects && Vec3.distance(intersection.intersection, markerProps.position) < _this.MAX_MARKER_TO_BOARD_DISTANCE) {
|
||||
if (intersection.intersects && Vec3.distance(intersection.intersection, markerProps.position) <= _this.DRAW_ON_BOARD_DISTANCE) {
|
||||
_this.currentWhiteboard = intersection.entityID;
|
||||
var whiteboardRotation = Entities.getEntityProperties(_this.currentWhiteboard, "rotation").rotation;
|
||||
_this.whiteboardNormal = Quat.getFront(whiteboardRotation);
|
||||
Overlays.editOverlay(_this.laserPointer, {
|
||||
visible: true,
|
||||
position: intersection.intersection,
|
||||
rotation: whiteboardRotation
|
||||
})
|
||||
_this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[_this.hand]);
|
||||
if (_this.triggerValue > _this.PAINTING_TRIGGER_THRESHOLD) {
|
||||
|
||||
_this.paint(intersection.intersection)
|
||||
} else {
|
||||
_this.resetStroke();
|
||||
}
|
||||
|
||||
} else {
|
||||
if (_this.currentStroke) {
|
||||
_this.resetStroke();
|
||||
}
|
||||
|
||||
Overlays.editOverlay(_this.laserPointer, {
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
startEquip: function() {
|
||||
_this.startNearGrab();
|
||||
},
|
||||
|
||||
continueEquip: function() {
|
||||
_this.continueNearGrab();
|
||||
},
|
||||
|
||||
newStroke: function(position) {
|
||||
|
@ -135,12 +108,7 @@
|
|||
position: position,
|
||||
textures: _this.MARKER_TEXTURE_URL,
|
||||
color: _this.markerColor,
|
||||
lifetime: 5000,
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
}
|
||||
}),
|
||||
lifetime: 5000
|
||||
});
|
||||
|
||||
_this.linePoints = [];
|
||||
|
@ -170,7 +138,8 @@
|
|||
_this.normals.push(_this.whiteboardNormal);
|
||||
|
||||
var strokeWidths = [];
|
||||
for (var i = 0; i < _this.linePoints.length; i++) {
|
||||
var i;
|
||||
for (i = 0; i < _this.linePoints.length; i++) {
|
||||
// Create a temp array of stroke widths for calligraphy effect - start and end should be less wide
|
||||
var pointsFromCenter = Math.abs(_this.linePoints.length / 2 - i);
|
||||
var pointWidth = map(pointsFromCenter, 0, this.linePoints.length / 2, _this.STROKE_WIDTH_RANGE.max, this.STROKE_WIDTH_RANGE.min);
|
||||
|
@ -191,6 +160,7 @@
|
|||
_this.oldPosition = position;
|
||||
}
|
||||
},
|
||||
|
||||
resetStroke: function() {
|
||||
|
||||
Entities.editEntity(_this.currentStroke, {
|
||||
|
@ -203,26 +173,9 @@
|
|||
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
_this.laserPointer = Overlays.addOverlay("circle3d", {
|
||||
color: {
|
||||
red: 220,
|
||||
green: 35,
|
||||
blue: 53
|
||||
},
|
||||
solid: true,
|
||||
size: 0.01,
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
unload: function() {
|
||||
Overlays.deleteOverlay(_this.laserPointer);
|
||||
_this.strokes.forEach(function(stroke) {
|
||||
Entities.deleteEntity(stroke);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new MarkerTip();
|
||||
});
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
//
|
||||
// Created by The Content Team 4/10/216
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var whiteboardPath = Script.resolvePath('wrapper.js');
|
||||
Script.include(whiteboardPath);
|
||||
|
||||
var whiteboard = new Whiteboard({
|
||||
x: 1104,
|
||||
y: 460.5,
|
||||
z: -77
|
||||
}, {
|
||||
x: 0,
|
||||
y: -133,
|
||||
z: 0
|
||||
});
|
62
unpublishedScripts/DomainContent/Home/whiteboard/swiper.js
Normal file
62
unpublishedScripts/DomainContent/Home/whiteboard/swiper.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Created by James B. Pollack @imgntn 6/8/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
//
|
||||
|
||||
(function() {
|
||||
|
||||
var _this;
|
||||
|
||||
Swiper = function() {
|
||||
_this = this;
|
||||
}
|
||||
|
||||
Swiper.prototype = {
|
||||
busy: false,
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
Script.update.connect(this.update);
|
||||
},
|
||||
clickReleaseOnEntity: function() {
|
||||
this.createSupplies();
|
||||
},
|
||||
update: function() {
|
||||
if (_this.busy === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
var position = Entities.getEntityProperties(_this.entityID).position;
|
||||
var TRIGGER_THRESHOLD = 0.11;
|
||||
|
||||
var leftHandPosition = MyAvatar.getLeftPalmPosition();
|
||||
var rightHandPosition = MyAvatar.getRightPalmPosition();
|
||||
|
||||
var leftDistance = Vec3.distance(leftHandPosition, position)
|
||||
var rightDistance = Vec3.distance(rightHandPosition, position)
|
||||
|
||||
if (rightDistance < TRIGGER_THRESHOLD || leftDistance < TRIGGER_THRESHOLD) {
|
||||
_this.createSupplies();
|
||||
_this.busy = true;
|
||||
Script.setTimeout(function() {
|
||||
_this.busy = false;
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
|
||||
createSupplies: function() {
|
||||
var myProperties = Entities.getEntityProperties(this.entityID);
|
||||
|
||||
Entities.callEntityMethod(myProperties.parentID, "createMarkers");
|
||||
Entities.callEntityMethod(myProperties.parentID, "createEraser");
|
||||
|
||||
},
|
||||
unload: function() {
|
||||
Script.update.disconnect(this.update);
|
||||
}
|
||||
|
||||
}
|
||||
return new Swiper
|
||||
})
|
347
unpublishedScripts/DomainContent/Home/whiteboard/utils.js
Normal file
347
unpublishedScripts/DomainContent/Home/whiteboard/utils.js
Normal file
|
@ -0,0 +1,347 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/29
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
map = function(value, min1, max1, min2, max2) {
|
||||
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
|
||||
}
|
||||
|
||||
vec3toStr = function(v, digits) {
|
||||
if (!digits) {
|
||||
digits = 3;
|
||||
}
|
||||
return "{ " + v.x.toFixed(digits) + ", " + v.y.toFixed(digits) + ", " + v.z.toFixed(digits) + " }";
|
||||
}
|
||||
|
||||
quatToStr = function(q, digits) {
|
||||
if (!digits) {
|
||||
digits = 3;
|
||||
}
|
||||
return "{ " + q.w.toFixed(digits) + ", " + q.x.toFixed(digits) + ", " +
|
||||
q.y.toFixed(digits) + ", " + q.z.toFixed(digits) + " }";
|
||||
}
|
||||
|
||||
vec3equal = function(v0, v1) {
|
||||
return (v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z);
|
||||
}
|
||||
|
||||
colorMix = function(colorA, colorB, mix) {
|
||||
var result = {};
|
||||
for (var key in colorA) {
|
||||
result[key] = (colorA[key] * (1 - mix)) + (colorB[key] * mix);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
scaleLine = function(start, end, scale) {
|
||||
var v = Vec3.subtract(end, start);
|
||||
var length = Vec3.length(v);
|
||||
v = Vec3.multiply(scale, v);
|
||||
return Vec3.sum(start, v);
|
||||
}
|
||||
|
||||
findAction = function(name) {
|
||||
return Controller.findAction(name);
|
||||
}
|
||||
|
||||
addLine = function(origin, vector, color) {
|
||||
if (!color) {
|
||||
color = COLORS.WHITE
|
||||
}
|
||||
return Entities.addEntity(mergeObjects(LINE_PROTOTYPE, {
|
||||
position: origin,
|
||||
linePoints: [
|
||||
ZERO_VECTOR,
|
||||
vector,
|
||||
],
|
||||
color: color
|
||||
}));
|
||||
}
|
||||
|
||||
// FIXME fetch from a subkey of user data to support non-destructive modifications
|
||||
setEntityUserData = function(id, data) {
|
||||
var json = JSON.stringify(data)
|
||||
Entities.editEntity(id, {
|
||||
userData: json
|
||||
});
|
||||
}
|
||||
|
||||
// FIXME do non-destructive modification of the existing user data
|
||||
getEntityUserData = function(id) {
|
||||
var results = null;
|
||||
var properties = Entities.getEntityProperties(id, "userData");
|
||||
if (properties.userData) {
|
||||
try {
|
||||
results = JSON.parse(properties.userData);
|
||||
} catch (err) {
|
||||
logDebug(err);
|
||||
logDebug(properties.userData);
|
||||
}
|
||||
}
|
||||
return results ? results : {};
|
||||
}
|
||||
|
||||
|
||||
// Non-destructively modify the user data of an entity.
|
||||
setEntityCustomData = function(customKey, id, data) {
|
||||
var userData = getEntityUserData(id);
|
||||
if (data == null) {
|
||||
delete userData[customKey];
|
||||
} else {
|
||||
userData[customKey] = data;
|
||||
}
|
||||
setEntityUserData(id, userData);
|
||||
}
|
||||
|
||||
getEntityCustomData = function(customKey, id, defaultValue) {
|
||||
var userData = getEntityUserData(id);
|
||||
if (undefined != userData[customKey]) {
|
||||
return userData[customKey];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
mergeObjects = function(proto, custom) {
|
||||
var result = {};
|
||||
for (var attrname in proto) {
|
||||
result[attrname] = proto[attrname];
|
||||
}
|
||||
for (var attrname in custom) {
|
||||
result[attrname] = custom[attrname];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LOG_WARN = 1;
|
||||
|
||||
logWarn = function(str) {
|
||||
if (LOG_WARN) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR = 1;
|
||||
|
||||
logError = function(str) {
|
||||
if (LOG_ERROR) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO = 1;
|
||||
|
||||
logInfo = function(str) {
|
||||
if (LOG_INFO) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG = 0;
|
||||
|
||||
logDebug = function(str) {
|
||||
if (LOG_DEBUG) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TRACE = 0;
|
||||
|
||||
logTrace = function(str) {
|
||||
if (LOG_TRACE) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the penetration between a point and a sphere (centered at the origin)
|
||||
// if point is inside sphere: returns true and stores the result in 'penetration'
|
||||
// (the vector that would move the point outside the sphere)
|
||||
// otherwise returns false
|
||||
findSphereHit = function(point, sphereRadius) {
|
||||
var EPSILON = 0.000001; //smallish positive number - used as margin of error for some computations
|
||||
var vectorLength = Vec3.length(point);
|
||||
if (vectorLength < EPSILON) {
|
||||
return true;
|
||||
}
|
||||
var distance = vectorLength - sphereRadius;
|
||||
if (distance < 0.0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
findSpherePointHit = function(sphereCenter, sphereRadius, point) {
|
||||
return findSphereHit(Vec3.subtract(point, sphereCenter), sphereRadius);
|
||||
}
|
||||
|
||||
findSphereSphereHit = function(firstCenter, firstRadius, secondCenter, secondRadius) {
|
||||
return findSpherePointHit(firstCenter, firstRadius + secondRadius, secondCenter);
|
||||
}
|
||||
|
||||
// Given a vec3 v, return a vec3 that is the same vector relative to the avatars
|
||||
// DEFAULT eye position, rotated into the avatars reference frame.
|
||||
getEyeRelativePosition = function(v) {
|
||||
return Vec3.sum(MyAvatar.getDefaultEyePosition(), Vec3.multiplyQbyV(MyAvatar.orientation, v));
|
||||
}
|
||||
|
||||
getAvatarRelativeRotation = function(q) {
|
||||
return Quat.multiply(MyAvatar.orientation, q);
|
||||
}
|
||||
|
||||
pointInExtents = function(point, minPoint, maxPoint) {
|
||||
return (point.x >= minPoint.x && point.x <= maxPoint.x) &&
|
||||
(point.y >= minPoint.y && point.y <= maxPoint.y) &&
|
||||
(point.z >= minPoint.z && point.z <= maxPoint.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an HSL color value to RGB. Conversion formula
|
||||
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
|
||||
* Assumes h, s, and l are contained in the set [0, 1] and
|
||||
* returns r, g, and b in the set [0, 255].
|
||||
*
|
||||
* @param Number h The hue
|
||||
* @param Number s The saturation
|
||||
* @param Number l The lightness
|
||||
* @return Array The RGB representation
|
||||
*/
|
||||
hslToRgb = function(hsl) {
|
||||
var r, g, b;
|
||||
if (hsl.s == 0) {
|
||||
r = g = b = hsl.l; // achromatic
|
||||
} else {
|
||||
var hue2rgb = function hue2rgb(p, q, t) {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1 / 2) return q;
|
||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||
return p;
|
||||
}
|
||||
|
||||
var q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s;
|
||||
var p = 2 * hsl.l - q;
|
||||
r = hue2rgb(p, q, hsl.h + 1 / 3);
|
||||
g = hue2rgb(p, q, hsl.h);
|
||||
b = hue2rgb(p, q, hsl.h - 1 / 3);
|
||||
}
|
||||
|
||||
return {
|
||||
red: Math.round(r * 255),
|
||||
green: Math.round(g * 255),
|
||||
blue: Math.round(b * 255)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
orientationOf = function(vector) {
|
||||
var Y_AXIS = {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 0
|
||||
};
|
||||
var X_AXIS = {
|
||||
x: 1,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
|
||||
var theta = 0.0;
|
||||
|
||||
var RAD_TO_DEG = 180.0 / Math.PI;
|
||||
var direction, yaw, pitch;
|
||||
direction = Vec3.normalize(vector);
|
||||
yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS);
|
||||
pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS);
|
||||
return Quat.multiply(yaw, pitch);
|
||||
}
|
||||
|
||||
randFloat = function(low, high) {
|
||||
return low + Math.random() * (high - low);
|
||||
}
|
||||
|
||||
|
||||
randInt = function(low, high) {
|
||||
return Math.floor(randFloat(low, high));
|
||||
}
|
||||
|
||||
hexToRgb = function(hex) {
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
red: parseInt(result[1], 16),
|
||||
green: parseInt(result[2], 16),
|
||||
blue: parseInt(result[3], 16)
|
||||
} : null;
|
||||
}
|
||||
|
||||
calculateHandSizeRatio = function() {
|
||||
// Get the ratio of the current avatar's hand to Owen's hand
|
||||
|
||||
var standardCenterHandPoint = 0.11288;
|
||||
var jointNames = MyAvatar.getJointNames();
|
||||
//get distance from handJoint up to leftHandIndex3 as a proxy for center of hand
|
||||
var wristToFingertipDistance = 0;;
|
||||
for (var i = 0; i < jointNames.length; i++) {
|
||||
var jointName = jointNames[i];
|
||||
print(jointName)
|
||||
if (jointName.indexOf("LeftHandIndex") !== -1) {
|
||||
// translations are relative to parent joint, so simply add them together
|
||||
// joints face down the y-axis
|
||||
var translation = MyAvatar.getDefaultJointTranslation(i).y;
|
||||
wristToFingertipDistance += translation;
|
||||
}
|
||||
}
|
||||
// Right now units are in cm, so convert to meters
|
||||
wristToFingertipDistance /= 100;
|
||||
|
||||
var centerHandPoint = wristToFingertipDistance / 2;
|
||||
|
||||
// Compare against standard hand (Owen)
|
||||
var handSizeRatio = centerHandPoint / standardCenterHandPoint;
|
||||
return handSizeRatio;
|
||||
}
|
||||
|
||||
clamp = function(val, min, max) {
|
||||
return Math.max(min, Math.min(max, val))
|
||||
}
|
||||
|
||||
attachChildToParent = function(childName, parentName, position, searchRadius) {
|
||||
var childEntity, parentEntity;
|
||||
var entities = Entities.findEntities(position, searchRadius)
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
// first go through and find the entity we want to attach to its parent
|
||||
var entity = entities[i];
|
||||
var name = Entities.getEntityProperties(entity, "name").name;
|
||||
if (name === childName) {
|
||||
childEntity = entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!childEntity) {
|
||||
print("You are trying to attach an entity that doesn't exist! Returning");
|
||||
}
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
// first go through and find the entity we want to attach to its parent
|
||||
var entity = entities[i];
|
||||
var name = Entities.getEntityProperties(entity, "name").name;
|
||||
if (name === parentName) {
|
||||
parentEntity = entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentEntity) {
|
||||
print("You are trying to attach an entity to a parent that doesn't exist! Returning");
|
||||
return;
|
||||
}
|
||||
|
||||
print("Successfully attached " + childName + " to " + parentName);
|
||||
Entities.editEntity(childEntity, {parentID: parentEntity});
|
||||
}
|
211
unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js
Normal file
211
unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js
Normal file
|
@ -0,0 +1,211 @@
|
|||
// Created by James B. Pollack @imgntn 6/8/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
//
|
||||
|
||||
(function() {
|
||||
|
||||
var _this;
|
||||
var MARKER_SCRIPT_URL = "atp:/whiteboard/markerEntityScript.js";
|
||||
var ERASER_SCRIPT_URL = "atp:/whiteboard/eraserEntityScript.js";
|
||||
|
||||
Whiteboard = function() {
|
||||
_this = this;
|
||||
}
|
||||
|
||||
Whiteboard.prototype = {
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
this.setup();
|
||||
},
|
||||
unload: function() {
|
||||
|
||||
},
|
||||
setup: function() {
|
||||
|
||||
var props = Entities.getEntityProperties(_this.entityID);
|
||||
this.spawnRotation = Quat.safeEulerAngles(props.rotation);
|
||||
this.spawnPosition = props.position;
|
||||
this.orientation = Quat.fromPitchYawRollDegrees(this.spawnRotation.x, this.spawnRotation.y, this.spawnRotation.z);
|
||||
this.markerRotation = Quat.fromVec3Degrees({
|
||||
x: this.spawnRotation.x + 10,
|
||||
y: this.spawnRotation.y - 90,
|
||||
z: this.spawnRotation.z
|
||||
});
|
||||
|
||||
},
|
||||
createMarkers: function() {
|
||||
_this.setup();
|
||||
var modelURLS = [
|
||||
"atp:/whiteboard/marker-blue.fbx",
|
||||
"atp:/whiteboard/marker-red.fbx",
|
||||
"atp:/whiteboard/marker-black.fbx",
|
||||
];
|
||||
|
||||
var markerPosition = Vec3.sum(_this.spawnPosition, Vec3.multiply(Quat.getFront(_this.orientation), -0.1));
|
||||
|
||||
_this.createMarker(modelURLS[0], markerPosition, {
|
||||
red: 10,
|
||||
green: 10,
|
||||
blue: 200
|
||||
});
|
||||
|
||||
_this.createMarker(modelURLS[1], markerPosition, {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 10
|
||||
});
|
||||
|
||||
_this.createMarker(modelURLS[2], markerPosition, {
|
||||
red: 10,
|
||||
green: 10,
|
||||
blue: 10
|
||||
});
|
||||
},
|
||||
createMarker: function(modelURL, markerPosition, markerColor) {
|
||||
|
||||
var markerProperties = {
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
rotation: _this.markerRotation,
|
||||
shapeType: "box",
|
||||
name: "hifi_model_marker",
|
||||
dynamic: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
position: markerPosition,
|
||||
dimensions: {
|
||||
x: 0.027,
|
||||
y: 0.027,
|
||||
z: 0.164
|
||||
},
|
||||
lifetime: 86400,
|
||||
script: MARKER_SCRIPT_URL,
|
||||
userData: JSON.stringify({
|
||||
'grabbableKey': {
|
||||
'grabbable': true
|
||||
},
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
},
|
||||
originalPosition: markerPosition,
|
||||
originalRotation: _this.markerRotation,
|
||||
markerColor: markerColor,
|
||||
wearable: {
|
||||
joints: {
|
||||
RightHand: [{
|
||||
x: 0.001,
|
||||
y: 0.139,
|
||||
z: 0.050
|
||||
}, {
|
||||
x: -0.73,
|
||||
y: -0.043,
|
||||
z: -0.108,
|
||||
w: -0.666
|
||||
}],
|
||||
LeftHand: [{
|
||||
x: 0.007,
|
||||
y: 0.151,
|
||||
z: 0.061
|
||||
}, {
|
||||
x: -0.417,
|
||||
y: 0.631,
|
||||
z: -0.389,
|
||||
w: -0.525
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var marker = Entities.addEntity(markerProperties);
|
||||
|
||||
},
|
||||
createEraser: function() {
|
||||
_this.setup();
|
||||
var ERASER_MODEL_URL = "atp:/whiteboard/eraser-2.fbx";
|
||||
|
||||
var eraserPosition = Vec3.sum(_this.spawnPosition, Vec3.multiply(Quat.getFront(_this.orientation), -0.1));
|
||||
eraserPosition = Vec3.sum(eraserPosition, Vec3.multiply(-0.5, Quat.getRight(_this.orientation)));
|
||||
var eraserRotation = _this.markerRotation;
|
||||
|
||||
var eraserProps = {
|
||||
type: "Model",
|
||||
name: "hifi_model_whiteboardEraser",
|
||||
modelURL: ERASER_MODEL_URL,
|
||||
position: eraserPosition,
|
||||
script: ERASER_SCRIPT_URL,
|
||||
shapeType: "box",
|
||||
lifetime: 86400,
|
||||
dimensions: {
|
||||
x: 0.0858,
|
||||
y: 0.0393,
|
||||
z: 0.2083
|
||||
},
|
||||
rotation: eraserRotation,
|
||||
dynamic: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -10,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
},
|
||||
'grabbableKey': {
|
||||
'grabbable': true
|
||||
},
|
||||
originalPosition: eraserPosition,
|
||||
originalRotation: eraserRotation,
|
||||
wearable: {
|
||||
joints: {
|
||||
RightHand: [{
|
||||
x: 0.020,
|
||||
y: 0.120,
|
||||
z: 0.049
|
||||
}, {
|
||||
x: 0.1004,
|
||||
y: 0.6424,
|
||||
z: 0.717,
|
||||
w: 0.250
|
||||
}],
|
||||
LeftHand: [{
|
||||
x: -0.005,
|
||||
y: 0.1101,
|
||||
z: 0.053
|
||||
}, {
|
||||
x: 0.723,
|
||||
y: 0.289,
|
||||
z: 0.142,
|
||||
w: 0.610
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var eraser = Entities.addEntity(eraserProps);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return new Whiteboard();
|
||||
})
|
|
@ -0,0 +1,149 @@
|
|||
{
|
||||
"Entities": [{
|
||||
"clientOnly": 0,
|
||||
"compoundShapeURL": "atp:/whiteboard/handScannerSwitch_phys.obj",
|
||||
"created": "2016-06-14T18:08:49Z",
|
||||
"dimensions": {
|
||||
"x": 0.11707025021314621,
|
||||
"y": 0.16469044983386993,
|
||||
"z": 0.10442595928907394
|
||||
},
|
||||
"id": "{21d2185f-4161-484d-bb0f-70bdc307700d}",
|
||||
"modelURL": "atp:/whiteboard/handScannerSwitch_tall_VR.fbx",
|
||||
"name": "hifi_whiteboardSwiper",
|
||||
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}",
|
||||
"position": {
|
||||
"x": -0.86872124671936035,
|
||||
"y": -0.33092412352561951,
|
||||
"z": 0.072394371032714844
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 0.22744926810264587,
|
||||
"x": 4.9953713417053223,
|
||||
"y": 0.33575963973999023,
|
||||
"z": 1.1766284704208374
|
||||
},
|
||||
"rotation": {
|
||||
"w": 0.71929502487182617,
|
||||
"x": -4.57763671875e-05,
|
||||
"y": -0.69472801685333252,
|
||||
"z": -1.52587890625e-05
|
||||
},
|
||||
"script": "atp:/whiteboard/swiper.js",
|
||||
"shapeType": "compound",
|
||||
"type": "Model",
|
||||
"userData": "{\"hifiHomeKey\":{\"reset\":true}}"
|
||||
}, {
|
||||
"clientOnly": 0,
|
||||
"color": {
|
||||
"blue": 200,
|
||||
"green": 10,
|
||||
"red": 200
|
||||
},
|
||||
"created": "2016-06-14T18:08:49Z",
|
||||
"dimensions": {
|
||||
"x": 1.8200000524520874,
|
||||
"y": 1.7999999523162842,
|
||||
"z": 0.0099999997764825821
|
||||
},
|
||||
"id": "{5572abff-1575-48e8-bc79-1d6373046fe9}",
|
||||
"name": "hifi-whiteboardDrawingSurface",
|
||||
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}",
|
||||
"position": {
|
||||
"x": -0.019987192004919052,
|
||||
"y": 0.45400944352149963,
|
||||
"z": 0.020008884370326996
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 2.5597851276397705,
|
||||
"x": 3.3173346519470215,
|
||||
"y": -0.045509219169616699,
|
||||
"z": -0.66857552528381348
|
||||
},
|
||||
"rotation": {
|
||||
"w": 1,
|
||||
"x": -1.52587890625e-05,
|
||||
"y": -1.52587890625e-05,
|
||||
"z": -1.52587890625e-05
|
||||
},
|
||||
"shape": "Cube",
|
||||
"type": "Box",
|
||||
"visible": 0,
|
||||
"userData": "{\"hifiHomeKey\":{\"reset\":true}}"
|
||||
}, {
|
||||
"clientOnly": 0,
|
||||
"color": {
|
||||
"blue": 200,
|
||||
"green": 10,
|
||||
"red": 200
|
||||
},
|
||||
"created": "2016-06-14T18:08:49Z",
|
||||
"dimensions": {
|
||||
"x": 1.8200000524520874,
|
||||
"y": 1.7999999523162842,
|
||||
"z": 0.0099999997764825821
|
||||
},
|
||||
"id": "{22152131-5ac7-4758-a5bc-3dda3f034eb4}",
|
||||
"name": "hifi-whiteboardDrawingSurface",
|
||||
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}",
|
||||
"position": {
|
||||
"x": -0.020041000097990036,
|
||||
"y": 0.45001220703125,
|
||||
"z": -0.019985578954219818
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 2.5597851276397705,
|
||||
"x": 3.2840065956115723,
|
||||
"y": -0.049505829811096191,
|
||||
"z": -0.6464693546295166
|
||||
},
|
||||
"rotation": {
|
||||
"w": 1,
|
||||
"x": -1.52587890625e-05,
|
||||
"y": -1.52587890625e-05,
|
||||
"z": -1.52587890625e-05
|
||||
},
|
||||
"shape": "Cube",
|
||||
"type": "Box",
|
||||
"visible": 0,
|
||||
"userData": "{\"hifiHomeKey\":{\"reset\":true}}"
|
||||
}, {
|
||||
"clientOnly": 0,
|
||||
"compoundShapeURL": "atp:/whiteboard/whiteboardCollisionHull.obj",
|
||||
"created": "2016-06-14T18:08:49Z",
|
||||
"dimensions": {
|
||||
"x": 1.8600000143051147,
|
||||
"y": 2.7000000476837158,
|
||||
"z": 0.46360000967979431
|
||||
},
|
||||
"gravity": {
|
||||
"x": 0,
|
||||
"y": -9.8,
|
||||
"z": 0
|
||||
},
|
||||
"id": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}",
|
||||
"modelURL": "atp:/whiteboard/Whiteboard-4.fbx",
|
||||
"name": "hifi_whiteboard",
|
||||
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"queryAACube": {
|
||||
"scale": 3.3112723827362061,
|
||||
"x": -1.655636191368103,
|
||||
"y": -1.655636191368103,
|
||||
"z": -1.655636191368103
|
||||
},
|
||||
"rotation": {
|
||||
"w": -0.30053186416625977,
|
||||
"x": -2.1577336156042293e-05,
|
||||
"y": 0.95376050472259521,
|
||||
"z": 2.824626790243201e-07
|
||||
},
|
||||
"script": "atp:/whiteboard/whiteboard.js",
|
||||
"shapeType": "compound",
|
||||
"type": "Model",
|
||||
"userData": "{\"hifiHomeKey\":{\"reset\":true}}"
|
||||
}],
|
||||
"Version": 60
|
||||
}
|
|
@ -1,282 +0,0 @@
|
|||
//
|
||||
// whiteboardSpawner.js
|
||||
// examples/homeContent/whiteboardV2
|
||||
//
|
||||
// Created by Eric Levina on 2/17/16
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Run this script to spawn a whiteboard, markers, and an eraser.
|
||||
// To draw on the whiteboard, equip a marker and hold down trigger with marker tip pointed at whiteboard
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
var ERASER_SCRIPT_URL = Script.resolvePath("eraserEntityScript.js");
|
||||
|
||||
var MARKER_SCRIPT_URL = Script.resolvePath("markerEntityScript.js");
|
||||
|
||||
Whiteboard = function(spawnPosition, spawnRotation) {
|
||||
|
||||
var orientation = Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z);
|
||||
var markers = [];
|
||||
var markerRotation = Quat.fromVec3Degrees({
|
||||
x: spawnRotation.x + 10,
|
||||
y: spawnRotation.y - 90,
|
||||
z: spawnRotation.z
|
||||
});
|
||||
var whiteboardPosition = spawnPosition;
|
||||
var whiteboardRotation = orientation;
|
||||
|
||||
var WHITEBOARD_MODEL_URL = "atp:/whiteboard/Whiteboard-6.fbx";
|
||||
var WHITEBOARD_COLLISION_HULL_URL = "atp:/whiteboard/whiteboardCollisionHull.obj";
|
||||
|
||||
var whiteboard = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "home_model_whiteboard",
|
||||
modelURL: WHITEBOARD_MODEL_URL,
|
||||
position: whiteboardPosition,
|
||||
rotation: whiteboardRotation,
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL: WHITEBOARD_COLLISION_HULL_URL,
|
||||
dimensions: {
|
||||
x: 1.86,
|
||||
y: 2.7,
|
||||
z: 0.4636
|
||||
},
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
|
||||
var whiteboardSurfacePosition = Vec3.sum(whiteboardPosition, {
|
||||
x: 0.0,
|
||||
y: 0.45,
|
||||
z: 0.0
|
||||
});
|
||||
whiteboardSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(-0.02, Quat.getRight(whiteboardRotation)));
|
||||
var moveForwardDistance = 0.02;
|
||||
whiteboardFrontSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(-moveForwardDistance, Quat.getFront(whiteboardRotation)));
|
||||
var WHITEBOARD_SURFACE_NAME = "home_box_whiteboardDrawingSurface";
|
||||
var whiteboardSurfaceSettings = {
|
||||
type: "Box",
|
||||
name: WHITEBOARD_SURFACE_NAME,
|
||||
dimensions: {
|
||||
x: 1.82,
|
||||
y: 1.8,
|
||||
z: 0.01
|
||||
},
|
||||
color: {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 200
|
||||
},
|
||||
position: whiteboardFrontSurfacePosition,
|
||||
rotation: whiteboardRotation,
|
||||
visible: false,
|
||||
parentID: whiteboard,
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
}
|
||||
}),
|
||||
}
|
||||
var whiteboardFrontDrawingSurface = Entities.addEntity(whiteboardSurfaceSettings);
|
||||
|
||||
|
||||
whiteboardBackSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(moveForwardDistance, Quat.getFront(whiteboardRotation)));
|
||||
whiteboardSurfaceSettings.position = whiteboardBackSurfacePosition;
|
||||
|
||||
var whiteboardBackDrawingSurface = Entities.addEntity(whiteboardSurfaceSettings);
|
||||
|
||||
|
||||
var WHITEBOARD_RACK_DEPTH = 1.9;
|
||||
|
||||
|
||||
|
||||
// ************ ERASER ************************************************
|
||||
var ERASER_MODEL_URL = "atp:/whiteboard/eraser-2.fbx";
|
||||
|
||||
|
||||
|
||||
var eraserPosition = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(whiteboardRotation), -0.1));
|
||||
eraserPosition = Vec3.sum(eraserPosition, Vec3.multiply(-0.5, Quat.getRight(whiteboardRotation)));
|
||||
var eraserRotation = markerRotation;
|
||||
|
||||
var eraserProps = {
|
||||
type: "Model",
|
||||
name: "home_model_whiteboardEraser",
|
||||
modelURL: ERASER_MODEL_URL,
|
||||
position: eraserPosition,
|
||||
script: ERASER_SCRIPT_URL,
|
||||
shapeType: "box",
|
||||
dimensions: {
|
||||
x: 0.0858,
|
||||
y: 0.0393,
|
||||
z: 0.2083
|
||||
},
|
||||
rotation: eraserRotation,
|
||||
dynamic: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -10,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
},
|
||||
originalPosition: eraserPosition,
|
||||
originalRotation: eraserRotation,
|
||||
wearable: {
|
||||
joints: {
|
||||
RightHand: [{
|
||||
x: 0.020,
|
||||
y: 0.120,
|
||||
z: 0.049
|
||||
}, {
|
||||
x: 0.1004,
|
||||
y: 0.6424,
|
||||
z: 0.717,
|
||||
w: 0.250
|
||||
}],
|
||||
LeftHand: [{
|
||||
x: -0.005,
|
||||
y: 0.1101,
|
||||
z: 0.053
|
||||
}, {
|
||||
x: 0.723,
|
||||
y: 0.289,
|
||||
z: 0.142,
|
||||
w: 0.610
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
function createMarkers() {
|
||||
var modelURLS = [
|
||||
"atp:/whiteboard/marker-blue.fbx",
|
||||
"atp:/whiteboard/marker-red.fbx",
|
||||
"atp:/whiteboard/marker-black.fbx",
|
||||
];
|
||||
|
||||
|
||||
var markerPosition = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(whiteboardRotation), -0.1));
|
||||
|
||||
createMarker(modelURLS[0], markerPosition, {
|
||||
red: 10,
|
||||
green: 10,
|
||||
blue: 200
|
||||
});
|
||||
|
||||
markerPosition = Vec3.sum(markerPosition, Vec3.multiply(-0.2, Quat.getFront(markerRotation)));
|
||||
createMarker(modelURLS[1], markerPosition, {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 10
|
||||
});
|
||||
|
||||
markerPosition = Vec3.sum(markerPosition, Vec3.multiply(0.4, Quat.getFront(markerRotation)));
|
||||
createMarker(modelURLS[2], markerPosition, {
|
||||
red: 10,
|
||||
green: 10,
|
||||
blue: 10
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function createMarker(modelURL, markerPosition, markerColor) {
|
||||
var marker = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
rotation: markerRotation,
|
||||
shapeType: "box",
|
||||
name: "home_model_marker",
|
||||
dynamic: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
position: markerPosition,
|
||||
dimensions: {
|
||||
x: 0.027,
|
||||
y: 0.027,
|
||||
z: 0.164
|
||||
},
|
||||
script: MARKER_SCRIPT_URL,
|
||||
userData: JSON.stringify({
|
||||
'hifiHomeKey': {
|
||||
'reset': true
|
||||
},
|
||||
originalPosition: markerPosition,
|
||||
originalRotation: markerRotation,
|
||||
markerColor: markerColor,
|
||||
wearable: {
|
||||
joints: {
|
||||
RightHand: [{
|
||||
x: 0.001,
|
||||
y: 0.139,
|
||||
z: 0.050
|
||||
}, {
|
||||
x: -0.73,
|
||||
y: -0.043,
|
||||
z: -0.108,
|
||||
w: -0.666
|
||||
}],
|
||||
LeftHand: [{
|
||||
x: 0.007,
|
||||
y: 0.151,
|
||||
z: 0.061
|
||||
}, {
|
||||
x: -0.417,
|
||||
y: 0.631,
|
||||
z: -0.389,
|
||||
w: -0.525
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
markers.push(marker);
|
||||
|
||||
}
|
||||
var eraser;
|
||||
Script.setTimeout(function() {
|
||||
eraser = Entities.addEntity(eraserProps);
|
||||
createMarkers();
|
||||
}, 1500)
|
||||
|
||||
function cleanup() {
|
||||
print('WHITEBOARD CLEANUP')
|
||||
Entities.deleteEntity(whiteboard);
|
||||
Entities.deleteEntity(whiteboardFrontDrawingSurface);
|
||||
Entities.deleteEntity(whiteboardBackDrawingSurface);
|
||||
Entities.deleteEntity(eraser);
|
||||
markers.forEach(function(marker) {
|
||||
Entities.deleteEntity(marker);
|
||||
});
|
||||
}
|
||||
|
||||
this.cleanup = cleanup;
|
||||
|
||||
print('CREATED WHITEBOARD')
|
||||
}
|
Loading…
Reference in a new issue