mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
164 lines • 5.48 kB
JavaScript
import { Color, RepeatWrapping, Vector2, VideoTexture } from "three";
import loadTexture from "../../utils/loaders/loadTexture";
import { Reactive } from "@lincode/reactivity";
import queueDebounce from "../../../utils/queueDebounce";
import { deg2Rad } from "@lincode/math";
const mapNames = ["map", "alphaMap"];
const queueTextureRepeat = queueDebounce();
export default class TexturedBasicMixin {
materialCloned;
tryCloneMaterial() {
if (this.materialCloned)
return;
this.materialCloned = true;
//@ts-ignore
this.material = this.nativeObject3d.material = this.material.clone();
//@ts-ignore
this.then(() => this.material.dispose());
}
get color() {
return "#" + this.material.color.getHexString();
}
set color(val) {
this.tryCloneMaterial();
this.material.color = new Color(val);
}
get fog() {
return this.material.fog;
}
set fog(val) {
this.tryCloneMaterial();
this.material.fog = val;
}
_opacity;
get opacity() {
return (this._opacity ??= 1);
}
set opacity(val) {
this.tryCloneMaterial();
this._opacity = val;
this.material.opacity = val;
this.material.transparent = val <= 1;
//@ts-ignore
this.nativeObject3d.visible = !!val;
}
applyTexture(mapNames) {
const repeat = this._textureRepeat;
const flipY = this._textureFlipY;
const rotation = this._textureRotation;
queueTextureRepeat(this, () => {
this.tryCloneMaterial();
for (const name of mapNames) {
//@ts-ignore
const map = this.material[name];
if (!map)
return;
repeat !== undefined && (map.repeat = repeat);
flipY !== undefined && (map.flipY = flipY);
rotation !== undefined && (map.rotation = rotation * deg2Rad);
map.needsUpdate = true;
}
});
}
videoTextureState;
textureState;
initTexture() {
if (this.textureState)
return;
this.tryCloneMaterial();
const videoTextureState = (this.videoTextureState = new Reactive(undefined));
const textureState = (this.textureState = new Reactive(undefined));
//@ts-ignore
this.createEffect(() => {
const url = textureState.get();
const videoURL = videoTextureState.get();
if (videoURL) {
let video;
if (typeof videoURL === "string") {
video = document.createElement("video");
video.crossOrigin = "anonymous";
video.src = videoURL;
video.loop = true;
video.autoplay = true;
video.muted = true;
video.playsInline = true;
video.play();
}
else
video = videoURL;
const videoTexture = new VideoTexture(video, undefined, RepeatWrapping, RepeatWrapping);
const { material } = this;
const { map } = material;
material.map = videoTexture;
material.needsUpdate = true;
this.applyTexture(mapNames);
return () => {
video.pause();
videoTexture.dispose();
material.map = map;
material.needsUpdate = true;
};
}
if (!url)
return;
const { material } = this;
const { map } = material;
material.map = loadTexture(url);
this.applyTexture(mapNames);
return () => {
material.map = map;
this.material.needsUpdate = true;
};
}, [videoTextureState.get, textureState.get]);
}
get videoTexture() {
return this.videoTextureState?.get();
}
set videoTexture(url) {
this.initTexture();
this.videoTextureState.set(url);
}
get texture() {
return this.textureState?.get();
}
set texture(url) {
this.initTexture();
this.textureState.set(url);
}
_alphaMap;
get alphaMap() {
return this._alphaMap;
}
set alphaMap(val) {
this.tryCloneMaterial();
this._alphaMap = val;
this.material.alphaMap = val ? loadTexture(val) : null;
this.applyTexture(mapNames);
}
_textureRepeat;
get textureRepeat() {
return this._textureRepeat;
}
set textureRepeat(val) {
typeof val === "number" && (val = new Vector2(val, val));
this._textureRepeat = val;
this.applyTexture(mapNames);
}
_textureFlipY;
get textureFlipY() {
return this._textureFlipY;
}
set textureFlipY(val) {
this._textureFlipY = val;
this.applyTexture(mapNames);
}
_textureRotation;
get textureRotation() {
return this._textureRotation;
}
set textureRotation(val) {
this._textureRotation = val;
this.applyTexture(mapNames);
}
}
//# sourceMappingURL=TexturedBasicMixin.js.map