mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 01:12:48 +02:00
Merge pull request #10002 from fayeli/tablet-photobooth
Photobooth Improvements: Using Tablet & Ability to Rotate Model
This commit is contained in:
commit
d1827cf12c
4 changed files with 340 additions and 334 deletions
0
interface/resources/fonts/hifi-glyphs.ttf
Executable file → Normal file
0
interface/resources/fonts/hifi-glyphs.ttf
Executable file → Normal file
|
@ -2,166 +2,151 @@
|
|||
<head>
|
||||
<title>Photo Booth</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../../system/html/css/edit-style.css">
|
||||
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||
|
||||
<script>
|
||||
var EventBridge;
|
||||
var openEventBridge = function (callback) {
|
||||
var WebChannel = new QWebChannel(qt.webChannelTransport, function (channel) {
|
||||
EventBridge = WebChannel.objects.eventBridgeWrapper.eventBridge;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
var emit = function (eventType, data) {
|
||||
data = data || {};
|
||||
data.type = eventType;
|
||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||
};
|
||||
|
||||
function loaded () {
|
||||
openEventBridge(function () {
|
||||
emit("onLoad", {value: "faye"});
|
||||
|
||||
var elModelURL = document.getElementById("model-url");
|
||||
var elReloadModelButton = document.getElementById("reload-model-button");
|
||||
var elCamera = document.getElementById("property-camera");
|
||||
//var elLightingPreset = document.getElementById("property-lighting-preset");
|
||||
var elPictureButton = document.getElementById("picture-button");
|
||||
|
||||
elReloadModelButton.addEventListener('click', function() {
|
||||
emit("onClickReloadModelButton", {value: elModelURL.value});
|
||||
});
|
||||
elCamera.addEventListener('change', function() {
|
||||
emit("onSelectCamera", {value: this.value});
|
||||
});
|
||||
// elLightingPreset.addEventListener('change', function() {
|
||||
// emit("onSelectLightingPreset", {value: "faye"});
|
||||
// });
|
||||
elPictureButton.addEventListener('click', function() {
|
||||
emit("onClickPictureButton", {value: "faye"});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Drop downs
|
||||
function setDropdownText(dropdown) {
|
||||
var lis = dropdown.parentNode.getElementsByTagName("li");
|
||||
var text = "";
|
||||
for (var i = 0; i < lis.length; i++) {
|
||||
if (lis[i].getAttribute("value") === dropdown.value) {
|
||||
text = lis[i].textContent;
|
||||
}
|
||||
}
|
||||
dropdown.firstChild.textContent = text;
|
||||
}
|
||||
function toggleDropdown(event) {
|
||||
var element = event.target;
|
||||
if (element.nodeName !== "DT") {
|
||||
element = element.parentNode;
|
||||
}
|
||||
element = element.parentNode;
|
||||
var isDropped = element.getAttribute("dropped");
|
||||
element.setAttribute("dropped", isDropped !== "true" ? "true" : "false");
|
||||
}
|
||||
function setDropdownValue(event) {
|
||||
var dt = event.target.parentNode.parentNode.previousSibling;
|
||||
dt.value = event.target.getAttribute("value");
|
||||
dt.firstChild.textContent = event.target.textContent;
|
||||
|
||||
dt.parentNode.setAttribute("dropped", "false");
|
||||
|
||||
var evt = document.createEvent("HTMLEvents");
|
||||
evt.initEvent("change", true, true);
|
||||
dt.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
var elDropdowns = document.getElementsByTagName("select");
|
||||
for (var i = 0; i < elDropdowns.length; i++) {
|
||||
var options = elDropdowns[i].getElementsByTagName("option");
|
||||
var selectedOption = 0;
|
||||
for (var j = 0; j < options.length; j++) {
|
||||
if (options[j].getAttribute("selected") === "selected") {
|
||||
selectedOption = j;
|
||||
}
|
||||
}
|
||||
var div = elDropdowns[i].parentNode;
|
||||
|
||||
var dl = document.createElement("dl");
|
||||
div.appendChild(dl);
|
||||
|
||||
var dt = document.createElement("dt");
|
||||
dt.name = elDropdowns[i].name;
|
||||
dt.id = elDropdowns[i].id;
|
||||
dt.addEventListener("click", toggleDropdown, true);
|
||||
dl.appendChild(dt);
|
||||
|
||||
var span = document.createElement("span");
|
||||
span.setAttribute("value", options[selectedOption].value);
|
||||
span.textContent = options[selectedOption].firstChild.textContent;
|
||||
dt.appendChild(span);
|
||||
|
||||
var span = document.createElement("span");
|
||||
span.textContent = "5"; // caratDn
|
||||
dt.appendChild(span);
|
||||
|
||||
var dd = document.createElement("dd");
|
||||
dl.appendChild(dd);
|
||||
|
||||
var ul = document.createElement("ul");
|
||||
dd.appendChild(ul);
|
||||
|
||||
for (var j = 0; j < options.length; j++) {
|
||||
var li = document.createElement("li");
|
||||
li.setAttribute("value", options[j].value);
|
||||
li.textContent = options[j].firstChild.textContent;
|
||||
li.addEventListener("click", setDropdownValue);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
elDropdowns = document.getElementsByTagName("select");
|
||||
while (elDropdowns.length > 0) {
|
||||
var el = elDropdowns[0];
|
||||
el.parentNode.removeChild(el);
|
||||
elDropdowns = document.getElementsByTagName("select");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
|
||||
<style>
|
||||
</style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: 90px;
|
||||
background: linear-gradient(#2b2b2b, #1e1e1e);
|
||||
font-family: Raleway-Bold;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
width: 480px;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 90px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.slider {
|
||||
margin-left: 70px;
|
||||
}
|
||||
|
||||
#camera-toggle {
|
||||
font-family: Raleway-Bold;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
height: 28px;
|
||||
min-width: 120px;
|
||||
padding: 0px 18px;
|
||||
margin-right: 0px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
color: #121212;
|
||||
background-color: #afafaf;
|
||||
background: linear-gradient(#fff 20%, #afafaf 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown li {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body onload="loaded()">
|
||||
<div id="properties-list">
|
||||
<div class="property url refresh">
|
||||
<label>Model URL</label>
|
||||
<input type="text" id="model-url"></input>
|
||||
<input type="button" id="reload-model-button" class="glyph" value="F">
|
||||
</div>
|
||||
<!--
|
||||
<div class="property dropdown">
|
||||
<label>Lighting Preset</label>
|
||||
<select id="property-lighting-preset">
|
||||
<option>Default Lighting</option>
|
||||
<option>Sam's Cool Light</option>
|
||||
<option>Alan's Light Magic</option>
|
||||
</select>
|
||||
</div>
|
||||
-->
|
||||
<div class="property dropdown">
|
||||
<label>Camera</label>
|
||||
<select id="property-camera">
|
||||
<option>First Person Camera</option>
|
||||
<option>Main Camera</option>
|
||||
<option>Left Camera</option>
|
||||
<option>Right Camera</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="property">
|
||||
<input id="picture-button" type="button" class="blue" value="Take Picture">
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<div>Photobooth</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div id="properties-list">
|
||||
<div class="property url refresh">
|
||||
<label>Model URL</label>
|
||||
<input type="text" id="model-url"></input>
|
||||
<input type="button" id="reload-model-button" class="glyph" value="F">
|
||||
</div>
|
||||
<div class="property">
|
||||
<label>Rotate Model</label>
|
||||
<input
|
||||
id="rotate-slider"
|
||||
type="text"
|
||||
data-provide="slider"
|
||||
data-slider-ticks="[-180, 0, 180]"
|
||||
data-slider-ticks-labels='["clockwise", "centre", "anti-clockwise"]'
|
||||
data-slider-min="-180"
|
||||
data-slider-max="180"
|
||||
data-slider-step="1"
|
||||
data-slider-value="0"
|
||||
data-slider-tooltip="show"
|
||||
>
|
||||
</div>
|
||||
<div class="property">
|
||||
<label>Camera</label>
|
||||
<div class="dropdown">
|
||||
<button id="camera-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
First Person Camera
|
||||
<span class="glyphicon glyphicon-menu-down"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li>First Person Camera</li>
|
||||
<li>Main Camera</li>
|
||||
<li>Left Camera</li>
|
||||
<li>Right Camera</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<input id="picture-button" type="button" class="blue" value="Take Picture">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
|
||||
<script>
|
||||
|
||||
// Helper function to emit web events to photoboothApp.js
|
||||
function emit(eventType, eventData) {
|
||||
var eventObject = {
|
||||
"app": "photobooth",
|
||||
"type": eventType,
|
||||
"data": eventData
|
||||
};
|
||||
EventBridge.emitWebEvent(JSON.stringify(eventObject));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Send a ready event to hifi
|
||||
emit("ready", null);
|
||||
// Send an event when camera selection changes
|
||||
$(".dropdown-menu li").click(function() {
|
||||
console.log("clicked " + this.textContent);
|
||||
$("#camera-toggle").text(this.textContent + " ");
|
||||
$("#camera-toggle").append("<span class='glyphicon glyphicon-menu-down'></span>");
|
||||
emit("onSelectCamera", {value: this.textContent});
|
||||
});
|
||||
// Send an event to hifi to trigger snapshot
|
||||
$("#picture-button").click(function() {
|
||||
emit("onClickPictureButton", null);
|
||||
});
|
||||
// Send an event to hifi for loading the given model URL
|
||||
$("#reload-model-button").click(function() {
|
||||
emit("onClickReloadModelButton", {value: $("#model-url").val()});
|
||||
});
|
||||
$("#rotate-slider").slider().on("slide", function(e){
|
||||
console.log("slided " + e.value);
|
||||
emit("onRotateSlider", {value: e.value});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
(function () {
|
||||
var SNAPSHOT_DELAY = 500; // 500ms
|
||||
var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html");
|
||||
var PHOTOBOOTH_SETUP_JSON_URL = Script.resolvePath("./photoboothSetup.json");
|
||||
var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165};
|
||||
|
||||
var PhotoBooth = {};
|
||||
PhotoBooth.init = function () {
|
||||
var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL);
|
||||
var forwardFactor = 10;
|
||||
var forwardUnitVector = Vec3.normalize(Quat.getForward(MyAvatar.orientation));
|
||||
var forwardOffset = Vec3.multiply(forwardUnitVector,forwardFactor);
|
||||
var rightFactor = 3;
|
||||
// TODO: rightUnitVec is unused and spawnLocation declaration is incorrect
|
||||
var rightUnitVec = Vec3.normalize(Quat.getRight(MyAvatar.orientation));
|
||||
var spawnLocation = Vec3.sum(Vec3.sum(MyAvatar.position,forwardOffset),rightFactor);
|
||||
if (success) {
|
||||
this.pastedEntityIDs = Clipboard.pasteEntities(spawnLocation);
|
||||
this.processPastedEntities();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
PhotoBooth.processPastedEntities = function () {
|
||||
var cameraResults = {};
|
||||
var modelResult;
|
||||
var modelPos;
|
||||
this.pastedEntityIDs.forEach(function(id) {
|
||||
var props = Entities.getEntityProperties(id);
|
||||
var parts = props["name"].split(":");
|
||||
if (parts[0] === "Photo Booth Camera") {
|
||||
cameraResults[parts[1]] = id;
|
||||
}
|
||||
if (parts[0] === "Photo Booth Model") {
|
||||
modelResult = id;
|
||||
modelPos = props.position;
|
||||
}
|
||||
});
|
||||
print(JSON.stringify(cameraResults));
|
||||
print(JSON.stringify(modelResult));
|
||||
this.cameraEntities = cameraResults;
|
||||
this.modelEntityID = modelResult;
|
||||
this.centrePos = modelPos;
|
||||
};
|
||||
|
||||
// replace the model in scene with new model
|
||||
PhotoBooth.changeModel = function (newModelURL) {
|
||||
// deletes old model
|
||||
Entities.deleteEntity(this.modelEntityID);
|
||||
// create new model at centre of the photobooth
|
||||
var newProps = {
|
||||
name: "Photo Booth Model",
|
||||
type: "Model",
|
||||
modelURL: newModelURL,
|
||||
position: this.centrePos
|
||||
};
|
||||
var newModelEntityID = Entities.addEntity(newProps);
|
||||
|
||||
// scale model dimensions to fit in bounding box
|
||||
var scaleModel = function () {
|
||||
newProps = Entities.getEntityProperties(newModelEntityID);
|
||||
var myDimensions = newProps.dimensions;
|
||||
print("myDimensions: " + JSON.stringify(myDimensions));
|
||||
var k;
|
||||
if (myDimensions.x > MODEL_BOUNDING_BOX_DIMENSIONS.x) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.x / myDimensions.x;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
if (myDimensions.y > MODEL_BOUNDING_BOX_DIMENSIONS.y) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.y / myDimensions.y;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
if (myDimensions.z > MODEL_BOUNDING_BOX_DIMENSIONS.z) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.z / myDimensions.z;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
// position the new model on the table
|
||||
var y_offset = (MODEL_BOUNDING_BOX_DIMENSIONS.y - myDimensions.y) / 2;
|
||||
var myPosition = Vec3.sum(newProps.position, {x:0, y:-y_offset, z:0});
|
||||
Entities.editEntity(newModelEntityID,{position: myPosition, dimensions: myDimensions});
|
||||
};
|
||||
|
||||
// add a delay before scaling to make sure the entity server have gotten the right model dimensions
|
||||
Script.setTimeout(function () {
|
||||
scaleModel();
|
||||
}, 400);
|
||||
|
||||
this.modelEntityID = newModelEntityID;
|
||||
};
|
||||
|
||||
PhotoBooth.destroy = function () {
|
||||
this.pastedEntityIDs.forEach(function(id) {
|
||||
Entities.deleteEntity(id);
|
||||
});
|
||||
Entities.deleteEntity(this.modelEntityID);
|
||||
};
|
||||
|
||||
var main = function () {
|
||||
PhotoBooth.init();
|
||||
|
||||
var photoboothWindowListener = {};
|
||||
photoboothWindowListener.onLoad = function (event) {
|
||||
print("loaded" + event.value);
|
||||
if (!event.hasOwnProperty("value")){
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
photoboothWindowListener.onSelectCamera = function (event) {
|
||||
print("selected camera " + event.value);
|
||||
if (!event.hasOwnProperty("value")){
|
||||
return;
|
||||
}
|
||||
if (event.value === "First Person Camera") {
|
||||
Camera.mode = "first person";
|
||||
} else {
|
||||
Camera.mode = "entity";
|
||||
var cameraID = PhotoBooth.cameraEntities[event.value];
|
||||
Camera.setCameraEntity(cameraID);
|
||||
}
|
||||
};
|
||||
|
||||
photoboothWindowListener.onSelectLightingPreset = function (event) {
|
||||
print("selected lighting preset" + event.value);
|
||||
if (!event.hasOwnProperty("value")){
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
photoboothWindowListener.onClickPictureButton = function (event) {
|
||||
print("clicked picture button");
|
||||
// hide HUD tool bar
|
||||
toolbar.writeProperty("visible", false);
|
||||
// hide Overlays (such as Running Scripts or other Dialog UI)
|
||||
Menu.setIsOptionChecked("Overlays", false);
|
||||
// hide mouse cursor
|
||||
Reticle.visible = false;
|
||||
// giving a delay here before snapshotting so that there is time to hide toolbar and other UIs
|
||||
// void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio)
|
||||
Script.setTimeout(function () {
|
||||
Window.takeSnapshot(false, false, 1.91);
|
||||
// show hidden items after snapshot is taken
|
||||
toolbar.writeProperty("visible", true);
|
||||
Menu.setIsOptionChecked("Overlays", true);
|
||||
// unknown issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot
|
||||
// Reticle.visible = true;
|
||||
}, SNAPSHOT_DELAY);
|
||||
};
|
||||
|
||||
photoboothWindowListener.onClickReloadModelButton = function (event) {
|
||||
print("clicked reload model button " + event.value);
|
||||
PhotoBooth.changeModel(event.value);
|
||||
};
|
||||
|
||||
var photoboothWindow = new OverlayWebWindow({
|
||||
title: 'Photo Booth',
|
||||
source: PHOTOBOOTH_WINDOW_HTML_URL,
|
||||
width: 450,
|
||||
height: 450,
|
||||
visible: true
|
||||
});
|
||||
|
||||
photoboothWindow.webEventReceived.connect(function (data) {
|
||||
var event = JSON.parse(data);
|
||||
if (photoboothWindowListener[event.type]) {
|
||||
photoboothWindowListener[event.type](event);
|
||||
}
|
||||
});
|
||||
};
|
||||
main();
|
||||
|
||||
function cleanup() {
|
||||
Camera.mode = "first person";
|
||||
PhotoBooth.destroy();
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
199
scripts/developer/utilities/render/photobooth/photoboothApp.js
Normal file
199
scripts/developer/utilities/render/photobooth/photoboothApp.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
//
|
||||
// photobooth.js
|
||||
// scripts/developer/utilities/render/photobooth
|
||||
//
|
||||
// Created by Faye Li on 2 Nov 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
|
||||
//
|
||||
/* globals Tablet, Toolbars, Script, HMD, Controller, Menu */
|
||||
(function () {
|
||||
var SNAPSHOT_DELAY = 500; // 500ms
|
||||
var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html");
|
||||
var PHOTOBOOTH_SETUP_JSON_URL = Script.resolvePath("./photoboothSetup.json");
|
||||
var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165};
|
||||
var PhotoBooth = {};
|
||||
var photoboothCreated = false;
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var button = tablet.addButton({
|
||||
icon: "icons/tablet-icons/snap-i.svg",
|
||||
text: "PHOTOBOOTH"
|
||||
});
|
||||
|
||||
function onClicked() {
|
||||
if (photoboothCreated) {
|
||||
tablet.gotoHomeScreen();
|
||||
PhotoBooth.destroy();
|
||||
} else {
|
||||
tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL);
|
||||
PhotoBooth.init();
|
||||
}
|
||||
}
|
||||
|
||||
function onScreenChanged() {
|
||||
if (photoboothCreated) {
|
||||
tablet.gotoHomeScreen();
|
||||
PhotoBooth.destroy();
|
||||
button.editProperties({isActive: false});
|
||||
} else {
|
||||
button.editProperties({isActive: true});
|
||||
}
|
||||
}
|
||||
tablet.screenChanged.connect(onScreenChanged);
|
||||
button.clicked.connect(onClicked);
|
||||
tablet.webEventReceived.connect(onWebEventReceived);
|
||||
|
||||
|
||||
function onWebEventReceived(event) {
|
||||
print("photobooth.js received a web event:" + event);
|
||||
// Converts the event to a JavasScript Object
|
||||
if (typeof event === "string") {
|
||||
event = JSON.parse(event);
|
||||
}
|
||||
if (event.app === "photobooth") {
|
||||
if (event.type === "onClickPictureButton") {
|
||||
print("clicked picture button");
|
||||
// // hide HUD tool bar
|
||||
// toolbar.writeProperty("visible", false);
|
||||
// hide Overlays (such as Running Scripts or other Dialog UI)
|
||||
Menu.setIsOptionChecked("Overlays", false);
|
||||
// hide mouse cursor
|
||||
Reticle.visible = false;
|
||||
// hide tablet
|
||||
HMD.closeTablet();
|
||||
// // giving a delay here before snapshotting so that there is time to hide other UIs
|
||||
// void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio)
|
||||
Script.setTimeout(function () {
|
||||
Window.takeSnapshot(false, false, 1.91);
|
||||
// show hidden items after snapshot is taken
|
||||
// issue: currently there's no way to show tablet via a script command. user will have to manually open tablet again
|
||||
// issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot
|
||||
// Reticle.visible = true;
|
||||
// toolbar.writeProperty("visible", true);
|
||||
Menu.setIsOptionChecked("Overlays", true);
|
||||
}, SNAPSHOT_DELAY);
|
||||
} else if (event.type === "onClickReloadModelButton") {
|
||||
print("clicked reload model button " + event.data.value);
|
||||
PhotoBooth.changeModel(event.data.value);
|
||||
} else if (event.type === "onSelectCamera") {
|
||||
print("selected camera " + event.data.value);
|
||||
if (!event.data.hasOwnProperty("value")){
|
||||
return;
|
||||
}
|
||||
if (event.data.value === "First Person Camera") {
|
||||
Camera.mode = "first person";
|
||||
} else {
|
||||
Camera.mode = "entity";
|
||||
var cameraID = PhotoBooth.cameraEntities[event.data.value];
|
||||
Camera.setCameraEntity(cameraID);
|
||||
}
|
||||
} else if (event.type === "onRotateSlider") {
|
||||
var props = {};
|
||||
props.rotation = Quat.fromPitchYawRollDegrees(0, event.data.value, 0);
|
||||
Entities.editEntity(PhotoBooth.modelEntityID, props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PhotoBooth.init = function () {
|
||||
photoboothCreated = true;
|
||||
var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL);
|
||||
var frontFactor = 10;
|
||||
// getForward is preffered as getFront function is deprecated
|
||||
var frontUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation));
|
||||
var frontOffset = Vec3.multiply(frontUnitVec,frontFactor);
|
||||
var upFactor = 3;
|
||||
var upUnitVec = Vec3.normalize(Quat.getUp(MyAvatar.orientation));
|
||||
var upOffset = Vec3.multiply(upUnitVec, upFactor);
|
||||
var spawnLocation = Vec3.sum(MyAvatar.position,frontOffset);
|
||||
spawnLocation = Vec3.sum(spawnLocation, upOffset);
|
||||
if (success) {
|
||||
this.pastedEntityIDs = Clipboard.pasteEntities(spawnLocation);
|
||||
this.processPastedEntities();
|
||||
}
|
||||
};
|
||||
|
||||
PhotoBooth.processPastedEntities = function () {
|
||||
var cameraResults = {};
|
||||
var modelResult;
|
||||
var modelPos;
|
||||
this.pastedEntityIDs.forEach(function(id) {
|
||||
var props = Entities.getEntityProperties(id);
|
||||
var parts = props["name"].split(":");
|
||||
if (parts[0] === "Photo Booth Camera") {
|
||||
cameraResults[parts[1]] = id;
|
||||
}
|
||||
if (parts[0] === "Photo Booth Model") {
|
||||
modelResult = id;
|
||||
modelPos = props.position;
|
||||
}
|
||||
});
|
||||
print(JSON.stringify(cameraResults));
|
||||
print(JSON.stringify(modelResult));
|
||||
this.cameraEntities = cameraResults;
|
||||
this.modelEntityID = modelResult;
|
||||
this.centrePos = modelPos;
|
||||
};
|
||||
|
||||
// replace the model in scene with new model
|
||||
PhotoBooth.changeModel = function (newModelURL) {
|
||||
// deletes old model
|
||||
Entities.deleteEntity(this.modelEntityID);
|
||||
// create new model at centre of the photobooth
|
||||
var newProps = {
|
||||
name: "Photo Booth Model",
|
||||
type: "Model",
|
||||
modelURL: newModelURL,
|
||||
position: this.centrePos
|
||||
};
|
||||
var newModelEntityID = Entities.addEntity(newProps);
|
||||
|
||||
// scale model dimensions to fit in bounding box
|
||||
var scaleModel = function () {
|
||||
newProps = Entities.getEntityProperties(newModelEntityID);
|
||||
var myDimensions = newProps.dimensions;
|
||||
print("myDimensions: " + JSON.stringify(myDimensions));
|
||||
var k;
|
||||
if (myDimensions.x > MODEL_BOUNDING_BOX_DIMENSIONS.x) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.x / myDimensions.x;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
if (myDimensions.y > MODEL_BOUNDING_BOX_DIMENSIONS.y) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.y / myDimensions.y;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
if (myDimensions.z > MODEL_BOUNDING_BOX_DIMENSIONS.z) {
|
||||
k = MODEL_BOUNDING_BOX_DIMENSIONS.z / myDimensions.z;
|
||||
myDimensions = Vec3.multiply(k, myDimensions);
|
||||
}
|
||||
// position the new model on the table
|
||||
var y_offset = (MODEL_BOUNDING_BOX_DIMENSIONS.y - myDimensions.y) / 2;
|
||||
var myPosition = Vec3.sum(newProps.position, {x:0, y:-y_offset, z:0});
|
||||
Entities.editEntity(newModelEntityID,{position: myPosition, dimensions: myDimensions});
|
||||
};
|
||||
|
||||
// add a delay before scaling to make sure the entity server have gotten the right model dimensions
|
||||
Script.setTimeout(function () {
|
||||
scaleModel();
|
||||
}, 400);
|
||||
|
||||
this.modelEntityID = newModelEntityID;
|
||||
};
|
||||
|
||||
PhotoBooth.destroy = function () {
|
||||
this.pastedEntityIDs.forEach(function(id) {
|
||||
Entities.deleteEntity(id);
|
||||
});
|
||||
Entities.deleteEntity(this.modelEntityID);
|
||||
photoboothCreated = false;
|
||||
Camera.mode = "first person";
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
tablet.removeButton(button);
|
||||
PhotoBooth.destroy();
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
Loading…
Reference in a new issue