diff --git a/src/materials/Map.js b/src/materials/Map.js deleted file mode 100644 index a29d0db..0000000 --- a/src/materials/Map.js +++ /dev/null @@ -1,20 +0,0 @@ -import { defineComponent } from 'vue'; -import Texture from './Texture.js'; - -export default defineComponent({ - extends: Texture, - inject: ['material'], - created() { - this.material.setMap(this.texture); - }, - unmounted() { - this.material.setMap(null); - }, - methods: { - refreshTexture() { - this.createTexture(); - this.material.setMap(this.texture); - }, - }, - __hmrId: 'Map', -}); diff --git a/src/materials/Material.ts b/src/materials/Material.ts index e119389..b3769d0 100644 --- a/src/materials/Material.ts +++ b/src/materials/Material.ts @@ -53,7 +53,7 @@ export default defineComponent({ this.material.needsUpdate = needsUpdate } }, - setTexture(texture: Texture, key = 'map') { + setTexture(texture: Texture | null, key = 'map') { this.setProp(key, texture, true) }, addWatchers() { diff --git a/src/materials/Texture.js b/src/materials/Texture.js deleted file mode 100644 index 90df384..0000000 --- a/src/materials/Texture.js +++ /dev/null @@ -1,60 +0,0 @@ -import { defineComponent, watch } from 'vue'; -import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, TextureLoader, UVMapping } from 'three'; -import { bindProp } from '../tools'; - -export default defineComponent({ - inject: ['material'], - emits: ['loaded'], - props: { - name: { type: String, default: 'map' }, - uniform: { type: String, default: null }, - src: String, - onLoad: Function, - onProgress: Function, - onError: Function, - mapping: { type: Number, default: UVMapping }, - wrapS: { type: Number, default: ClampToEdgeWrapping }, - wrapT: { type: Number, default: ClampToEdgeWrapping }, - magFilter: { type: Number, default: LinearFilter }, - minFilter: { type: Number, default: LinearMipmapLinearFilter }, - repeat: { type: Object, default: { x: 1, y: 1 } }, - rotation: { type: Number, default: 0 }, - center: { type: Object, default: { x: 0, y: 0 } }, - }, - created() { - this.refreshTexture(); - watch(() => this.src, this.refreshTexture); - }, - unmounted() { - if (this.material && this.material.setTexture) this.material.setTexture(null, this.name); - this.texture.dispose(); - }, - methods: { - createTexture() { - this.texture = new TextureLoader().load(this.src, this.onLoaded, this.onProgress, this.onError); - const wathProps = ['mapping', 'wrapS', 'wrapT', 'magFilter', 'minFilter', 'repeat', 'rotation', 'rotation', 'center']; - wathProps.forEach(prop => { - bindProp(this, prop, this.texture); - }); - }, - refreshTexture() { - this.createTexture(); - // handle standard material - if (this.material && this.material.setTexture) { this.material.setTexture(this.texture, this.name); } - // handle shader material - else if (this.material && this.material.material.type === "ShaderMaterial") { - // require a `uniform` prop so we know what to call the uniform - if (!this.uniform) { - console.warn('"uniform" prop required to use texture in a shader.') - return - } - this.material.uniforms[this.uniform] = { value: this.texture }; - } - }, - onLoaded() { - if (this.onLoad) this.onLoad(); - this.$emit('loaded'); - }, - }, - render() { return []; }, -}); diff --git a/src/materials/Texture.ts b/src/materials/Texture.ts new file mode 100644 index 0000000..bf2fb1d --- /dev/null +++ b/src/materials/Texture.ts @@ -0,0 +1,67 @@ +import { defineComponent, PropType, watch } from 'vue' +import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, Texture, TextureLoader, UVMapping } from 'three' +import { bindProp } from '../tools' + +interface MaterialInterface { + uniforms: Record + setTexture(t: Texture | null, k: string): void +} + +interface TexureInterface { + material?: MaterialInterface + texture?: Texture +} + +export default defineComponent({ + inject: ['material'], + props: { + name: { type: String, default: 'map' }, + uniform: String, + src: String, + onLoad: Function as PropType<(t: Texture) => void>, + onProgress: Function as PropType<(e: ProgressEvent) => void>, + onError: Function as PropType<(e: ErrorEvent) => void>, + mapping: { type: Number, default: UVMapping }, + wrapS: { type: Number, default: ClampToEdgeWrapping }, + wrapT: { type: Number, default: ClampToEdgeWrapping }, + magFilter: { type: Number, default: LinearFilter }, + minFilter: { type: Number, default: LinearMipmapLinearFilter }, + repeat: { type: Object, default: () => ({ x: 1, y: 1 }) }, + rotation: { type: Number, default: 0 }, + center: { type: Object, default: () => ({ x: 0, y: 0 }) }, + }, + setup(): TexureInterface { + return {} + }, + created() { + this.refreshTexture() + watch(() => this.src, this.refreshTexture) + }, + unmounted() { + this.material?.setTexture(null, this.name) + this.texture?.dispose() + }, + methods: { + createTexture() { + if (!this.src) return false + this.texture = new TextureLoader().load(this.src, this.onLoaded, this.onProgress, this.onError) + const wathProps = ['mapping', 'wrapS', 'wrapT', 'magFilter', 'minFilter', 'repeat', 'rotation', 'rotation', 'center'] + wathProps.forEach(prop => { bindProp(this, prop, this.texture) }) + }, + refreshTexture() { + this.createTexture() + if (!this.texture) return false + + if (this.material) { + this.material.setTexture(this.texture, this.name) + if (this.uniform) { + this.material.uniforms[this.uniform] = { value: this.texture } + } + } + }, + onLoaded(t: Texture) { + if (this.onLoad) this.onLoad(t) + }, + }, + render() { return [] }, +})