Jean-Yves Didier

modified several scripts for debugging

{
"context" : {
"libraries" : [ "../components/filter.js", "../components/console.js"],
"components" : {
"loop": {
"type": "Filter",
"value": {
"signals": [ "newIteration", "endLoop" ],
"slots": [{
"slot": "setIterations",
"func": "n => { for(let i=0; i<n; i++){console.log(\"Loop: emitting\",i); self.emit(\"newIteration\",i);}self.emit(\"endLoop\");}"
}]
}
},
"dint": {
"type": "Filter",
"value": {
"slots": [{
"slot": "display",
"func": "n => console.log(\" DisplayInt:\",n)"
}]
}
},
"console": { "type":"Console", "value":"output"},
"statemachine" : {
"type": "StateMachine",
"value" : {
"initial": "state1",
"transitions" : {
"state1" : { "next" : "state2"}
}
}
}
}
},
"controller" : "statemachine",
"sheets" : {
"state1" : {
"preconnections" : [],
"postconnections" : [
{ "destination":"loop", "slot":"setIterations", "value":[4] }
],
"connections" : [
{ "source":"loop", "signal":"newIteration", "destination":"dint", "slot":"display" },
{ "source":"loop", "signal":"endLoop", "destination":"statemachine", "slot":"next" }
],
"cleanups" : []
},
"state2" : {
"preconnections" : [],
"postconnections" : [
{ "destination":"loop", "slot":"setIterations", "value":[8] }
],
"connections" : [
{ "source":"loop", "signal":"newIteration", "destination":"dint", "slot":"display" },
{ "source":"loop", "signal":"endLoop", "destination":"statemachine", "slot":"next" }
],
"cleanups" : []
}
}
}
<html>
<head>
<title>ARCS engine: filter example</title>
<script data-base-url="../.."
data-arcsapp="arcsapp.json"
type="module"
src="../../build/arcs_browser.js">
</script>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>ARCS in Web Browser, with filters</h1>
<div style="height:80vh; overflow: auto; border: solid 1px navy;">
<p id="output" style="margin: 5px; padding: 5px; font-family: monospace;"></p>
<div>
</body>
</html>
......@@ -3,7 +3,7 @@
"libraries" : [ "../components/video.js","../components/animator.js", "../components/qrcodedetector.js"],
"components" : {
"animator" : { "type": "Animator"},
"video" : { "type": "LiveSource", "value" : { "video": "#video", "facingMode": "user"}},
"video" : { "type": "LiveSource", "value" : { "video": "#video", "facingMode": "environment"}},
"detector" : { "type": "QRCodeDetector"},
"statemachine" : {
"type": "StateMachine",
......
@viewport {
width: device-width;
zoom: 1;
}
body {
font-family: sans-serif;
padding: 0px;
margin: 0px;
}
.info {
background: navy;
opacity: 0.6;
font-weight: bold;
font-size: 120%;
color: white;
}
.info p {
margin:0;
}
#coords {
position: absolute;
padding: 10px;
left: 10px;
top: 10px;
}
#container {
left:0px;
top:0px;
width: 100vw;
height: 100vh;
}
#notification {
position: absolute;
max-width: 80vw;
padding: 10px;
left: 10px;
bottom: 10px;
}
video {
position: absolute;
right: 0px;
top: 0px;
}
#logo {
position: absolute;
margin:0px;
padding:0px;
right: 0px;
bottom:0px;
}
{
"context" : {
"libraries" : [
"../components/xrviewer.js", "../components/uimapper.js",
"../components/video.js", "../components/qrcodedetector.js",
"../components/filter.js"
],
"components" : {
"video" : { "type": "LiveSource", "value": { "video": "video", "facingMode": "environment" }},
"viewer" : { "type": "XRViewer", "value": {
"sessionConfig": {
"optionalFeatures": [ "local-floor", "dom-overlay" ],
"domOverlay" : { "root": "#container"}
}
}
},
"trigger" : { "type": "Filter", "value": {
"signals": [ "onSessionStarted" ],
"slots" : [{
"slot": "triggerCamera",
"func": "(t,c,f) => {self.xr = self.xr || false; if(f && !self.xr) { self.xr = true; self.emit(\"onSessionStarted\"); } } "
}]
}
},
"display" : { "type": "UIMapper", "value": {
"slots" : {
"updatePosition" : [
{ "param" : "1.position.x", "field" : "#x.innerHTML", "format": "e=>e.toFixed(2)" },
{ "param" : "1.position.y", "field" : "#y.innerHTML", "format": "e=>e.toFixed(2)" },
{ "param" : "1.position.z", "field" : "#z.innerHTML", "format": "e=>e.toFixed(2)" }
]
}
}
},
"statemachine" : {
"type": "StateMachine",
"value" : {
"initial": "init",
"final": "end",
"transitions" : {
"init" : { "next" : "end"}
}
}
}
}
},
"controller" : "statemachine",
"sheets" : {
"init" : {
"preconnections" : [],
"postconnections" : [
{ "destination": "video", "slot": "start", "value": []},
{ "destination": "viewer", "slot": "start", "value": []}
],
"connections" : [
{ "source": "viewer", "signal": "onRender", "destination": "display", "slot": "updatePosition"},
{ "source": "viewer", "signal": "onRender", "destination": "trigger", "slot": "triggerCamera"},
{ "source": "trigger", "signal": "onSessionStarted", "destination": "video", "slot": "start"}
],
"cleanups" : []
},
"end" : {
"preconnections" : [],
"postconnections" : [],
"connections" : [],
"cleanups" : []
}
}
}
<html>
<head>
<title>ARCS: WebXR example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="arcs.css">
<script src="../../deps/mobileconsole/hnl.mobileConsole.js"></script>
<script>mobileConsole.init()</script>
<script type="module"
data-base-url="../.."
data-arcsapp="arcsapp.json"
src="../../build/arcs_browser.js">
</script>
</head>
<body>
<div id="container">
<div class="info" id="coords">
<p>X <span id="x"></span></p>
<p>Y <span id="y"></span></p>
<p>Z <span id="z"></span></p>
</div>
<video width=320 height=240 autoplay=true></video>
<div class="info" style="display: none;" id="notification">
</div>
<div id="logo">
<p style="color:white;">Powered by<br/>
<a href="http://arcs.ibisc.univ-evry.fr"><img src="../../docs/arcs_logo.png" alt="ARCS"/></a>
</p>
</div>
</div>
</body>
</html>
import * as ARCS from '../build/arcs.js';
import ARCS from '../build/arcs.js';
let Filter;
......@@ -31,14 +31,15 @@ Filter = ARCS.Component.create(
let self = this;
let _config = config || {};
self.signals = self.signals || {};
//self.signal(self.signals);
if (_config.signals) {
_config.signals.forEach(e => {
if (self.signals.indexOf(e) < 0) self.signals.push(e);
self.signals[e] = [];
});
}
if (_config.slots) {
_config.slots.forEach(e => {
if (!e.slot || !e.func) return;
......@@ -52,3 +53,6 @@ Filter = ARCS.Component.create(
[],
[]
);
export default {Filter: Filter};
......
......@@ -3,9 +3,9 @@ import ARCS from '../build/arcs.js';
let UIMapper ;
/**
* UIMapperConfigItem
* UIMapperSlot
* An item describing a slot for an UIMapper component
* @typedef {Object} UIMapperConfigItem
* @typedef {Object} UIMapperSlot
* @property param {string} a string representing a parameter. It can reach
* subcomponents of an object by using the notation X.subcomp1.subcomp2 ...
* where X value is the position index of the parameter
......@@ -20,10 +20,12 @@ let UIMapper ;
*/
/**
* UIMapperConfig
* An UIMapperConfig is a javascript object. Each property is describing a slot.
* Every property will be of type UIMapperConfigItem
* @typedef {Object} UIMapperConfig
* UIMapperSignal
* An item describing a signal for an UIMapper component
* @typedef {Object} UIMapperSignal
* @property selector {string} a CSS selector to target a DOM element
* @property event {string} the event of the DOM element that should trigger
* the signal.
*/
/**
......@@ -32,7 +34,11 @@ let UIMapper ;
* UIMapper is using metaprogramming, that is to say the configuration object
* will determine what are the needed slots for the component instance as well
* as the way they will tie to any HTML element.
* @param obj {UIMapperConfig} configuration object to initialize the component.
* @param obj {object} configuration object to initialize the component.
* @param obj.slots {object} an object where keys are slot names and descriptions
* objects of type UIMapperSlot
* @param obj.signals {object} an object where keys are signal names and
* descriptions objects of type UIMapperSlot
*/
UIMapper = ARCS.Component.create(
function(obj) {
......@@ -44,7 +50,7 @@ UIMapper = ARCS.Component.create(
let func = null;
if (format !== undefined) {
func = new Function(`return ${format}`)();
func = new Function('self', `return ${format}`)(self);
}
let fields = field.split('.');
......@@ -67,21 +73,43 @@ UIMapper = ARCS.Component.create(
}
};
obj = obj || {};
for(let p in obj) {
let slotName = p;
let slotFunction = function(pobj) {
return function() {
pobj.map( elt => {
mapFunction(elt.param, elt.field,elt.format, elt.value).apply(null, arguments);
if (obj.slots) {
for(let p in obj.slots) {
let slotName = p;
let slotFunction = function(pobj) {
return function() {
pobj.map( elt => {
mapFunction(elt.param, elt.field,elt.format, elt.value).apply(null, arguments);
});
};
}
if (self.slots.indexOf(slotName) < 0) {
self.slots.push(slotName);
self[slotName] = slotFunction(obj.slots[p]);
}
};
}
self.signals = self.signals || {};
let osignals = obj.signals;
if (osignals) {
for (let s in osignals) {
let signalName = s;
let signalDescr = osignals[s];
let domElt = document.querySelector(signalDescr.selector);
if (domElt) {
domElt.addEventListener(signalDescr.event, self => {
return e => self.emit(s, e)
});
};
}
if (self.slots.indexOf(slotName) < 0) {
self.slots.push(slotName);
self[slotName] = slotFunction(obj[p]);
}
self.signals[s] = [];
}
};
}
}, [], []
);
......
......@@ -56,6 +56,8 @@ LiveSource = ARCS.Component.create(
var handleMediaStream = function(stream) {
video.srcObject = stream;
stream.addEventListener('ended', e => console.log('video ended', e));
video.onloadedmetadata = e => video.play();
/*video.videoWidth=defaultWidth;
video.videoHeight=defaultHeight;*/
......
......@@ -26,11 +26,12 @@ XRViewer = ARCS.Component.create(
container = (_config.rootElement !== undefined)?
document.querySelector(_config.rootElement):document.body;
container = container || document.body;
let rootOverlay = container;
if (_config.sessionConfig && _config.sessionConfig.domOverlay
&& _config.sessionConfig.domOverlay && _config.sessionConfig.domOverlay.root) {
let rootOverlay = document.querySelector(_config.sessionConfig.domOverlay.root);
_config.sessionConfig.domOverlay.root = rootOverlay || document.body;
rootOverlay = document.querySelector(_config.sessionConfig.domOverlay.root) || rootOverlay;
_config.sessionConfig.domOverlay.root = rootOverlay; // || document.body;
}
......@@ -42,8 +43,9 @@ XRViewer = ARCS.Component.create(
renderer.setSize(container.width, container.height);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.xr.enabled = true;
renderer.xr.cameraAutoUpdate = false;
container.appendChild(renderer.domElement);
container.appendChild(ARButton.createButton(renderer,_config.sessionConfig));
rootOverlay.appendChild(ARButton.createButton(renderer,_config.sessionConfig));
var theta = 45;
camera = new THREE.PerspectiveCamera(theta, container.width / container.height, 0.01, 10);
......@@ -53,6 +55,11 @@ XRViewer = ARCS.Component.create(
scene.add(_light);
renderer.domElement.addEventListener('webglcontextlost', (event) => {
console.log(event);
});
/**
* Adds new objects to the current 3D scene
* @param scene {object} 3D object as defined by Three.js to add to the scene.
......@@ -74,6 +81,40 @@ XRViewer = ARCS.Component.create(
};
/**
* Sets the pose
* @param pos {object} a position with x, y and z coordinates
* @param rot {object} unused so far
* @slot
* @function XRViewer#setPose
*/
this.setPose = function(pos, rot) {
let session = renderer.xr.getSession();
let p = camera.position;
let q = new THREE.Quaternion();
q.setFromRotationMatrix(camera.matrixWorld);
session.requestReferenceSpace(renderer.xr.getReferenceSpace()).then(
(space) => {
let xrSpace = space;
xrSpace = xrSpace.getOffsetReferenceSpace(
new XRRigidTransform(
{ x: p.x, y: p.y, z: p.z, w: 1 },
{ x: q.x, y: q.y, z: q.z, w: q.w}
)
);
xrSpace = xrSpace.getOffsetReferenceSpace(
new XRRigidTransform(
{ x: pos.x, y: pos.y, z:pos.z, w:1},
{ x: 0, y:0, z:0, w:1}
)
);
}
);
};
/**
* Starts the animation loop.
* Each time an animation frame is obtained, preRender and postRender
* signals are triggered
......@@ -87,38 +128,25 @@ XRViewer = ARCS.Component.create(
};
let render = function (time, frame) {
self.emit("preRender",time,frame);
renderer.xr.updateCamera(camera);
self.emit("onRender",time,camera,frame);
renderer.render(scene, camera);
self.emit("postRender",time,camera);
}
},
/** @lends XRViewer.slots */
[
'setWidgets','addScene',
'removeScene','render',
],
['preRender','postRender']
['addScene','removeScene','start','setPose'],
['onRender']
);
/**
* emitted when a frame is obtained before rendering of the scene.
* Use this if you want to update the scenegraph.
* @function XRViewer#preRender
* @signal
* @param time {number} time elapsed since the beginning of the loop in seconds
* @param frame {object} an XRFrame as specified by WebXR
*/
/**
* emitted when a frame is obtained after rendering of the scene.
* @function XRViewer#postRender
* @function XRViewer#onRender
* @signal
* @param time {number} time elapsed since the beginning of the loop in seconds
* @param frame {object} an XRFrame as specified by WebXR
* @param camera {THREE.Camera} the camera object
* @param frame {XRFrame} a frame as setup by the WebXR loop
*/
export default {XRViewer: XRViewer};
......
This diff is collapsed. Click to expand it.