@needle-tools/engine 2.62.2-pre → 2.63.1-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/needle-engine.js +8191 -8013
  3. package/dist/needle-engine.umd.cjs +282 -199
  4. package/lib/engine/assets/index.d.ts +1 -0
  5. package/lib/engine/assets/index.js +4 -0
  6. package/lib/engine/assets/index.js.map +1 -0
  7. package/lib/engine/codegen/license.json +1 -0
  8. package/lib/engine/engine_element.js +1 -1
  9. package/lib/engine/engine_element.js.map +1 -1
  10. package/lib/engine/engine_element_loading.js +23 -4
  11. package/lib/engine/engine_element_loading.js.map +1 -1
  12. package/lib/engine/engine_license.d.ts +1 -0
  13. package/lib/engine/engine_license.js +210 -0
  14. package/lib/engine/engine_license.js.map +1 -0
  15. package/lib/engine/engine_physics.d.ts +3 -0
  16. package/lib/engine/engine_physics.js +13 -2
  17. package/lib/engine/engine_physics.js.map +1 -1
  18. package/lib/engine-components/Component.d.ts +4 -0
  19. package/lib/engine-components/Component.js +8 -0
  20. package/lib/engine-components/Component.js.map +1 -1
  21. package/lib/engine-components/ScreenCapture.d.ts +2 -2
  22. package/lib/engine-components/ScreenCapture.js +3 -1
  23. package/lib/engine-components/ScreenCapture.js.map +1 -1
  24. package/lib/engine-components/VideoPlayer.d.ts +2 -1
  25. package/lib/engine-components/VideoPlayer.js +9 -6
  26. package/lib/engine-components/VideoPlayer.js.map +1 -1
  27. package/lib/needle-engine.d.ts +1 -0
  28. package/lib/needle-engine.js +1 -0
  29. package/lib/needle-engine.js.map +1 -1
  30. package/lib/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +2 -2
  32. package/src/engine/assets/index.ts +4 -0
  33. package/src/engine/assets/logo.svg +1 -0
  34. package/src/engine/codegen/license.json +1 -0
  35. package/src/engine/engine_element.ts +1 -1
  36. package/src/engine/engine_element_loading.ts +28 -8
  37. package/src/engine/engine_license.ts +229 -0
  38. package/src/engine/engine_physics.ts +16 -2
  39. package/src/engine-components/Component.ts +8 -0
  40. package/src/engine-components/ScreenCapture.ts +3 -2
  41. package/src/engine-components/VideoPlayer.ts +10 -6
  42. package/src/needle-engine.ts +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "2.62.2-pre",
3
+ "version": "2.63.1-pre",
4
4
  "description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development, and can be deployed anywhere. It is flexible, extensible, and collaboration and XR come naturally.",
5
5
  "main": "dist/needle-engine.umd.cjs",
6
6
  "module": "dist/needle-engine.js",
@@ -60,7 +60,7 @@
60
60
  "@needle-tools/needle-component-compiler": "1.9.3",
61
61
  "@needle-tools/helper": "^0.2.1-pre",
62
62
  "@types/three": "0.146.0",
63
- "copy-files-from-to": "^3.3.0",
63
+ "copy-files-from-to": "^3.7.0",
64
64
  "esbuild": "^0.15.10",
65
65
  "esbuild-node-externals": "^1.5.0",
66
66
  "jsdoc-babel": "^0.5.0",
@@ -0,0 +1,4 @@
1
+
2
+ //@ts-ignore
3
+ import _logo from "./logo.svg"
4
+ export const logoSVG = _logo;
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="Ebene_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 160 187.74"><defs><style>.cls-1{fill:url(#Unbenannter_Verlauf_122);}.cls-2{fill:#f3e600;}.cls-3{fill:url(#Unbenannter_Verlauf_113);}.cls-4{fill:url(#gradient-6);}.cls-5{fill:url(#Unbenannter_Verlauf_110);}.cls-6{fill:url(#Unbenannter_Verlauf_101);}.cls-7{fill:#9c3;}.cls-8{fill:#ffe113;}.cls-9{fill:url(#gradient-5);}</style><linearGradient id="Unbenannter_Verlauf_113" x1="89.64" y1="184.81" x2="90.48" y2="21.85" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#62d399"/><stop offset=".51" stop-color="#acd842"/><stop offset=".9" stop-color="#d7db0a"/></linearGradient><linearGradient id="Unbenannter_Verlauf_110" x1="69.68" y1="178.9" x2="68.08" y2="16.77" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0ba398"/><stop offset=".5" stop-color="#4ca352"/><stop offset="1" stop-color="#76a30a"/></linearGradient><linearGradient id="Unbenannter_Verlauf_101" x1="36.6" y1="152.17" x2="34.7" y2="84.19" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset=".19" stop-color="#36a382"/><stop offset=".54" stop-color="#49a459"/><stop offset="1" stop-color="#76a30b"/></linearGradient><linearGradient id="Unbenannter_Verlauf_122" x1="15.82" y1="153.24" x2="18" y2="90.86" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#267880"/><stop offset=".51" stop-color="#457a5c"/><stop offset="1" stop-color="#717516"/></linearGradient><linearGradient id="gradient-6" x1="135.08" y1="135.43" x2="148.93" y2="63.47" gradientTransform="matrix(1, 0, 0, 1, 0, 0)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b0d939"/><stop offset="1" stop-color="#eadb04"/></linearGradient><linearGradient id="gradient-5" x1="-4163.25" y1="2285.12" x2="-4160.81" y2="2215.34" gradientTransform="translate(4801.15 -595.25) rotate(20)" gradientUnits="userSpaceOnUse"><stop offset=".17" stop-color="#74af52"/><stop offset=".48" stop-color="#99be32"/><stop offset="1" stop-color="#c0c40a"/></linearGradient><symbol id="needle-icon" viewBox="0 0 160 187.74"><g><polygon class="cls-3" points="79.32 36.98 79.32 187.74 95 174.54 101.59 18.23 79.32 36.98"/><polygon class="cls-5" points="79.32 36.98 57.05 18.23 63.64 174.54 79.32 187.74 79.32 36.98"/><polygon class="cls-6" points="25.19 104.83 33.82 153.87 46.32 138.92 43.86 82.5 25.19 104.83"/><polygon class="cls-1" points="25.19 104.83 0 90.24 16.97 144.1 33.82 153.87 25.19 104.83"/><polygon class="cls-7" points="43.86 82.5 18.69 67.98 0 90.24 25.18 104.83 43.86 82.5"/><polygon class="cls-4" points="134.82 78.69 124.85 135.19 140.43 126.15 160 64.1 134.82 78.69"/><polygon class="cls-9" points="134.82 78.69 116.14 56.36 113.28 121.36 124.85 135.19 134.82 78.69"/><polygon class="cls-8" points="160 64.1 141.31 41.84 116.14 56.36 134.81 78.69 160 64.1"/><polygon class="cls-2" points="101.59 18.23 79.32 0 57.05 18.23 79.32 36.98 101.59 18.23"/></g></symbol></defs><use width="160" height="187.74" xlink:href="#needle-icon"/></svg>
@@ -0,0 +1 @@
1
+ {}
@@ -214,7 +214,7 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
214
214
  }
215
215
  this._loadingProgress01 = 1;
216
216
  if (useDefaultLoading)
217
- this._loadingView?.onLoadingFinished("create scene");
217
+ this._loadingView?.onLoadingFinished("creating scene");
218
218
  this.classList.remove("loading");
219
219
  this.classList.add("loading-finished");
220
220
  if (debug)
@@ -2,6 +2,7 @@ import { showBalloonWarning } from "./api";
2
2
  import { Mathf } from "./engine_math";
3
3
  import { LoadingProgressArgs } from "./engine_setup";
4
4
  import { getParam } from "./engine_utils";
5
+ import { logoSVG } from "./assets"
5
6
 
6
7
  const debug = getParam("debugloadingbar");
7
8
  const debugRendering = getParam("debugloadingbarrendering");
@@ -64,13 +65,13 @@ export class EngineLoadingView implements ILoadingViewHandler {
64
65
  }
65
66
 
66
67
  onLoadingBegin(message?: string) {
67
- if(debug) console.log("Begin Loading")
68
+ if (debug) console.log("Begin Loading")
68
69
  if (!this._loadingElement) {
69
70
  for (let i = 0; i < this.container.children.length; i++) {
70
71
  const el = this.container.children[i] as HTMLElement;
71
72
  if (el.classList.contains(EngineLoadingView.LoadingContainerClassName)) {
72
73
  if (!this._allowCustomLoadingElement) {
73
- if(debug) console.warn("Remove custom loading container")
74
+ if (debug) console.warn("Remove custom loading container")
74
75
  this.container.removeChild(el);
75
76
  continue;
76
77
  }
@@ -102,7 +103,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
102
103
  if ("index" in progress)
103
104
  total01 = calculateProgress01(progress);
104
105
  if (!message && "name" in progress)
105
- this.setMessage(progress.name);
106
+ this.setMessage("loading " + progress.name);
106
107
  }
107
108
  this.loadingProgress = total01;
108
109
  if (message) this.setMessage(message);
@@ -125,11 +126,14 @@ export class EngineLoadingView implements ILoadingViewHandler {
125
126
  if (this._progressLoop) return;
126
127
  let dt = 1 / 12;
127
128
  const max = 1 - .05;
128
- if(debugRendering) dt = 1 / 500;
129
+ if (debugRendering) {
130
+ dt = 1 / 500;
131
+ if (typeof debugRendering === "number") dt *= debugRendering;
132
+ }
129
133
  this._progressLoop = setInterval(() => {
130
134
  if (this.loadingProgress >= 1 && this._progress >= max) {
131
135
  if (this._loadingElement) {
132
- if(debug) console.log("Hiding loading element");
136
+ if (debug) console.log("Hiding loading element");
133
137
  this._loadingElement.style.display = "none";
134
138
  this._loadingElement.remove();
135
139
  }
@@ -154,7 +158,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
154
158
  }
155
159
 
156
160
  private createLoadingElement(existing?: HTMLElement): HTMLElement {
157
- if(debug && !existing) console.log("Creating loading element");
161
+ if (debug && !existing) console.log("Creating loading element");
158
162
  this._loadingElement = existing || document.createElement("div");
159
163
  if (!existing) {
160
164
  this._loadingElement.style.position = "fixed";
@@ -186,9 +190,23 @@ export class EngineLoadingView implements ILoadingViewHandler {
186
190
  loadingBarContainer.style.display = "flex";
187
191
  loadingBarContainer.style.width = maxWidth + "%";
188
192
  loadingBarContainer.style.height = "2px";
189
- loadingBarContainer.style.background = "rgba(255,255,255,.1)"
193
+ loadingBarContainer.style.background = "rgba(255,255,255,.2)"
194
+ // loadingBarContainer.style.alignItems = "center";
190
195
  this._loadingElement.appendChild(loadingBarContainer);
191
196
 
197
+ const needleLogo = document.createElement("img");
198
+ const logoSize = 64;
199
+ needleLogo.style.width = `${logoSize}px`;
200
+ needleLogo.style.height = `${logoSize}px`;
201
+ needleLogo.style.position = "absolute";
202
+ needleLogo.style.left = "50%";
203
+ needleLogo.style.transform = `translate(-${logoSize * .5}px, -${logoSize + 32}px)`;
204
+ needleLogo.addEventListener("click", () => window.open("https://needle.tools", "_blank"));
205
+ needleLogo.style.cursor = "pointer";
206
+ needleLogo.style.pointerEvents = "all";
207
+ needleLogo.src = logoSVG;
208
+ loadingBarContainer.appendChild(needleLogo);
209
+
192
210
  this._loadingBar = document.createElement("div");
193
211
  loadingBarContainer.appendChild(this._loadingBar);
194
212
  const getGradientPos = function (t: number): string {
@@ -203,7 +221,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
203
221
  this._loadingTextContainer = document.createElement("div");
204
222
  this._loadingTextContainer.style.display = "flex";
205
223
  this._loadingTextContainer.style.justifyContent = "center";
206
- this._loadingTextContainer.style.marginTop = ".9em";
224
+ this._loadingTextContainer.style.marginTop = "1.2em";
207
225
  this._loadingElement.appendChild(this._loadingTextContainer);
208
226
 
209
227
  const messageContainer = document.createElement("div");
@@ -212,6 +230,8 @@ export class EngineLoadingView implements ILoadingViewHandler {
212
230
  messageContainer.style.fontSize = ".8em";
213
231
  messageContainer.style.paddingTop = ".5em";
214
232
  messageContainer.style.color = "rgba(255,255,255,.5)";
233
+ messageContainer.style.fontWeight = "200";
234
+ messageContainer.style.fontFamily = "Roboto, sans-serif";
215
235
  // messageContainer.style.border = "1px solid rgba(255,255,255,.1)";
216
236
  messageContainer.style.justifyContent = "center";
217
237
  this._loadingElement.appendChild(messageContainer);
@@ -0,0 +1,229 @@
1
+ import { getParam } from "./engine_utils";
2
+ import { ContextEvent, ContextRegistry } from "./engine_context_registry";
3
+ import { IContext } from "./engine_types";
4
+ import { logoSVG } from "./assets";
5
+
6
+ const debug = getParam("debuglicense");
7
+
8
+
9
+ // import licenseInformation from "./codegen/license.json";
10
+ let licenseInformation: any = null;
11
+ let licenseImportPromise: Promise<any> | null = null;
12
+ try {
13
+ licenseImportPromise = import("./codegen/license.json");
14
+ licenseImportPromise.then(res => {
15
+ licenseInformation = res.default;
16
+ licenseImportPromise = null;
17
+ if (debug) console.log("License imported via dynamic import", licenseInformation)
18
+ }).catch(err => { if (debug) console.error("Error on dynamic license import", err) });
19
+ }
20
+ catch (err) {
21
+ if (debug)
22
+ console.log("Importing license failed", err)
23
+ }
24
+
25
+
26
+ ContextRegistry.registerCallback(ContextEvent.ContextCreated, evt => {
27
+ showLicenseInfo(evt.context);
28
+ });
29
+
30
+ async function showLicenseInfo(ctx: IContext) {
31
+ try {
32
+ // if(licenseImportPromise) await licenseImportPromise;
33
+ //@ts-ignore
34
+ if (!licenseInformation || licenseInformation.hasLicense !== true || debug) return onNonCommercialVersionDetected(ctx);
35
+ }
36
+ catch (err) {
37
+ if (debug) console.log("License check failed", err)
38
+ return onNonCommercialVersionDetected(ctx)
39
+ }
40
+ if (debug) onNonCommercialVersionDetected(ctx)
41
+ }
42
+
43
+
44
+ const _licenseText = "🌵 <span class=\"text\">Made with <a href=\"https://needle.tools\" target=\"_blank\">Needle</a></span>";
45
+ const licenseElementClass = "needle-license-element";
46
+ const licenseDuration = 30000;
47
+ const licenseDelay = 600;
48
+
49
+ function onNonCommercialVersionDetected(ctx: IContext) {
50
+ insertNonCommercialUseHint(ctx);
51
+ sendNonCommercialUsageMessageToAnalyticsBackend();
52
+ }
53
+
54
+ function insertNonCommercialUseHint(ctx: IContext) {
55
+
56
+ let licenseText = _licenseText;
57
+ const licenseElement = createLicenseElement();
58
+ licenseElement.innerHTML = licenseText;
59
+
60
+ const style = createLicenseStyle();
61
+
62
+ const interval = setInterval(() => {
63
+ if (!licenseElement) return;
64
+ if (licenseElement.parentElement !== ctx.domElement) {
65
+ ctx.domElement.appendChild(licenseElement);
66
+ if (style) ctx.domElement.appendChild(style);
67
+ }
68
+ }, 100);
69
+
70
+ logNonCommercialUse();
71
+
72
+ let svg = `<img class="logo" src="${logoSVG}" style="width: 40px; height: 40px; margin-right: 2px; vertical-align: middle; margin-bottom: 2px;"/>`;
73
+ svg = "<a href=\"https://needle.tools\" target=\"_blank\">" + svg + "</a>";
74
+ licenseText = svg; //licenseText.replace("🌵", svg);
75
+ licenseElement.innerHTML = licenseText;
76
+
77
+ const removeDelay = licenseDuration + licenseDelay;
78
+ setTimeout(() => {
79
+ clearInterval(interval);
80
+ licenseElement?.remove();
81
+ }, removeDelay);
82
+
83
+ }
84
+
85
+ async function logNonCommercialUse(_logo?: string) {
86
+ const logo = "data:image/webp;base64,UklGRrABAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSKEAAAARN6CmbSM4WR7vdARON11EBDq3fLiNbVtVzpMCPlKAEzsx0Y/x+Ovuv4dn0EFE/ydAvz6YggXzgh5sVgXM/zOC/4sii7qgGvB5N7hmuQYwkvazWAu1JPW41FXSHq6pnaQWvqYH18Fc0j1hO/BFTtIeSBlJi5w6qIIO7IOrwhFsB2Yxukif0FTRLpXswHR8MxbslKe9VZsn/Ub5C7YFOpqSTABWUDgg6AAAAFAGAJ0BKiAAIAA+7VyoTqmkpCI3+qgBMB2JbACdMt69DwMIQBLhkTO6XwY00UEDK6cNIDnuNibPf0EgAP7Y1myuiQHLDsF/0h5unrGh6WAbv7aegg2ZMd3uRKfT/3SJztcaujYfTvMXspfCTmYcoO6a+vhC3ss4M8uM58t4siiu59I4aOl59e9Sr6xoxYlHf2v+NnBNpJYeJf8jABQAId/PXuBkLEFkiCucgSGEcfhvajql/j3reCGl0M5/9gQWy7ayNPs+wlvIxFnNfSlfuND4CZOCyxOHhRqOmHN4ULHo3tCSrUNvgAA=";
87
+ const style = `
88
+ font-size:18px;
89
+ background-size: contain;
90
+ background-position: left center;
91
+ background-repeat:no-repeat;
92
+ background-image:url('${logo}')
93
+ `;
94
+ let licenseText = "Needle Engine — non commercial version";
95
+ console.log("%c " + licenseText, style)
96
+ }
97
+
98
+ function createLicenseElement() {
99
+ const licenseElement = document.createElement("div");
100
+ licenseElement.classList.add(licenseElementClass);
101
+ licenseElement.setAttribute("data-needle_engine_license_element", "");
102
+ licenseElement.style.position = "fixed";
103
+ licenseElement.style.bottom = "12px";
104
+ licenseElement.style.right = "15px";
105
+
106
+ // licenseElement.style.textShadow = "0 0 2px rgba(200,200,200, 1)";
107
+ const maxPossibleZIndex = 2147483647;
108
+ licenseElement.style.zIndex = `${maxPossibleZIndex}`;
109
+ return licenseElement;
110
+ }
111
+
112
+ function createLicenseStyle() {
113
+ const licenseStyle = document.createElement("style");
114
+ const selector = "." + licenseElementClass;
115
+ licenseStyle.innerHTML = `
116
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;500&display=swap');
117
+
118
+ ${selector} {
119
+ font-family: 'Roboto', sans-serif !important;
120
+ font-weight: 300;
121
+ }
122
+
123
+ ${selector} a {
124
+ color: black;
125
+ text-decoration: none;
126
+ font-weight: 500;
127
+ }
128
+
129
+ @keyframes append-animate {
130
+ 0% {
131
+ transform: translate(0px, 10px);
132
+ opacity: 0;
133
+ pointer-events: none;
134
+ }
135
+ 1% {
136
+ transform: translate(0, -5px);
137
+ opacity: .9;
138
+ }
139
+ 2% {
140
+ transform: translate(0, 3px);
141
+ }
142
+ 6% {
143
+ transform: translate(0, 0px);
144
+ pointer-events: all;
145
+ opacity: 1;
146
+ }
147
+ 50% {
148
+ transform: scale(1)
149
+ }
150
+ 51% {
151
+ transform: scale(1.2)
152
+ }
153
+ 53% {
154
+ transform: scale(1)
155
+ }
156
+ 90% {
157
+ opacity: 1;
158
+ pointer-events: all;
159
+ transform: scale(1)
160
+ }
161
+ 100% {
162
+ opacity: 0;
163
+ pointer-events: none;
164
+ }
165
+ }
166
+ ${selector} {
167
+ opacity: 0;
168
+ pointer-events: none;
169
+ animation: append-animate;
170
+ animation-iteration-count: 1;
171
+ animation-duration: ${(licenseDuration / 1000)}s;
172
+ animation-delay: ${licenseDelay / 1000}s;
173
+ animation-easing: ease-in-out;
174
+ }
175
+
176
+ ${selector} .text, ${selector} a {
177
+ color: rgb(255, 0, 0);
178
+ mix-blend-mode: difference;
179
+ }
180
+
181
+ ${selector} .logo {
182
+ border-radius: 50%;
183
+ background-color: transparent;
184
+ padding: 5px;
185
+ transition: all 0.1s ease-in-out;
186
+ }
187
+
188
+ ${selector} .logo:hover {
189
+ transform: scale(1.3);
190
+ cursor: pointer;
191
+ }
192
+ `
193
+ return licenseStyle;
194
+ }
195
+
196
+
197
+ async function sendNonCommercialUsageMessageToAnalyticsBackend() {
198
+ try {
199
+ const analyticsBackendUrlForward = "https://urls.needle.tools/analytics-endpoint";
200
+ const res = await fetch(analyticsBackendUrlForward);
201
+ let analyticsUrl = await res.text();
202
+ if (analyticsUrl) {
203
+ if (debug) console.log("Analytics backend url", analyticsUrl);
204
+
205
+ // analyticsUrl = "http://localhost:3000/";
206
+
207
+ const currentUrl = window.location.href;
208
+
209
+ let endpoint = "api/v1/register/web-request";
210
+ if (!analyticsUrl.endsWith("/")) endpoint = "/" + endpoint;
211
+ const finalUrl = `${analyticsUrl}${endpoint}?type=non-commercial&url=${encodeURIComponent(currentUrl)}&hostname=${encodeURIComponent(window.location.hostname)}&pathname=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}&hash=${encodeURIComponent(window.location.hash)}`;
212
+ if (debug) console.log("Sending non-commercial usage message to analytics backend", finalUrl);
213
+
214
+
215
+ fetch(finalUrl,
216
+ {
217
+ mode: "no-cors"
218
+ })
219
+ .catch(err => {
220
+ if (debug)
221
+ console.log("Failed to send non-commercial usage message to analytics backend", err);
222
+ });
223
+ }
224
+ }
225
+ catch (err) {
226
+ if (debug)
227
+ console.log("Failed to send non-commercial usage message to analytics backend", err);
228
+ }
229
+ }
@@ -324,8 +324,22 @@ export class Physics {
324
324
  await RAPIER.init().then(() => RAPIER)
325
325
  Physics._didLoadPhysicsEngine = true;
326
326
  }
327
- const gravity = { x: 0.0, y: -9.81, z: 0.0 };
328
- this.world = new World(gravity);
327
+ this.world = new World(this._gravity);
328
+ }
329
+
330
+ private _gravity = { x: 0.0, y: -9.81, z: 0.0 };
331
+
332
+ get gravity() {
333
+ return this.world?.gravity ?? this._gravity;
334
+ }
335
+
336
+ set gravity(value: Vec3) {
337
+ if (this.world) {
338
+ this.world.gravity = value;
339
+ }
340
+ else {
341
+ this._gravity = value;
342
+ }
329
343
  }
330
344
 
331
345
  clearCaches() {
@@ -559,6 +559,14 @@ class Component implements IComponent, EventTarget {
559
559
  public get forward(): THREE.Vector3 {
560
560
  return Component._forward.set(0, 0, -1).applyQuaternion(this.worldQuaternion);
561
561
  }
562
+ private static _right: THREE.Vector3 = new THREE.Vector3();
563
+ public get right(): THREE.Vector3 {
564
+ return Component._right.set(1, 0, 0).applyQuaternion(this.worldQuaternion);
565
+ }
566
+ private static _up: THREE.Vector3 = new THREE.Vector3();
567
+ public get up(): THREE.Vector3 {
568
+ return Component._up.set(0, 1, 0).applyQuaternion(this.worldQuaternion);
569
+ }
562
570
 
563
571
 
564
572
 
@@ -5,7 +5,7 @@ import { Context } from "../engine/engine_setup";
5
5
  import { RoomEvents } from "../engine/engine_networking";
6
6
  import { UserJoinedOrLeftRoomModel } from "../engine/engine_networking";
7
7
  import { serializable } from "../engine/engine_serialization";
8
- import { IPointerClickHandler } from "./ui/PointerEvents";
8
+ import { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents";
9
9
  import { EventDispatcher } from "three";
10
10
  import { AudioSource } from "./AudioSource";
11
11
  import { getParam } from "../engine/engine_utils";
@@ -39,7 +39,8 @@ declare type ScreenCaptureOptions = {
39
39
 
40
40
  export class ScreenCapture extends Behaviour implements IPointerClickHandler {
41
41
 
42
- onPointerClick() {
42
+ onPointerClick(evt : PointerEventData) {
43
+ if(evt && evt.pointerId !== 0) return;
43
44
  if(this.context.connection.isInRoom === false) return;
44
45
  if (this.isReceiving) {
45
46
  if (this.videoPlayer)
@@ -122,6 +122,10 @@ export class VideoPlayer extends Behaviour {
122
122
  }
123
123
  }
124
124
 
125
+ get videoMaterial() {
126
+ return this._videoMaterial;
127
+ }
128
+
125
129
  get videoTexture() {
126
130
  return this._videoTexture;
127
131
  }
@@ -140,7 +144,7 @@ export class VideoPlayer extends Behaviour {
140
144
 
141
145
  private _videoElement: HTMLVideoElement | null = null;
142
146
  private _videoTexture: THREE.VideoTexture | null = null;
143
- private videoMaterial: Material | null = null;
147
+ private _videoMaterial: Material | null = null;
144
148
 
145
149
  private _isPlaying: boolean = false;
146
150
  private wasPlaying: boolean = false;
@@ -355,18 +359,18 @@ export class VideoPlayer extends Behaviour {
355
359
  if (mat) {
356
360
  this._targetObjects.push(target);
357
361
 
358
- if (mat !== this.videoMaterial) {
359
- this.videoMaterial = mat.clone();
360
- target["material"] = this.videoMaterial;
362
+ if (mat !== this._videoMaterial) {
363
+ this._videoMaterial = mat.clone();
364
+ target["material"] = this._videoMaterial;
361
365
  }
362
366
 
363
367
  if (!this.targetMaterialProperty) {
364
- (this.videoMaterial as any).map = this._videoTexture;
368
+ (this._videoMaterial as any).map = this._videoTexture;
365
369
  }
366
370
  else {
367
371
  switch (this.targetMaterialProperty) {
368
372
  default:
369
- (this.videoMaterial as any).map = this._videoTexture;
373
+ (this._videoMaterial as any).map = this._videoTexture;
370
374
  break;
371
375
  // doesnt render:
372
376
  // case "emissiveTexture":
@@ -50,3 +50,7 @@ if(!globalThis["THREE"]) {
50
50
  globalThis["THREE"] = THREE;
51
51
  }
52
52
  else console.warn("Threejs is already imported");
53
+
54
+
55
+
56
+ import "./engine/engine_license";