Added 3d closet demo, cleaned up menus.
410
index.html
@ -1,139 +1,266 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||||
<title>Deep Diagram</title>
|
<link href="/assets/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
|
||||||
<style>
|
<link href="/assets/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
|
||||||
body {
|
<link href="/assets/favicon-96x96.png" rel="icon" sizes="96x96" type="image/png">
|
||||||
width: 100vw;
|
<title>Deep Diagram</title>
|
||||||
height: 100vh;
|
<style>
|
||||||
margin: 0px;
|
body {
|
||||||
padding: 0px;
|
width: 100vw;
|
||||||
aspect-ratio: auto;
|
height: 100vh;
|
||||||
}
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
aspect-ratio: auto;
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
font-size: large;
|
||||||
|
color: #4444ee;
|
||||||
|
}
|
||||||
|
|
||||||
.scene {
|
.scene {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.webButton {
|
#gameCanvas {
|
||||||
position: fixed;
|
width: 100%;
|
||||||
bottom: 50px;
|
height: 100%;
|
||||||
left: 20px;
|
margin: 0px;
|
||||||
background: rgba(51, 51, 51, .7);
|
padding: 0px;
|
||||||
display: none;
|
background: transparent;
|
||||||
width: 80px;
|
}
|
||||||
height: 50px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.webMenu {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 50px;
|
|
||||||
left: 20px;
|
|
||||||
width: 50%;
|
|
||||||
height: 50%;
|
|
||||||
background: rgba(51, 51, 51, .9);
|
|
||||||
color: #fff;
|
|
||||||
z-index: 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.webMenu input {
|
div.overlay {
|
||||||
background: rgba(51, 51, 51, .9);
|
position: absolute;
|
||||||
}
|
background: #000;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 12;
|
||||||
|
width: 320px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
.webMenu label, .webMenu input {
|
div.overlay div {
|
||||||
|
background-color: #000000;
|
||||||
|
color: #FFD700;
|
||||||
|
padding: 15px 25px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
color: #fff;
|
div.overlay div a {
|
||||||
}
|
display: inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
border-color: #FFD700;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
.webMenu ul {
|
div.overlay div a:visited, div.overlay div a:link {
|
||||||
list-style-type: none;
|
color: white;
|
||||||
padding: 0px;
|
}
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.webMenu li label {
|
div.overlay div a:hover {
|
||||||
display: inline-block;
|
background-color: #FFD700;
|
||||||
width: 200px;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.webMenu li {
|
div.overlay div a {
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#gameCanvas {
|
}
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#questLaunch {
|
div.overlay input {
|
||||||
position: fixed;
|
display: inline-block;
|
||||||
top: 30px;
|
margin: 10px auto;
|
||||||
right: 30px;
|
text-decoration: none;
|
||||||
padding: 10px;
|
border-color: #FFD700;
|
||||||
background: #000;
|
border-style: solid;
|
||||||
color: #fff;
|
border-width: 1px;
|
||||||
font-size: 1.5em;
|
padding: 10px;
|
||||||
z-index: 100;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#download {
|
div#create {
|
||||||
position: fixed;
|
left: 50%;
|
||||||
z-index: 11;
|
top: 60%;
|
||||||
width: 200px;
|
transform: translate(-50%, -50%);
|
||||||
height: 20px;
|
z-index: 12;
|
||||||
position: absolute;
|
width: 320px;
|
||||||
bottom: 50px;
|
height: 240px;
|
||||||
left: 16px;
|
border: 3px inset #FFD700;
|
||||||
padding: 10px;
|
display: none;
|
||||||
background: #000;
|
}
|
||||||
color: #fff;
|
|
||||||
}
|
div.overlay div a.cancel {
|
||||||
</style>
|
font-size: small;
|
||||||
<link as="script" href="/newRelic.js" rel="preload">
|
font-weight: lighter;
|
||||||
<script src="/newRelic.js"></script>
|
font-style: italic;
|
||||||
<meta content="width=device-width, initial-scale=1, height=device-height" name="viewport">
|
background-color: #222211;
|
||||||
<meta content="An immersive vr diagramming experience based on a-frame and webxr" name="description">
|
color: #EEC755;
|
||||||
<link href="/assets/favicon-16x16.png" rel=icon sizes="16x16" type="image/png">
|
}
|
||||||
<link href="/assets/favicon-32x32.png" rel=icon sizes="32x32" type="image/png">
|
|
||||||
<link href="/assets/favicon-96x96.png" rel=icon sizes="96x96" type="image/png">
|
div.overlay div a.cancel:hover {
|
||||||
<link href="/manifest.webmanifest" rel="manifest"/>
|
background-color: #EEC700;
|
||||||
<script src='/niceware.js'></script>
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.mini {
|
||||||
|
left: 100px;
|
||||||
|
top: 200px;
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.mini img, #tutorial img {
|
||||||
|
width: 160px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.mini div a, #tutorial div a {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tutorial h1 {
|
||||||
|
font-size: x-large;
|
||||||
|
font-weight: bolder;
|
||||||
|
text-align: center;
|
||||||
|
color: #F9F9E9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tutorial {
|
||||||
|
z-index: 15;
|
||||||
|
left: 100px;
|
||||||
|
top: 560px;
|
||||||
|
width: 160px;
|
||||||
|
height: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#closekey, #closekey a:active, #closekey a:visited, #closekey a:link {
|
||||||
|
position: relative;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingGrid {
|
||||||
|
z-index: -1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<link as="script" href="/newRelic.js" rel="preload">
|
||||||
|
<script src="/newRelic.js"></script>
|
||||||
|
<meta content="width=device-width, initial-scale=1, height=device-height" name="viewport">
|
||||||
|
<meta content="An immersive vr diagramming experience based using webxr" name="description">
|
||||||
|
<link href="/manifest.webmanifest" rel="manifest"/>
|
||||||
|
<!--<script src='/niceware.js'></script>-->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<div class="overlay" id="tutorial">
|
||||||
|
<h1>Help</h1>
|
||||||
|
<div id="desktopTutorial"><a href="#" id="desktopLink">Desktop</a></div>
|
||||||
|
<div id="questTutorial"><a href="#" id="questLink">Quest</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="download"><a href="#" id="downloadLink">Download Model</a></div>
|
<div class="overlay mini" id="main">
|
||||||
|
<img height="120" src="/assets/ddd.svg" width="320">
|
||||||
|
<div id="startCreate"><a href="#" id="startCreateLink">Start</a></div>
|
||||||
|
<div id="download"><a href="#" id="downloadLink">Download Model</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="overlay" id="create">
|
||||||
|
<div><input id="createName" placeholder="Enter a name for your diagram" type="text"></div>
|
||||||
|
<div><input id="createPassword" placeholder="Enter a password (optional)" type="text"></div>
|
||||||
|
<div><a href="#" id="createActionLink">Create</a></div>
|
||||||
|
<div><a class="cancel" href="#" id="cancelCreateLink">Cancel</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="overlay" id="keyboardHelp">
|
||||||
|
<div id="closekey"><a href="#">X</a></div>
|
||||||
|
<img height="240" src="/assets/textures/keyboardhelp2.jpg" width="480">
|
||||||
|
<img height="240" src="/assets/textures/mousehelp.jpg" width="180">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<img id="loadingGrid" src="/assets/grid3.jpg"/>
|
||||||
<script>
|
<script>
|
||||||
/*
|
const create = document.querySelector('#startCreateLink');
|
||||||
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition
|
if (create) {
|
||||||
var SpeechGrammarList = SpeechGrammarList || window.webkitSpeechGrammarList
|
create.addEventListener('click', function (evt) {
|
||||||
var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent
|
evt.preventDefault();
|
||||||
var recognition = new SpeechRecognition();
|
document.querySelector('#main').style.display = 'none';
|
||||||
recognition.continuous = false;
|
document.querySelector('#create').style.display = 'block';
|
||||||
recognition.lang = 'en-US';
|
});
|
||||||
recognition.interimResults = true;
|
}
|
||||||
recognition.maxAlternatives = 1;
|
const cancel = document.querySelector('#cancelCreateLink');
|
||||||
recognition.onresult = function(event) {
|
if (cancel) {
|
||||||
console.log(event.results[0][0].transcript);
|
cancel.addEventListener('click', function (evt) {
|
||||||
}
|
evt.preventDefault();
|
||||||
recognition.onend = function() {
|
document.querySelector('#main').style.display = 'block';
|
||||||
console.log("recognition ended");
|
document.querySelector('#create').style.display = 'none';
|
||||||
recognition.start();
|
});
|
||||||
}
|
}
|
||||||
console.log("starting recognition");
|
const close = document.querySelector('#closekey a');
|
||||||
recognition.start();
|
if (close) {
|
||||||
|
close.addEventListener('click', function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
document.querySelector('#keyboardHelp').style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const desktopTutorial = document.querySelector('#desktopLink');
|
||||||
|
if (desktopTutorial) {
|
||||||
|
desktopTutorial.addEventListener('click', function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
// document.querySelector('#tutorial').style.display = 'none';
|
||||||
|
document.querySelector('#keyboardHelp').style.display = 'block';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const createAction = document.querySelector('#createActionLink');
|
||||||
|
if (createAction) {
|
||||||
|
createAction.addEventListener('click', function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
const value = document.querySelector('#createName').value;
|
||||||
|
if (value && value.length > 4) {
|
||||||
|
document.location.href = '/db/' + value;
|
||||||
|
} else {
|
||||||
|
window.alert('Name must be longer than 4 characters');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
/*
|
||||||
|
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition
|
||||||
|
var SpeechGrammarList = SpeechGrammarList || window.webkitSpeechGrammarList
|
||||||
|
var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent
|
||||||
|
var recognition = new SpeechRecognition();
|
||||||
|
recognition.continuous = false;
|
||||||
|
recognition.lang = 'en-US';
|
||||||
|
recognition.interimResults = true;
|
||||||
|
recognition.maxAlternatives = 1;
|
||||||
|
recognition.onresult = function(event) {
|
||||||
|
console.log(event.results[0][0].transcript);
|
||||||
|
}
|
||||||
|
recognition.onend = function() {
|
||||||
|
console.log("recognition ended");
|
||||||
|
recognition.start();
|
||||||
|
}
|
||||||
|
console.log("starting recognition");
|
||||||
|
recognition.start();
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script src="/src/vrApp.ts" type="module"></script>
|
<script src="/src/vrApp.ts" type="module"></script>
|
||||||
@ -141,42 +268,27 @@
|
|||||||
<div class="scene">
|
<div class="scene">
|
||||||
<canvas id="gameCanvas"></canvas>
|
<canvas id="gameCanvas"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<div class="webButton">
|
|
||||||
<button id="menuButton">Open Menu</button>
|
|
||||||
</div>
|
|
||||||
<div class="webMenu">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<label for="newRelicAccount">New Relic Account</label>
|
|
||||||
<input id="newRelicAccount" type="text" value="">
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label for="newRelicClient">New Relic Client</label>
|
|
||||||
<input id="newRelicClient" type="text" value="">
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<button id="webButton">Save</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
const button = document.querySelector('#menuButton');
|
|
||||||
if (button) {
|
|
||||||
button.addEventListener('click', (e) => {
|
|
||||||
const menu = document.querySelector('.webMenu');
|
|
||||||
//const button = document.querySelector('#webButton');
|
|
||||||
|
|
||||||
if (menu.style.display === 'block') {
|
|
||||||
menu.style.display = 'none';
|
|
||||||
button.innerText = "Open Menu";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
menu.style.display = 'block';
|
|
||||||
button.innerText = "Close Menu";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
<style>
|
||||||
|
#keyboardHelp {
|
||||||
|
display: none;
|
||||||
|
width: 665px;
|
||||||
|
height: 312px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyboardHelp .button {
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyboardHelp div {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</html>
|
</html>
|
||||||
@ -28,8 +28,6 @@
|
|||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"@typed-mxgraph/typed-mxgraph": "^1.0.8",
|
"@typed-mxgraph/typed-mxgraph": "^1.0.8",
|
||||||
"@types/node": "^18.14.0",
|
"@types/node": "^18.14.0",
|
||||||
"dexie": "^3.2.4",
|
|
||||||
"dexie-observable": "^4.0.1-beta.13",
|
|
||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"@types/file-saver": "^2.0.6",
|
"@types/file-saver": "^2.0.6",
|
||||||
@ -37,15 +35,11 @@
|
|||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"mxgraph": "^4.2.2",
|
"mxgraph": "^4.2.2",
|
||||||
"niceware": "^4.0.0",
|
"niceware": "^4.0.0",
|
||||||
"p2p-data-channel": "^1.10.7",
|
|
||||||
"pouchdb": "^8.0.1",
|
"pouchdb": "^8.0.1",
|
||||||
"pouchdb-find": "^7.2.2",
|
"pouchdb-find": "^7.2.2",
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"recordrtc": "^5.6.2",
|
|
||||||
"ring-client-api": "11.7.7",
|
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0"
|
||||||
"material-components-web": "^11.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
|||||||
BIN
public/android-icon-192x192.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
4312
public/arch_demo.xml
BIN
public/assets/Android.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
43
public/assets/ddd.svg
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 669 B After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 15 KiB |
BIN
public/assets/grid.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/assets/grid2.png
Normal file
|
After Width: | Height: | Size: 867 KiB |
BIN
public/assets/grid3.jpg
Normal file
|
After Width: | Height: | Size: 661 KiB |
BIN
public/assets/iPhone.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/assets/textures/keyboard.jpg
Normal file
|
After Width: | Height: | Size: 8.8 MiB |
BIN
public/assets/textures/keyboardhelp.jpg
Normal file
|
After Width: | Height: | Size: 8.8 MiB |
BIN
public/assets/textures/keyboardhelp2.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/assets/textures/mouse.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
public/assets/textures/mousehelp.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
@ -1,63 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Chart 1",
|
|
||||||
"series": [
|
|
||||||
{
|
|
||||||
"name": "series 1",
|
|
||||||
"values": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"start": "2015-01-01",
|
|
||||||
"end": "2015-12-31",
|
|
||||||
"value": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "2",
|
|
||||||
"start": "2016-01-01",
|
|
||||||
"end": "2016-12-31",
|
|
||||||
"value": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "3",
|
|
||||||
"start": "2017-01-01",
|
|
||||||
"end": "2017-12-31",
|
|
||||||
"value": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4",
|
|
||||||
"start": "2018-01-01",
|
|
||||||
"end": "2018-12-31",
|
|
||||||
"value": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "series 2",
|
|
||||||
"values": [
|
|
||||||
{
|
|
||||||
"id": "1",
|
|
||||||
"start": "2015-01-01",
|
|
||||||
"end": "2015-12-31",
|
|
||||||
"value": 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "2",
|
|
||||||
"start": "2016-01-01",
|
|
||||||
"end": "2016-12-31",
|
|
||||||
"value": 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "3",
|
|
||||||
"start": "2017-01-01",
|
|
||||||
"end": "2017-12-31",
|
|
||||||
"value": 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4",
|
|
||||||
"start": "2018-01-01",
|
|
||||||
"end": "2018-12-31",
|
|
||||||
"value": 8
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 32 KiB |
@ -9,14 +9,14 @@
|
|||||||
"description": "Immersive diagraming tool to dig into deeper meaning behind your ideas",
|
"description": "Immersive diagraming tool to dig into deeper meaning behind your ideas",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/android-icon-192x192.png",
|
"src": "/Android.png",
|
||||||
"sizes": "192x192",
|
"sizes": "196x196",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/icon-512x512.png",
|
"src": "/iPhone.png",
|
||||||
"sizes": "512x512",
|
"sizes": "180x180",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 630 KiB |
@ -1,10 +1,6 @@
|
|||||||
const VERSION = '0';
|
const VERSION = '0';
|
||||||
const CACHE = "pwabuilder-offline";
|
const CACHE = "pwabuilder-offline";
|
||||||
const PRECACHE_ASSETS = [
|
const PRECACHE_ASSETS = []
|
||||||
'/grass1.jpeg',
|
|
||||||
'/loading-loading-forever.gif',
|
|
||||||
'/outdoor_field2.jpeg'
|
|
||||||
]
|
|
||||||
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js');
|
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js');
|
||||||
|
|
||||||
self.addEventListener("message", (event) => {
|
self.addEventListener("message", (event) => {
|
||||||
|
|||||||
@ -7,56 +7,60 @@ import {
|
|||||||
PhysicsShapeType,
|
PhysicsShapeType,
|
||||||
Scene,
|
Scene,
|
||||||
TransformNode,
|
TransformNode,
|
||||||
Vector3
|
Vector3,
|
||||||
|
WebXRDefaultExperience
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
|
|
||||||
import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial";
|
import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial";
|
||||||
|
|
||||||
export function buildRig(scene: Scene): Mesh {
|
export function buildRig(scene: Scene, xr: WebXRDefaultExperience): Mesh {
|
||||||
const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: 1.6}, scene);
|
const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: .2}, scene);
|
||||||
|
|
||||||
const cameratransform = new TransformNode("cameraTransform", scene);
|
const cameratransform = new TransformNode("cameraTransform", scene);
|
||||||
cameratransform.parent = rigMesh;
|
cameratransform.parent = rigMesh;
|
||||||
cameratransform.position = new Vector3(0, -.8, 0);
|
xr.baseExperience.onInitialXRPoseSetObservable.add((state) => {
|
||||||
|
|
||||||
|
xr.baseExperience.camera.parent = cameratransform;
|
||||||
|
xr.baseExperience.camera.position = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
for (const cam of scene.cameras) {
|
for (const cam of scene.cameras) {
|
||||||
cam.parent = cameratransform;
|
cam.parent = cameratransform;
|
||||||
console.log(cam.absoluteRotation);
|
if (cam.getClassName() == "FreeCamera") {
|
||||||
|
//cameratransform.position = new Vector3(0, 1.6, 0);
|
||||||
|
//cam.position.set(0, 1.6, 0);
|
||||||
|
} else {
|
||||||
|
//cameratransform.position = new Vector3(0, 1.6, 0);
|
||||||
|
//cam.position.set(0, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene.onActiveCameraChanged.add(() => {
|
||||||
scene.onActiveCameraChanged.add((s) => {
|
for (const cam of scene.cameras) {
|
||||||
|
cam.parent = cameratransform;
|
||||||
|
if (cam.getClassName() == "FreeCamera") {
|
||||||
|
//cameratransform.position = new Vector3(0, 1.6, 0);
|
||||||
|
//cam.position.set(0, 1.6, 0);
|
||||||
|
} else {
|
||||||
|
//cameratransform.position = new Vector3(0, 0, 0);
|
||||||
|
//cam.position.set(0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
cameratransform.rotation.set(0, Math.PI, 0);
|
cameratransform.rotation.set(0, Math.PI, 0);
|
||||||
s.activeCamera.parent = cameratransform;
|
//s.activeCamera.parent = cameratransform;
|
||||||
});
|
});
|
||||||
rigMesh.material = buildStandardMaterial("rigMaterial", scene, "#2222ff");
|
rigMesh.material = buildStandardMaterial("rigMaterial", scene, "#2222ff");
|
||||||
rigMesh.setAbsolutePosition(new Vector3(0, .01, 3));
|
rigMesh.setAbsolutePosition(new Vector3(0, .01, 3));
|
||||||
const home = new AxesViewer(scene, .5);
|
rigMesh.isPickable = false;
|
||||||
|
new AxesViewer(scene, .25);
|
||||||
rigMesh.lookAt(new Vector3(0, 0.01, 0));
|
rigMesh.lookAt(new Vector3(0, 0.01, 0));
|
||||||
rigMesh.visibility = 0;
|
rigMesh.visibility = 1;
|
||||||
const rigAggregate =
|
const rigAggregate =
|
||||||
new PhysicsAggregate(
|
new PhysicsAggregate(
|
||||||
rigMesh,
|
rigMesh,
|
||||||
PhysicsShapeType.CYLINDER,
|
PhysicsShapeType.CYLINDER,
|
||||||
{friction: 0, center: Vector3.Zero(), mass: 50, restitution: .1},
|
{friction: 0, center: Vector3.Zero(), mass: 50, restitution: .01},
|
||||||
scene);
|
scene);
|
||||||
|
|
||||||
|
|
||||||
/*const rightFoot = MeshBuilder.CreateBox("rightFoot", {width: .1, height: .1, depth: .2}, scene);
|
|
||||||
const rightFootAggregate =
|
|
||||||
new PhysicsAggregate(
|
|
||||||
rightFoot,
|
|
||||||
PhysicsShapeType.BOX,
|
|
||||||
{ friction: 0, center: Vector3.Zero(), radius: .2, pointA: new Vector3(0, 0, 0),
|
|
||||||
pointB: new Vector3(0, 1.5, 0), mass: 50, restitution: .1},
|
|
||||||
scene);
|
|
||||||
rightFootAggregate.body.setMotionType(PhysicsMotionType.ANIMATED);
|
|
||||||
rightFoot.parent= rigAggregate.transformNode;
|
|
||||||
rightFoot.material = rigMaterial;
|
|
||||||
rightFoot.position.y=.05;
|
|
||||||
rightFoot.position.x=.2;
|
|
||||||
rightFoot.position.z= 2;
|
|
||||||
|
|
||||||
*/
|
|
||||||
rigAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
|
rigAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
|
||||||
return rigMesh;
|
return rigMesh;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export class Rigplatform {
|
|||||||
this.diagramManager = diagramManager;
|
this.diagramManager = diagramManager;
|
||||||
this.controllers = controllers;
|
this.controllers = controllers;
|
||||||
this.xr = xr;
|
this.xr = xr;
|
||||||
this.rigMesh = buildRig(scene);
|
this.rigMesh = buildRig(scene, xr);
|
||||||
|
|
||||||
this.fixRotation();
|
this.fixRotation();
|
||||||
this.initializeControllers();
|
this.initializeControllers();
|
||||||
@ -163,7 +163,7 @@ export class Rigplatform {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
//this.xr.baseExperience.camera.position = new Vector3(0, 0, 0);
|
||||||
if (controller) {
|
if (controller) {
|
||||||
controller.setRig(this);
|
controller.setRig(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {AbstractMesh, MeshBuilder, Scene} from "@babylonjs/core";
|
import {AbstractMesh, KeyboardEventTypes, MeshBuilder, Scene} from "@babylonjs/core";
|
||||||
import {Rigplatform} from "./rigplatform";
|
import {Rigplatform} from "./rigplatform";
|
||||||
import {ControllerEventType, Controllers} from "./controllers";
|
import {ControllerEventType, Controllers} from "./controllers";
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
@ -40,20 +40,38 @@ export class WebController {
|
|||||||
|
|
||||||
this.scene.onKeyboardObservable.add((kbInfo) => {
|
this.scene.onKeyboardObservable.add((kbInfo) => {
|
||||||
this.logger.debug(kbInfo);
|
this.logger.debug(kbInfo);
|
||||||
|
const canvas = document.querySelector('#gameCanvas');
|
||||||
|
|
||||||
|
if (canvas && kbInfo.event.target != canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (kbInfo.type == KeyboardEventTypes.KEYUP) {
|
||||||
|
this.rig.turn(0);
|
||||||
|
}
|
||||||
if (kbInfo.type == 1) {
|
if (kbInfo.type == 1) {
|
||||||
switch (kbInfo.event.key) {
|
switch (kbInfo.event.key) {
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
|
case "w":
|
||||||
this.rig.forwardback(-this.speed);
|
this.rig.forwardback(-this.speed);
|
||||||
break;
|
break;
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
|
case "s":
|
||||||
this.rig.forwardback(this.speed);
|
this.rig.forwardback(this.speed);
|
||||||
break;
|
break;
|
||||||
case "ArrowLeft":
|
case "ArrowLeft":
|
||||||
|
case "a":
|
||||||
this.rig.leftright(-this.speed);
|
this.rig.leftright(-this.speed);
|
||||||
break;
|
break;
|
||||||
|
case "A":
|
||||||
|
this.rig.turn(-this.speed);
|
||||||
|
break;
|
||||||
case "ArrowRight":
|
case "ArrowRight":
|
||||||
|
case "d":
|
||||||
this.rig.leftright(this.speed);
|
this.rig.leftright(this.speed);
|
||||||
break;
|
break;
|
||||||
|
case "D":
|
||||||
|
this.rig.turn(this.speed);
|
||||||
|
break;
|
||||||
case "]":
|
case "]":
|
||||||
this.speed *= 1.5;
|
this.speed *= 1.5;
|
||||||
break;
|
break;
|
||||||
@ -70,6 +88,7 @@ export class WebController {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
this.logger.debug(kbInfo.event);
|
this.logger.debug(kbInfo.event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {DiagramEntity, DiagramEntityType} from "../types/diagramEntity";
|
import {DiagramEntity, DiagramEntityType} from "../types/diagramEntity";
|
||||||
import {AbstractMesh, InstancedMesh, Mesh, Quaternion, Scene, Vector3} from "@babylonjs/core";
|
import {AbstractMesh, InstancedMesh, Mesh, Quaternion, Scene, Vector3} from "@babylonjs/core";
|
||||||
import {DiagramConnection} from "../diagramConnection";
|
import {DiagramConnection} from "../diagramConnection";
|
||||||
import {TextLabel} from "../../objects/textLabel";
|
import {updateTextNode} from "../../util/functions/updateTextNode";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial";
|
import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial";
|
||||||
@ -80,7 +80,7 @@ function mapMetadata(entity: DiagramEntity, newMesh: AbstractMesh, scene: Scene)
|
|||||||
}
|
}
|
||||||
if (entity.text) {
|
if (entity.text) {
|
||||||
newMesh.metadata.text = entity.text;
|
newMesh.metadata.text = entity.text;
|
||||||
TextLabel.updateTextNode(newMesh, entity.text);
|
updateTextNode(newMesh, entity.text);
|
||||||
}
|
}
|
||||||
if (entity.from) {
|
if (entity.from) {
|
||||||
newMesh.metadata.from = entity.from;
|
newMesh.metadata.from = entity.from;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import {DiagramEvent, DiagramEventType} from "../types/diagramEntity";
|
|||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {applyPhysics} from "./diagramShapePhysics";
|
import {applyPhysics} from "./diagramShapePhysics";
|
||||||
import {ActionManager, PhysicsMotionType, Scene} from "@babylonjs/core";
|
import {ActionManager, PhysicsMotionType, Scene} from "@babylonjs/core";
|
||||||
import {TextLabel} from "../../objects/textLabel";
|
import {updateTextNode} from "../../util/functions/updateTextNode";
|
||||||
import {Toolbox} from "../../toolbox/toolbox";
|
import {Toolbox} from "../../toolbox/toolbox";
|
||||||
import {DiaSounds} from "../../util/diaSounds";
|
import {DiaSounds} from "../../util/diaSounds";
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export function diagramEventHandler(event: DiagramEvent,
|
|||||||
break;
|
break;
|
||||||
case DiagramEventType.DROP:
|
case DiagramEventType.DROP:
|
||||||
if (isDiagramEntity(mesh) && (mesh.metadata.template.indexOf('#') > -1)) {
|
if (isDiagramEntity(mesh) && (mesh.metadata.template.indexOf('#') > -1)) {
|
||||||
TextLabel.updateTextNode(mesh, entity.text);
|
updateTextNode(mesh, entity.text);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DiagramEventType.ADD:
|
case DiagramEventType.ADD:
|
||||||
|
|||||||
@ -271,9 +271,8 @@ export class PouchdbPersistenceManager {
|
|||||||
|
|
||||||
private async beginSync(remoteDbName: string) {
|
private async beginSync(remoteDbName: string) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
//const remoteDbName = "db1";
|
//const remoteDbName = "db1";
|
||||||
const remoteUserName = "user1";
|
const remoteUserName = remoteDbName;
|
||||||
const password = "password";
|
const password = "password";
|
||||||
const dbs = await axios.get(import.meta.env.VITE_SYNCDB_ENDPOINT + '_all_dbs');
|
const dbs = await axios.get(import.meta.env.VITE_SYNCDB_ENDPOINT + '_all_dbs');
|
||||||
if (dbs.data.indexOf(remoteDbName) == -1) {
|
if (dbs.data.indexOf(remoteDbName) == -1) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import {DiagramEvent, DiagramEventType} from "../diagram/types/diagramEntity";
|
|||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {InputTextView} from "../information/inputTextView";
|
import {InputTextView} from "../information/inputTextView";
|
||||||
import {DiaSounds} from "../util/diaSounds";
|
import {DiaSounds} from "../util/diaSounds";
|
||||||
import {TextLabel} from "../objects/textLabel";
|
import {updateTextNode} from "../util/functions/updateTextNode";
|
||||||
import {DiagramConnection} from "../diagram/diagramConnection";
|
import {DiagramConnection} from "../diagram/diagramConnection";
|
||||||
|
|
||||||
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
|
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
|
||||||
@ -29,6 +29,7 @@ import {SoccerMenu} from "../soccer/soccerMenu";
|
|||||||
import {CameraMenu} from "./cameraMenu";
|
import {CameraMenu} from "./cameraMenu";
|
||||||
import {exportGltf} from "../util/functions/exportGltf";
|
import {exportGltf} from "../util/functions/exportGltf";
|
||||||
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
||||||
|
import {ScaleMenu} from "./scaleMenu";
|
||||||
|
|
||||||
export class EditMenu extends AbstractMenu {
|
export class EditMenu extends AbstractMenu {
|
||||||
private state: EditMenuState = EditMenuState.NONE;
|
private state: EditMenuState = EditMenuState.NONE;
|
||||||
@ -161,8 +162,10 @@ export class EditMenu extends AbstractMenu {
|
|||||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event, -1);
|
this.diagramManager.onDiagramEventObservable.notifyObservers(event, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private scaleMenu: ScaleMenu;
|
||||||
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
|
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
|
||||||
super(scene, xr, controllers);
|
super(scene, xr, controllers);
|
||||||
|
//this.scaleMenu = new ScaleMenu(this.scene, this.xr, this.controllers);
|
||||||
this.sounds = new DiaSounds(scene);
|
this.sounds = new DiaSounds(scene);
|
||||||
this.diagramManager = diagramManager;
|
this.diagramManager = diagramManager;
|
||||||
this.gizmoManager = new GizmoManager(scene);
|
this.gizmoManager = new GizmoManager(scene);
|
||||||
@ -177,16 +180,16 @@ export class EditMenu extends AbstractMenu {
|
|||||||
|
|
||||||
panel.columns = 4;
|
panel.columns = 4;
|
||||||
this.manager.addControl(panel);
|
this.manager.addControl(panel);
|
||||||
panel.addControl(this.makeButton("Cameras", "camera"));
|
//panel.addControl(this.makeButton("Cameras", "camera"));
|
||||||
panel.addControl(this.makeButton("Modify", "modify"));
|
//panel.addControl(this.makeButton("Modify", "modify"));
|
||||||
panel.addControl(this.makeButton("Remove", "remove"));
|
panel.addControl(this.makeButton("Remove", "remove"));
|
||||||
panel.addControl(this.makeButton("Add Label", "label"));
|
panel.addControl(this.makeButton("Label", "label"));
|
||||||
panel.addControl(this.makeButton("Copy", "copy"));
|
panel.addControl(this.makeButton("Copy", "copy"));
|
||||||
panel.addControl(this.makeButton("Connect", "connect"));
|
panel.addControl(this.makeButton("Connect", "connect"));
|
||||||
panel.addControl(this.makeButton("Export GLTF", "exportgltf"));
|
//panel.addControl(this.makeButton("Export GLTF", "exportgltf"));
|
||||||
panel.addControl(this.makeButton("Recolor", "recolor"));
|
//panel.addControl(this.makeButton("Recolor", "recolor"));
|
||||||
panel.addControl(this.makeButton("New Relic", "newrelic"));
|
//panel.addControl(this.makeButton("New Relic", "newrelic"));
|
||||||
panel.addControl(this.makeButton("Soccer", "soccer"));
|
//panel.addControl(this.makeButton("Soccer", "soccer"));
|
||||||
//panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
|
//panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
|
||||||
this.manager.controlScaling = .1;
|
this.manager.controlScaling = .1;
|
||||||
this.scene.onPointerObservable.add((pointerInfo) => {
|
this.scene.onPointerObservable.add((pointerInfo) => {
|
||||||
@ -240,7 +243,7 @@ export class EditMenu extends AbstractMenu {
|
|||||||
textInput.show();
|
textInput.show();
|
||||||
textInput.onTextObservable.addOnce((value) => {
|
textInput.onTextObservable.addOnce((value) => {
|
||||||
this.persist(mesh, value.text);
|
this.persist(mesh, value.text);
|
||||||
TextLabel.updateTextNode(mesh, value.text);
|
updateTextNode(mesh, value.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -267,19 +270,7 @@ export class EditMenu extends AbstractMenu {
|
|||||||
private modifyMesh(mesh: AbstractMesh) {
|
private modifyMesh(mesh: AbstractMesh) {
|
||||||
if (isDiagramEntity(mesh) &&
|
if (isDiagramEntity(mesh) &&
|
||||||
mesh.parent?.parent?.id != "toolbox") {
|
mesh.parent?.parent?.id != "toolbox") {
|
||||||
if (this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh?.id == mesh.id) {
|
this.scaleMenu.changeMesh(mesh);
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh = null;
|
|
||||||
} else {
|
|
||||||
this.gizmoManager.attachToMesh(mesh);
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.onScaleBoxDragObservable.add(() => {
|
|
||||||
this.diagramManager.onDiagramEventObservable.notifyObservers({
|
|
||||||
type: DiagramEventType.MODIFY,
|
|
||||||
entity: toDiagramEntity(mesh),
|
|
||||||
}, -1
|
|
||||||
)
|
|
||||||
this.logger.debug(mesh.scaling);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
108
src/menus/scaleMenu.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import {AbstractMesh, Scene, TransformNode, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
|
||||||
|
|
||||||
|
import {Controllers} from "../controllers/controllers";
|
||||||
|
import {DiaSounds} from "../util/diaSounds";
|
||||||
|
import {AbstractMenu} from "./abstractMenu";
|
||||||
|
|
||||||
|
import {GUI3DManager, Slider3D} from "@babylonjs/gui";
|
||||||
|
|
||||||
|
export class ScaleMenu extends AbstractMenu {
|
||||||
|
private sounds: DiaSounds;
|
||||||
|
private mesh: AbstractMesh;
|
||||||
|
private xSlider: Slider3D;
|
||||||
|
private ySlider: Slider3D;
|
||||||
|
private zSlider: Slider3D;
|
||||||
|
private transformNode: TransformNode;
|
||||||
|
private xTransformNode: TransformNode;
|
||||||
|
private yTransformNode: TransformNode;
|
||||||
|
private zTransformNode: TransformNode;
|
||||||
|
|
||||||
|
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
|
||||||
|
super(scene, xr, controllers);
|
||||||
|
|
||||||
|
this.sounds = new DiaSounds(scene);
|
||||||
|
this.transformNode = new TransformNode("scaleMenu", scene);
|
||||||
|
this.xTransformNode = new TransformNode("xTransformNode", scene);
|
||||||
|
this.xTransformNode.parent = this.transformNode;
|
||||||
|
|
||||||
|
this.yTransformNode = new TransformNode("yTransformNode", scene);
|
||||||
|
this.yTransformNode.parent = this.transformNode;
|
||||||
|
|
||||||
|
this.zTransformNode = new TransformNode("zTransformNode", scene);
|
||||||
|
this.zTransformNode.parent = this.transformNode;
|
||||||
|
|
||||||
|
//super.createHandle(this.transformNode);
|
||||||
|
this.transformNode.position.y = 0;
|
||||||
|
this.transformNode.position.z = 0;
|
||||||
|
this.transformNode.position.x = 0;
|
||||||
|
|
||||||
|
this.buildMenu();
|
||||||
|
|
||||||
|
//this.transformNode.position.y = 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeMesh(mesh: AbstractMesh) {
|
||||||
|
this.mesh = mesh;
|
||||||
|
this.xSlider.value = mesh.scaling.x;
|
||||||
|
this.ySlider.value = mesh.scaling.y;
|
||||||
|
this.zSlider.value = mesh.scaling.z;
|
||||||
|
|
||||||
|
const two = new Vector3(2, 2, 2);
|
||||||
|
this.transformNode.position = this.mesh.absolutePosition.clone();
|
||||||
|
this.transformNode.rotation = this.mesh.absoluteRotationQuaternion.toEulerAngles();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildMenu() {
|
||||||
|
const manager = new GUI3DManager(this.scene);
|
||||||
|
//manager.rootContainer.position.y = 2;
|
||||||
|
//manager.rootContainer.node.position.y = 2;
|
||||||
|
this.xSlider = new Slider3D("xslider");
|
||||||
|
this.ySlider = new Slider3D("xslider");
|
||||||
|
this.zSlider = new Slider3D("xslider");
|
||||||
|
|
||||||
|
manager.addControl(this.xSlider);
|
||||||
|
manager.addControl(this.ySlider);
|
||||||
|
manager.addControl(this.zSlider);
|
||||||
|
this.xSlider.linkToTransformNode(this.xTransformNode);
|
||||||
|
this.ySlider.linkToTransformNode(this.yTransformNode);
|
||||||
|
this.zSlider.linkToTransformNode(this.zTransformNode);
|
||||||
|
|
||||||
|
this.xTransformNode.position = new Vector3(0, 0, .6);
|
||||||
|
this.xTransformNode.rotation.y = Math.PI;
|
||||||
|
this.yTransformNode.position = new Vector3(.6, .6, .6);
|
||||||
|
this.yTransformNode.rotation.z = Math.PI / 2;
|
||||||
|
this.zTransformNode.position = new Vector3(.6, .6, 0);
|
||||||
|
this.zTransformNode.rotation.y = Math.PI / 2;
|
||||||
|
setValues(this.xSlider);
|
||||||
|
setValues(this.ySlider);
|
||||||
|
setValues(this.zSlider);
|
||||||
|
this.xSlider.onValueChangedObservable.add((value) => {
|
||||||
|
if (this.mesh) {
|
||||||
|
this.mesh.scaling.x = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.ySlider.onValueChangedObservable.add((value) => {
|
||||||
|
if (this.mesh) {
|
||||||
|
this.mesh.scaling.y = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.zSlider.onValueChangedObservable.add((value) => {
|
||||||
|
if (this.mesh) {
|
||||||
|
this.mesh.scaling.z = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.transformNode.scaling.x = .5;
|
||||||
|
this.transformNode.scaling.y = .5;
|
||||||
|
this.transformNode.scaling.z = .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setValues(slider: Slider3D) {
|
||||||
|
slider.minimum = .1;
|
||||||
|
slider.maximum = 1;
|
||||||
|
slider.step = .1;
|
||||||
|
slider.value = .1;
|
||||||
|
}
|
||||||
@ -1,75 +0,0 @@
|
|||||||
import {AbstractMesh, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core";
|
|
||||||
import log from "loglevel";
|
|
||||||
|
|
||||||
export class TextLabel {
|
|
||||||
private static logger: log.Logger = log.getLogger('TextLabel');
|
|
||||||
|
|
||||||
public static updateTextNode(mesh: AbstractMesh, text: string) {
|
|
||||||
if (!mesh) {
|
|
||||||
this.logger.error("updateTextNode: mesh is null");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const textNodes = mesh.getChildren((node) => {
|
|
||||||
return node.metadata?.label == true;
|
|
||||||
});
|
|
||||||
if (textNodes && textNodes.length > 0) {
|
|
||||||
textNodes.forEach((node) => {
|
|
||||||
node.dispose(false, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set font
|
|
||||||
const height = 0.05;
|
|
||||||
const font_size = 24;
|
|
||||||
const font = "bold " + font_size + "px Arial";
|
|
||||||
//Set height for dynamic texture
|
|
||||||
const DTHeight = 1.5 * font_size; //or set as wished
|
|
||||||
//Calc Ratio
|
|
||||||
const ratio = height / DTHeight;
|
|
||||||
|
|
||||||
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
|
|
||||||
const temp = new DynamicTexture("DynamicTexture", 32, mesh.getScene());
|
|
||||||
const tmpctx = temp.getContext();
|
|
||||||
tmpctx.font = font;
|
|
||||||
const DTWidth = tmpctx.measureText(text).width + 8;
|
|
||||||
|
|
||||||
//Calculate width the plane has to be
|
|
||||||
const planeWidth = DTWidth * ratio;
|
|
||||||
|
|
||||||
//Create dynamic texture and write the text
|
|
||||||
const dynamicTexture = new DynamicTexture("DynamicTexture", {
|
|
||||||
width: DTWidth,
|
|
||||||
height: DTHeight
|
|
||||||
}, mesh.getScene(), false);
|
|
||||||
const mat = new StandardMaterial("mat", mesh.getScene());
|
|
||||||
mat.diffuseTexture = dynamicTexture;
|
|
||||||
//mat.emissiveColor = Color3.White();
|
|
||||||
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true);
|
|
||||||
//Create plane and set dynamic texture as material
|
|
||||||
//const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
|
||||||
const plane1 = this.createPlane(mat, mesh, text, planeWidth, height);
|
|
||||||
const plane2 = this.createPlane(mat, mesh, text, planeWidth, height);
|
|
||||||
plane2.rotation.y = Math.PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
|
|
||||||
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
|
||||||
|
|
||||||
plane.material = mat;
|
|
||||||
//plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
|
||||||
plane.metadata = {exportable: true, label: true};
|
|
||||||
|
|
||||||
const yOffset = mesh.getBoundingInfo().boundingSphere.maximum.y;
|
|
||||||
plane.parent = mesh;
|
|
||||||
|
|
||||||
plane.scaling.y = (1 / mesh.scaling.y);
|
|
||||||
plane.scaling.x = (1 / mesh.scaling.x);
|
|
||||||
plane.scaling.z = (1 / mesh.scaling.z);
|
|
||||||
plane.position.y = yOffset + (height * plane.scaling.y);
|
|
||||||
return plane;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -45,7 +45,7 @@ export class Ball {
|
|||||||
|
|
||||||
private buildBall() {
|
private buildBall() {
|
||||||
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
|
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
|
||||||
(meshes, particleSystems, skeletons, animationGroups) => {
|
(meshes) => {
|
||||||
this.logger.debug('ball loaded');
|
this.logger.debug('ball loaded');
|
||||||
this.mesh = meshes[0];
|
this.mesh = meshes[0];
|
||||||
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
|
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
|
||||||
|
|||||||
@ -11,6 +11,10 @@ export function buildColor(color: Color3, scene: Scene, parent: TransformNode, i
|
|||||||
//const material = new PBRMaterial("material-" + color.toHexString(), scene);
|
//const material = new PBRMaterial("material-" + color.toHexString(), scene);
|
||||||
const material = new StandardMaterial("material-" + color.toHexString(), scene);
|
const material = new StandardMaterial("material-" + color.toHexString(), scene);
|
||||||
material.diffuseColor = color;
|
material.diffuseColor = color;
|
||||||
|
material.roughness = 1;
|
||||||
|
material.specularPower = 1;
|
||||||
|
//material.emissiveColor = color;
|
||||||
|
|
||||||
//const material = new StandardMaterial("material-" + color.toHexString(), scene);
|
//const material = new StandardMaterial("material-" + color.toHexString(), scene);
|
||||||
//material.albedoColor = color;
|
//material.albedoColor = color;
|
||||||
//material.metallic = 1;
|
//material.metallic = 1;
|
||||||
|
|||||||
@ -7,16 +7,19 @@ export function buildMesh(type: ToolType, toolname: string, scene: Scene): Mesh
|
|||||||
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1}, scene);
|
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1}, scene);
|
||||||
|
|
||||||
case ToolType.SPHERE:
|
case ToolType.SPHERE:
|
||||||
return MeshBuilder.CreateSphere(toolname, {diameter: 1}, scene);
|
return MeshBuilder.CreateIcoSphere(toolname, {subdivisions: 5, radius: .5}, scene);
|
||||||
|
//return MeshBuilder.CreateSphere(toolname, {diameter: 1}, scene);
|
||||||
|
|
||||||
case ToolType.CYLINDER:
|
case ToolType.CYLINDER:
|
||||||
return MeshBuilder.CreateCylinder(toolname, {height: 1, diameter: 1}, scene);
|
return MeshBuilder.CreateCylinder(toolname, {height: 1, diameter: 1, subdivisions: 1, tessellation: 12}, scene);
|
||||||
|
|
||||||
case ToolType.CONE:
|
case ToolType.CONE:
|
||||||
return MeshBuilder.CreateCylinder(toolname, {
|
return MeshBuilder.CreateCylinder(toolname, {
|
||||||
diameterTop: 0,
|
diameterTop: 0,
|
||||||
|
subdivisions: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
diameterBottom: 1
|
diameterBottom: 1,
|
||||||
|
tessellation: 12
|
||||||
}, scene);
|
}, scene);
|
||||||
|
|
||||||
case ToolType.PLANE:
|
case ToolType.PLANE:
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import {AppConfig} from "../util/appConfig";
|
|||||||
import Hls from "hls.js";
|
import Hls from "hls.js";
|
||||||
import log, {Logger} from "loglevel";
|
import log, {Logger} from "loglevel";
|
||||||
|
|
||||||
|
|
||||||
export class Introduction {
|
export class Introduction {
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private manager: GUI3DManager;
|
private manager: GUI3DManager;
|
||||||
|
|||||||
24
src/tutorial/tutorial.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {AppConfig} from "../util/appConfig";
|
||||||
|
import {Scene} from "@babylonjs/core";
|
||||||
|
|
||||||
|
export class Tutorial {
|
||||||
|
private scene: Scene;
|
||||||
|
private config: AppConfig;
|
||||||
|
|
||||||
|
constructor(scene: Scene, config: AppConfig) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.config = config;
|
||||||
|
const advance = document.querySelector('#advanceLink');
|
||||||
|
if (advance) {
|
||||||
|
advance.addEventListener('click', () => {
|
||||||
|
this.advance();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Tutorial');
|
||||||
|
}
|
||||||
|
|
||||||
|
private advance() {
|
||||||
|
window.alert('here');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
Color3,
|
||||||
GroundMesh,
|
GroundMesh,
|
||||||
HemisphericLight,
|
HemisphericLight,
|
||||||
|
Material,
|
||||||
MeshBuilder,
|
MeshBuilder,
|
||||||
Observable,
|
Observable,
|
||||||
PBRMaterial,
|
PBRMaterial,
|
||||||
PhotoDome,
|
|
||||||
PhysicsAggregate,
|
PhysicsAggregate,
|
||||||
PhysicsShapeType,
|
PhysicsShapeType,
|
||||||
|
PointsCloudSystem,
|
||||||
Scene,
|
Scene,
|
||||||
Sound,
|
Sound,
|
||||||
Texture,
|
Texture,
|
||||||
|
TransformNode,
|
||||||
Vector3
|
Vector3
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
import {CustomPhysics} from "./customPhysics";
|
import {CustomPhysics} from "./customPhysics";
|
||||||
import {DiaSounds} from "./diaSounds";
|
import {DiaSounds} from "./diaSounds";
|
||||||
import {AppConfig} from "./appConfig";
|
import {AppConfig} from "./appConfig";
|
||||||
|
import {GridMaterial} from "@babylonjs/materials";
|
||||||
|
|
||||||
|
|
||||||
export class CustomEnvironment {
|
export class CustomEnvironment {
|
||||||
@ -25,8 +29,13 @@ export class CustomEnvironment {
|
|||||||
constructor(scene: Scene, name: string = "default", config: AppConfig) {
|
constructor(scene: Scene, name: string = "default", config: AppConfig) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
new HemisphericLight("light1", new Vector3(1, 1, 0), scene);
|
const loading = document.querySelector('#loadingGrid');
|
||||||
new HemisphericLight("light2", new Vector3(-1, 1, 0), scene);
|
if (loading) {
|
||||||
|
loading.remove();
|
||||||
|
}
|
||||||
|
const light = new HemisphericLight("light1", new Vector3(.1, 1, 0), scene);
|
||||||
|
light.groundColor = new Color3(.1, .1, .1)
|
||||||
|
light.intensity = .6;
|
||||||
|
|
||||||
const physics = new CustomPhysics(this.scene, config);
|
const physics = new CustomPhysics(this.scene, config);
|
||||||
physics
|
physics
|
||||||
@ -35,15 +44,11 @@ export class CustomEnvironment {
|
|||||||
const ground = this.createGround();
|
const ground = this.createGround();
|
||||||
this._groundMeshObservable.notifyObservers(ground);
|
this._groundMeshObservable.notifyObservers(ground);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private initSounds() {
|
||||||
const photo = new PhotoDome('sky',
|
|
||||||
'/assets/textures/outdoor_field4.jpeg', {},
|
|
||||||
scene);
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sounds = new DiaSounds(scene);
|
const sounds = new DiaSounds(this.scene);
|
||||||
window.setTimeout((sound) => {
|
window.setTimeout((sound) => {
|
||||||
sound.play()
|
sound.play()
|
||||||
}, 2000, sounds.background);
|
}, 2000, sounds.background);
|
||||||
@ -72,38 +77,104 @@ export class CustomEnvironment {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get groundMeshObservable() {
|
public get groundMeshObservable() {
|
||||||
return this._groundMeshObservable;
|
return this._groundMeshObservable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createGround() {
|
private createGround() {
|
||||||
const scene = this.scene;
|
const scene = this.scene;
|
||||||
const groundMaterial = new PBRMaterial("groundMaterial", scene);
|
|
||||||
const gText = new Texture("/assets/textures/grass1.jpeg", scene);
|
|
||||||
gText.uScale = 30;
|
|
||||||
gText.vScale = 30;
|
|
||||||
groundMaterial.albedoTexture = gText;
|
|
||||||
groundMaterial.metallic = 0;
|
|
||||||
groundMaterial.roughness = 1;
|
|
||||||
const grassBump = new Texture("/assets/textures/grassnormal.png", scene);
|
|
||||||
grassBump.uScale = 20;
|
|
||||||
grassBump.vScale = 20;
|
|
||||||
groundMaterial.bumpTexture =
|
|
||||||
grassBump;
|
|
||||||
|
|
||||||
const ground: GroundMesh = MeshBuilder.CreateGround("ground", {
|
const ground: GroundMesh = MeshBuilder.CreateGround("ground", {
|
||||||
width: 100,
|
width: 20,
|
||||||
height: 100,
|
height: 20,
|
||||||
subdivisions: 1
|
subdivisions: 1
|
||||||
}, scene);
|
}, scene);
|
||||||
|
createPoints(scene, 20, 20);
|
||||||
|
ground.material = createGridMaterial(scene, Color3.FromHexString("#aaffaa"), Color3.FromHexString("#111511"));
|
||||||
|
const color1 = Color3.FromHexString("#ff9999");
|
||||||
|
const color2 = Color3.FromHexString("#221111");
|
||||||
|
const color3 = Color3.FromHexString("#9999ff");
|
||||||
|
const color4 = Color3.FromHexString("#111115");
|
||||||
|
|
||||||
|
|
||||||
|
this.createWall(new Vector3(0, 10, 10), new Vector3(0, 0, 0), color3, color4);
|
||||||
|
this.createWall(new Vector3(0, 10, -10), new Vector3(0, Math.PI, 0), color3, color4);
|
||||||
|
this.createWall(new Vector3(10, 10, 0), new Vector3(0, Math.PI / 2, 0), color1, color2);
|
||||||
|
this.createWall(new Vector3(-10, 10, 0), new Vector3(0, -Math.PI / 2, 0), color1, color2);
|
||||||
|
|
||||||
ground.material = groundMaterial;
|
|
||||||
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, scene);
|
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, scene);
|
||||||
//buildAvatar(scene);
|
//buildAvatar(scene);
|
||||||
return ground;
|
return ground;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createWall(position: Vector3, rotation: Vector3, color1: Color3, color2: Color3) {
|
||||||
|
const scene = this.scene;
|
||||||
|
const wall = MeshBuilder.CreatePlane("wall", {width: 20, height: 20}, scene);
|
||||||
|
wall.position = position;
|
||||||
|
wall.rotation = rotation;
|
||||||
|
wall.material = createGridMaterial(scene, color1, color2);
|
||||||
|
return wall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPoints(scene: Scene, divisions: number = 10, scale: number = 80) {
|
||||||
|
const half = .5;
|
||||||
|
const increment = 1 / divisions;
|
||||||
|
let x = -half;
|
||||||
|
let y = -half;
|
||||||
|
let z = -half;
|
||||||
|
const baseTransform = new TransformNode("baseTransform", scene);
|
||||||
|
baseTransform.scaling = new Vector3(scale, scale, scale);
|
||||||
|
baseTransform.position = new Vector3(0, scale / 2, 0);
|
||||||
|
const pcs = new PointsCloudSystem("pcs", 1, scene);
|
||||||
|
|
||||||
|
pcs.addPoints((divisions + 1) ** 3, function (particle) {
|
||||||
|
particle.position.x = x;
|
||||||
|
particle.position.y = y;
|
||||||
|
particle.position.z = z;
|
||||||
|
|
||||||
|
x += increment;
|
||||||
|
if (x > half) {
|
||||||
|
x = -half
|
||||||
|
y += increment;
|
||||||
|
if (y > half) {
|
||||||
|
y = -half;
|
||||||
|
z += increment;
|
||||||
|
if (z > half) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const mesh = await pcs.buildMeshAsync();
|
||||||
|
mesh.visibility = .5;
|
||||||
|
mesh.parent = baseTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createGridMaterial(scene: Scene, lineColor: Color3, mainColor: Color3): Material {
|
||||||
|
const material = new GridMaterial("gridMaterial", scene);
|
||||||
|
material.minorUnitVisibility = .1;
|
||||||
|
material.gridRatio = .1;
|
||||||
|
material.majorUnitFrequency = 10;
|
||||||
|
material.mainColor = mainColor;
|
||||||
|
material.lineColor = lineColor;
|
||||||
|
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createGrassGround(scene: Scene): Material {
|
||||||
|
const groundMaterial = new PBRMaterial("groundMaterial", scene);
|
||||||
|
const gText = new Texture("/assets/textures/grass1.jpeg", scene);
|
||||||
|
gText.uScale = 10;
|
||||||
|
gText.vScale = 10;
|
||||||
|
groundMaterial.albedoTexture = gText;
|
||||||
|
groundMaterial.metallic = 0;
|
||||||
|
groundMaterial.roughness = 1;
|
||||||
|
const grassBump = new Texture("/assets/textures/grassnormal.png", scene);
|
||||||
|
grassBump.uScale = 20;
|
||||||
|
grassBump.vScale = 20;
|
||||||
|
groundMaterial.bumpTexture =
|
||||||
|
grassBump;
|
||||||
|
return groundMaterial;
|
||||||
}
|
}
|
||||||
@ -11,6 +11,9 @@ export function buildQuestLink() {
|
|||||||
a.target = "_blank";
|
a.target = "_blank";
|
||||||
a.innerText = "Launch On Quest";
|
a.innerText = "Launch On Quest";
|
||||||
div.appendChild(a);
|
div.appendChild(a);
|
||||||
document.body.appendChild(div);
|
const main = document.querySelector('#main');
|
||||||
|
if (main) {
|
||||||
|
//main.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
69
src/util/functions/createCloset.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import {
|
||||||
|
AssetContainer,
|
||||||
|
Color3,
|
||||||
|
Mesh,
|
||||||
|
MeshBuilder,
|
||||||
|
Scalar,
|
||||||
|
Scene,
|
||||||
|
SceneLoader,
|
||||||
|
SpotLight,
|
||||||
|
StandardMaterial,
|
||||||
|
Vector3
|
||||||
|
} from "@babylonjs/core";
|
||||||
|
|
||||||
|
|
||||||
|
export function createCloset(scene: Scene) {
|
||||||
|
const width = 1.8;
|
||||||
|
const height = 2.4;
|
||||||
|
const material = new StandardMaterial("closet", scene);
|
||||||
|
material.maxSimultaneousLights = 10;
|
||||||
|
material.diffuseColor = Color3.FromHexString("#ffffee");
|
||||||
|
const back = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: width, height: height}, scene);
|
||||||
|
back.position.z = -.9 / 2;
|
||||||
|
back.material = material;
|
||||||
|
back.position.y = height / 2;
|
||||||
|
const left = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: .9, height: height}, scene);
|
||||||
|
const left2 = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: .15, height: height}, scene);
|
||||||
|
left2.position.z = .9 / 2;
|
||||||
|
left2.position.x = -width / 2 + .15 / 2;
|
||||||
|
left2.position.y = height / 2;
|
||||||
|
left.material = material;
|
||||||
|
left2.material = material;
|
||||||
|
const right = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: .9, height: height}, scene);
|
||||||
|
const right2 = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: .15, height: height}, scene);
|
||||||
|
right2.position.x = width / 2 - .15 / 2;
|
||||||
|
right2.position.y = height / 2;
|
||||||
|
right2.position.z = .9 / 2;
|
||||||
|
right2.material = material
|
||||||
|
right.material = material;
|
||||||
|
left.position.y = height / 2;
|
||||||
|
right.position.y = height / 2;
|
||||||
|
left.position.x = width / 2;
|
||||||
|
right.position.x = -width / 2;
|
||||||
|
left.rotation.y = Math.PI / 2;
|
||||||
|
right.rotation.y = Math.PI / 2;
|
||||||
|
const front = MeshBuilder.CreatePlane("back", {sideOrientation: Mesh.DOUBLESIDE, width: width - .3, height: .35}, scene);
|
||||||
|
front.material = material;
|
||||||
|
front.position.y = height - .35 / 2;
|
||||||
|
front.position.z = .9 / 2;
|
||||||
|
const width2 = width * .9;
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
const l = Scalar.Lerp(-width2 / 2, width2 / 2, (width / 5) * i);
|
||||||
|
const light = new SpotLight("light", new Vector3(l, 2, (.9 / 2) - .01),
|
||||||
|
new Vector3(0, 0, -1), Math.PI / 1.5, 5, scene);
|
||||||
|
light.intensity = .3;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneLoader.LoadAssetContainer("/assets/textures/washer/LG Trom Wash Tower Object Collection_2color/LG Trom Wash Tower_white/", "LG Trom Wash.gltf", scene,
|
||||||
|
(container: AssetContainer) => {
|
||||||
|
const model = container.instantiateModelsToScene(undefined, false, {doNotInstantiate: true});
|
||||||
|
const node = model.rootNodes[0];
|
||||||
|
node.scaling.scaleInPlace(.00098);
|
||||||
|
node.position.x -= .42;
|
||||||
|
const bounds = node.getHierarchyBoundingVectors(true);
|
||||||
|
console.log((bounds.max.x - bounds.min.x) * 39.37);
|
||||||
|
console.log('here');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -20,6 +20,9 @@ export async function groundMeshObserver(ground, scene, diagramManager, controll
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
xr.baseExperience.onInitialXRPoseSetObservable.add((camera) => {
|
||||||
|
//camera.position = new Vector3(0, -1.6, 0);
|
||||||
|
});
|
||||||
|
|
||||||
if (spinner) {
|
if (spinner) {
|
||||||
spinner.hide();
|
spinner.hide();
|
||||||
@ -30,17 +33,23 @@ export async function groundMeshObserver(ground, scene, diagramManager, controll
|
|||||||
this.logger.debug(ev);
|
this.logger.debug(ev);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
xr.baseExperience.onStateChangedObservable.add((state) => {
|
xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||||
if (state == WebXRState.IN_XR) {
|
switch (state) {
|
||||||
scene.audioEnabled = true;
|
case WebXRState.IN_XR:
|
||||||
//xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
scene.audioEnabled = true;
|
||||||
//xr.baseExperience.camera.setTarget(new Vector3(0, 1.6, 3));
|
|
||||||
window.addEventListener(('pa-button-state-change'), (event: any) => {
|
//xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
||||||
if (event.detail) {
|
//xr.baseExperience.camera.setTarget(new Vector3(0, 1.6, 3));
|
||||||
log.debug('App', event.detail);
|
window.addEventListener(('pa-button-state-change'), (event: any) => {
|
||||||
}
|
if (event.detail) {
|
||||||
});
|
log.debug('App', event.detail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
import('../../controllers/rigplatform').then((rigmodule) => {
|
import('../../controllers/rigplatform').then((rigmodule) => {
|
||||||
const rig = new rigmodule.Rigplatform(scene, xr, diagramManager, controllers);
|
const rig = new rigmodule.Rigplatform(scene, xr, diagramManager, controllers);
|
||||||
@ -58,8 +67,6 @@ export async function groundMeshObserver(ground, scene, diagramManager, controll
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const config = new ConfigMenu(scene, xr, controllers, diagramManager.config);
|
const config = new ConfigMenu(scene, xr, controllers, diagramManager.config);
|
||||||
|
|
||||||
|
|
||||||
const webController = new WebController(scene, rig, diagramManager, controllers);
|
const webController = new WebController(scene, rig, diagramManager, controllers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
74
src/util/functions/updateTextNode.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import {AbstractMesh, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core";
|
||||||
|
import log from "loglevel";
|
||||||
|
|
||||||
|
|
||||||
|
const textLogger: log.Logger = log.getLogger('TextLabel');
|
||||||
|
|
||||||
|
export function updateTextNode(mesh: AbstractMesh, text: string) {
|
||||||
|
if (!mesh) {
|
||||||
|
textLogger.error("updateTextNode: mesh is null");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const textNodes = mesh.getChildren((node) => {
|
||||||
|
return node.metadata?.label == true;
|
||||||
|
});
|
||||||
|
if (textNodes && textNodes.length > 0) {
|
||||||
|
textNodes.forEach((node) => {
|
||||||
|
node.dispose(false, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set font
|
||||||
|
const height = 0.05;
|
||||||
|
const font_size = 24;
|
||||||
|
const font = "bold " + font_size + "px Arial";
|
||||||
|
//Set height for dynamic texture
|
||||||
|
const DTHeight = 1.5 * font_size; //or set as wished
|
||||||
|
//Calc Ratio
|
||||||
|
const ratio = height / DTHeight;
|
||||||
|
|
||||||
|
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
|
||||||
|
const temp = new DynamicTexture("DynamicTexture", 32, mesh.getScene());
|
||||||
|
const tmpctx = temp.getContext();
|
||||||
|
tmpctx.font = font;
|
||||||
|
const DTWidth = tmpctx.measureText(text).width + 8;
|
||||||
|
|
||||||
|
//Calculate width the plane has to be
|
||||||
|
const planeWidth = DTWidth * ratio;
|
||||||
|
|
||||||
|
//Create dynamic texture and write the text
|
||||||
|
const dynamicTexture = new DynamicTexture("DynamicTexture", {
|
||||||
|
width: DTWidth,
|
||||||
|
height: DTHeight
|
||||||
|
}, mesh.getScene(), false);
|
||||||
|
const mat = new StandardMaterial("mat", mesh.getScene());
|
||||||
|
mat.diffuseTexture = dynamicTexture;
|
||||||
|
//mat.emissiveColor = Color3.White();
|
||||||
|
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true);
|
||||||
|
//Create plane and set dynamic texture as material
|
||||||
|
//const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
||||||
|
const plane1 = createPlane(mat, mesh, text, planeWidth, height);
|
||||||
|
const plane2 = createPlane(mat, mesh, text, planeWidth, height);
|
||||||
|
plane2.rotation.y = Math.PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
|
||||||
|
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
|
||||||
|
|
||||||
|
plane.material = mat;
|
||||||
|
//plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||||
|
plane.metadata = {exportable: true, label: true};
|
||||||
|
|
||||||
|
const yOffset = mesh.getBoundingInfo().boundingSphere.maximum.y;
|
||||||
|
plane.parent = mesh;
|
||||||
|
|
||||||
|
plane.scaling.y = (1 / mesh.scaling.y);
|
||||||
|
plane.scaling.x = (1 / mesh.scaling.x);
|
||||||
|
plane.scaling.z = (1 / mesh.scaling.z);
|
||||||
|
plane.position.y = yOffset + (height * plane.scaling.y);
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
@ -19,7 +19,6 @@ export class Spinner {
|
|||||||
constructor(scene: Scene) {
|
constructor(scene: Scene) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.build();
|
this.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public show() {
|
public show() {
|
||||||
@ -33,7 +32,7 @@ export class Spinner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private build() {
|
private build() {
|
||||||
const spinner: AbstractMesh = MeshBuilder.CreateSphere("spinner", {diameter: 1}, this.scene);
|
const spinner: AbstractMesh = MeshBuilder.CreateSphere("spinner", {diameter: 2}, this.scene);
|
||||||
const material = new StandardMaterial("spinner", this.scene);
|
const material = new StandardMaterial("spinner", this.scene);
|
||||||
const text = new DynamicTexture("spinner", {width: 1024, height: 1024}, this.scene, false);
|
const text = new DynamicTexture("spinner", {width: 1024, height: 1024}, this.scene, false);
|
||||||
text.drawText("Please Wait", 250, 500, "bold 150px Segoe UI", "white", "transparent", true, true);
|
text.drawText("Please Wait", 250, 500, "bold 150px Segoe UI", "white", "transparent", true, true);
|
||||||
@ -82,6 +81,8 @@ export class Spinner {
|
|||||||
particleSystem.emitter = spinner;
|
particleSystem.emitter = spinner;
|
||||||
particleSystem.parent = spinner;
|
particleSystem.parent = spinner;
|
||||||
spinner.position.y = 1;
|
spinner.position.y = 1;
|
||||||
|
spinner.position.z = 6;
|
||||||
|
|
||||||
this.spinner = spinner;
|
this.spinner = spinner;
|
||||||
this.spinner.setEnabled(false);
|
this.spinner.setEnabled(false);
|
||||||
this.particleSystem = particleSystem;
|
this.particleSystem = particleSystem;
|
||||||
|
|||||||
26
src/vrApp.ts
@ -12,9 +12,10 @@ import {PouchdbPersistenceManager} from "./integration/pouchdbPersistenceManager
|
|||||||
import {addSceneInspector} from "./util/functions/sceneInspctor";
|
import {addSceneInspector} from "./util/functions/sceneInspctor";
|
||||||
import {groundMeshObserver} from "./util/functions/groundMeshObserver";
|
import {groundMeshObserver} from "./util/functions/groundMeshObserver";
|
||||||
import {MainMenu} from "./menus/mainMenu";
|
import {MainMenu} from "./menus/mainMenu";
|
||||||
import {Introduction} from "./tutorial/introduction";
|
|
||||||
import {buildQuestLink} from "./util/functions/buildQuestLink";
|
import {buildQuestLink} from "./util/functions/buildQuestLink";
|
||||||
import {exportGltf} from "./util/functions/exportGltf";
|
import {exportGltf} from "./util/functions/exportGltf";
|
||||||
|
import {Tutorial} from "./tutorial/tutorial";
|
||||||
|
|
||||||
|
|
||||||
export class VrApp {
|
export class VrApp {
|
||||||
private scene: Scene;
|
private scene: Scene;
|
||||||
@ -23,16 +24,11 @@ export class VrApp {
|
|||||||
private logger: Logger = log.getLogger('App');
|
private logger: Logger = log.getLogger('App');
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
log.setDefaultLevel('warn');
|
log.setDefaultLevel('warn');
|
||||||
|
|
||||||
log.getLogger('App').setLevel('debug');
|
log.getLogger('App').setLevel('debug');
|
||||||
log.getLogger('DiagramManager').setLevel('debug');
|
log.getLogger('DiagramManager').setLevel('debug');
|
||||||
|
|
||||||
const canvas = document.querySelector('#gameCanvas');
|
const canvas = document.querySelector('#gameCanvas');
|
||||||
|
|
||||||
this.logger.debug('App', 'gameCanvas created');
|
this.logger.debug('App', 'gameCanvas created');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize(canvas: HTMLCanvasElement) {
|
public async initialize(canvas: HTMLCanvasElement) {
|
||||||
@ -46,6 +42,7 @@ export class VrApp {
|
|||||||
const spinner = new Spinner(scene);
|
const spinner = new Spinner(scene);
|
||||||
spinner.show();
|
spinner.show();
|
||||||
const config = new AppConfig();
|
const config = new AppConfig();
|
||||||
|
const tutorial = new Tutorial(scene, config);
|
||||||
const controllers = new Controllers();
|
const controllers = new Controllers();
|
||||||
const toolbox = new Toolbox(scene, controllers);
|
const toolbox = new Toolbox(scene, controllers);
|
||||||
const diagramManager = new DiagramManager(scene, controllers, toolbox, config);
|
const diagramManager = new DiagramManager(scene, controllers, toolbox, config);
|
||||||
@ -54,18 +51,16 @@ export class VrApp {
|
|||||||
db.setDiagramManager(diagramManager);
|
db.setDiagramManager(diagramManager);
|
||||||
db.configObserver.add((newConfig) => {
|
db.configObserver.add((newConfig) => {
|
||||||
if (!newConfig.demoCompleted) {
|
if (!newConfig.demoCompleted) {
|
||||||
const demo = new Introduction(scene, config);
|
const main = document.querySelector('#main');
|
||||||
|
} else {
|
||||||
|
const create = document.querySelector('#create');
|
||||||
}
|
}
|
||||||
config.onConfigChangedObservable.notifyObservers(newConfig, 1);
|
config.onConfigChangedObservable.notifyObservers(newConfig, 1);
|
||||||
});
|
});
|
||||||
config.onConfigChangedObservable.add((newConfig) => {
|
config.onConfigChangedObservable.add((newConfig) => {
|
||||||
db.setConfig(newConfig);
|
db.setConfig(newConfig);
|
||||||
}, 2, false, this);
|
}, 2, false, this);
|
||||||
|
|
||||||
|
|
||||||
await db.initialize();
|
await db.initialize();
|
||||||
|
|
||||||
|
|
||||||
const camera: FreeCamera = new FreeCamera("Main Camera",
|
const camera: FreeCamera = new FreeCamera("Main Camera",
|
||||||
new Vector3(0, 1.6, 0), scene);
|
new Vector3(0, 1.6, 0), scene);
|
||||||
//camera.setTarget(new Vector3(0, 1.6, -3));
|
//camera.setTarget(new Vector3(0, 1.6, -3));
|
||||||
@ -112,15 +107,6 @@ export class VrApp {
|
|||||||
exportGltf(scene);
|
exportGltf(scene);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
const base = new TransformNode("chart");
|
|
||||||
base.position.y = .25;
|
|
||||||
base.position.z = -5;
|
|
||||||
const chart = new Timeseries(base);
|
|
||||||
chart.setData(genData());
|
|
||||||
*/
|
|
||||||
//const newRelic = new NewRelicQuery(scene);
|
|
||||||
//newRelic.getSales();
|
|
||||||
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
|
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
|
||||||
let i = 0;
|
let i = 0;
|
||||||
this.engine.runRenderLoop(() => {
|
this.engine.runRenderLoop(() => {
|
||||||
|
|||||||