Needs a lot of cleanup. Data has been de-duplicated, and where identical copies existed, one of them has been replaced with a symlink. Some files have been excluded, such as binaries, installers and debug dumps. Some of that may still be present.
304 lines
No EOL
8.8 KiB
JavaScript
304 lines
No EOL
8.8 KiB
JavaScript
"use strict";
|
|
|
|
//
|
|
// focus.js
|
|
// Sam Cake Lab
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
(function() {
|
|
|
|
function Cam() {
|
|
this._enabled = false;
|
|
|
|
this._aspectRatio = 2.0;
|
|
this._height = 1024;
|
|
|
|
this._fov = 10.0;
|
|
|
|
this._exposure = 0.0;
|
|
|
|
this._position = Camera.position;
|
|
this._orientation = Camera.orientation;
|
|
|
|
this._name = "focus";
|
|
this._shotNum = 0;
|
|
};
|
|
|
|
Cam.prototype = {
|
|
init: function() {
|
|
this.updateImageSize();
|
|
this.updateTransform();
|
|
this.updateFov();
|
|
this.updateExposure();
|
|
this.updateTone();
|
|
},
|
|
|
|
// Image Size
|
|
aspectRatio: function() { return this._aspectRatio; },
|
|
height: function() { return this._height; },
|
|
width: function() { return this._height * this._aspectRatio; },
|
|
|
|
updateImageSize: function() {
|
|
this.config().resetSizeSpectatorCamera(this.width(), this.height());
|
|
},
|
|
setAspectRatio: function(ar) {
|
|
ar = Math.min(10, Math.max(ar, 0.1))
|
|
this.updateImageSize();
|
|
},
|
|
setHeight: function(h) {
|
|
this._height = Math.max(1, h)
|
|
this.updateImageSize();
|
|
},
|
|
setWidth: function(w) {
|
|
this._height = Math.max(1, w) / this.aspectRatio();
|
|
this.updateImageSize();
|
|
},
|
|
setWidthHeight: function(w, h) {
|
|
this._height = Math.max(1, h);
|
|
this._aspectRatio = Math.max(1, w) / this._height;
|
|
this.updateImageSize();
|
|
},
|
|
|
|
// Activation
|
|
config: function() {
|
|
return Render.getConfig("SecondaryCamera");
|
|
},
|
|
enable: function() {
|
|
this._enabled = true;
|
|
this.config().enableSecondaryCameraRenderConfigs(true);
|
|
},
|
|
disable: function() {
|
|
this._enabled = false;
|
|
this.config().enableSecondaryCameraRenderConfigs(false);
|
|
},
|
|
|
|
// Transform
|
|
position: function() { return this._position; },
|
|
orientation: function() { return this._orientation; },
|
|
updateTransform: function() {
|
|
this.config().position = this._position;
|
|
this.config().orientation = this._orientation;
|
|
},
|
|
setTransform: function(pos, ori) {
|
|
this._position = pos;
|
|
this._orientation = ori;
|
|
this.updateTransform();
|
|
},
|
|
setPosition: function(pos) {
|
|
this._position = pos;
|
|
this.updateTransform();
|
|
},
|
|
setOrientation: function(ori) {
|
|
this._orientation = ori;
|
|
this.updateTransform();
|
|
},
|
|
|
|
// Focus
|
|
fov: function() { return this._fov; },
|
|
updateFov: function() {
|
|
this.config().vFoV = this._fov;
|
|
},
|
|
setFov: function(fov) {
|
|
this._fov = Math.min(180, Math.max(0.1, fov));
|
|
this.updateFov();
|
|
},
|
|
|
|
// Exposure
|
|
exposure: function() { return this._exposure; },
|
|
updateExposure: function() {
|
|
Render.getConfig("SecondaryCameraJob.ToneMapping").exposure = this._exposure;
|
|
},
|
|
setExposure: function(exposure) {
|
|
this._exposure = Math.min(5, Math.max(-5, exposure));
|
|
this.updateExposure();
|
|
},
|
|
|
|
// Tone
|
|
updateTone: function() {
|
|
Render.getConfig("SecondaryCameraJob.ToneMapping").curve = 0;
|
|
},
|
|
|
|
// Shot!
|
|
shoot: function() {
|
|
var d = new Date();
|
|
var name = this._name + '-' + d.getMonth() + '.' + + d.getDate() + '-' + d.getHours() + '.' + d.getMinutes() + '-' + this._shotNum;
|
|
Window.takeSecondaryCameraSnapshot(false, name);
|
|
this._shotNum++;
|
|
this.updateTone();
|
|
},
|
|
};
|
|
|
|
var cam = new Cam();
|
|
cam.init();
|
|
|
|
var overlays = [];
|
|
var overlayFrames = {};
|
|
|
|
var viewFinderOverlay = false;
|
|
var DIM = {x: 1.0, y: -1.0, z: 0.0};
|
|
var avatarHeadJoint = MyAvatar.getJointIndex("Head");
|
|
|
|
|
|
function getCamePos(i) {
|
|
return Vec3.sum(Camera.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5 + 0.2 * i, y: -0.3, z: -1 }))
|
|
}
|
|
function updateFrames() {
|
|
for (var i = 0; i < overlays.length; i++) {
|
|
overlayFrames[overlays[i]] = { position: getCamePos(i), rotation: Camera.orientation }
|
|
}
|
|
Overlays.editOverlays(overlayFrames)
|
|
|
|
}
|
|
|
|
function updateOverlay() {
|
|
// The only way I found to update the viewFinderOverlay without turning the spectator camera on and off is to delete and recreate the
|
|
// overlay, which is inefficient but resizing the window shouldn't be performed often
|
|
if (viewFinderOverlay) {
|
|
Overlays.deleteOverlay(viewFinderOverlay);
|
|
}
|
|
viewFinderOverlay = Overlays.addOverlay("image3d", {
|
|
url: "resource://spectatorCameraFrame",
|
|
emissive: true,
|
|
parentID: MyAvatar.SELF_ID,
|
|
parentJointIndex: -7,
|
|
alpha: 1,
|
|
localRotation: { w: 1, x: 0, y: 0, z: 0 },
|
|
localPosition: { x: 0, y: 0.0, z: -1.0 },
|
|
dimensions: DIM,
|
|
});
|
|
}
|
|
|
|
var accumulated = 0;
|
|
function theUpdate(deltaTime) {
|
|
|
|
accumulated += deltaTime;
|
|
if (accumulated > 1)
|
|
updateFrames()
|
|
|
|
cam.setTransform(Camera.position, Camera.orientation);
|
|
}
|
|
|
|
|
|
|
|
function takeShot() {
|
|
cam.shoot();
|
|
}
|
|
|
|
function turnOn() {
|
|
// createAppWindow();
|
|
cam.enable();
|
|
cam.setAspectRatio(2.0);
|
|
cam.setTransform(Camera.position, Camera.orientation);
|
|
|
|
updateOverlay()
|
|
|
|
Script.update.connect(theUpdate);
|
|
|
|
initUIFromCam();
|
|
}
|
|
function turnOff() {
|
|
// killAppWindow();
|
|
Script.update.disconnect(theUpdate);
|
|
|
|
cam.disable();
|
|
|
|
for (var i = 0; i < overlays.length; i++) {
|
|
Overlays.deleteOverlay(overlays[i]);
|
|
}
|
|
Overlays.deleteOverlay(viewFinderOverlay);
|
|
}
|
|
|
|
var AppUi = Script.require('appUi');
|
|
|
|
|
|
//*****************************************************
|
|
// THE APP TABLET ICON ON OFF + "?" + Date.now()
|
|
//*****************************************************
|
|
var TABLET_BUTTON_NAME = "Focus";
|
|
var ICON_URL = Script.resolvePath("./focus.svg");
|
|
var ACTIVE_ICON_URL = Script.resolvePath("./focus.svg");
|
|
|
|
function fromAppUI (message) {
|
|
if (message.focusApp !== undefined) {
|
|
print("fromAppUI: " + JSON.stringify(message))
|
|
switch (message.focusApp) {
|
|
case "takeShot":
|
|
takeShot();
|
|
break;
|
|
case "setFov":
|
|
cam.setFov(message.params[0]);
|
|
break;
|
|
case "setExposure":
|
|
cam.setExposure(message.params[0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var UI_URL = Script.resolvePath("./focus.qml");
|
|
|
|
var appWindow = null
|
|
function createAppWindow() {
|
|
appWindow = Desktop.createWindow(UI_URL, {
|
|
title: 'Shot!',
|
|
flags: Desktop.ALWAYS_ON_TOP,
|
|
presentationMode: Desktop.PresentationMode.NATIVE,
|
|
size: {x: 300, y: 300}
|
|
});
|
|
appWindow.closed.connect(killAppWindow);
|
|
appWindow.fromQml.connect(fromAppUI);
|
|
}
|
|
|
|
function killAppWindow() {
|
|
if (appWindow !== null) {
|
|
appWindow.closed.disconnect(killAppWindow);
|
|
appWindow.fromQml.disconnect(fromAppUI);
|
|
appWindow.close()
|
|
appWindow = null
|
|
}
|
|
}
|
|
function sendToUI(message) {
|
|
if (appWindow) {
|
|
appWindow.sendToQml(message);
|
|
}
|
|
}
|
|
|
|
function initUIFromCam() {
|
|
sendToUI({ 'initFOV': cam.fov() });
|
|
sendToUI({ 'initExposure': cam.exposure() });
|
|
}
|
|
|
|
var ui;
|
|
function startup() {
|
|
ui = new AppUi({
|
|
buttonName: TABLET_BUTTON_NAME,
|
|
home: UI_URL,
|
|
onOpened: function () {
|
|
print("Hello Focus!");
|
|
turnOn()
|
|
},
|
|
onClosed: function () {
|
|
turnOff()
|
|
print("Bye Focus!");
|
|
},
|
|
onMessage: fromAppUI,
|
|
normalButton: ICON_URL,
|
|
activeButton: ACTIVE_ICON_URL
|
|
});
|
|
}
|
|
startup();
|
|
|
|
|
|
Script.scriptEnding.connect(function () {
|
|
turnOff()
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}()); |