Repository: vue-gl/vue-gl
Pull request #546 (2019-05-23 01:05:49)

Scene fog and background
Feature asked in this [issue](https://github.com/vue-gl/vue-gl/issues/540)

[vgl-scene]:
- new props : fog
- new props : backgroundColor
- new props : backgroundTexture
- new unit tests on init and changing props



Patch:
diff --git a/docs/property-types.md b/docs/property-types.md
index c6b861f..2e74580 100644
--- a/docs/property-types.md
+++ b/docs/property-types.md
@@ -67,5 +67,7 @@ Following list shows all property types and parsing schemas.
   Parsed as an array of float numbers.
 - ***vector2Array***
   Parsed as an array of vector2s.
+- ***fog***
+  Space-separated paramaters as color, near and far, corresponding [THREE.Fog](https://threejs.org/docs/#api/en/scenes/Fog)
 - ***names***
   A string or an array of string.
diff --git a/src/parsers.js b/src/parsers.js
index e81254b..edd17e4 100644
--- a/src/parsers.js
+++ b/src/parsers.js
@@ -4,6 +4,8 @@ import {
   Euler,
   Spherical,
   Quaternion,
+  Fog,
+  Color,
 } from 'three';
 
 /**
@@ -54,3 +56,17 @@ export function parseArray(str) {
 export function parseVector2Array(str) {
   return parseArray(str).map(elm => parseVector2(elm));
 }
+
+/**
+ * Returns a parsed fog object
+ */
+export function parseFog(str) {
+  return str.isFog ? str : new Fog(...str.trim().split(/\s+/).map((elm, i) => (i === 0 ? elm : parseFloat(elm))));
+}
+
+/**
+ * Returns a parsed Color object
+ */
+export function parseColor(str) {
+  return str.isColor ? str : new Color(str);
+}
diff --git a/src/scenes/vgl-scene.js b/src/scenes/vgl-scene.js
index 5cb392d..a8b1845 100644
--- a/src/scenes/vgl-scene.js
+++ b/src/scenes/vgl-scene.js
@@ -1,5 +1,7 @@
 import { Scene } from 'three';
 import VglObject3d from '../core/vgl-object3d';
+import { parseFog, parseColor } from '../parsers';
+import { string, fog } from '../validators';
 
 /**
  * This is where you place objects,
@@ -10,12 +12,42 @@ import VglObject3d from '../core/vgl-object3d';
 
 export default {
   mixins: [VglObject3d],
+  props: {
+    /** the color, near and far parameters of the scene's fog */
+    fog: {
+      type: fog,
+    },
+    /**
+     * Expecting to accept a string representing a color.
+     * Will be overwrited by backgroundTexture prop if both props are set
+    */
+    backgroundColor: string,
+    /** Expecting to accept a string representing a texture name. */
+    backgroundTexture: string,
+  },
   computed: {
     inst: () => new Scene(),
   },
+  methods: {
+    setBackgroundTexture() {
+      const { vglNamespace: { textures }, inst, backgroundTexture } = this;
+      if (backgroundTexture in textures) inst.background = textures[backgroundTexture];
+    },
+  },
+  created() {
+    const { vglNamespace: { beforeRender }, setBackgroundTexture } = this;
+    beforeRender.unshift(setBackgroundTexture);
+  },
   watch: {
     inst: {
-      handler(inst) { this.vglNamespace.scenes[this.name] = inst; },
+      handler(inst) {
+        this.vglNamespace.scenes[this.name] = inst;
+        if (this.fog) this.inst.fog = parseFog(this.fog);
+        if (this.backgroundColor) this.inst.background = parseColor(this.backgroundColor);
+        if (this.backgroundTexture) {
+          this.inst.background = this.vglNamespace.textures[this.backgroundTexture] || null;
+        }
+      },
       immediate: true,
     },
     name(name, oldName) {
@@ -23,9 +55,19 @@ export default {
       if (scenes[oldName] === inst) delete scenes[oldName];
       scenes[name] = inst;
     },
+    fog(newFog) {
+      this.inst.fog = parseFog(newFog);
+    },
+    backgroundColor(color) {
+      this.inst.background = parseColor(color);
+    },
+    backgroundTexture(name) {
+      this.inst.background = this.vglNamespace.textures[name] || null;
+    },
   },
   beforeDestroy() {
-    const { vglNamespace: { scenes }, inst } = this;
+    const { vglNamespace: { scenes, beforeRender }, inst, setBackgroundTexture } = this;
     if (scenes[this.name] === inst) delete scenes[this.name];
+    beforeRender.splice(beforeRender.indexOf(setBackgroundTexture), 1);
   },
 };
diff --git a/src/validators.js b/src/validators.js
index b64b269..cd51a00 100644
--- a/src/validators.js
+++ b/src/validators.js
@@ -4,6 +4,7 @@ import {
   Euler,
   Vector2,
   Quaternion,
+  Fog,
 } from 'three';
 
 export const number = [String, Number];
@@ -16,4 +17,5 @@ export const vector2 = [String, Vector2];
 export const quaternion = [String, Quaternion];
 export const floatArray = [String, Array];
 export const vector2Array = [String, Array];
+export const fog = [String, Fog];
 export const names = [String, Array];


Test patch:
diff --git a/test/scenes/vgl-scene.spec.js b/test/scenes/vgl-scene.spec.js
index a0222e6..4f70af6 100644
--- a/test/scenes/vgl-scene.spec.js
+++ b/test/scenes/vgl-scene.spec.js
@@ -16,4 +16,28 @@ describe('VglScene', () => {
     expect(Object.keys(new (Vue.extend(VglScene))({ inject }).$props))
       .toEqual(expect.arrayContaining(Object.keys($props)));
   });
+  test('the propertie "backgroundColor" of the instance should be specified by props', () => {
+    const { inst } = new (Vue.extend(VglScene))({ inject, propsData: { backgroundColor: '#8aeda3' } });
+    expect(inst.background.getHex()).toBe(0x8aeda3);
+  });
+  test('the propertie "fog" of the instance should be specified by props', () => {
+    const { inst } = new (Vue.extend(VglScene))({ inject, propsData: { fog: '#8aeda3 10 100' } });
+    expect(inst.fog.color.getHex()).toBe(0x8aeda3);
+    expect(inst.fog.near).toBe(parseFloat(10));
+    expect(inst.fog.far).toBe(parseFloat(100));
+  });
+  test('the properties "backgroundColor" of the instance should change after props change', async () => {
+    const vm = new (Vue.extend(VglScene))({ inject });
+    vm.backgroundColor = '#6751f2';
+    await vm.$nextTick();
+    expect(vm.inst.background.getHex()).toBe(0x6751f2);
+  });
+  test('the properties "fog" of the instance should change after props change', async () => {
+    const vm = new (Vue.extend(VglScene))({ inject });
+    vm.fog = '#6751f2 10 100';
+    await vm.$nextTick();
+    expect(vm.inst.fog.color.getHex()).toBe(0x6751f2);
+    expect(vm.inst.fog.near).toBe(parseFloat(10));
+    expect(vm.inst.fog.far).toBe(parseFloat(100));
+  });
 });