|
@@ -1,10 +1,11 @@
|
|
|
import XStaticMesh from "./XStaticMesh.js"
|
|
|
import EMeshType from "./enum/EMeshType.js"
|
|
|
import Logger from "./Logger.js"
|
|
|
+import Stream from "./Stream.js";
|
|
|
|
|
|
-const logger = new Logger('XTelevision')
|
|
|
+const logger = new Logger('Television')
|
|
|
export default class XTelevision {
|
|
|
- constructor(e, t, r, n) {
|
|
|
+ constructor(scene, meshUrl, scenemanager, option) {
|
|
|
E(this, "videoElement");
|
|
|
E(this, "meshPath");
|
|
|
E(this, "scene");
|
|
@@ -15,14 +16,15 @@ export default class XTelevision {
|
|
|
E(this, "widthHeightScale");
|
|
|
E(this, "fitMode");
|
|
|
E(this, "_scenemanager");
|
|
|
- if (this.scene = e,
|
|
|
- this.meshPath = t,
|
|
|
- this._scenemanager = r,
|
|
|
- n != null) {
|
|
|
- const {vAng: o=0, widthHeightScale: a=-1, fitMode: s="fill"} = n;
|
|
|
- this.vAng = o,
|
|
|
- this.widthHeightScale = a,
|
|
|
- this.fitMode = s
|
|
|
+
|
|
|
+ this.scene = scene
|
|
|
+ this.meshPath = meshUrl
|
|
|
+ this._scenemanager = scenemanager
|
|
|
+ if (option != null) {
|
|
|
+ const {vAng=0, widthHeightScale=-1, fitMode="fill"} = option;
|
|
|
+ this.vAng = vAng,
|
|
|
+ this.widthHeightScale = widthHeightScale,
|
|
|
+ this.fitMode = fitMode
|
|
|
}
|
|
|
}
|
|
|
set tvWidthHeightscale(e) {
|
|
@@ -51,39 +53,38 @@ export default class XTelevision {
|
|
|
n
|
|
|
}
|
|
|
async setUrl(e) {
|
|
|
- const {url: t, isLive: r=!1, poster: n=null, bLoop: o=!1, bMuted: a=!0} = e || {};
|
|
|
- if (typeof t != "string")
|
|
|
- return logger.error("[Engine] Tv setUrl Error, url must be string: ", t),
|
|
|
+ const {url, isLive: r=!1, poster: n=null, bLoop: o=!1, bMuted: a=!0} = e || {};
|
|
|
+
|
|
|
+ if (typeof url != "string")
|
|
|
+ return logger.error("[Engine] Tv setUrl Error, url must be string: ", url),
|
|
|
Promise.reject(new XTvMediaUrlError("[Engine] url must be string"));
|
|
|
+
|
|
|
if (this.videoElement) {
|
|
|
- this.videoElement.src = t,
|
|
|
+ this.videoElement.src = url,
|
|
|
n != null && n.length > 0 && (this.videoElement.poster = n);
|
|
|
const l = this.play();
|
|
|
return "bMuted"in e && l !== void 0 && l.then(()=>{
|
|
|
this.videoElement.muted = a
|
|
|
- }
|
|
|
- ),
|
|
|
+ }),
|
|
|
this.videoElement.addEventListener("loadedmetadata", u=>{
|
|
|
- this.videoElement.videoWidth > 0 ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight) : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
- }
|
|
|
- ),
|
|
|
+ this.videoElement.videoWidth > 0
|
|
|
+ ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight)
|
|
|
+ : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
+ }),
|
|
|
Promise.resolve(this)
|
|
|
}
|
|
|
- const s = this.createElement(t, o);
|
|
|
- return n != null && n.length > 0 && (s.poster = n),
|
|
|
- this.setVideo(s, r).then(()=>{
|
|
|
- var u;
|
|
|
- const l = (u = this.videoElement) == null ? void 0 : u.play();
|
|
|
+
|
|
|
+ const s = this.createElement(url, o);
|
|
|
+ n != null && n.length > 0 && (s.poster = n)
|
|
|
+ return this.setVideo(s, r).then(()=>{
|
|
|
+ const l = this.videoElement && this.videoElement.play();
|
|
|
"bMuted"in e && l !== void 0 && l.then(()=>{
|
|
|
this.videoElement.muted = a
|
|
|
- }
|
|
|
- )
|
|
|
- }
|
|
|
- ).catch(l=>{
|
|
|
+ })
|
|
|
+ }).catch(l=>{
|
|
|
logger.error("[Engine] setUrl error! " + l),
|
|
|
new XTvMediaUrlError("[Engine] setUrl error! " + l)
|
|
|
- }
|
|
|
- )
|
|
|
+ })
|
|
|
}
|
|
|
setCurrentTime(e) {
|
|
|
if (!this.videoElement) {
|
|
@@ -136,76 +137,104 @@ export default class XTelevision {
|
|
|
this.videoMat.setFloat("tvWidthHeightScale", this.widthHeightScale),
|
|
|
this.videoMat.setFloat("bforceforceKeepContent", -1)) : this.videoMat.setFloat("tvWidthHeightScale", -1)
|
|
|
}
|
|
|
- async setVideo(e, t=!1, r=!0) {
|
|
|
- return this.tvMeshs.length != 0 ? (logger.warn(`[Engine] Set Video. length!=0, mesh: ${this.meshPath}, src: ${e.src}`),
|
|
|
- new Promise((n,o)=>{
|
|
|
- if (!(e instanceof HTMLVideoElement))
|
|
|
- return logger.error("[Engine] Error, param of setVideo must be a HTMLVideoElement"),
|
|
|
- o(new XTvVideoElementError("[Engine] param of setVideo must be a HTMLVideoElement"));
|
|
|
- this.videoElement = e,
|
|
|
- r == !1 && (t == !1 || checkOS().isIOS) && e.crossOrigin !== "anonymous" && (e.crossOrigin = "anonymous",
|
|
|
- e.load()),
|
|
|
- this.videoElement.addEventListener("loadedmetadata", a=>{
|
|
|
- this.videoElement.videoWidth > 0 ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight) : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
- }
|
|
|
- ),
|
|
|
- this.videoTexture.updateURL(this.videoElement.src),
|
|
|
- n(this)
|
|
|
- }
|
|
|
- )) : (logger.warn(`[Engine] Set Video. length==0, mesh: ${this.meshPath}, src: ${e.src}`),
|
|
|
- this.meshPath == "" ? (logger.error("[Engine] Error, television meshPath is empty."),
|
|
|
- Promise.reject(new XTvVideoElementError("[Engine] Error, television meshPath is empty."))) : this._scenemanager.urlTransformer(this.meshPath).then(n=>new Promise((o,a)=>e instanceof HTMLVideoElement ? (this.videoElement = e,
|
|
|
- r == !1 && (t == !1 || checkOS().isIOS) && e.crossOrigin !== "anonymous" && (e.crossOrigin = "anonymous",
|
|
|
- e.load()),
|
|
|
- BABYLON.SceneLoader.LoadAssetContainerAsync("", n, this.scene, null, ".glb").then(s=>{
|
|
|
- for (let u = s.materials.length - 1; u >= 0; --u)
|
|
|
- s.materials[u].dispose();
|
|
|
- const l = [];
|
|
|
- this.videoTexture = new VideoTexture("videoTex_" + Date.now(),e,this.scene,!1,!0,void 0,{
|
|
|
- autoPlay: !0,
|
|
|
- autoUpdateTexture: !0,
|
|
|
- muted: !0
|
|
|
- }),
|
|
|
- this.videoTexture.vAng = this.vAng,
|
|
|
- this.videoMat = new ShaderMaterial("videoMat_" + Date.now(),this.scene,{
|
|
|
- vertexSource: tvVertex,
|
|
|
- fragmentSource: tvFragment
|
|
|
- },{
|
|
|
- attributes: ["uv", "position"],
|
|
|
- uniforms: ["view", "projection", "worldViewProjection", "world"]
|
|
|
- }),
|
|
|
- this.videoMat.setTexture("texture_video", this.videoTexture),
|
|
|
- this.videoMat.setFloat("tvWidthHeightScale", -1),
|
|
|
- this.videoMat.setFloat("mvWidthHeightScale", 16 / 9),
|
|
|
- this.videoMat.setFloat("bforceforceKeepContent", -1),
|
|
|
- this.videoMat.backFaceCulling = !1,
|
|
|
- this.videoMat.sideOrientation = BABYLON.Mesh.FRONTSIDE,
|
|
|
- this.videoElement.addEventListener("loadedmetadata", u=>{
|
|
|
- this.videoElement.videoWidth > 0 ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight) : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
- }
|
|
|
- );
|
|
|
- for (let u = 0; u < s.meshes.length; ++u)
|
|
|
- s.meshes[u].visibility = 1,
|
|
|
- s.meshes[u].isPickable = !0,
|
|
|
- s.meshes[u].checkCollisions = !1,
|
|
|
- s.meshes[u].material = this.videoMat,
|
|
|
- "hasVertexAlpha"in s.meshes[u] && (s.meshes[u].hasVertexAlpha = !1),
|
|
|
- this.scene.addMesh(s.meshes[u]),
|
|
|
- l.push(new XStaticMesh({
|
|
|
- id: s.meshes[u].id,
|
|
|
- mesh: s.meshes[u],
|
|
|
- xtype: EMeshType.Tv
|
|
|
- }));
|
|
|
- this.changeTvFitMode(),
|
|
|
- this.tvMeshs = l,
|
|
|
- this.toggle(!0),
|
|
|
- o(this)
|
|
|
- }
|
|
|
- ).catch(s=>{
|
|
|
- logger.error("[Engine] setVideo: create Tv by input mesh error! " + s),
|
|
|
- a(new XTvModelError("[Engine] setVideo: create Tv by input mesh error! " + s))
|
|
|
- }
|
|
|
- )) : a(new XTvVideoElementError("[Engine] param of setVideo must be a HTMLVideoElement")))))
|
|
|
+ async setVideo(e, t=!1, r=!0)
|
|
|
+ {
|
|
|
+ return this.tvMeshs.length != 0 ? (
|
|
|
+ logger.warn(`[Engine] Set Video. length!=0, mesh: ${this.meshPath}, src: ${e.src}`),
|
|
|
+
|
|
|
+ new Promise((n,o)=>
|
|
|
+ {
|
|
|
+ if (!(e instanceof HTMLVideoElement))
|
|
|
+ return logger.error("[Engine] Error, param of setVideo must be a HTMLVideoElement"),
|
|
|
+ o(new XTvVideoElementError("[Engine] param of setVideo must be a HTMLVideoElement"));
|
|
|
+
|
|
|
+ this.videoElement = e,
|
|
|
+
|
|
|
+ r == !1
|
|
|
+ && (t == !1 || checkOS().isIOS)
|
|
|
+ && e.crossOrigin !== "anonymous"
|
|
|
+ && (e.crossOrigin = "anonymous", e.load()),
|
|
|
+
|
|
|
+ this.videoElement.addEventListener("loadedmetadata", a=>{
|
|
|
+ this.videoElement.videoWidth > 0 ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight) : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
+ }),
|
|
|
+ this.videoTexture.updateURL(this.videoElement.src),
|
|
|
+
|
|
|
+ n(this)
|
|
|
+ })
|
|
|
+ ) : (
|
|
|
+ logger.warn(`[Engine] Set Video. length==0, mesh: ${this.meshPath}, src: ${e.src}`),
|
|
|
+
|
|
|
+ this.meshPath == ""
|
|
|
+ ? (
|
|
|
+ logger.error("[Engine] Error, television meshPath is empty."),
|
|
|
+ Promise.reject(new XTvVideoElementError("[Engine] Error, television meshPath is empty."))
|
|
|
+ )
|
|
|
+ : this._scenemanager.urlTransformer(this.meshPath).then(n => new Promise((o,a) =>
|
|
|
+ e instanceof HTMLVideoElement
|
|
|
+ ? (
|
|
|
+ this.videoElement = e,
|
|
|
+
|
|
|
+ r == !1
|
|
|
+ && (t == !1 || checkOS().isIOS)
|
|
|
+ && e.crossOrigin !== "anonymous"
|
|
|
+ && (e.crossOrigin = "anonymous", e.load()),
|
|
|
+
|
|
|
+ BABYLON.SceneLoader.LoadAssetContainerAsync("", n, this.scene, null, ".glb").then(s=>{
|
|
|
+ for (let u = s.materials.length - 1; u >= 0; --u) s.materials[u].dispose();
|
|
|
+
|
|
|
+ this.videoTexture = new BABYLON.VideoTexture("videoTex_" + Date.now(),e,this.scene,!1,!0,void 0,{
|
|
|
+ autoPlay: !0,
|
|
|
+ autoUpdateTexture: !0,
|
|
|
+ muted: !0
|
|
|
+ }),
|
|
|
+ this.videoTexture.vAng = this.vAng,
|
|
|
+ this.videoMat = new BABYLON.ShaderMaterial("videoMat_" + Date.now(),this.scene,{
|
|
|
+ vertexSource: tvVertex,
|
|
|
+ fragmentSource: tvFragment
|
|
|
+ },{
|
|
|
+ attributes: ["uv", "position"],
|
|
|
+ uniforms: ["view", "projection", "worldViewProjection", "world"]
|
|
|
+ }),
|
|
|
+ this.videoMat.setTexture("texture_video", this.videoTexture),
|
|
|
+ this.videoMat.setFloat("tvWidthHeightScale", -1),
|
|
|
+ this.videoMat.setFloat("mvWidthHeightScale", 16 / 9),
|
|
|
+ this.videoMat.setFloat("bforceforceKeepContent", -1),
|
|
|
+ this.videoMat.backFaceCulling = !1,
|
|
|
+ this.videoMat.sideOrientation = BABYLON.Mesh.FRONTSIDE,
|
|
|
+
|
|
|
+ this.videoElement.addEventListener("loadedmetadata", u=>{
|
|
|
+ this.videoElement.videoWidth > 0
|
|
|
+ ? this.videoMat.setFloat("mvWidthHeightScale", this.videoElement.videoWidth / this.videoElement.videoHeight)
|
|
|
+ : this.videoMat.setFloat("mvWidthHeightScale", 16 / 9)
|
|
|
+ });
|
|
|
+
|
|
|
+ const tvMeshs = [];
|
|
|
+ for (let u = 0; u < s.meshes.length; ++u)
|
|
|
+ s.meshes[u].visibility = 1,
|
|
|
+ s.meshes[u].isPickable = !0,
|
|
|
+ s.meshes[u].checkCollisions = !1,
|
|
|
+ s.meshes[u].material = this.videoMat,
|
|
|
+ "hasVertexAlpha"in s.meshes[u] && (s.meshes[u].hasVertexAlpha = !1),
|
|
|
+ this.scene.addMesh(s.meshes[u]),
|
|
|
+ tvMeshs.push(new XStaticMesh({
|
|
|
+ id: s.meshes[u].id,
|
|
|
+ mesh: s.meshes[u],
|
|
|
+ xtype: EMeshType.Tv
|
|
|
+ }));
|
|
|
+
|
|
|
+ this.changeTvFitMode(),
|
|
|
+ this.tvMeshs = tvMeshs,
|
|
|
+ this.toggle(!0),
|
|
|
+ o(this)
|
|
|
+ }).catch(s=>{
|
|
|
+ logger.error("[Engine] setVideo: create Tv by input mesh error! " + s),
|
|
|
+ a(new XTvModelError("[Engine] setVideo: create Tv by input mesh error! " + s))
|
|
|
+ })
|
|
|
+ )
|
|
|
+ : a(new XTvVideoElementError("[Engine] param of setVideo must be a HTMLVideoElement"))
|
|
|
+ ))
|
|
|
+ )
|
|
|
}
|
|
|
async setSameVideo(e, t="") {
|
|
|
return e == null || e == null ? (logger.error("[Engine] setSameVideo: input material is null or undefined "),
|